diff --git a/[refs] b/[refs] index e32a5fdf6716..2923da08b551 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 99efb9369c54fa98fc354a9ad4bc8c59f3212ff4 +refs/heads/master: a3da8e451321c31d88cebd12c234d0aac2a1cc35 diff --git a/trunk/Documentation/ABI/obsolete/proc-pid-oom_adj b/trunk/Documentation/ABI/obsolete/proc-pid-oom_adj deleted file mode 100644 index cf63f264ce0f..000000000000 --- a/trunk/Documentation/ABI/obsolete/proc-pid-oom_adj +++ /dev/null @@ -1,22 +0,0 @@ -What: /proc//oom_adj -When: August 2012 -Why: /proc//oom_adj allows userspace to influence the oom killer's - badness heuristic used to determine which task to kill when the kernel - is out of memory. - - The badness heuristic has since been rewritten since the introduction of - this tunable such that its meaning is deprecated. The value was - implemented as a bitshift on a score generated by the badness() - function that did not have any precise units of measure. With the - rewrite, the score is given as a proportion of available memory to the - task allocating pages, so using a bitshift which grows the score - exponentially is, thus, impossible to tune with fine granularity. - - A much more powerful interface, /proc//oom_score_adj, was - introduced with the oom killer rewrite that allows users to increase or - decrease the badness() score linearly. This interface will replace - /proc//oom_adj. - - A warning will be emitted to the kernel log if an application uses this - deprecated interface. After it is printed once, future warnings will be - suppressed until the kernel is rebooted. diff --git a/trunk/Documentation/filesystems/xfs-delayed-logging-design.txt b/trunk/Documentation/filesystems/xfs-delayed-logging-design.txt index 7445bf335dae..96d0df28bed3 100644 --- a/trunk/Documentation/filesystems/xfs-delayed-logging-design.txt +++ b/trunk/Documentation/filesystems/xfs-delayed-logging-design.txt @@ -794,6 +794,17 @@ designed. Roadmap: +2.6.37 Remove experimental tag from mount option + => should be roughly 6 months after initial merge + => enough time to: + => gain confidence and fix problems reported by early + adopters (a.k.a. guinea pigs) + => address worst performance regressions and undesired + behaviours + => start tuning/optimising code for parallelism + => start tuning/optimising algorithms consuming + excessive CPU time + 2.6.39 Switch default mount option to use delayed logging => should be roughly 12 months after initial merge => enough time to shake out remaining problems before next round of diff --git a/trunk/Documentation/leds-class.txt b/trunk/Documentation/leds-class.txt index 58b266bd1846..8fd5ca2ae32d 100644 --- a/trunk/Documentation/leds-class.txt +++ b/trunk/Documentation/leds-class.txt @@ -60,18 +60,15 @@ Hardware accelerated blink of LEDs Some LEDs can be programmed to blink without any CPU interaction. To support this feature, a LED driver can optionally implement the -blink_set() function (see ). To set an LED to blinking, -however, it is better to use use the API function led_blink_set(), -as it will check and implement software fallback if necessary. - -To turn off blinking again, use the API function led_brightness_set() -as that will not just set the LED brightness but also stop any software -timers that may have been required for blinking. - -The blink_set() function should choose a user friendly blinking value -if it is called with *delay_on==0 && *delay_off==0 parameters. In this -case the driver should give back the chosen value through delay_on and -delay_off parameters to the leds subsystem. +blink_set() function (see ). If implemented, triggers can +attempt to use it before falling back to software timers. The blink_set() +function should return 0 if the blink setting is supported, or -EINVAL +otherwise, which means that LED blinking will be handled by software. + +The blink_set() function should choose a user friendly blinking +value if it is called with *delay_on==0 && *delay_off==0 parameters. In +this case the driver should give back the chosen value through delay_on +and delay_off parameters to the leds subsystem. Setting the brightness to zero with brightness_set() callback function should completely turn off the LED and cancel the previously programmed diff --git a/trunk/Documentation/leds/leds-lp5521.txt b/trunk/Documentation/leds/leds-lp5521.txt deleted file mode 100644 index c4d8d151e0fe..000000000000 --- a/trunk/Documentation/leds/leds-lp5521.txt +++ /dev/null @@ -1,88 +0,0 @@ -Kernel driver for lp5521 -======================== - -* National Semiconductor LP5521 led driver chip -* Datasheet: http://www.national.com/pf/LP/LP5521.html - -Authors: Mathias Nyman, Yuri Zaporozhets, Samu Onkalo -Contact: Samu Onkalo (samu.p.onkalo-at-nokia.com) - -Description ------------ - -LP5521 can drive up to 3 channels. Leds can be controlled directly via -the led class control interface. Channels have generic names: -lp5521:channelx, where x is 0 .. 2 - -All three channels can be also controlled using the engine micro programs. -More details of the instructions can be found from the public data sheet. - -Control interface for the engines: -x is 1 .. 3 -enginex_mode : disabled, load, run -enginex_load : store program (visible only in engine load mode) - -Example (start to blink the channel 2 led): -cd /sys/class/leds/lp5521:channel2/device -echo "load" > engine3_mode -echo "037f4d0003ff6000" > engine3_load -echo "run" > engine3_mode - -stop the engine: -echo "disabled" > engine3_mode - -sysfs contains a selftest entry. -The test communicates with the chip and checks that -the clock mode is automatically set to the requested one. - -Each channel has its own led current settings. -/sys/class/leds/lp5521:channel0/led_current - RW -/sys/class/leds/lp5521:channel0/max_current - RO -Format: 10x mA i.e 10 means 1.0 mA - -example platform data: - -Note: chan_nr can have values between 0 and 2. - -static struct lp5521_led_config lp5521_led_config[] = { - { - .chan_nr = 0, - .led_current = 50, - .max_current = 130, - }, { - .chan_nr = 1, - .led_current = 0, - .max_current = 130, - }, { - .chan_nr = 2, - .led_current = 0, - .max_current = 130, - } -}; - -static int lp5521_setup(void) -{ - /* setup HW resources */ -} - -static void lp5521_release(void) -{ - /* Release HW resources */ -} - -static void lp5521_enable(bool state) -{ - /* Control of chip enable signal */ -} - -static struct lp5521_platform_data lp5521_platform_data = { - .led_config = lp5521_led_config, - .num_channels = ARRAY_SIZE(lp5521_led_config), - .clock_mode = LP5521_CLOCK_EXT, - .setup_resources = lp5521_setup, - .release_resources = lp5521_release, - .enable = lp5521_enable, -}; - -If the current is set to 0 in the platform data, that channel is -disabled and it is not visible in the sysfs. diff --git a/trunk/Documentation/leds/leds-lp5523.txt b/trunk/Documentation/leds/leds-lp5523.txt deleted file mode 100644 index fad2feb8b7ce..000000000000 --- a/trunk/Documentation/leds/leds-lp5523.txt +++ /dev/null @@ -1,83 +0,0 @@ -Kernel driver for lp5523 -======================== - -* National Semiconductor LP5523 led driver chip -* Datasheet: http://www.national.com/pf/LP/LP5523.html - -Authors: Mathias Nyman, Yuri Zaporozhets, Samu Onkalo -Contact: Samu Onkalo (samu.p.onkalo-at-nokia.com) - -Description ------------ -LP5523 can drive up to 9 channels. Leds can be controlled directly via -the led class control interface. Channels have generic names: -lp5523:channelx where x is 0...8 - -The chip provides 3 engines. Each engine can control channels without -interaction from the main CPU. Details of the micro engine code can be found -from the public data sheet. Leds can be muxed to different channels. - -Control interface for the engines: -x is 1 .. 3 -enginex_mode : disabled, load, run -enginex_load : microcode load (visible only in load mode) -enginex_leds : led mux control (visible only in load mode) - -cd /sys/class/leds/lp5523:channel2/device -echo "load" > engine3_mode -echo "9d80400004ff05ff437f0000" > engine3_load -echo "111111111" > engine3_leds -echo "run" > engine3_mode - -sysfs contains a selftest entry. It measures each channel -voltage level and checks if it looks reasonable. If the level is too high, -the led is missing; if the level is too low, there is a short circuit. - -Selftest uses always the current from the platform data. - -Each channel contains led current settings. -/sys/class/leds/lp5523:channel2/led_current - RW -/sys/class/leds/lp5523:channel2/max_current - RO -Format: 10x mA i.e 10 means 1.0 mA - -Example platform data: - -Note - chan_nr can have values between 0 and 8. - -static struct lp5523_led_config lp5523_led_config[] = { - { - .chan_nr = 0, - .led_current = 50, - .max_current = 130, - }, -... - }, { - .chan_nr = 8, - .led_current = 50, - .max_current = 130, - } -}; - -static int lp5523_setup(void) -{ - /* Setup HW resources */ -} - -static void lp5523_release(void) -{ - /* Release HW resources */ -} - -static void lp5523_enable(bool state) -{ - /* Control chip enable signal */ -} - -static struct lp5523_platform_data lp5523_platform_data = { - .led_config = lp5523_led_config, - .num_channels = ARRAY_SIZE(lp5523_led_config), - .clock_mode = LP5523_CLOCK_EXT, - .setup_resources = lp5523_setup, - .release_resources = lp5523_release, - .enable = lp5523_enable, -}; diff --git a/trunk/Documentation/sysctl/kernel.txt b/trunk/Documentation/sysctl/kernel.txt index 209e1584c3dc..3894eaa23486 100644 --- a/trunk/Documentation/sysctl/kernel.txt +++ b/trunk/Documentation/sysctl/kernel.txt @@ -28,7 +28,6 @@ show up in /proc/sys/kernel: - core_uses_pid - ctrl-alt-del - dentry-state -- dmesg_restrict - domainname - hostname - hotplug @@ -214,19 +213,6 @@ to decide what to do with it. ============================================================== -dmesg_restrict: - -This toggle indicates whether unprivileged users are prevented from using -dmesg(8) to view messages from the kernel's log buffer. When -dmesg_restrict is set to (0) there are no restrictions. When -dmesg_restrict is set set to (1), users must have CAP_SYS_ADMIN to use -dmesg(8). - -The kernel config option CONFIG_SECURITY_DMESG_RESTRICT sets the default -value of dmesg_restrict. - -============================================================== - domainname & hostname: These files can be used to set the NIS/YP domainname and the diff --git a/trunk/arch/um/include/asm/ptrace-generic.h b/trunk/arch/um/include/asm/ptrace-generic.h index b7c5bab9bd77..2cd899f75a3c 100644 --- a/trunk/arch/um/include/asm/ptrace-generic.h +++ b/trunk/arch/um/include/asm/ptrace-generic.h @@ -38,8 +38,8 @@ struct pt_regs { struct task_struct; -extern long subarch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data); +extern long subarch_ptrace(struct task_struct *child, long request, long addr, + long data); extern unsigned long getreg(struct task_struct *child, int regno); extern int putreg(struct task_struct *child, int regno, unsigned long value); extern int get_fpregs(struct user_i387_struct __user *buf, diff --git a/trunk/arch/um/kernel/ptrace.c b/trunk/arch/um/kernel/ptrace.c index 701b672c1122..a5e33f29bbeb 100644 --- a/trunk/arch/um/kernel/ptrace.c +++ b/trunk/arch/um/kernel/ptrace.c @@ -122,7 +122,7 @@ long arch_ptrace(struct task_struct *child, long request, break; case PTRACE_SET_THREAD_AREA: - ret = ptrace_set_thread_area(child, addr, vp); + ret = ptrace_set_thread_area(child, addr, datavp); break; case PTRACE_FAULTINFO: { diff --git a/trunk/crypto/pcrypt.c b/trunk/crypto/pcrypt.c index 75586f1f86e7..de3078215fe6 100644 --- a/trunk/crypto/pcrypt.c +++ b/trunk/crypto/pcrypt.c @@ -504,6 +504,7 @@ static int pcrypt_init_padata(struct padata_pcrypt *pcrypt, static void pcrypt_fini_padata(struct padata_pcrypt *pcrypt) { + kobject_put(&pcrypt->pinst->kobj); free_cpumask_var(pcrypt->cb_cpumask->mask); kfree(pcrypt->cb_cpumask); diff --git a/trunk/drivers/char/agp/intel-gtt.c b/trunk/drivers/char/agp/intel-gtt.c index 9272c38dd3c6..6b6760ea2435 100644 --- a/trunk/drivers/char/agp/intel-gtt.c +++ b/trunk/drivers/char/agp/intel-gtt.c @@ -1210,14 +1210,14 @@ static void gen6_write_entry(dma_addr_t addr, unsigned int entry, unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; u32 pte_flags; - if (type_mask == AGP_USER_MEMORY) + if (type_mask == AGP_USER_UNCACHED_MEMORY) pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { - pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; + pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; if (gfdt) pte_flags |= GEN6_PTE_GFDT; } else { /* set 'normal'/'cached' to LLC by default */ - pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; + pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; if (gfdt) pte_flags |= GEN6_PTE_GFDT; } diff --git a/trunk/drivers/gpu/drm/drm_crtc_helper.c b/trunk/drivers/gpu/drm/drm_crtc_helper.c index f7af91cb273d..dcbeb98f195a 100644 --- a/trunk/drivers/gpu/drm/drm_crtc_helper.c +++ b/trunk/drivers/gpu/drm/drm_crtc_helper.c @@ -276,7 +276,7 @@ static bool drm_encoder_crtc_ok(struct drm_encoder *encoder, struct drm_crtc *tmp; int crtc_mask = 1; - WARN(!crtc, "checking null crtc?\n"); + WARN(!crtc, "checking null crtc?"); dev = crtc->dev; diff --git a/trunk/drivers/gpu/drm/drm_edid.c b/trunk/drivers/gpu/drm/drm_edid.c index a245d17165ae..c1a26217a530 100644 --- a/trunk/drivers/gpu/drm/drm_edid.c +++ b/trunk/drivers/gpu/drm/drm_edid.c @@ -240,7 +240,7 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, .addr = DDC_ADDR, .flags = I2C_M_RD, .len = len, - .buf = buf, + .buf = buf + start, } }; @@ -253,7 +253,7 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, static u8 * drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) { - int i, j = 0, valid_extensions = 0; + int i, j = 0; u8 *block, *new; if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) @@ -280,28 +280,14 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) for (j = 1; j <= block[0x7e]; j++) { for (i = 0; i < 4; i++) { - if (drm_do_probe_ddc_edid(adapter, - block + (valid_extensions + 1) * EDID_LENGTH, - j, EDID_LENGTH)) + if (drm_do_probe_ddc_edid(adapter, block, j, + EDID_LENGTH)) goto out; - if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH)) { - valid_extensions++; + if (drm_edid_block_valid(block + j * EDID_LENGTH)) break; - } } if (i == 4) - dev_warn(connector->dev->dev, - "%s: Ignoring invalid EDID block %d.\n", - drm_get_connector_name(connector), j); - } - - if (valid_extensions != block[0x7e]) { - block[EDID_LENGTH-1] += block[0x7e] - valid_extensions; - block[0x7e] = valid_extensions; - new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); - if (!new) - goto out; - block = new; + goto carp; } return block; diff --git a/trunk/drivers/gpu/drm/i915/i915_drv.c b/trunk/drivers/gpu/drm/i915/i915_drv.c index 80745f85902c..3467dd420760 100644 --- a/trunk/drivers/gpu/drm/i915/i915_drv.c +++ b/trunk/drivers/gpu/drm/i915/i915_drv.c @@ -44,7 +44,7 @@ unsigned int i915_fbpercrtc = 0; module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); unsigned int i915_powersave = 1; -module_param_named(powersave, i915_powersave, int, 0600); +module_param_named(powersave, i915_powersave, int, 0400); unsigned int i915_lvds_downclock = 0; module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); diff --git a/trunk/drivers/gpu/drm/i915/i915_drv.h b/trunk/drivers/gpu/drm/i915/i915_drv.h index 90414ae86afc..2c2c19b6285e 100644 --- a/trunk/drivers/gpu/drm/i915/i915_drv.h +++ b/trunk/drivers/gpu/drm/i915/i915_drv.h @@ -1321,7 +1321,6 @@ static inline void i915_write(struct drm_i915_private *dev_priv, u32 reg, #define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type) #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) -#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) #define PRIMARY_RINGBUFFER_SIZE (128*1024) diff --git a/trunk/drivers/gpu/drm/i915/i915_gem.c b/trunk/drivers/gpu/drm/i915/i915_gem.c index ef188e391406..8eb8453208b5 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem.c @@ -2172,7 +2172,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj) static int i915_ring_idle(struct drm_device *dev, struct intel_ring_buffer *ring) { - if (list_empty(&ring->gpu_write_list) && list_empty(&ring->active_list)) + if (list_empty(&ring->gpu_write_list)) return 0; i915_gem_flush_ring(dev, NULL, ring, @@ -2190,7 +2190,9 @@ i915_gpu_idle(struct drm_device *dev) int ret; lists_empty = (list_empty(&dev_priv->mm.flushing_list) && - list_empty(&dev_priv->mm.active_list)); + list_empty(&dev_priv->render_ring.active_list) && + list_empty(&dev_priv->bsd_ring.active_list) && + list_empty(&dev_priv->blt_ring.active_list)); if (lists_empty) return 0; @@ -3106,8 +3108,7 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, * write domain */ if (obj->write_domain && - (obj->write_domain != obj->pending_read_domains || - obj_priv->ring != ring)) { + obj->write_domain != obj->pending_read_domains) { flush_domains |= obj->write_domain; invalidate_domains |= obj->pending_read_domains & ~obj->write_domain; @@ -3496,52 +3497,6 @@ i915_gem_execbuffer_pin(struct drm_device *dev, return 0; } -static int -i915_gem_execbuffer_move_to_gpu(struct drm_device *dev, - struct drm_file *file, - struct intel_ring_buffer *ring, - struct drm_gem_object **objects, - int count) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - int ret, i; - - /* Zero the global flush/invalidate flags. These - * will be modified as new domains are computed - * for each object - */ - dev->invalidate_domains = 0; - dev->flush_domains = 0; - dev_priv->mm.flush_rings = 0; - for (i = 0; i < count; i++) - i915_gem_object_set_to_gpu_domain(objects[i], ring); - - if (dev->invalidate_domains | dev->flush_domains) { -#if WATCH_EXEC - DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", - __func__, - dev->invalidate_domains, - dev->flush_domains); -#endif - i915_gem_flush(dev, file, - dev->invalidate_domains, - dev->flush_domains, - dev_priv->mm.flush_rings); - } - - for (i = 0; i < count; i++) { - struct drm_i915_gem_object *obj = to_intel_bo(objects[i]); - /* XXX replace with semaphores */ - if (obj->ring && ring != obj->ring) { - ret = i915_gem_object_wait_rendering(&obj->base, true); - if (ret) - return ret; - } - } - - return 0; -} - /* Throttle our rendering by waiting until the ring has completed our requests * emitted over 20 msec ago. * @@ -3802,10 +3757,33 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, goto err; } - ret = i915_gem_execbuffer_move_to_gpu(dev, file, ring, - object_list, args->buffer_count); - if (ret) - goto err; + /* Zero the global flush/invalidate flags. These + * will be modified as new domains are computed + * for each object + */ + dev->invalidate_domains = 0; + dev->flush_domains = 0; + dev_priv->mm.flush_rings = 0; + + for (i = 0; i < args->buffer_count; i++) { + struct drm_gem_object *obj = object_list[i]; + + /* Compute new gpu domains and update invalidate/flush */ + i915_gem_object_set_to_gpu_domain(obj, ring); + } + + if (dev->invalidate_domains | dev->flush_domains) { +#if WATCH_EXEC + DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", + __func__, + dev->invalidate_domains, + dev->flush_domains); +#endif + i915_gem_flush(dev, file, + dev->invalidate_domains, + dev->flush_domains, + dev_priv->mm.flush_rings); + } for (i = 0; i < args->buffer_count; i++) { struct drm_gem_object *obj = object_list[i]; @@ -4065,7 +4043,8 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) alignment = i915_gem_get_gtt_alignment(obj); if (obj_priv->gtt_offset & (alignment - 1)) { WARN(obj_priv->pin_count, - "bo is already pinned with incorrect alignment: offset=%x, req.alignment=%x\n", + "bo is already pinned with incorrect alignment:" + " offset=%x, req.alignment=%x\n", obj_priv->gtt_offset, alignment); ret = i915_gem_object_unbind(obj); if (ret) @@ -4877,24 +4856,17 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, struct drm_file *file_priv) { struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - void *vaddr = obj_priv->phys_obj->handle->vaddr + args->offset; - char __user *user_data = (char __user *) (uintptr_t) args->data_ptr; - - DRM_DEBUG_DRIVER("vaddr %p, %lld\n", vaddr, args->size); + void *obj_addr; + int ret; + char __user *user_data; - if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) { - unsigned long unwritten; + user_data = (char __user *) (uintptr_t) args->data_ptr; + obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; - /* The physical object once assigned is fixed for the lifetime - * of the obj, so we can safely drop the lock and continue - * to access vaddr. - */ - mutex_unlock(&dev->struct_mutex); - unwritten = copy_from_user(vaddr, user_data, args->size); - mutex_lock(&dev->struct_mutex); - if (unwritten) - return -EFAULT; - } + DRM_DEBUG_DRIVER("obj_addr %p, %lld\n", obj_addr, args->size); + ret = copy_from_user(obj_addr, user_data, args->size); + if (ret) + return -EFAULT; drm_agp_chipset_flush(dev); return 0; @@ -4928,7 +4900,9 @@ i915_gpu_is_active(struct drm_device *dev) int lists_empty; lists_empty = list_empty(&dev_priv->mm.flushing_list) && - list_empty(&dev_priv->mm.active_list); + list_empty(&dev_priv->render_ring.active_list) && + list_empty(&dev_priv->bsd_ring.active_list) && + list_empty(&dev_priv->blt_ring.active_list); return !lists_empty; } diff --git a/trunk/drivers/gpu/drm/i915/i915_gem_evict.c b/trunk/drivers/gpu/drm/i915/i915_gem_evict.c index d8ae7d1d0cc6..43a4013f53fa 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem_evict.c @@ -165,7 +165,9 @@ i915_gem_evict_everything(struct drm_device *dev) lists_empty = (list_empty(&dev_priv->mm.inactive_list) && list_empty(&dev_priv->mm.flushing_list) && - list_empty(&dev_priv->mm.active_list)); + list_empty(&dev_priv->render_ring.active_list) && + list_empty(&dev_priv->bsd_ring.active_list) && + list_empty(&dev_priv->blt_ring.active_list)); if (lists_empty) return -ENOSPC; @@ -182,7 +184,9 @@ i915_gem_evict_everything(struct drm_device *dev) lists_empty = (list_empty(&dev_priv->mm.inactive_list) && list_empty(&dev_priv->mm.flushing_list) && - list_empty(&dev_priv->mm.active_list)); + list_empty(&dev_priv->render_ring.active_list) && + list_empty(&dev_priv->bsd_ring.active_list) && + list_empty(&dev_priv->blt_ring.active_list)); BUG_ON(!lists_empty); return 0; diff --git a/trunk/drivers/gpu/drm/i915/i915_suspend.c b/trunk/drivers/gpu/drm/i915/i915_suspend.c index 454c064f8ef7..989c19d2d959 100644 --- a/trunk/drivers/gpu/drm/i915/i915_suspend.c +++ b/trunk/drivers/gpu/drm/i915/i915_suspend.c @@ -862,10 +862,8 @@ int i915_restore_state(struct drm_device *dev) /* Clock gating state */ intel_init_clock_gating(dev); - if (HAS_PCH_SPLIT(dev)) { + if (HAS_PCH_SPLIT(dev)) ironlake_enable_drps(dev); - intel_init_emon(dev); - } /* Cache mode state */ I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); diff --git a/trunk/drivers/gpu/drm/i915/intel_display.c b/trunk/drivers/gpu/drm/i915/intel_display.c index 48d8fd686ea9..990f065374b2 100644 --- a/trunk/drivers/gpu/drm/i915/intel_display.c +++ b/trunk/drivers/gpu/drm/i915/intel_display.c @@ -1681,37 +1681,6 @@ static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock) udelay(500); } -static void intel_fdi_normal_train(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - u32 reg, temp; - - /* enable normal train */ - reg = FDI_TX_CTL(pipe); - temp = I915_READ(reg); - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; - I915_WRITE(reg, temp); - - reg = FDI_RX_CTL(pipe); - temp = I915_READ(reg); - if (HAS_PCH_CPT(dev)) { - temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; - temp |= FDI_LINK_TRAIN_NORMAL_CPT; - } else { - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_NONE; - } - I915_WRITE(reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE); - - /* wait one idle pattern time */ - POSTING_READ(reg); - udelay(1000); -} - /* The FDI link training functions for ILK/Ibexpeak. */ static void ironlake_fdi_link_train(struct drm_crtc *crtc) { @@ -1798,6 +1767,27 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) DRM_DEBUG_KMS("FDI train done\n"); + /* enable normal train */ + reg = FDI_TX_CTL(pipe); + temp = I915_READ(reg); + temp &= ~FDI_LINK_TRAIN_NONE; + temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; + I915_WRITE(reg, temp); + + reg = FDI_RX_CTL(pipe); + temp = I915_READ(reg); + if (HAS_PCH_CPT(dev)) { + temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; + temp |= FDI_LINK_TRAIN_NORMAL_CPT; + } else { + temp &= ~FDI_LINK_TRAIN_NONE; + temp |= FDI_LINK_TRAIN_NONE; + } + I915_WRITE(reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE); + + /* wait one idle pattern time */ + POSTING_READ(reg); + udelay(1000); } static const int const snb_b_fdi_train_param [] = { @@ -2100,8 +2090,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe))); I915_WRITE(TRANS_VSYNC(pipe), I915_READ(VSYNC(pipe))); - intel_fdi_normal_train(crtc); - /* For PCH DP, enable TRANS_DP_CTL */ if (HAS_PCH_CPT(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { @@ -2212,10 +2200,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) udelay(100); /* Ironlake workaround, disable clock pointer after downing FDI */ - if (HAS_PCH_IBX(dev)) - I915_WRITE(FDI_RX_CHICKEN(pipe), - I915_READ(FDI_RX_CHICKEN(pipe) & - ~FDI_RX_PHASE_SYNC_POINTER_ENABLE)); + I915_WRITE(FDI_RX_CHICKEN(pipe), + I915_READ(FDI_RX_CHICKEN(pipe) & + ~FDI_RX_PHASE_SYNC_POINTER_ENABLE)); /* still set train pattern 1 */ reg = FDI_TX_CTL(pipe); @@ -5594,19 +5581,20 @@ void ironlake_enable_drps(struct drm_device *dev) fmin = (rgvmodectl & MEMMODE_FMIN_MASK); fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT; + fstart = fmax; vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT; - dev_priv->fmax = fmax; /* IPS callback will increase this */ + dev_priv->fmax = fstart; /* IPS callback will increase this */ dev_priv->fstart = fstart; - dev_priv->max_delay = fstart; + dev_priv->max_delay = fmax; dev_priv->min_delay = fmin; dev_priv->cur_delay = fstart; - DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", - fmax, fmin, fstart); + DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", fmax, fmin, + fstart); I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN); diff --git a/trunk/drivers/gpu/drm/i915/intel_dp.c b/trunk/drivers/gpu/drm/i915/intel_dp.c index c8e005553310..891f4f1d63b1 100644 --- a/trunk/drivers/gpu/drm/i915/intel_dp.c +++ b/trunk/drivers/gpu/drm/i915/intel_dp.c @@ -1517,7 +1517,7 @@ g4x_dp_detect(struct intel_dp *intel_dp) status = connector_status_connected; } - return status; + return bit; } /** diff --git a/trunk/drivers/gpu/drm/i915/intel_drv.h b/trunk/drivers/gpu/drm/i915/intel_drv.h index 21551fe74541..9af9f86a8765 100644 --- a/trunk/drivers/gpu/drm/i915/intel_drv.h +++ b/trunk/drivers/gpu/drm/i915/intel_drv.h @@ -296,7 +296,6 @@ extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, extern void intel_init_clock_gating(struct drm_device *dev); extern void ironlake_enable_drps(struct drm_device *dev); extern void ironlake_disable_drps(struct drm_device *dev); -extern void intel_init_emon(struct drm_device *dev); extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj, diff --git a/trunk/drivers/gpu/drm/i915/intel_lvds.c b/trunk/drivers/gpu/drm/i915/intel_lvds.c index 4324a326f98e..f1a649990ea9 100644 --- a/trunk/drivers/gpu/drm/i915/intel_lvds.c +++ b/trunk/drivers/gpu/drm/i915/intel_lvds.c @@ -481,8 +481,11 @@ static int intel_lvds_get_modes(struct drm_connector *connector) struct drm_device *dev = connector->dev; struct drm_display_mode *mode; - if (intel_lvds->edid) + if (intel_lvds->edid) { + drm_mode_connector_update_edid_property(connector, + intel_lvds->edid); return drm_add_edid_modes(connector, intel_lvds->edid); + } mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode); if (mode == 0) @@ -936,16 +939,7 @@ void intel_lvds_init(struct drm_device *dev) */ intel_lvds->edid = drm_get_edid(connector, &dev_priv->gmbus[pin].adapter); - if (intel_lvds->edid) { - if (drm_add_edid_modes(connector, - intel_lvds->edid)) { - drm_mode_connector_update_edid_property(connector, - intel_lvds->edid); - } else { - kfree(intel_lvds->edid); - intel_lvds->edid = NULL; - } - } + if (!intel_lvds->edid) { /* Didn't get an EDID, so * Set wide sync ranges so we get all modes diff --git a/trunk/drivers/gpu/drm/i915/intel_opregion.c b/trunk/drivers/gpu/drm/i915/intel_opregion.c index 9b0d9a867aea..917c7dc3cd6b 100644 --- a/trunk/drivers/gpu/drm/i915/intel_opregion.c +++ b/trunk/drivers/gpu/drm/i915/intel_opregion.c @@ -512,6 +512,6 @@ int intel_opregion_setup(struct drm_device *dev) return 0; err_out: - iounmap(base); + iounmap(opregion->header); return err; } diff --git a/trunk/drivers/gpu/drm/i915/intel_overlay.c b/trunk/drivers/gpu/drm/i915/intel_overlay.c index 02ff0a481f47..afb96d25219a 100644 --- a/trunk/drivers/gpu/drm/i915/intel_overlay.c +++ b/trunk/drivers/gpu/drm/i915/intel_overlay.c @@ -946,9 +946,7 @@ static int check_overlay_src(struct drm_device *dev, { int uv_hscale = uv_hsubsampling(rec->flags); int uv_vscale = uv_vsubsampling(rec->flags); - u32 stride_mask; - int depth; - u32 tmp; + u32 stride_mask, depth, tmp; /* check src dimensions */ if (IS_845G(dev) || IS_I830(dev)) { diff --git a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c index b83306f9244b..09f2dc353ae2 100644 --- a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -177,7 +177,7 @@ static int init_ring_common(struct drm_device *dev, I915_WRITE_CTL(ring, ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES) - | RING_REPORT_64K | RING_VALID); + | RING_NO_REPORT | RING_VALID); head = I915_READ_HEAD(ring) & HEAD_ADDR; /* If the head is still not zero, the ring is dead */ @@ -654,10 +654,6 @@ void intel_cleanup_ring_buffer(struct drm_device *dev, i915_gem_object_unpin(ring->gem_object); drm_gem_object_unreference(ring->gem_object); ring->gem_object = NULL; - - if (ring->cleanup) - ring->cleanup(ring); - cleanup_status_page(dev, ring); } @@ -692,17 +688,6 @@ int intel_wait_ring_buffer(struct drm_device *dev, { unsigned long end; drm_i915_private_t *dev_priv = dev->dev_private; - u32 head; - - head = intel_read_status_page(ring, 4); - if (head) { - ring->head = head & HEAD_ADDR; - ring->space = ring->head - (ring->tail + 8); - if (ring->space < 0) - ring->space += ring->size; - if (ring->space >= n) - return 0; - } trace_i915_ring_wait_begin (dev); end = jiffies + 3 * HZ; @@ -869,125 +854,19 @@ blt_ring_put_user_irq(struct drm_device *dev, /* do nothing */ } - -/* Workaround for some stepping of SNB, - * each time when BLT engine ring tail moved, - * the first command in the ring to be parsed - * should be MI_BATCH_BUFFER_START - */ -#define NEED_BLT_WORKAROUND(dev) \ - (IS_GEN6(dev) && (dev->pdev->revision < 8)) - -static inline struct drm_i915_gem_object * -to_blt_workaround(struct intel_ring_buffer *ring) -{ - return ring->private; -} - -static int blt_ring_init(struct drm_device *dev, - struct intel_ring_buffer *ring) -{ - if (NEED_BLT_WORKAROUND(dev)) { - struct drm_i915_gem_object *obj; - u32 __iomem *ptr; - int ret; - - obj = to_intel_bo(i915_gem_alloc_object(dev, 4096)); - if (obj == NULL) - return -ENOMEM; - - ret = i915_gem_object_pin(&obj->base, 4096); - if (ret) { - drm_gem_object_unreference(&obj->base); - return ret; - } - - ptr = kmap(obj->pages[0]); - iowrite32(MI_BATCH_BUFFER_END, ptr); - iowrite32(MI_NOOP, ptr+1); - kunmap(obj->pages[0]); - - ret = i915_gem_object_set_to_gtt_domain(&obj->base, false); - if (ret) { - i915_gem_object_unpin(&obj->base); - drm_gem_object_unreference(&obj->base); - return ret; - } - - ring->private = obj; - } - - return init_ring_common(dev, ring); -} - -static void blt_ring_begin(struct drm_device *dev, - struct intel_ring_buffer *ring, - int num_dwords) -{ - if (ring->private) { - intel_ring_begin(dev, ring, num_dwords+2); - intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START); - intel_ring_emit(dev, ring, to_blt_workaround(ring)->gtt_offset); - } else - intel_ring_begin(dev, ring, 4); -} - -static void blt_ring_flush(struct drm_device *dev, - struct intel_ring_buffer *ring, - u32 invalidate_domains, - u32 flush_domains) -{ - blt_ring_begin(dev, ring, 4); - intel_ring_emit(dev, ring, MI_FLUSH_DW); - intel_ring_emit(dev, ring, 0); - intel_ring_emit(dev, ring, 0); - intel_ring_emit(dev, ring, 0); - intel_ring_advance(dev, ring); -} - -static u32 -blt_ring_add_request(struct drm_device *dev, - struct intel_ring_buffer *ring, - u32 flush_domains) -{ - u32 seqno = i915_gem_get_seqno(dev); - - blt_ring_begin(dev, ring, 4); - intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX); - intel_ring_emit(dev, ring, - I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - intel_ring_emit(dev, ring, seqno); - intel_ring_emit(dev, ring, MI_USER_INTERRUPT); - intel_ring_advance(dev, ring); - - DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno); - return seqno; -} - -static void blt_ring_cleanup(struct intel_ring_buffer *ring) -{ - if (!ring->private) - return; - - i915_gem_object_unpin(ring->private); - drm_gem_object_unreference(ring->private); - ring->private = NULL; -} - static const struct intel_ring_buffer gen6_blt_ring = { .name = "blt ring", .id = RING_BLT, .mmio_base = BLT_RING_BASE, .size = 32 * PAGE_SIZE, - .init = blt_ring_init, + .init = init_ring_common, .write_tail = ring_write_tail, - .flush = blt_ring_flush, - .add_request = blt_ring_add_request, + .flush = gen6_ring_flush, + .add_request = ring_add_request, .get_seqno = ring_status_page_get_seqno, .user_irq_get = blt_ring_get_user_irq, .user_irq_put = blt_ring_put_user_irq, .dispatch_gem_execbuffer = gen6_ring_dispatch_gem_execbuffer, - .cleanup = blt_ring_cleanup, }; int intel_init_render_ring_buffer(struct drm_device *dev) diff --git a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.h b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.h index 3126c2681983..a05aff0e5764 100644 --- a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -63,7 +63,6 @@ struct intel_ring_buffer { struct drm_i915_gem_execbuffer2 *exec, struct drm_clip_rect *cliprects, uint64_t exec_offset); - void (*cleanup)(struct intel_ring_buffer *ring); /** * List of objects currently involved in rendering from the @@ -99,8 +98,6 @@ struct intel_ring_buffer { wait_queue_head_t irq_queue; drm_local_map_t map; - - void *private; }; static inline u32 diff --git a/trunk/drivers/gpu/drm/radeon/evergreen.c b/trunk/drivers/gpu/drm/radeon/evergreen.c index 488c36c8f5e6..f12a5b3ec050 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen.c @@ -2033,7 +2033,7 @@ int evergreen_irq_set(struct radeon_device *rdev) u32 grbm_int_cntl = 0; if (!rdev->irq.installed) { - WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); + WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n"); return -EINVAL; } /* don't enable anything if the ih is disabled */ @@ -2295,7 +2295,6 @@ int evergreen_irq_process(struct radeon_device *rdev) case 0: /* D1 vblank */ if (disp_int & LB_D1_VBLANK_INTERRUPT) { drm_handle_vblank(rdev->ddev, 0); - rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); @@ -2317,7 +2316,6 @@ int evergreen_irq_process(struct radeon_device *rdev) case 0: /* D2 vblank */ if (disp_int_cont & LB_D2_VBLANK_INTERRUPT) { drm_handle_vblank(rdev->ddev, 1); - rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); @@ -2339,7 +2337,6 @@ int evergreen_irq_process(struct radeon_device *rdev) case 0: /* D3 vblank */ if (disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { drm_handle_vblank(rdev->ddev, 2); - rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; DRM_DEBUG("IH: D3 vblank\n"); @@ -2361,7 +2358,6 @@ int evergreen_irq_process(struct radeon_device *rdev) case 0: /* D4 vblank */ if (disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { drm_handle_vblank(rdev->ddev, 3); - rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; DRM_DEBUG("IH: D4 vblank\n"); @@ -2383,7 +2379,6 @@ int evergreen_irq_process(struct radeon_device *rdev) case 0: /* D5 vblank */ if (disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { drm_handle_vblank(rdev->ddev, 4); - rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; DRM_DEBUG("IH: D5 vblank\n"); @@ -2405,7 +2400,6 @@ int evergreen_irq_process(struct radeon_device *rdev) case 0: /* D6 vblank */ if (disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { drm_handle_vblank(rdev->ddev, 5); - rdev->pm.vblank_sync = true; wake_up(&rdev->irq.vblank_queue); disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; DRM_DEBUG("IH: D6 vblank\n"); diff --git a/trunk/drivers/gpu/drm/radeon/r100.c b/trunk/drivers/gpu/drm/radeon/r100.c index 8e10aa9f74b0..0e8f28a68927 100644 --- a/trunk/drivers/gpu/drm/radeon/r100.c +++ b/trunk/drivers/gpu/drm/radeon/r100.c @@ -442,7 +442,7 @@ int r100_pci_gart_init(struct radeon_device *rdev) int r; if (rdev->gart.table.ram.ptr) { - WARN(1, "R100 PCI GART already initialized\n"); + WARN(1, "R100 PCI GART already initialized.\n"); return 0; } /* Initialize common gart structure */ @@ -516,7 +516,7 @@ int r100_irq_set(struct radeon_device *rdev) uint32_t tmp = 0; if (!rdev->irq.installed) { - WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); + WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n"); WREG32(R_000040_GEN_INT_CNTL, 0); return -EINVAL; } diff --git a/trunk/drivers/gpu/drm/radeon/r300.c b/trunk/drivers/gpu/drm/radeon/r300.c index cde1d3480d93..34527e600fe9 100644 --- a/trunk/drivers/gpu/drm/radeon/r300.c +++ b/trunk/drivers/gpu/drm/radeon/r300.c @@ -91,7 +91,7 @@ int rv370_pcie_gart_init(struct radeon_device *rdev) int r; if (rdev->gart.table.vram.robj) { - WARN(1, "RV370 PCIE GART already initialized\n"); + WARN(1, "RV370 PCIE GART already initialized.\n"); return 0; } /* Initialize common gart structure */ diff --git a/trunk/drivers/gpu/drm/radeon/r600.c b/trunk/drivers/gpu/drm/radeon/r600.c index 0f806cc7dc75..33952a12f0a3 100644 --- a/trunk/drivers/gpu/drm/radeon/r600.c +++ b/trunk/drivers/gpu/drm/radeon/r600.c @@ -97,8 +97,14 @@ u32 rv6xx_get_temp(struct radeon_device *rdev) { u32 temp = (RREG32(CG_THERMAL_STATUS) & ASIC_T_MASK) >> ASIC_T_SHIFT; + u32 actual_temp = 0; - return temp * 1000; + if ((temp >> 7) & 1) + actual_temp = 0; + else + actual_temp = (temp >> 1) & 0xff; + + return actual_temp * 1000; } void r600_pm_get_dynpm_state(struct radeon_device *rdev) @@ -913,7 +919,7 @@ int r600_pcie_gart_init(struct radeon_device *rdev) int r; if (rdev->gart.table.vram.robj) { - WARN(1, "R600 PCIE GART already initialized\n"); + WARN(1, "R600 PCIE GART already initialized.\n"); return 0; } /* Initialize common gart structure */ @@ -2989,7 +2995,7 @@ int r600_irq_set(struct radeon_device *rdev) u32 hdmi1, hdmi2; if (!rdev->irq.installed) { - WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); + WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n"); return -EINVAL; } /* don't enable anything if the ih is disabled */ diff --git a/trunk/drivers/gpu/drm/radeon/radeon_atombios.c b/trunk/drivers/gpu/drm/radeon/radeon_atombios.c index 87ead090c7d5..04cac7ec9039 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_atombios.c @@ -526,6 +526,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) if (crev < 2) return false; + router.valid = false; + obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset); path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) (ctx->bios + data_offset + @@ -622,8 +624,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) if (connector_type == DRM_MODE_CONNECTOR_Unknown) continue; - router.ddc_valid = false; - router.cd_valid = false; for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) { uint8_t grph_obj_id, grph_obj_num, grph_obj_type; @@ -647,8 +647,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) usDeviceTag)); } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) { + router.valid = false; for (k = 0; k < router_obj->ucNumberOfObjects; k++) { - u16 router_obj_id = le16_to_cpu(router_obj->asObjects[k].usObjectID); + u16 router_obj_id = le16_to_cpu(router_obj->asObjects[j].usObjectID); if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) { ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *) (ctx->bios + data_offset + @@ -656,7 +657,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) ATOM_I2C_RECORD *i2c_record; ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path; - ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *cd_path; ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table = (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *) (ctx->bios + data_offset + @@ -690,18 +690,10 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE: ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *) record; - router.ddc_valid = true; - router.ddc_mux_type = ddc_path->ucMuxType; - router.ddc_mux_control_pin = ddc_path->ucMuxControlPin; - router.ddc_mux_state = ddc_path->ucMuxState[enum_id]; - break; - case ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE: - cd_path = (ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD *) - record; - router.cd_valid = true; - router.cd_mux_type = cd_path->ucMuxType; - router.cd_mux_control_pin = cd_path->ucMuxControlPin; - router.cd_mux_state = cd_path->ucMuxState[enum_id]; + router.valid = true; + router.mux_type = ddc_path->ucMuxType; + router.mux_control_pin = ddc_path->ucMuxControlPin; + router.mux_state = ddc_path->ucMuxState[enum_id]; break; } record = (ATOM_COMMON_RECORD_HEADER *) @@ -868,8 +860,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE; struct radeon_router router; - router.ddc_valid = false; - router.cd_valid = false; + router.valid = false; bios_connectors = kzalloc(bc_size, GFP_KERNEL); if (!bios_connectors) diff --git a/trunk/drivers/gpu/drm/radeon/radeon_connectors.c b/trunk/drivers/gpu/drm/radeon/radeon_connectors.c index fe6c74780f18..4dac4b0a02ee 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_connectors.c @@ -183,13 +183,13 @@ radeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector, continue; if (priority == true) { - DRM_DEBUG_KMS("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict)); - DRM_DEBUG_KMS("in favor of %s\n", drm_get_connector_name(connector)); + DRM_INFO("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict)); + DRM_INFO("in favor of %s\n", drm_get_connector_name(connector)); conflict->status = connector_status_disconnected; radeon_connector_update_scratch_regs(conflict, connector_status_disconnected); } else { - DRM_DEBUG_KMS("2: conflicting encoders switching off %s\n", drm_get_connector_name(connector)); - DRM_DEBUG_KMS("in favor of %s\n", drm_get_connector_name(conflict)); + DRM_INFO("2: conflicting encoders switching off %s\n", drm_get_connector_name(connector)); + DRM_INFO("in favor of %s\n", drm_get_connector_name(conflict)); current_status = connector_status_disconnected; } break; @@ -432,13 +432,13 @@ static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, mode->vdisplay == native_mode->vdisplay) { *native_mode = *mode; drm_mode_set_crtcinfo(native_mode, CRTC_INTERLACE_HALVE_V); - DRM_DEBUG_KMS("Determined LVDS native mode details from EDID\n"); + DRM_INFO("Determined LVDS native mode details from EDID\n"); break; } } } if (!native_mode->clock) { - DRM_DEBUG_KMS("No LVDS native mode details, disabling RMX\n"); + DRM_INFO("No LVDS native mode details, disabling RMX\n"); radeon_encoder->rmx_type = RMX_OFF; } } @@ -1116,7 +1116,7 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_connector->shared_ddc = true; shared_ddc = true; } - if (radeon_connector->router_bus && router->ddc_valid && + if (radeon_connector->router_bus && router->valid && (radeon_connector->router.router_id == router->router_id)) { radeon_connector->shared_ddc = false; shared_ddc = false; @@ -1136,7 +1136,7 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_connector->connector_object_id = connector_object_id; radeon_connector->hpd = *hpd; radeon_connector->router = *router; - if (router->ddc_valid || router->cd_valid) { + if (router->valid) { radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info); if (!radeon_connector->router_bus) goto failed; diff --git a/trunk/drivers/gpu/drm/radeon/radeon_display.c b/trunk/drivers/gpu/drm/radeon/radeon_display.c index 1df4dc6c063c..0383631da69c 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_display.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_display.c @@ -315,14 +315,10 @@ static void radeon_print_display_setup(struct drm_device *dev) radeon_connector->ddc_bus->rec.en_data_reg, radeon_connector->ddc_bus->rec.y_clk_reg, radeon_connector->ddc_bus->rec.y_data_reg); - if (radeon_connector->router.ddc_valid) + if (radeon_connector->router_bus) DRM_INFO(" DDC Router 0x%x/0x%x\n", - radeon_connector->router.ddc_mux_control_pin, - radeon_connector->router.ddc_mux_state); - if (radeon_connector->router.cd_valid) - DRM_INFO(" Clock/Data Router 0x%x/0x%x\n", - radeon_connector->router.cd_mux_control_pin, - radeon_connector->router.cd_mux_state); + radeon_connector->router.mux_control_pin, + radeon_connector->router.mux_state); } else { if (connector->connector_type == DRM_MODE_CONNECTOR_VGA || connector->connector_type == DRM_MODE_CONNECTOR_DVII || @@ -402,8 +398,8 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) int ret = 0; /* on hw with routers, select right port */ - if (radeon_connector->router.ddc_valid) - radeon_router_select_ddc_port(radeon_connector); + if (radeon_connector->router.valid) + radeon_router_select_port(radeon_connector); if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { @@ -436,8 +432,8 @@ static int radeon_ddc_dump(struct drm_connector *connector) int ret = 0; /* on hw with routers, select right port */ - if (radeon_connector->router.ddc_valid) - radeon_router_select_ddc_port(radeon_connector); + if (radeon_connector->router.valid) + radeon_router_select_port(radeon_connector); if (!radeon_connector->ddc_bus) return -1; diff --git a/trunk/drivers/gpu/drm/radeon/radeon_encoders.c b/trunk/drivers/gpu/drm/radeon/radeon_encoders.c index f678257c42e6..ae58b6849a2e 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_encoders.c @@ -1520,7 +1520,6 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); if (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) { @@ -1532,13 +1531,6 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) radeon_atom_output_lock(encoder, true); radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); - /* select the clock/data port if it uses a router */ - if (connector) { - struct radeon_connector *radeon_connector = to_radeon_connector(connector); - if (radeon_connector->router.cd_valid) - radeon_router_select_cd_port(radeon_connector); - } - /* this is needed for the pll/ss setup to work correctly in some cases */ atombios_set_encoder_crtc_source(encoder); } @@ -1555,23 +1547,6 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig; - - /* check for pre-DCE3 cards with shared encoders; - * can't really use the links individually, so don't disable - * the encoder if it's in use by another connector - */ - if (!ASIC_IS_DCE3(rdev)) { - struct drm_encoder *other_encoder; - struct radeon_encoder *other_radeon_encoder; - - list_for_each_entry(other_encoder, &dev->mode_config.encoder_list, head) { - other_radeon_encoder = to_radeon_encoder(other_encoder); - if ((radeon_encoder->encoder_id == other_radeon_encoder->encoder_id) && - drm_helper_encoder_in_use(other_encoder)) - goto disable_done; - } - } - radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); switch (radeon_encoder->encoder_id) { @@ -1611,7 +1586,6 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) break; } -disable_done: if (radeon_encoder_is_digital(encoder)) { if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) r600_hdmi_disable(encoder); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_fence.c b/trunk/drivers/gpu/drm/radeon/radeon_fence.c index daacb281dfaf..216392d0353b 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_fence.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_fence.c @@ -240,8 +240,7 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr) */ if (seq == rdev->fence_drv.last_seq && radeon_gpu_is_lockup(rdev)) { /* good news we believe it's a lockup */ - WARN(1, "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", - fence->seq, seq); + WARN(1, "GPU lockup (waiting for 0x%08X last fence id 0x%08X)\n", fence->seq, seq); /* FIXME: what should we do ? marking everyone * as signaled for now */ diff --git a/trunk/drivers/gpu/drm/radeon/radeon_i2c.c b/trunk/drivers/gpu/drm/radeon/radeon_i2c.c index 0cfbba02c4d0..6a13ee38a5b9 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_i2c.c @@ -53,8 +53,8 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector) }; /* on hw with routers, select right port */ - if (radeon_connector->router.ddc_valid) - radeon_router_select_ddc_port(radeon_connector); + if (radeon_connector->router.valid) + radeon_router_select_port(radeon_connector); ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); if (ret == 2) @@ -1084,51 +1084,26 @@ void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c_bus, addr, val); } -/* ddc router switching */ -void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector) +/* router switching */ +void radeon_router_select_port(struct radeon_connector *radeon_connector) { u8 val; - if (!radeon_connector->router.ddc_valid) + if (!radeon_connector->router.valid) return; radeon_i2c_get_byte(radeon_connector->router_bus, radeon_connector->router.i2c_addr, 0x3, &val); - val &= ~radeon_connector->router.ddc_mux_control_pin; + val &= radeon_connector->router.mux_control_pin; radeon_i2c_put_byte(radeon_connector->router_bus, radeon_connector->router.i2c_addr, 0x3, val); radeon_i2c_get_byte(radeon_connector->router_bus, radeon_connector->router.i2c_addr, 0x1, &val); - val &= ~radeon_connector->router.ddc_mux_control_pin; - val |= radeon_connector->router.ddc_mux_state; - radeon_i2c_put_byte(radeon_connector->router_bus, - radeon_connector->router.i2c_addr, - 0x1, val); -} - -/* clock/data router switching */ -void radeon_router_select_cd_port(struct radeon_connector *radeon_connector) -{ - u8 val; - - if (!radeon_connector->router.cd_valid) - return; - - radeon_i2c_get_byte(radeon_connector->router_bus, - radeon_connector->router.i2c_addr, - 0x3, &val); - val &= ~radeon_connector->router.cd_mux_control_pin; - radeon_i2c_put_byte(radeon_connector->router_bus, - radeon_connector->router.i2c_addr, - 0x3, val); - radeon_i2c_get_byte(radeon_connector->router_bus, - radeon_connector->router.i2c_addr, - 0x1, &val); - val &= ~radeon_connector->router.cd_mux_control_pin; - val |= radeon_connector->router.cd_mux_state; + val &= radeon_connector->router.mux_control_pin; + val |= radeon_connector->router.mux_state; radeon_i2c_put_byte(radeon_connector->router_bus, radeon_connector->router.i2c_addr, 0x1, val); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_mode.h b/trunk/drivers/gpu/drm/radeon/radeon_mode.h index 680f57644e86..92457163d070 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_mode.h +++ b/trunk/drivers/gpu/drm/radeon/radeon_mode.h @@ -401,19 +401,13 @@ struct radeon_hpd { }; struct radeon_router { + bool valid; u32 router_id; struct radeon_i2c_bus_rec i2c_info; u8 i2c_addr; - /* i2c mux */ - bool ddc_valid; - u8 ddc_mux_type; - u8 ddc_mux_control_pin; - u8 ddc_mux_state; - /* clock/data mux */ - bool cd_valid; - u8 cd_mux_type; - u8 cd_mux_control_pin; - u8 cd_mux_state; + u8 mux_type; + u8 mux_control_pin; + u8 mux_state; }; struct radeon_connector { @@ -494,8 +488,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c, u8 slave_addr, u8 addr, u8 val); -extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector); -extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); +extern void radeon_router_select_port(struct radeon_connector *radeon_connector); extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_object.c b/trunk/drivers/gpu/drm/radeon/radeon_object.c index 8eb183466015..d7ab91416410 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_object.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_object.c @@ -102,8 +102,6 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, type = ttm_bo_type_device; } *bo_ptr = NULL; - -retry: bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; @@ -111,6 +109,8 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, bo->gobj = gobj; bo->surface_reg = -1; INIT_LIST_HEAD(&bo->list); + +retry: radeon_ttm_placement_from_domain(bo, domain); /* Kernel allocation are uninterruptible */ mutex_lock(&rdev->vram_mutex); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_ttm.c b/trunk/drivers/gpu/drm/radeon/radeon_ttm.c index 01c2c736a1da..fe95bb35317e 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_ttm.c @@ -689,8 +689,7 @@ static int radeon_ttm_backend_bind(struct ttm_backend *backend, gtt = container_of(backend, struct radeon_ttm_backend, backend); gtt->offset = bo_mem->start << PAGE_SHIFT; if (!gtt->num_pages) { - WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", - gtt->num_pages, bo_mem, backend); + WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", gtt->num_pages, bo_mem, backend); } r = radeon_gart_bind(gtt->rdev, gtt->offset, gtt->num_pages, gtt->pages); diff --git a/trunk/drivers/gpu/drm/radeon/rs400.c b/trunk/drivers/gpu/drm/radeon/rs400.c index 5512e4e5e636..f683e51a2a06 100644 --- a/trunk/drivers/gpu/drm/radeon/rs400.c +++ b/trunk/drivers/gpu/drm/radeon/rs400.c @@ -78,7 +78,7 @@ int rs400_gart_init(struct radeon_device *rdev) int r; if (rdev->gart.table.ram.ptr) { - WARN(1, "RS400 GART already initialized\n"); + WARN(1, "RS400 GART already initialized.\n"); return 0; } /* Check gart size */ diff --git a/trunk/drivers/gpu/drm/radeon/rs600.c b/trunk/drivers/gpu/drm/radeon/rs600.c index f1c6e02c2e6b..b091a1f6fa4e 100644 --- a/trunk/drivers/gpu/drm/radeon/rs600.c +++ b/trunk/drivers/gpu/drm/radeon/rs600.c @@ -375,7 +375,7 @@ int rs600_gart_init(struct radeon_device *rdev) int r; if (rdev->gart.table.vram.robj) { - WARN(1, "RS600 GART already initialized\n"); + WARN(1, "RS600 GART already initialized.\n"); return 0; } /* Initialize common gart structure */ @@ -505,7 +505,7 @@ int rs600_irq_set(struct radeon_device *rdev) ~S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1); if (!rdev->irq.installed) { - WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); + WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n"); WREG32(R_000040_GEN_INT_CNTL, 0); return -EINVAL; } diff --git a/trunk/drivers/gpu/drm/ttm/ttm_bo.c b/trunk/drivers/gpu/drm/ttm/ttm_bo.c index 3ca77dc03915..a1cb783c7131 100644 --- a/trunk/drivers/gpu/drm/ttm/ttm_bo.c +++ b/trunk/drivers/gpu/drm/ttm/ttm_bo.c @@ -27,6 +27,14 @@ /* * Authors: Thomas Hellstrom */ +/* Notes: + * + * We store bo pointer in drm_mm_node struct so we know which bo own a + * specific node. There is no protection on the pointer, thus to make + * sure things don't go berserk you have to access this pointer while + * holding the global lru lock and make sure anytime you free a node you + * reset the pointer to NULL. + */ #include "ttm/ttm_module.h" #include "ttm/ttm_bo_driver.h" @@ -37,7 +45,6 @@ #include #include #include -#include #define TTM_ASSERT_LOCKED(param) #define TTM_DEBUG(fmt, arg...) @@ -445,11 +452,6 @@ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) ttm_bo_mem_put(bo, &bo->mem); atomic_set(&bo->reserved, 0); - - /* - * Make processes trying to reserve really pick it up. - */ - smp_mb__after_atomic_dec(); wake_up_all(&bo->event_queue); } @@ -458,7 +460,7 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) struct ttm_bo_device *bdev = bo->bdev; struct ttm_bo_global *glob = bo->glob; struct ttm_bo_driver *driver; - void *sync_obj = NULL; + void *sync_obj; void *sync_obj_arg; int put_count; int ret; @@ -493,20 +495,17 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) spin_lock(&glob->lru_lock); } queue: - driver = bdev->driver; - if (bo->sync_obj) - sync_obj = driver->sync_obj_ref(bo->sync_obj); + sync_obj = bo->sync_obj; sync_obj_arg = bo->sync_obj_arg; + driver = bdev->driver; kref_get(&bo->list_kref); list_add_tail(&bo->ddestroy, &bdev->ddestroy); spin_unlock(&glob->lru_lock); spin_unlock(&bo->lock); - if (sync_obj) { + if (sync_obj) driver->sync_obj_flush(sync_obj, sync_obj_arg); - driver->sync_obj_unref(&sync_obj); - } schedule_delayed_work(&bdev->wq, ((HZ / 100) < 1) ? 1 : HZ / 100); } @@ -823,6 +822,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, bool no_wait_gpu) { struct ttm_bo_device *bdev = bo->bdev; + struct ttm_bo_global *glob = bdev->glob; struct ttm_mem_type_manager *man = &bdev->man[mem_type]; int ret; @@ -832,6 +832,12 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, return ret; if (mem->mm_node) break; + spin_lock(&glob->lru_lock); + if (list_empty(&man->lru)) { + spin_unlock(&glob->lru_lock); + break; + } + spin_unlock(&glob->lru_lock); ret = ttm_mem_evict_first(bdev, mem_type, interruptible, no_wait_reserve, no_wait_gpu); if (unlikely(ret != 0)) @@ -1119,9 +1125,35 @@ EXPORT_SYMBOL(ttm_bo_validate); int ttm_bo_check_placement(struct ttm_buffer_object *bo, struct ttm_placement *placement) { - BUG_ON((placement->fpfn || placement->lpfn) && - (bo->mem.num_pages > (placement->lpfn - placement->fpfn))); + int i; + if (placement->fpfn || placement->lpfn) { + if (bo->mem.num_pages > (placement->lpfn - placement->fpfn)) { + printk(KERN_ERR TTM_PFX "Page number range to small " + "Need %lu pages, range is [%u, %u]\n", + bo->mem.num_pages, placement->fpfn, + placement->lpfn); + return -EINVAL; + } + } + for (i = 0; i < placement->num_placement; i++) { + if (!capable(CAP_SYS_ADMIN)) { + if (placement->placement[i] & TTM_PL_FLAG_NO_EVICT) { + printk(KERN_ERR TTM_PFX "Need to be root to " + "modify NO_EVICT status.\n"); + return -EINVAL; + } + } + } + for (i = 0; i < placement->num_busy_placement; i++) { + if (!capable(CAP_SYS_ADMIN)) { + if (placement->busy_placement[i] & TTM_PL_FLAG_NO_EVICT) { + printk(KERN_ERR TTM_PFX "Need to be root to " + "modify NO_EVICT status.\n"); + return -EINVAL; + } + } + } return 0; } @@ -1144,10 +1176,6 @@ int ttm_bo_init(struct ttm_bo_device *bdev, num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; if (num_pages == 0) { printk(KERN_ERR TTM_PFX "Illegal buffer object size.\n"); - if (destroy) - (*destroy)(bo); - else - kfree(bo); return -EINVAL; } bo->destroy = destroy; @@ -1341,9 +1369,18 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, int ret = -EINVAL; struct ttm_mem_type_manager *man; - BUG_ON(type >= TTM_NUM_MEM_TYPES); + if (type >= TTM_NUM_MEM_TYPES) { + printk(KERN_ERR TTM_PFX "Illegal memory type %d\n", type); + return ret; + } + man = &bdev->man[type]; - BUG_ON(man->has_type); + if (man->has_type) { + printk(KERN_ERR TTM_PFX + "Memory manager already initialized for type %d\n", + type); + return ret; + } ret = bdev->driver->init_mem_type(bdev, type, man); if (ret) @@ -1352,6 +1389,13 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, ret = 0; if (type != TTM_PL_SYSTEM) { + if (!p_size) { + printk(KERN_ERR TTM_PFX + "Zero size memory manager type %d\n", + type); + return ret; + } + ret = (*man->func->init)(man, p_size); if (ret) return ret; diff --git a/trunk/drivers/gpu/drm/ttm/ttm_bo_manager.c b/trunk/drivers/gpu/drm/ttm/ttm_bo_manager.c index 038e947d00f9..7410c190c891 100644 --- a/trunk/drivers/gpu/drm/ttm/ttm_bo_manager.c +++ b/trunk/drivers/gpu/drm/ttm/ttm_bo_manager.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright (c) 2007-2010 VMware, Inc., Palo Alto, CA., USA + * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -31,29 +31,20 @@ #include "ttm/ttm_module.h" #include "ttm/ttm_bo_driver.h" #include "ttm/ttm_placement.h" -#include "drm_mm.h" +#include #include -#include +#include +#include +#include #include -/** - * Currently we use a spinlock for the lock, but a mutex *may* be - * more appropriate to reduce scheduling latency if the range manager - * ends up with very fragmented allocation patterns. - */ - -struct ttm_range_manager { - struct drm_mm mm; - spinlock_t lock; -}; - static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, struct ttm_buffer_object *bo, struct ttm_placement *placement, struct ttm_mem_reg *mem) { - struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; - struct drm_mm *mm = &rman->mm; + struct ttm_bo_global *glob = man->bdev->glob; + struct drm_mm *mm = man->priv; struct drm_mm_node *node = NULL; unsigned long lpfn; int ret; @@ -66,19 +57,19 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, if (unlikely(ret)) return ret; - spin_lock(&rman->lock); + spin_lock(&glob->lru_lock); node = drm_mm_search_free_in_range(mm, mem->num_pages, mem->page_alignment, placement->fpfn, lpfn, 1); if (unlikely(node == NULL)) { - spin_unlock(&rman->lock); + spin_unlock(&glob->lru_lock); return 0; } node = drm_mm_get_block_atomic_range(node, mem->num_pages, - mem->page_alignment, - placement->fpfn, - lpfn); - spin_unlock(&rman->lock); + mem->page_alignment, + placement->fpfn, + lpfn); + spin_unlock(&glob->lru_lock); } while (node == NULL); mem->mm_node = node; @@ -89,12 +80,12 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { - struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; + struct ttm_bo_global *glob = man->bdev->glob; if (mem->mm_node) { - spin_lock(&rman->lock); + spin_lock(&glob->lru_lock); drm_mm_put_block(mem->mm_node); - spin_unlock(&rman->lock); + spin_unlock(&glob->lru_lock); mem->mm_node = NULL; } } @@ -102,49 +93,49 @@ static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man, static int ttm_bo_man_init(struct ttm_mem_type_manager *man, unsigned long p_size) { - struct ttm_range_manager *rman; + struct drm_mm *mm; int ret; - rman = kzalloc(sizeof(*rman), GFP_KERNEL); - if (!rman) + mm = kzalloc(sizeof(*mm), GFP_KERNEL); + if (!mm) return -ENOMEM; - ret = drm_mm_init(&rman->mm, 0, p_size); + ret = drm_mm_init(mm, 0, p_size); if (ret) { - kfree(rman); + kfree(mm); return ret; } - spin_lock_init(&rman->lock); - man->priv = rman; + man->priv = mm; return 0; } static int ttm_bo_man_takedown(struct ttm_mem_type_manager *man) { - struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; - struct drm_mm *mm = &rman->mm; + struct ttm_bo_global *glob = man->bdev->glob; + struct drm_mm *mm = man->priv; + int ret = 0; - spin_lock(&rman->lock); + spin_lock(&glob->lru_lock); if (drm_mm_clean(mm)) { drm_mm_takedown(mm); - spin_unlock(&rman->lock); - kfree(rman); + kfree(mm); man->priv = NULL; - return 0; - } - spin_unlock(&rman->lock); - return -EBUSY; + } else + ret = -EBUSY; + spin_unlock(&glob->lru_lock); + return ret; } static void ttm_bo_man_debug(struct ttm_mem_type_manager *man, const char *prefix) { - struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; + struct ttm_bo_global *glob = man->bdev->glob; + struct drm_mm *mm = man->priv; - spin_lock(&rman->lock); - drm_mm_debug_table(&rman->mm, prefix); - spin_unlock(&rman->lock); + spin_lock(&glob->lru_lock); + drm_mm_debug_table(mm, prefix); + spin_unlock(&glob->lru_lock); } const struct ttm_mem_type_manager_func ttm_bo_manager_func = { diff --git a/trunk/drivers/gpu/drm/ttm/ttm_tt.c b/trunk/drivers/gpu/drm/ttm/ttm_tt.c index af789dc869b9..a7bab87a548b 100644 --- a/trunk/drivers/gpu/drm/ttm/ttm_tt.c +++ b/trunk/drivers/gpu/drm/ttm/ttm_tt.c @@ -440,8 +440,10 @@ int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) return ret; ret = be->func->bind(be, bo_mem); - if (unlikely(ret != 0)) + if (ret) { + printk(KERN_ERR TTM_PFX "Couldn't bind backend.\n"); return ret; + } ttm->state = tt_bound; diff --git a/trunk/drivers/gpu/drm/via/via_dmablit.c b/trunk/drivers/gpu/drm/via/via_dmablit.c index 3e038a394c51..9b5b4d9dd62c 100644 --- a/trunk/drivers/gpu/drm/via/via_dmablit.c +++ b/trunk/drivers/gpu/drm/via/via_dmablit.c @@ -235,9 +235,9 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride - 1)) - first_pfn + 1; - vsg->pages = vzalloc(sizeof(struct page *) * vsg->num_pages); - if (NULL == vsg->pages) + if (NULL == (vsg->pages = vmalloc(sizeof(struct page *) * vsg->num_pages))) return -ENOMEM; + memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages); down_read(¤t->mm->mmap_sem); ret = get_user_pages(current, current->mm, (unsigned long)xfer->mem_addr, diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 76954e3528c1..51d9f9f1d7f2 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -691,7 +691,6 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data, fence_rep.error = ret; fence_rep.fence_seq = (uint64_t) sequence; - fence_rep.pad64 = 0; user_fence_rep = (struct drm_vmw_fence_rep __user *) (unsigned long)arg->fence_rep; diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index cceeb42789b6..87c6e6156d7d 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -720,8 +720,6 @@ static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb) &vmw_vram_ne_placement, false, &vmw_dmabuf_bo_free); vmw_overlay_resume_all(dev_priv); - if (unlikely(ret != 0)) - vfbs->buffer = NULL; return ret; } @@ -732,9 +730,6 @@ static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb) struct vmw_framebuffer_surface *vfbs = vmw_framebuffer_to_vfbs(&vfb->base); - if (unlikely(vfbs->buffer == NULL)) - return 0; - bo = &vfbs->buffer->base; ttm_bo_unref(&bo); vfbs->buffer = NULL; diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 29113c9b26a8..a01c47ddb5bc 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -557,7 +557,7 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv) return -EINVAL; } - dev_priv->ldu_priv = kmalloc(sizeof(*dev_priv->ldu_priv), GFP_KERNEL); + dev_priv->ldu_priv = kmalloc(GFP_KERNEL, sizeof(*dev_priv->ldu_priv)); if (!dev_priv->ldu_priv) return -ENOMEM; diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c index f1a52f9e7298..df2036ed18d5 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c @@ -585,7 +585,7 @@ int vmw_overlay_init(struct vmw_private *dev_priv) return -ENOSYS; } - overlay = kmalloc(sizeof(*overlay), GFP_KERNEL); + overlay = kmalloc(GFP_KERNEL, sizeof(*overlay)); if (!overlay) return -ENOMEM; diff --git a/trunk/drivers/gpu/stub/Kconfig b/trunk/drivers/gpu/stub/Kconfig index 0e1edd7311ff..742c423567cf 100644 --- a/trunk/drivers/gpu/stub/Kconfig +++ b/trunk/drivers/gpu/stub/Kconfig @@ -3,9 +3,6 @@ config STUB_POULSBO depends on PCI # Poulsbo stub depends on ACPI_VIDEO when ACPI is enabled # but for select to work, need to select ACPI_VIDEO's dependencies, ick - select VIDEO_OUTPUT_CONTROL if ACPI - select BACKLIGHT_CLASS_DEVICE if ACPI - select INPUT if ACPI select ACPI_VIDEO if ACPI help Choose this option if you have a system that has Intel GMA500 diff --git a/trunk/drivers/leds/Kconfig b/trunk/drivers/leds/Kconfig index 77b8fd20cd90..cc2a88d5192f 100644 --- a/trunk/drivers/leds/Kconfig +++ b/trunk/drivers/leds/Kconfig @@ -10,7 +10,7 @@ menuconfig NEW_LEDS if NEW_LEDS config LEDS_CLASS - bool "LED Class Support" + tristate "LED Class Support" help This option enables the led sysfs class in /sys/class/leds. You'll need this to do anything useful with LEDs. If unsure, say N. @@ -176,24 +176,6 @@ config LEDS_LP3944 To compile this driver as a module, choose M here: the module will be called leds-lp3944. -config LEDS_LP5521 - tristate "LED Support for N.S. LP5521 LED driver chip" - depends on LEDS_CLASS && I2C - help - If you say yes here you get support for the National Semiconductor - LP5521 LED driver. It is 3 channel chip with programmable engines. - Driver provides direct control via LED class and interface for - programming the engines. - -config LEDS_LP5523 - tristate "LED Support for N.S. LP5523 LED driver chip" - depends on LEDS_CLASS && I2C - help - If you say yes here you get support for the National Semiconductor - LP5523 LED driver. It is 9 channel chip with programmable engines. - Driver provides direct control via LED class and interface for - programming the engines. - config LEDS_CLEVO_MAIL tristate "Mail LED on Clevo notebook" depends on X86 && SERIO_I8042 && DMI diff --git a/trunk/drivers/leds/Makefile b/trunk/drivers/leds/Makefile index aae6989ff6b6..9c96db40ef6d 100644 --- a/trunk/drivers/leds/Makefile +++ b/trunk/drivers/leds/Makefile @@ -23,8 +23,6 @@ obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o -obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o -obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o obj-$(CONFIG_LEDS_FSG) += leds-fsg.o diff --git a/trunk/drivers/leds/led-class.c b/trunk/drivers/leds/led-class.c index 211e21f34bd5..260660076507 100644 --- a/trunk/drivers/leds/led-class.c +++ b/trunk/drivers/leds/led-class.c @@ -81,79 +81,6 @@ static struct device_attribute led_class_attrs[] = { __ATTR_NULL, }; -static void led_timer_function(unsigned long data) -{ - struct led_classdev *led_cdev = (void *)data; - unsigned long brightness; - unsigned long delay; - - if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) { - led_set_brightness(led_cdev, LED_OFF); - return; - } - - brightness = led_get_brightness(led_cdev); - if (!brightness) { - /* Time to switch the LED on. */ - brightness = led_cdev->blink_brightness; - delay = led_cdev->blink_delay_on; - } else { - /* Store the current brightness value to be able - * to restore it when the delay_off period is over. - */ - led_cdev->blink_brightness = brightness; - brightness = LED_OFF; - delay = led_cdev->blink_delay_off; - } - - led_set_brightness(led_cdev, brightness); - - mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay)); -} - -static void led_stop_software_blink(struct led_classdev *led_cdev) -{ - /* deactivate previous settings */ - del_timer_sync(&led_cdev->blink_timer); - led_cdev->blink_delay_on = 0; - led_cdev->blink_delay_off = 0; -} - -static void led_set_software_blink(struct led_classdev *led_cdev, - unsigned long delay_on, - unsigned long delay_off) -{ - int current_brightness; - - current_brightness = led_get_brightness(led_cdev); - if (current_brightness) - led_cdev->blink_brightness = current_brightness; - if (!led_cdev->blink_brightness) - led_cdev->blink_brightness = led_cdev->max_brightness; - - if (delay_on == led_cdev->blink_delay_on && - delay_off == led_cdev->blink_delay_off) - return; - - led_stop_software_blink(led_cdev); - - led_cdev->blink_delay_on = delay_on; - led_cdev->blink_delay_off = delay_off; - - /* never on - don't blink */ - if (!delay_on) - return; - - /* never off - just set to brightness */ - if (!delay_off) { - led_set_brightness(led_cdev, led_cdev->blink_brightness); - return; - } - - mod_timer(&led_cdev->blink_timer, jiffies + 1); -} - - /** * led_classdev_suspend - suspend an led_classdev. * @led_cdev: the led_classdev to suspend. @@ -221,10 +148,6 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) led_update_brightness(led_cdev); - init_timer(&led_cdev->blink_timer); - led_cdev->blink_timer.function = led_timer_function; - led_cdev->blink_timer.data = (unsigned long)led_cdev; - #ifdef CONFIG_LEDS_TRIGGERS led_trigger_set_default(led_cdev); #endif @@ -234,6 +157,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) return 0; } + EXPORT_SYMBOL_GPL(led_classdev_register); /** @@ -251,9 +175,6 @@ void led_classdev_unregister(struct led_classdev *led_cdev) up_write(&led_cdev->trigger_lock); #endif - /* Stop blinking */ - led_brightness_set(led_cdev, LED_OFF); - device_unregister(led_cdev->dev); down_write(&leds_list_lock); @@ -262,30 +183,6 @@ void led_classdev_unregister(struct led_classdev *led_cdev) } EXPORT_SYMBOL_GPL(led_classdev_unregister); -void led_blink_set(struct led_classdev *led_cdev, - unsigned long *delay_on, - unsigned long *delay_off) -{ - if (led_cdev->blink_set && - led_cdev->blink_set(led_cdev, delay_on, delay_off)) - return; - - /* blink with 1 Hz as default if nothing specified */ - if (!*delay_on && !*delay_off) - *delay_on = *delay_off = 500; - - led_set_software_blink(led_cdev, *delay_on, *delay_off); -} -EXPORT_SYMBOL(led_blink_set); - -void led_brightness_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - led_stop_software_blink(led_cdev); - led_cdev->brightness_set(led_cdev, brightness); -} -EXPORT_SYMBOL(led_brightness_set); - static int __init leds_init(void) { leds_class = class_create(THIS_MODULE, "leds"); diff --git a/trunk/drivers/leds/led-triggers.c b/trunk/drivers/leds/led-triggers.c index c41eb6180c9c..f1c00db88b5e 100644 --- a/trunk/drivers/leds/led-triggers.c +++ b/trunk/drivers/leds/led-triggers.c @@ -113,7 +113,7 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger) if (led_cdev->trigger->deactivate) led_cdev->trigger->deactivate(led_cdev); led_cdev->trigger = NULL; - led_brightness_set(led_cdev, LED_OFF); + led_set_brightness(led_cdev, LED_OFF); } if (trigger) { write_lock_irqsave(&trigger->leddev_list_lock, flags); diff --git a/trunk/drivers/leds/leds-gpio.c b/trunk/drivers/leds/leds-gpio.c index 4d9fa38d9ff6..ea57e05d08f3 100644 --- a/trunk/drivers/leds/leds-gpio.c +++ b/trunk/drivers/leds/leds-gpio.c @@ -316,7 +316,7 @@ static struct of_platform_driver of_gpio_leds_driver = { static int __init gpio_led_init(void) { - int ret = 0; + int ret; #ifdef CONFIG_LEDS_GPIO_PLATFORM ret = platform_driver_register(&gpio_led_driver); diff --git a/trunk/drivers/leds/leds-lp5521.c b/trunk/drivers/leds/leds-lp5521.c deleted file mode 100644 index 3782f31f06d2..000000000000 --- a/trunk/drivers/leds/leds-lp5521.c +++ /dev/null @@ -1,821 +0,0 @@ -/* - * LP5521 LED chip driver. - * - * Copyright (C) 2010 Nokia Corporation - * - * Contact: Samu Onkalo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LP5521_PROGRAM_LENGTH 32 /* in bytes */ - -#define LP5521_MAX_LEDS 3 /* Maximum number of LEDs */ -#define LP5521_MAX_ENGINES 3 /* Maximum number of engines */ - -#define LP5521_ENG_MASK_BASE 0x30 /* 00110000 */ -#define LP5521_ENG_STATUS_MASK 0x07 /* 00000111 */ - -#define LP5521_CMD_LOAD 0x15 /* 00010101 */ -#define LP5521_CMD_RUN 0x2a /* 00101010 */ -#define LP5521_CMD_DIRECT 0x3f /* 00111111 */ -#define LP5521_CMD_DISABLED 0x00 /* 00000000 */ - -/* Registers */ -#define LP5521_REG_ENABLE 0x00 -#define LP5521_REG_OP_MODE 0x01 -#define LP5521_REG_R_PWM 0x02 -#define LP5521_REG_G_PWM 0x03 -#define LP5521_REG_B_PWM 0x04 -#define LP5521_REG_R_CURRENT 0x05 -#define LP5521_REG_G_CURRENT 0x06 -#define LP5521_REG_B_CURRENT 0x07 -#define LP5521_REG_CONFIG 0x08 -#define LP5521_REG_R_CHANNEL_PC 0x09 -#define LP5521_REG_G_CHANNEL_PC 0x0A -#define LP5521_REG_B_CHANNEL_PC 0x0B -#define LP5521_REG_STATUS 0x0C -#define LP5521_REG_RESET 0x0D -#define LP5521_REG_GPO 0x0E -#define LP5521_REG_R_PROG_MEM 0x10 -#define LP5521_REG_G_PROG_MEM 0x30 -#define LP5521_REG_B_PROG_MEM 0x50 - -#define LP5521_PROG_MEM_BASE LP5521_REG_R_PROG_MEM -#define LP5521_PROG_MEM_SIZE 0x20 - -/* Base register to set LED current */ -#define LP5521_REG_LED_CURRENT_BASE LP5521_REG_R_CURRENT - -/* Base register to set the brightness */ -#define LP5521_REG_LED_PWM_BASE LP5521_REG_R_PWM - -/* Bits in ENABLE register */ -#define LP5521_MASTER_ENABLE 0x40 /* Chip master enable */ -#define LP5521_LOGARITHMIC_PWM 0x80 /* Logarithmic PWM adjustment */ -#define LP5521_EXEC_RUN 0x2A - -/* Bits in CONFIG register */ -#define LP5521_PWM_HF 0x40 /* PWM: 0 = 256Hz, 1 = 558Hz */ -#define LP5521_PWRSAVE_EN 0x20 /* 1 = Power save mode */ -#define LP5521_CP_MODE_OFF 0 /* Charge pump (CP) off */ -#define LP5521_CP_MODE_BYPASS 8 /* CP forced to bypass mode */ -#define LP5521_CP_MODE_1X5 0x10 /* CP forced to 1.5x mode */ -#define LP5521_CP_MODE_AUTO 0x18 /* Automatic mode selection */ -#define LP5521_R_TO_BATT 4 /* R out: 0 = CP, 1 = Vbat */ -#define LP5521_CLK_SRC_EXT 0 /* Ext-clk source (CLK_32K) */ -#define LP5521_CLK_INT 1 /* Internal clock */ -#define LP5521_CLK_AUTO 2 /* Automatic clock selection */ - -/* Status */ -#define LP5521_EXT_CLK_USED 0x08 - -struct lp5521_engine { - const struct attribute_group *attributes; - int id; - u8 mode; - u8 prog_page; - u8 engine_mask; -}; - -struct lp5521_led { - int id; - u8 chan_nr; - u8 led_current; - u8 max_current; - struct led_classdev cdev; - struct work_struct brightness_work; - u8 brightness; -}; - -struct lp5521_chip { - struct lp5521_platform_data *pdata; - struct mutex lock; /* Serialize control */ - struct i2c_client *client; - struct lp5521_engine engines[LP5521_MAX_ENGINES]; - struct lp5521_led leds[LP5521_MAX_LEDS]; - u8 num_channels; - u8 num_leds; -}; - -#define cdev_to_led(c) container_of(c, struct lp5521_led, cdev) -#define engine_to_lp5521(eng) container_of((eng), struct lp5521_chip, \ - engines[(eng)->id - 1]) -#define led_to_lp5521(led) container_of((led), struct lp5521_chip, \ - leds[(led)->id]) - -static void lp5521_led_brightness_work(struct work_struct *work); - -static inline int lp5521_write(struct i2c_client *client, u8 reg, u8 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - -static int lp5521_read(struct i2c_client *client, u8 reg, u8 *buf) -{ - s32 ret; - - ret = i2c_smbus_read_byte_data(client, reg); - if (ret < 0) - return -EIO; - - *buf = ret; - return 0; -} - -static int lp5521_set_engine_mode(struct lp5521_engine *engine, u8 mode) -{ - struct lp5521_chip *chip = engine_to_lp5521(engine); - struct i2c_client *client = chip->client; - int ret; - u8 engine_state; - - /* Only transition between RUN and DIRECT mode are handled here */ - if (mode == LP5521_CMD_LOAD) - return 0; - - if (mode == LP5521_CMD_DISABLED) - mode = LP5521_CMD_DIRECT; - - ret = lp5521_read(client, LP5521_REG_OP_MODE, &engine_state); - - /* set mode only for this engine */ - engine_state &= ~(engine->engine_mask); - mode &= engine->engine_mask; - engine_state |= mode; - ret |= lp5521_write(client, LP5521_REG_OP_MODE, engine_state); - - return ret; -} - -static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern) -{ - struct lp5521_chip *chip = engine_to_lp5521(eng); - struct i2c_client *client = chip->client; - int ret; - int addr; - u8 mode; - - /* move current engine to direct mode and remember the state */ - ret = lp5521_set_engine_mode(eng, LP5521_CMD_DIRECT); - usleep_range(1000, 10000); - ret |= lp5521_read(client, LP5521_REG_OP_MODE, &mode); - - /* For loading, all the engines to load mode */ - lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT); - usleep_range(1000, 10000); - lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_LOAD); - usleep_range(1000, 10000); - - addr = LP5521_PROG_MEM_BASE + eng->prog_page * LP5521_PROG_MEM_SIZE; - i2c_smbus_write_i2c_block_data(client, - addr, - LP5521_PROG_MEM_SIZE, - pattern); - - ret |= lp5521_write(client, LP5521_REG_OP_MODE, mode); - return ret; -} - -static int lp5521_set_led_current(struct lp5521_chip *chip, int led, u8 curr) -{ - return lp5521_write(chip->client, - LP5521_REG_LED_CURRENT_BASE + chip->leds[led].chan_nr, - curr); -} - -static void lp5521_init_engine(struct lp5521_chip *chip, - const struct attribute_group *attr_group) -{ - int i; - for (i = 0; i < ARRAY_SIZE(chip->engines); i++) { - chip->engines[i].id = i + 1; - chip->engines[i].engine_mask = LP5521_ENG_MASK_BASE >> (i * 2); - chip->engines[i].prog_page = i; - chip->engines[i].attributes = &attr_group[i]; - } -} - -static int lp5521_configure(struct i2c_client *client, - const struct attribute_group *attr_group) -{ - struct lp5521_chip *chip = i2c_get_clientdata(client); - int ret; - - lp5521_init_engine(chip, attr_group); - - lp5521_write(client, LP5521_REG_RESET, 0xff); - - usleep_range(10000, 20000); - - /* Set all PWMs to direct control mode */ - ret = lp5521_write(client, LP5521_REG_OP_MODE, 0x3F); - - /* Enable auto-powersave, set charge pump to auto, red to battery */ - ret |= lp5521_write(client, LP5521_REG_CONFIG, - LP5521_PWRSAVE_EN | LP5521_CP_MODE_AUTO | LP5521_R_TO_BATT); - - /* Initialize all channels PWM to zero -> leds off */ - ret |= lp5521_write(client, LP5521_REG_R_PWM, 0); - ret |= lp5521_write(client, LP5521_REG_G_PWM, 0); - ret |= lp5521_write(client, LP5521_REG_B_PWM, 0); - - /* Set engines are set to run state when OP_MODE enables engines */ - ret |= lp5521_write(client, LP5521_REG_ENABLE, - LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM | - LP5521_EXEC_RUN); - /* enable takes 500us */ - usleep_range(500, 20000); - - return ret; -} - -static int lp5521_run_selftest(struct lp5521_chip *chip, char *buf) -{ - int ret; - u8 status; - - ret = lp5521_read(chip->client, LP5521_REG_STATUS, &status); - if (ret < 0) - return ret; - - /* Check that ext clock is really in use if requested */ - if (chip->pdata && chip->pdata->clock_mode == LP5521_CLOCK_EXT) - if ((status & LP5521_EXT_CLK_USED) == 0) - return -EIO; - return 0; -} - -static void lp5521_set_brightness(struct led_classdev *cdev, - enum led_brightness brightness) -{ - struct lp5521_led *led = cdev_to_led(cdev); - led->brightness = (u8)brightness; - schedule_work(&led->brightness_work); -} - -static void lp5521_led_brightness_work(struct work_struct *work) -{ - struct lp5521_led *led = container_of(work, - struct lp5521_led, - brightness_work); - struct lp5521_chip *chip = led_to_lp5521(led); - struct i2c_client *client = chip->client; - - mutex_lock(&chip->lock); - lp5521_write(client, LP5521_REG_LED_PWM_BASE + led->chan_nr, - led->brightness); - mutex_unlock(&chip->lock); -} - -/* Detect the chip by setting its ENABLE register and reading it back. */ -static int lp5521_detect(struct i2c_client *client) -{ - int ret; - u8 buf; - - ret = lp5521_write(client, LP5521_REG_ENABLE, - LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM); - if (ret) - return ret; - usleep_range(1000, 10000); - ret = lp5521_read(client, LP5521_REG_ENABLE, &buf); - if (ret) - return ret; - if (buf != (LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM)) - return -ENODEV; - - return 0; -} - -/* Set engine mode and create appropriate sysfs attributes, if required. */ -static int lp5521_set_mode(struct lp5521_engine *engine, u8 mode) -{ - struct lp5521_chip *chip = engine_to_lp5521(engine); - struct i2c_client *client = chip->client; - struct device *dev = &client->dev; - int ret = 0; - - /* if in that mode already do nothing, except for run */ - if (mode == engine->mode && mode != LP5521_CMD_RUN) - return 0; - - if (mode == LP5521_CMD_RUN) { - ret = lp5521_set_engine_mode(engine, LP5521_CMD_RUN); - } else if (mode == LP5521_CMD_LOAD) { - lp5521_set_engine_mode(engine, LP5521_CMD_DISABLED); - lp5521_set_engine_mode(engine, LP5521_CMD_LOAD); - - ret = sysfs_create_group(&dev->kobj, engine->attributes); - if (ret) - return ret; - } else if (mode == LP5521_CMD_DISABLED) { - lp5521_set_engine_mode(engine, LP5521_CMD_DISABLED); - } - - /* remove load attribute from sysfs if not in load mode */ - if (engine->mode == LP5521_CMD_LOAD && mode != LP5521_CMD_LOAD) - sysfs_remove_group(&dev->kobj, engine->attributes); - - engine->mode = mode; - - return ret; -} - -static int lp5521_do_store_load(struct lp5521_engine *engine, - const char *buf, size_t len) -{ - struct lp5521_chip *chip = engine_to_lp5521(engine); - struct i2c_client *client = chip->client; - int ret, nrchars, offset = 0, i = 0; - char c[3]; - unsigned cmd; - u8 pattern[LP5521_PROGRAM_LENGTH] = {0}; - - while ((offset < len - 1) && (i < LP5521_PROGRAM_LENGTH)) { - /* separate sscanfs because length is working only for %s */ - ret = sscanf(buf + offset, "%2s%n ", c, &nrchars); - ret = sscanf(c, "%2x", &cmd); - if (ret != 1) - goto fail; - pattern[i] = (u8)cmd; - - offset += nrchars; - i++; - } - - /* Each instruction is 16bit long. Check that length is even */ - if (i % 2) - goto fail; - - mutex_lock(&chip->lock); - ret = lp5521_load_program(engine, pattern); - mutex_unlock(&chip->lock); - - if (ret) { - dev_err(&client->dev, "failed loading pattern\n"); - return ret; - } - - return len; -fail: - dev_err(&client->dev, "wrong pattern format\n"); - return -EINVAL; -} - -static ssize_t store_engine_load(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len, int nr) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lp5521_chip *chip = i2c_get_clientdata(client); - return lp5521_do_store_load(&chip->engines[nr - 1], buf, len); -} - -#define store_load(nr) \ -static ssize_t store_engine##nr##_load(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t len) \ -{ \ - return store_engine_load(dev, attr, buf, len, nr); \ -} -store_load(1) -store_load(2) -store_load(3) - -static ssize_t show_engine_mode(struct device *dev, - struct device_attribute *attr, - char *buf, int nr) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lp5521_chip *chip = i2c_get_clientdata(client); - switch (chip->engines[nr - 1].mode) { - case LP5521_CMD_RUN: - return sprintf(buf, "run\n"); - case LP5521_CMD_LOAD: - return sprintf(buf, "load\n"); - case LP5521_CMD_DISABLED: - return sprintf(buf, "disabled\n"); - default: - return sprintf(buf, "disabled\n"); - } -} - -#define show_mode(nr) \ -static ssize_t show_engine##nr##_mode(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_engine_mode(dev, attr, buf, nr); \ -} -show_mode(1) -show_mode(2) -show_mode(3) - -static ssize_t store_engine_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len, int nr) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lp5521_chip *chip = i2c_get_clientdata(client); - struct lp5521_engine *engine = &chip->engines[nr - 1]; - mutex_lock(&chip->lock); - - if (!strncmp(buf, "run", 3)) - lp5521_set_mode(engine, LP5521_CMD_RUN); - else if (!strncmp(buf, "load", 4)) - lp5521_set_mode(engine, LP5521_CMD_LOAD); - else if (!strncmp(buf, "disabled", 8)) - lp5521_set_mode(engine, LP5521_CMD_DISABLED); - - mutex_unlock(&chip->lock); - return len; -} - -#define store_mode(nr) \ -static ssize_t store_engine##nr##_mode(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t len) \ -{ \ - return store_engine_mode(dev, attr, buf, len, nr); \ -} -store_mode(1) -store_mode(2) -store_mode(3) - -static ssize_t show_max_current(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct lp5521_led *led = cdev_to_led(led_cdev); - - return sprintf(buf, "%d\n", led->max_current); -} - -static ssize_t show_current(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct lp5521_led *led = cdev_to_led(led_cdev); - - return sprintf(buf, "%d\n", led->led_current); -} - -static ssize_t store_current(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct lp5521_led *led = cdev_to_led(led_cdev); - struct lp5521_chip *chip = led_to_lp5521(led); - ssize_t ret; - unsigned long curr; - - if (strict_strtoul(buf, 0, &curr)) - return -EINVAL; - - if (curr > led->max_current) - return -EINVAL; - - mutex_lock(&chip->lock); - ret = lp5521_set_led_current(chip, led->id, curr); - mutex_unlock(&chip->lock); - - if (ret < 0) - return ret; - - led->led_current = (u8)curr; - - return len; -} - -static ssize_t lp5521_selftest(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lp5521_chip *chip = i2c_get_clientdata(client); - int ret; - - mutex_lock(&chip->lock); - ret = lp5521_run_selftest(chip, buf); - mutex_unlock(&chip->lock); - return sprintf(buf, "%s\n", ret ? "FAIL" : "OK"); -} - -/* led class device attributes */ -static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current); -static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL); - -static struct attribute *lp5521_led_attributes[] = { - &dev_attr_led_current.attr, - &dev_attr_max_current.attr, - NULL, -}; - -static struct attribute_group lp5521_led_attribute_group = { - .attrs = lp5521_led_attributes -}; - -/* device attributes */ -static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO, - show_engine1_mode, store_engine1_mode); -static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO, - show_engine2_mode, store_engine2_mode); -static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO, - show_engine3_mode, store_engine3_mode); -static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load); -static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load); -static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load); -static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL); - -static struct attribute *lp5521_attributes[] = { - &dev_attr_engine1_mode.attr, - &dev_attr_engine2_mode.attr, - &dev_attr_engine3_mode.attr, - &dev_attr_selftest.attr, - NULL -}; - -static struct attribute *lp5521_engine1_attributes[] = { - &dev_attr_engine1_load.attr, - NULL -}; - -static struct attribute *lp5521_engine2_attributes[] = { - &dev_attr_engine2_load.attr, - NULL -}; - -static struct attribute *lp5521_engine3_attributes[] = { - &dev_attr_engine3_load.attr, - NULL -}; - -static const struct attribute_group lp5521_group = { - .attrs = lp5521_attributes, -}; - -static const struct attribute_group lp5521_engine_group[] = { - {.attrs = lp5521_engine1_attributes }, - {.attrs = lp5521_engine2_attributes }, - {.attrs = lp5521_engine3_attributes }, -}; - -static int lp5521_register_sysfs(struct i2c_client *client) -{ - struct device *dev = &client->dev; - return sysfs_create_group(&dev->kobj, &lp5521_group); -} - -static void lp5521_unregister_sysfs(struct i2c_client *client) -{ - struct lp5521_chip *chip = i2c_get_clientdata(client); - struct device *dev = &client->dev; - int i; - - sysfs_remove_group(&dev->kobj, &lp5521_group); - - for (i = 0; i < ARRAY_SIZE(chip->engines); i++) { - if (chip->engines[i].mode == LP5521_CMD_LOAD) - sysfs_remove_group(&dev->kobj, - chip->engines[i].attributes); - } - - for (i = 0; i < chip->num_leds; i++) - sysfs_remove_group(&chip->leds[i].cdev.dev->kobj, - &lp5521_led_attribute_group); -} - -static int __init lp5521_init_led(struct lp5521_led *led, - struct i2c_client *client, - int chan, struct lp5521_platform_data *pdata) -{ - struct device *dev = &client->dev; - char name[32]; - int res; - - if (chan >= LP5521_MAX_LEDS) - return -EINVAL; - - if (pdata->led_config[chan].led_current == 0) - return 0; - - led->led_current = pdata->led_config[chan].led_current; - led->max_current = pdata->led_config[chan].max_current; - led->chan_nr = pdata->led_config[chan].chan_nr; - - if (led->chan_nr >= LP5521_MAX_LEDS) { - dev_err(dev, "Use channel numbers between 0 and %d\n", - LP5521_MAX_LEDS - 1); - return -EINVAL; - } - - snprintf(name, sizeof(name), "%s:channel%d", client->name, chan); - led->cdev.brightness_set = lp5521_set_brightness; - led->cdev.name = name; - res = led_classdev_register(dev, &led->cdev); - if (res < 0) { - dev_err(dev, "couldn't register led on channel %d\n", chan); - return res; - } - - res = sysfs_create_group(&led->cdev.dev->kobj, - &lp5521_led_attribute_group); - if (res < 0) { - dev_err(dev, "couldn't register current attribute\n"); - led_classdev_unregister(&led->cdev); - return res; - } - return 0; -} - -static int lp5521_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct lp5521_chip *chip; - struct lp5521_platform_data *pdata; - int ret, i, led; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - - i2c_set_clientdata(client, chip); - chip->client = client; - - pdata = client->dev.platform_data; - - if (!pdata) { - dev_err(&client->dev, "no platform data\n"); - ret = -EINVAL; - goto fail1; - } - - mutex_init(&chip->lock); - - chip->pdata = pdata; - - if (pdata->setup_resources) { - ret = pdata->setup_resources(); - if (ret < 0) - goto fail1; - } - - if (pdata->enable) { - pdata->enable(0); - usleep_range(1000, 10000); - pdata->enable(1); - usleep_range(1000, 10000); /* Spec says min 500us */ - } - - ret = lp5521_detect(client); - - if (ret) { - dev_err(&client->dev, "Chip not found\n"); - goto fail2; - } - - dev_info(&client->dev, "%s programmable led chip found\n", id->name); - - ret = lp5521_configure(client, lp5521_engine_group); - if (ret < 0) { - dev_err(&client->dev, "error configuring chip\n"); - goto fail2; - } - - /* Initialize leds */ - chip->num_channels = pdata->num_channels; - chip->num_leds = 0; - led = 0; - for (i = 0; i < pdata->num_channels; i++) { - /* Do not initialize channels that are not connected */ - if (pdata->led_config[i].led_current == 0) - continue; - - ret = lp5521_init_led(&chip->leds[led], client, i, pdata); - if (ret) { - dev_err(&client->dev, "error initializing leds\n"); - goto fail3; - } - chip->num_leds++; - - chip->leds[led].id = led; - /* Set initial LED current */ - lp5521_set_led_current(chip, led, - chip->leds[led].led_current); - - INIT_WORK(&(chip->leds[led].brightness_work), - lp5521_led_brightness_work); - - led++; - } - - ret = lp5521_register_sysfs(client); - if (ret) { - dev_err(&client->dev, "registering sysfs failed\n"); - goto fail3; - } - return ret; -fail3: - for (i = 0; i < chip->num_leds; i++) { - led_classdev_unregister(&chip->leds[i].cdev); - cancel_work_sync(&chip->leds[i].brightness_work); - } -fail2: - if (pdata->enable) - pdata->enable(0); - if (pdata->release_resources) - pdata->release_resources(); -fail1: - kfree(chip); - return ret; -} - -static int lp5521_remove(struct i2c_client *client) -{ - struct lp5521_chip *chip = i2c_get_clientdata(client); - int i; - - lp5521_unregister_sysfs(client); - - for (i = 0; i < chip->num_leds; i++) { - led_classdev_unregister(&chip->leds[i].cdev); - cancel_work_sync(&chip->leds[i].brightness_work); - } - - if (chip->pdata->enable) - chip->pdata->enable(0); - if (chip->pdata->release_resources) - chip->pdata->release_resources(); - kfree(chip); - return 0; -} - -static const struct i2c_device_id lp5521_id[] = { - { "lp5521", 0 }, /* Three channel chip */ - { } -}; -MODULE_DEVICE_TABLE(i2c, lp5521_id); - -static struct i2c_driver lp5521_driver = { - .driver = { - .name = "lp5521", - }, - .probe = lp5521_probe, - .remove = lp5521_remove, - .id_table = lp5521_id, -}; - -static int __init lp5521_init(void) -{ - int ret; - - ret = i2c_add_driver(&lp5521_driver); - - if (ret < 0) - printk(KERN_ALERT "Adding lp5521 driver failed\n"); - - return ret; -} - -static void __exit lp5521_exit(void) -{ - i2c_del_driver(&lp5521_driver); -} - -module_init(lp5521_init); -module_exit(lp5521_exit); - -MODULE_AUTHOR("Mathias Nyman, Yuri Zaporozhets, Samu Onkalo"); -MODULE_DESCRIPTION("LP5521 LED engine"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/leds/leds-lp5523.c b/trunk/drivers/leds/leds-lp5523.c deleted file mode 100644 index 1e11fcc08b28..000000000000 --- a/trunk/drivers/leds/leds-lp5523.c +++ /dev/null @@ -1,1065 +0,0 @@ -/* - * lp5523.c - LP5523 LED Driver - * - * Copyright (C) 2010 Nokia Corporation - * - * Contact: Samu Onkalo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LP5523_REG_ENABLE 0x00 -#define LP5523_REG_OP_MODE 0x01 -#define LP5523_REG_RATIOMETRIC_MSB 0x02 -#define LP5523_REG_RATIOMETRIC_LSB 0x03 -#define LP5523_REG_ENABLE_LEDS_MSB 0x04 -#define LP5523_REG_ENABLE_LEDS_LSB 0x05 -#define LP5523_REG_LED_CNTRL_BASE 0x06 -#define LP5523_REG_LED_PWM_BASE 0x16 -#define LP5523_REG_LED_CURRENT_BASE 0x26 -#define LP5523_REG_CONFIG 0x36 -#define LP5523_REG_CHANNEL1_PC 0x37 -#define LP5523_REG_CHANNEL2_PC 0x38 -#define LP5523_REG_CHANNEL3_PC 0x39 -#define LP5523_REG_STATUS 0x3a -#define LP5523_REG_GPO 0x3b -#define LP5523_REG_VARIABLE 0x3c -#define LP5523_REG_RESET 0x3d -#define LP5523_REG_TEMP_CTRL 0x3e -#define LP5523_REG_TEMP_READ 0x3f -#define LP5523_REG_TEMP_WRITE 0x40 -#define LP5523_REG_LED_TEST_CTRL 0x41 -#define LP5523_REG_LED_TEST_ADC 0x42 -#define LP5523_REG_ENG1_VARIABLE 0x45 -#define LP5523_REG_ENG2_VARIABLE 0x46 -#define LP5523_REG_ENG3_VARIABLE 0x47 -#define LP5523_REG_MASTER_FADER1 0x48 -#define LP5523_REG_MASTER_FADER2 0x49 -#define LP5523_REG_MASTER_FADER3 0x4a -#define LP5523_REG_CH1_PROG_START 0x4c -#define LP5523_REG_CH2_PROG_START 0x4d -#define LP5523_REG_CH3_PROG_START 0x4e -#define LP5523_REG_PROG_PAGE_SEL 0x4f -#define LP5523_REG_PROG_MEM 0x50 - -#define LP5523_CMD_LOAD 0x15 /* 00010101 */ -#define LP5523_CMD_RUN 0x2a /* 00101010 */ -#define LP5523_CMD_DISABLED 0x00 /* 00000000 */ - -#define LP5523_ENABLE 0x40 -#define LP5523_AUTO_INC 0x40 -#define LP5523_PWR_SAVE 0x20 -#define LP5523_PWM_PWR_SAVE 0x04 -#define LP5523_CP_1 0x08 -#define LP5523_CP_1_5 0x10 -#define LP5523_CP_AUTO 0x18 -#define LP5523_INT_CLK 0x01 -#define LP5523_AUTO_CLK 0x02 -#define LP5523_EN_LEDTEST 0x80 -#define LP5523_LEDTEST_DONE 0x80 - -#define LP5523_DEFAULT_CURRENT 50 /* microAmps */ -#define LP5523_PROGRAM_LENGTH 32 /* in bytes */ -#define LP5523_PROGRAM_PAGES 6 -#define LP5523_ADC_SHORTCIRC_LIM 80 - -#define LP5523_LEDS 9 -#define LP5523_ENGINES 3 - -#define LP5523_ENG_MASK_BASE 0x30 /* 00110000 */ - -#define LP5523_ENG_STATUS_MASK 0x07 /* 00000111 */ - -#define LP5523_IRQ_FLAGS IRQF_TRIGGER_FALLING - -#define LP5523_EXT_CLK_USED 0x08 - -#define LED_ACTIVE(mux, led) (!!(mux & (0x0001 << led))) -#define SHIFT_MASK(id) (((id) - 1) * 2) - -struct lp5523_engine { - const struct attribute_group *attributes; - int id; - u8 mode; - u8 prog_page; - u8 mux_page; - u16 led_mux; - u8 engine_mask; -}; - -struct lp5523_led { - int id; - u8 chan_nr; - u8 led_current; - u8 max_current; - struct led_classdev cdev; - struct work_struct brightness_work; - u8 brightness; -}; - -struct lp5523_chip { - struct mutex lock; /* Serialize control */ - struct i2c_client *client; - struct lp5523_engine engines[LP5523_ENGINES]; - struct lp5523_led leds[LP5523_LEDS]; - struct lp5523_platform_data *pdata; - u8 num_channels; - u8 num_leds; -}; - -#define cdev_to_led(c) container_of(c, struct lp5523_led, cdev) - -static struct lp5523_chip *engine_to_lp5523(struct lp5523_engine *engine) -{ - return container_of(engine, struct lp5523_chip, - engines[engine->id - 1]); -} - -static struct lp5523_chip *led_to_lp5523(struct lp5523_led *led) -{ - return container_of(led, struct lp5523_chip, - leds[led->id]); -} - -static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode); -static int lp5523_set_engine_mode(struct lp5523_engine *engine, u8 mode); -static int lp5523_load_program(struct lp5523_engine *engine, u8 *pattern); - -static void lp5523_led_brightness_work(struct work_struct *work); - -static int lp5523_write(struct i2c_client *client, u8 reg, u8 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - -static int lp5523_read(struct i2c_client *client, u8 reg, u8 *buf) -{ - s32 ret = i2c_smbus_read_byte_data(client, reg); - - if (ret < 0) - return -EIO; - - *buf = ret; - return 0; -} - -static int lp5523_detect(struct i2c_client *client) -{ - int ret; - u8 buf; - - ret = lp5523_write(client, LP5523_REG_ENABLE, 0x40); - if (ret) - return ret; - ret = lp5523_read(client, LP5523_REG_ENABLE, &buf); - if (ret) - return ret; - if (buf == 0x40) - return 0; - else - return -ENODEV; -} - -static int lp5523_configure(struct i2c_client *client) -{ - struct lp5523_chip *chip = i2c_get_clientdata(client); - int ret = 0; - u8 status; - - /* one pattern per engine setting led mux start and stop addresses */ - u8 pattern[][LP5523_PROGRAM_LENGTH] = { - { 0x9c, 0x30, 0x9c, 0xb0, 0x9d, 0x80, 0xd8, 0x00, 0}, - { 0x9c, 0x40, 0x9c, 0xc0, 0x9d, 0x80, 0xd8, 0x00, 0}, - { 0x9c, 0x50, 0x9c, 0xd0, 0x9d, 0x80, 0xd8, 0x00, 0}, - }; - - lp5523_write(client, LP5523_REG_RESET, 0xff); - - usleep_range(10000, 100000); - - ret |= lp5523_write(client, LP5523_REG_ENABLE, LP5523_ENABLE); - /* Chip startup time after reset is 500 us */ - usleep_range(1000, 10000); - - ret |= lp5523_write(client, LP5523_REG_CONFIG, - LP5523_AUTO_INC | LP5523_PWR_SAVE | - LP5523_CP_AUTO | LP5523_AUTO_CLK | - LP5523_PWM_PWR_SAVE); - - /* turn on all leds */ - ret |= lp5523_write(client, LP5523_REG_ENABLE_LEDS_MSB, 0x01); - ret |= lp5523_write(client, LP5523_REG_ENABLE_LEDS_LSB, 0xff); - - /* hardcode 32 bytes of memory for each engine from program memory */ - ret |= lp5523_write(client, LP5523_REG_CH1_PROG_START, 0x00); - ret |= lp5523_write(client, LP5523_REG_CH2_PROG_START, 0x10); - ret |= lp5523_write(client, LP5523_REG_CH3_PROG_START, 0x20); - - /* write led mux address space for each channel */ - ret |= lp5523_load_program(&chip->engines[0], pattern[0]); - ret |= lp5523_load_program(&chip->engines[1], pattern[1]); - ret |= lp5523_load_program(&chip->engines[2], pattern[2]); - - if (ret) { - dev_err(&client->dev, "could not load mux programs\n"); - return -1; - } - - /* set all engines exec state and mode to run 00101010 */ - ret |= lp5523_write(client, LP5523_REG_ENABLE, - (LP5523_CMD_RUN | LP5523_ENABLE)); - - ret |= lp5523_write(client, LP5523_REG_OP_MODE, LP5523_CMD_RUN); - - if (ret) { - dev_err(&client->dev, "could not start mux programs\n"); - return -1; - } - - /* Wait 3ms and check the engine status */ - usleep_range(3000, 20000); - lp5523_read(client, LP5523_REG_STATUS, &status); - status &= LP5523_ENG_STATUS_MASK; - - if (status == LP5523_ENG_STATUS_MASK) { - dev_dbg(&client->dev, "all engines configured\n"); - } else { - dev_info(&client->dev, "status == %x\n", status); - dev_err(&client->dev, "cound not configure LED engine\n"); - return -1; - } - - dev_info(&client->dev, "disabling engines\n"); - - ret |= lp5523_write(client, LP5523_REG_OP_MODE, LP5523_CMD_DISABLED); - - return ret; -} - -static int lp5523_set_engine_mode(struct lp5523_engine *engine, u8 mode) -{ - struct lp5523_chip *chip = engine_to_lp5523(engine); - struct i2c_client *client = chip->client; - int ret; - u8 engine_state; - - ret = lp5523_read(client, LP5523_REG_OP_MODE, &engine_state); - if (ret) - goto fail; - - engine_state &= ~(engine->engine_mask); - - /* set mode only for this engine */ - mode &= engine->engine_mask; - - engine_state |= mode; - - ret |= lp5523_write(client, LP5523_REG_OP_MODE, engine_state); -fail: - return ret; -} - -static int lp5523_load_mux(struct lp5523_engine *engine, u16 mux) -{ - struct lp5523_chip *chip = engine_to_lp5523(engine); - struct i2c_client *client = chip->client; - int ret = 0; - - ret |= lp5523_set_engine_mode(engine, LP5523_CMD_LOAD); - - ret |= lp5523_write(client, LP5523_REG_PROG_PAGE_SEL, engine->mux_page); - ret |= lp5523_write(client, LP5523_REG_PROG_MEM, - (u8)(mux >> 8)); - ret |= lp5523_write(client, LP5523_REG_PROG_MEM + 1, (u8)(mux)); - engine->led_mux = mux; - - return ret; -} - -static int lp5523_load_program(struct lp5523_engine *engine, u8 *pattern) -{ - struct lp5523_chip *chip = engine_to_lp5523(engine); - struct i2c_client *client = chip->client; - - int ret = 0; - - ret |= lp5523_set_engine_mode(engine, LP5523_CMD_LOAD); - - ret |= lp5523_write(client, LP5523_REG_PROG_PAGE_SEL, - engine->prog_page); - ret |= i2c_smbus_write_i2c_block_data(client, LP5523_REG_PROG_MEM, - LP5523_PROGRAM_LENGTH, pattern); - - return ret; -} - -static int lp5523_run_program(struct lp5523_engine *engine) -{ - struct lp5523_chip *chip = engine_to_lp5523(engine); - struct i2c_client *client = chip->client; - int ret; - - ret = lp5523_write(client, LP5523_REG_ENABLE, - LP5523_CMD_RUN | LP5523_ENABLE); - if (ret) - goto fail; - - ret = lp5523_set_engine_mode(engine, LP5523_CMD_RUN); -fail: - return ret; -} - -static int lp5523_mux_parse(const char *buf, u16 *mux, size_t len) -{ - int i; - u16 tmp_mux = 0; - len = len < LP5523_LEDS ? len : LP5523_LEDS; - for (i = 0; i < len; i++) { - switch (buf[i]) { - case '1': - tmp_mux |= (1 << i); - break; - case '0': - break; - case '\n': - i = len; - break; - default: - return -1; - } - } - *mux = tmp_mux; - - return 0; -} - -static void lp5523_mux_to_array(u16 led_mux, char *array) -{ - int i, pos = 0; - for (i = 0; i < LP5523_LEDS; i++) - pos += sprintf(array + pos, "%x", LED_ACTIVE(led_mux, i)); - - array[pos] = '\0'; -} - -/*--------------------------------------------------------------*/ -/* Sysfs interface */ -/*--------------------------------------------------------------*/ - -static ssize_t show_engine_leds(struct device *dev, - struct device_attribute *attr, - char *buf, int nr) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lp5523_chip *chip = i2c_get_clientdata(client); - char mux[LP5523_LEDS + 1]; - - lp5523_mux_to_array(chip->engines[nr - 1].led_mux, mux); - - return sprintf(buf, "%s\n", mux); -} - -#define show_leds(nr) \ -static ssize_t show_engine##nr##_leds(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_engine_leds(dev, attr, buf, nr); \ -} -show_leds(1) -show_leds(2) -show_leds(3) - -static ssize_t store_engine_leds(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len, int nr) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lp5523_chip *chip = i2c_get_clientdata(client); - u16 mux = 0; - - if (lp5523_mux_parse(buf, &mux, len)) - return -EINVAL; - - if (lp5523_load_mux(&chip->engines[nr - 1], mux)) - return -EINVAL; - - return len; -} - -#define store_leds(nr) \ -static ssize_t store_engine##nr##_leds(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t len) \ -{ \ - return store_engine_leds(dev, attr, buf, len, nr); \ -} -store_leds(1) -store_leds(2) -store_leds(3) - -static ssize_t lp5523_selftest(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lp5523_chip *chip = i2c_get_clientdata(client); - int i, ret, pos = 0; - int led = 0; - u8 status, adc, vdd; - - mutex_lock(&chip->lock); - - ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status); - if (ret < 0) - goto fail; - - /* Check that ext clock is really in use if requested */ - if ((chip->pdata) && (chip->pdata->clock_mode == LP5523_CLOCK_EXT)) - if ((status & LP5523_EXT_CLK_USED) == 0) - goto fail; - - /* Measure VDD (i.e. VBAT) first (channel 16 corresponds to VDD) */ - lp5523_write(chip->client, LP5523_REG_LED_TEST_CTRL, - LP5523_EN_LEDTEST | 16); - usleep_range(3000, 10000); - ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status); - if (!(status & LP5523_LEDTEST_DONE)) - usleep_range(3000, 10000); - - ret |= lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &vdd); - vdd--; /* There may be some fluctuation in measurement */ - - for (i = 0; i < LP5523_LEDS; i++) { - /* Skip non-existing channels */ - if (chip->pdata->led_config[i].led_current == 0) - continue; - - /* Set default current */ - lp5523_write(chip->client, - LP5523_REG_LED_CURRENT_BASE + i, - chip->pdata->led_config[i].led_current); - - lp5523_write(chip->client, LP5523_REG_LED_PWM_BASE + i, 0xff); - /* let current stabilize 2ms before measurements start */ - usleep_range(2000, 10000); - lp5523_write(chip->client, - LP5523_REG_LED_TEST_CTRL, - LP5523_EN_LEDTEST | i); - /* ledtest takes 2.7ms */ - usleep_range(3000, 10000); - ret = lp5523_read(chip->client, LP5523_REG_STATUS, &status); - if (!(status & LP5523_LEDTEST_DONE)) - usleep_range(3000, 10000); - ret |= lp5523_read(chip->client, LP5523_REG_LED_TEST_ADC, &adc); - - if (adc >= vdd || adc < LP5523_ADC_SHORTCIRC_LIM) - pos += sprintf(buf + pos, "LED %d FAIL\n", i); - - lp5523_write(chip->client, LP5523_REG_LED_PWM_BASE + i, 0x00); - - /* Restore current */ - lp5523_write(chip->client, - LP5523_REG_LED_CURRENT_BASE + i, - chip->leds[led].led_current); - led++; - } - if (pos == 0) - pos = sprintf(buf, "OK\n"); - goto release_lock; -fail: - pos = sprintf(buf, "FAIL\n"); - -release_lock: - mutex_unlock(&chip->lock); - - return pos; -} - -static void lp5523_set_brightness(struct led_classdev *cdev, - enum led_brightness brightness) -{ - struct lp5523_led *led = cdev_to_led(cdev); - - led->brightness = (u8)brightness; - - schedule_work(&led->brightness_work); -} - -static void lp5523_led_brightness_work(struct work_struct *work) -{ - struct lp5523_led *led = container_of(work, - struct lp5523_led, - brightness_work); - struct lp5523_chip *chip = led_to_lp5523(led); - struct i2c_client *client = chip->client; - - mutex_lock(&chip->lock); - - lp5523_write(client, LP5523_REG_LED_PWM_BASE + led->chan_nr, - led->brightness); - - mutex_unlock(&chip->lock); -} - -static int lp5523_do_store_load(struct lp5523_engine *engine, - const char *buf, size_t len) -{ - struct lp5523_chip *chip = engine_to_lp5523(engine); - struct i2c_client *client = chip->client; - int ret, nrchars, offset = 0, i = 0; - char c[3]; - unsigned cmd; - u8 pattern[LP5523_PROGRAM_LENGTH] = {0}; - - while ((offset < len - 1) && (i < LP5523_PROGRAM_LENGTH)) { - /* separate sscanfs because length is working only for %s */ - ret = sscanf(buf + offset, "%2s%n ", c, &nrchars); - ret = sscanf(c, "%2x", &cmd); - if (ret != 1) - goto fail; - pattern[i] = (u8)cmd; - - offset += nrchars; - i++; - } - - /* Each instruction is 16bit long. Check that length is even */ - if (i % 2) - goto fail; - - mutex_lock(&chip->lock); - - ret = lp5523_load_program(engine, pattern); - mutex_unlock(&chip->lock); - - if (ret) { - dev_err(&client->dev, "failed loading pattern\n"); - return ret; - } - - return len; -fail: - dev_err(&client->dev, "wrong pattern format\n"); - return -EINVAL; -} - -static ssize_t store_engine_load(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len, int nr) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lp5523_chip *chip = i2c_get_clientdata(client); - return lp5523_do_store_load(&chip->engines[nr - 1], buf, len); -} - -#define store_load(nr) \ -static ssize_t store_engine##nr##_load(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t len) \ -{ \ - return store_engine_load(dev, attr, buf, len, nr); \ -} -store_load(1) -store_load(2) -store_load(3) - -static ssize_t show_engine_mode(struct device *dev, - struct device_attribute *attr, - char *buf, int nr) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lp5523_chip *chip = i2c_get_clientdata(client); - switch (chip->engines[nr - 1].mode) { - case LP5523_CMD_RUN: - return sprintf(buf, "run\n"); - case LP5523_CMD_LOAD: - return sprintf(buf, "load\n"); - case LP5523_CMD_DISABLED: - return sprintf(buf, "disabled\n"); - default: - return sprintf(buf, "disabled\n"); - } -} - -#define show_mode(nr) \ -static ssize_t show_engine##nr##_mode(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_engine_mode(dev, attr, buf, nr); \ -} -show_mode(1) -show_mode(2) -show_mode(3) - -static ssize_t store_engine_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len, int nr) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lp5523_chip *chip = i2c_get_clientdata(client); - struct lp5523_engine *engine = &chip->engines[nr - 1]; - mutex_lock(&chip->lock); - - if (!strncmp(buf, "run", 3)) - lp5523_set_mode(engine, LP5523_CMD_RUN); - else if (!strncmp(buf, "load", 4)) - lp5523_set_mode(engine, LP5523_CMD_LOAD); - else if (!strncmp(buf, "disabled", 8)) - lp5523_set_mode(engine, LP5523_CMD_DISABLED); - - mutex_unlock(&chip->lock); - return len; -} - -#define store_mode(nr) \ -static ssize_t store_engine##nr##_mode(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t len) \ -{ \ - return store_engine_mode(dev, attr, buf, len, nr); \ -} -store_mode(1) -store_mode(2) -store_mode(3) - -static ssize_t show_max_current(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct lp5523_led *led = cdev_to_led(led_cdev); - - return sprintf(buf, "%d\n", led->max_current); -} - -static ssize_t show_current(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct lp5523_led *led = cdev_to_led(led_cdev); - - return sprintf(buf, "%d\n", led->led_current); -} - -static ssize_t store_current(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct lp5523_led *led = cdev_to_led(led_cdev); - struct lp5523_chip *chip = led_to_lp5523(led); - ssize_t ret; - unsigned long curr; - - if (strict_strtoul(buf, 0, &curr)) - return -EINVAL; - - if (curr > led->max_current) - return -EINVAL; - - mutex_lock(&chip->lock); - ret = lp5523_write(chip->client, - LP5523_REG_LED_CURRENT_BASE + led->chan_nr, - (u8)curr); - mutex_unlock(&chip->lock); - - if (ret < 0) - return ret; - - led->led_current = (u8)curr; - - return len; -} - -/* led class device attributes */ -static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current); -static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL); - -static struct attribute *lp5523_led_attributes[] = { - &dev_attr_led_current.attr, - &dev_attr_max_current.attr, - NULL, -}; - -static struct attribute_group lp5523_led_attribute_group = { - .attrs = lp5523_led_attributes -}; - -/* device attributes */ -static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO, - show_engine1_mode, store_engine1_mode); -static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO, - show_engine2_mode, store_engine2_mode); -static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO, - show_engine3_mode, store_engine3_mode); -static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUGO, - show_engine1_leds, store_engine1_leds); -static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUGO, - show_engine2_leds, store_engine2_leds); -static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUGO, - show_engine3_leds, store_engine3_leds); -static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load); -static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load); -static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load); -static DEVICE_ATTR(selftest, S_IRUGO, lp5523_selftest, NULL); - -static struct attribute *lp5523_attributes[] = { - &dev_attr_engine1_mode.attr, - &dev_attr_engine2_mode.attr, - &dev_attr_engine3_mode.attr, - &dev_attr_selftest.attr, - NULL -}; - -static struct attribute *lp5523_engine1_attributes[] = { - &dev_attr_engine1_load.attr, - &dev_attr_engine1_leds.attr, - NULL -}; - -static struct attribute *lp5523_engine2_attributes[] = { - &dev_attr_engine2_load.attr, - &dev_attr_engine2_leds.attr, - NULL -}; - -static struct attribute *lp5523_engine3_attributes[] = { - &dev_attr_engine3_load.attr, - &dev_attr_engine3_leds.attr, - NULL -}; - -static const struct attribute_group lp5523_group = { - .attrs = lp5523_attributes, -}; - -static const struct attribute_group lp5523_engine_group[] = { - {.attrs = lp5523_engine1_attributes }, - {.attrs = lp5523_engine2_attributes }, - {.attrs = lp5523_engine3_attributes }, -}; - -static int lp5523_register_sysfs(struct i2c_client *client) -{ - struct device *dev = &client->dev; - int ret; - - ret = sysfs_create_group(&dev->kobj, &lp5523_group); - if (ret < 0) - return ret; - - return 0; -} - -static void lp5523_unregister_sysfs(struct i2c_client *client) -{ - struct lp5523_chip *chip = i2c_get_clientdata(client); - struct device *dev = &client->dev; - int i; - - sysfs_remove_group(&dev->kobj, &lp5523_group); - - for (i = 0; i < ARRAY_SIZE(chip->engines); i++) - if (chip->engines[i].mode == LP5523_CMD_LOAD) - sysfs_remove_group(&dev->kobj, &lp5523_engine_group[i]); - - for (i = 0; i < chip->num_leds; i++) - sysfs_remove_group(&chip->leds[i].cdev.dev->kobj, - &lp5523_led_attribute_group); -} - -/*--------------------------------------------------------------*/ -/* Set chip operating mode */ -/*--------------------------------------------------------------*/ -static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode) -{ - /* engine to chip */ - struct lp5523_chip *chip = engine_to_lp5523(engine); - struct i2c_client *client = chip->client; - struct device *dev = &client->dev; - int ret = 0; - - /* if in that mode already do nothing, except for run */ - if (mode == engine->mode && mode != LP5523_CMD_RUN) - return 0; - - if (mode == LP5523_CMD_RUN) { - ret = lp5523_run_program(engine); - } else if (mode == LP5523_CMD_LOAD) { - lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED); - lp5523_set_engine_mode(engine, LP5523_CMD_LOAD); - - ret = sysfs_create_group(&dev->kobj, engine->attributes); - if (ret) - return ret; - } else if (mode == LP5523_CMD_DISABLED) { - lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED); - } - - /* remove load attribute from sysfs if not in load mode */ - if (engine->mode == LP5523_CMD_LOAD && mode != LP5523_CMD_LOAD) - sysfs_remove_group(&dev->kobj, engine->attributes); - - engine->mode = mode; - - return ret; -} - -/*--------------------------------------------------------------*/ -/* Probe, Attach, Remove */ -/*--------------------------------------------------------------*/ -static int __init lp5523_init_engine(struct lp5523_engine *engine, int id) -{ - if (id < 1 || id > LP5523_ENGINES) - return -1; - engine->id = id; - engine->engine_mask = LP5523_ENG_MASK_BASE >> SHIFT_MASK(id); - engine->prog_page = id - 1; - engine->mux_page = id + 2; - engine->attributes = &lp5523_engine_group[id - 1]; - - return 0; -} - -static int __init lp5523_init_led(struct lp5523_led *led, struct device *dev, - int chan, struct lp5523_platform_data *pdata) -{ - char name[32]; - int res; - - if (chan >= LP5523_LEDS) - return -EINVAL; - - if (pdata->led_config[chan].led_current) { - led->led_current = pdata->led_config[chan].led_current; - led->max_current = pdata->led_config[chan].max_current; - led->chan_nr = pdata->led_config[chan].chan_nr; - - if (led->chan_nr >= LP5523_LEDS) { - dev_err(dev, "Use channel numbers between 0 and %d\n", - LP5523_LEDS - 1); - return -EINVAL; - } - - snprintf(name, 32, "lp5523:channel%d", chan); - - led->cdev.name = name; - led->cdev.brightness_set = lp5523_set_brightness; - res = led_classdev_register(dev, &led->cdev); - if (res < 0) { - dev_err(dev, "couldn't register led on channel %d\n", - chan); - return res; - } - res = sysfs_create_group(&led->cdev.dev->kobj, - &lp5523_led_attribute_group); - if (res < 0) { - dev_err(dev, "couldn't register current attribute\n"); - led_classdev_unregister(&led->cdev); - return res; - } - } else { - led->led_current = 0; - } - return 0; -} - -static struct i2c_driver lp5523_driver; - -static int lp5523_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct lp5523_chip *chip; - struct lp5523_platform_data *pdata; - int ret, i, led; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - - i2c_set_clientdata(client, chip); - chip->client = client; - - pdata = client->dev.platform_data; - - if (!pdata) { - dev_err(&client->dev, "no platform data\n"); - ret = -EINVAL; - goto fail1; - } - - mutex_init(&chip->lock); - - chip->pdata = pdata; - - if (pdata->setup_resources) { - ret = pdata->setup_resources(); - if (ret < 0) - goto fail1; - } - - if (pdata->enable) { - pdata->enable(0); - usleep_range(1000, 10000); - pdata->enable(1); - usleep_range(1000, 10000); /* Spec says min 500us */ - } - - ret = lp5523_detect(client); - if (ret) - goto fail2; - - dev_info(&client->dev, "LP5523 Programmable led chip found\n"); - - /* Initialize engines */ - for (i = 0; i < ARRAY_SIZE(chip->engines); i++) { - ret = lp5523_init_engine(&chip->engines[i], i + 1); - if (ret) { - dev_err(&client->dev, "error initializing engine\n"); - goto fail2; - } - } - ret = lp5523_configure(client); - if (ret < 0) { - dev_err(&client->dev, "error configuring chip\n"); - goto fail2; - } - - /* Initialize leds */ - chip->num_channels = pdata->num_channels; - chip->num_leds = 0; - led = 0; - for (i = 0; i < pdata->num_channels; i++) { - /* Do not initialize channels that are not connected */ - if (pdata->led_config[i].led_current == 0) - continue; - - ret = lp5523_init_led(&chip->leds[led], &client->dev, i, pdata); - if (ret) { - dev_err(&client->dev, "error initializing leds\n"); - goto fail3; - } - chip->num_leds++; - - chip->leds[led].id = led; - /* Set LED current */ - lp5523_write(client, - LP5523_REG_LED_CURRENT_BASE + chip->leds[led].chan_nr, - chip->leds[led].led_current); - - INIT_WORK(&(chip->leds[led].brightness_work), - lp5523_led_brightness_work); - - led++; - } - - ret = lp5523_register_sysfs(client); - if (ret) { - dev_err(&client->dev, "registering sysfs failed\n"); - goto fail3; - } - return ret; -fail3: - for (i = 0; i < chip->num_leds; i++) { - led_classdev_unregister(&chip->leds[i].cdev); - cancel_work_sync(&chip->leds[i].brightness_work); - } -fail2: - if (pdata->enable) - pdata->enable(0); - if (pdata->release_resources) - pdata->release_resources(); -fail1: - kfree(chip); - return ret; -} - -static int lp5523_remove(struct i2c_client *client) -{ - struct lp5523_chip *chip = i2c_get_clientdata(client); - int i; - - lp5523_unregister_sysfs(client); - - for (i = 0; i < chip->num_leds; i++) { - led_classdev_unregister(&chip->leds[i].cdev); - cancel_work_sync(&chip->leds[i].brightness_work); - } - - if (chip->pdata->enable) - chip->pdata->enable(0); - if (chip->pdata->release_resources) - chip->pdata->release_resources(); - kfree(chip); - return 0; -} - -static const struct i2c_device_id lp5523_id[] = { - { "lp5523", 0 }, - { } -}; - -MODULE_DEVICE_TABLE(i2c, lp5523_id); - -static struct i2c_driver lp5523_driver = { - .driver = { - .name = "lp5523", - }, - .probe = lp5523_probe, - .remove = lp5523_remove, - .id_table = lp5523_id, -}; - -static int __init lp5523_init(void) -{ - int ret; - - ret = i2c_add_driver(&lp5523_driver); - - if (ret < 0) - printk(KERN_ALERT "Adding lp5523 driver failed\n"); - - return ret; -} - -static void __exit lp5523_exit(void) -{ - i2c_del_driver(&lp5523_driver); -} - -module_init(lp5523_init); -module_exit(lp5523_exit); - -MODULE_AUTHOR("Mathias Nyman "); -MODULE_DESCRIPTION("LP5523 LED engine"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/leds/ledtrig-timer.c b/trunk/drivers/leds/ledtrig-timer.c index b09bcbeade9c..82b77bd482ff 100644 --- a/trunk/drivers/leds/ledtrig-timer.c +++ b/trunk/drivers/leds/ledtrig-timer.c @@ -12,25 +12,73 @@ */ #include +#include #include #include +#include +#include #include +#include +#include #include #include +#include #include "leds.h" +struct timer_trig_data { + int brightness_on; /* LED brightness during "on" period. + * (LED_OFF < brightness_on <= LED_FULL) + */ + unsigned long delay_on; /* milliseconds on */ + unsigned long delay_off; /* milliseconds off */ + struct timer_list timer; +}; + +static void led_timer_function(unsigned long data) +{ + struct led_classdev *led_cdev = (struct led_classdev *) data; + struct timer_trig_data *timer_data = led_cdev->trigger_data; + unsigned long brightness; + unsigned long delay; + + if (!timer_data->delay_on || !timer_data->delay_off) { + led_set_brightness(led_cdev, LED_OFF); + return; + } + + brightness = led_get_brightness(led_cdev); + if (!brightness) { + /* Time to switch the LED on. */ + brightness = timer_data->brightness_on; + delay = timer_data->delay_on; + } else { + /* Store the current brightness value to be able + * to restore it when the delay_off period is over. + */ + timer_data->brightness_on = brightness; + brightness = LED_OFF; + delay = timer_data->delay_off; + } + + led_set_brightness(led_cdev, brightness); + + mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay)); +} + static ssize_t led_delay_on_show(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct timer_trig_data *timer_data = led_cdev->trigger_data; - return sprintf(buf, "%lu\n", led_cdev->blink_delay_on); + return sprintf(buf, "%lu\n", timer_data->delay_on); } static ssize_t led_delay_on_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct timer_trig_data *timer_data = led_cdev->trigger_data; int ret = -EINVAL; char *after; unsigned long state = simple_strtoul(buf, &after, 10); @@ -40,7 +88,21 @@ static ssize_t led_delay_on_store(struct device *dev, count++; if (count == size) { - led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off); + if (timer_data->delay_on != state) { + /* the new value differs from the previous */ + timer_data->delay_on = state; + + /* deactivate previous settings */ + del_timer_sync(&timer_data->timer); + + /* try to activate hardware acceleration, if any */ + if (!led_cdev->blink_set || + led_cdev->blink_set(led_cdev, + &timer_data->delay_on, &timer_data->delay_off)) { + /* no hardware acceleration, blink via timer */ + mod_timer(&timer_data->timer, jiffies + 1); + } + } ret = count; } @@ -51,14 +113,16 @@ static ssize_t led_delay_off_show(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct timer_trig_data *timer_data = led_cdev->trigger_data; - return sprintf(buf, "%lu\n", led_cdev->blink_delay_off); + return sprintf(buf, "%lu\n", timer_data->delay_off); } static ssize_t led_delay_off_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct timer_trig_data *timer_data = led_cdev->trigger_data; int ret = -EINVAL; char *after; unsigned long state = simple_strtoul(buf, &after, 10); @@ -68,7 +132,21 @@ static ssize_t led_delay_off_store(struct device *dev, count++; if (count == size) { - led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state); + if (timer_data->delay_off != state) { + /* the new value differs from the previous */ + timer_data->delay_off = state; + + /* deactivate previous settings */ + del_timer_sync(&timer_data->timer); + + /* try to activate hardware acceleration, if any */ + if (!led_cdev->blink_set || + led_cdev->blink_set(led_cdev, + &timer_data->delay_on, &timer_data->delay_off)) { + /* no hardware acceleration, blink via timer */ + mod_timer(&timer_data->timer, jiffies + 1); + } + } ret = count; } @@ -80,34 +158,60 @@ static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store); static void timer_trig_activate(struct led_classdev *led_cdev) { + struct timer_trig_data *timer_data; int rc; - led_cdev->trigger_data = NULL; + timer_data = kzalloc(sizeof(struct timer_trig_data), GFP_KERNEL); + if (!timer_data) + return; + + timer_data->brightness_on = led_get_brightness(led_cdev); + if (timer_data->brightness_on == LED_OFF) + timer_data->brightness_on = led_cdev->max_brightness; + led_cdev->trigger_data = timer_data; + + init_timer(&timer_data->timer); + timer_data->timer.function = led_timer_function; + timer_data->timer.data = (unsigned long) led_cdev; rc = device_create_file(led_cdev->dev, &dev_attr_delay_on); if (rc) - return; + goto err_out; rc = device_create_file(led_cdev->dev, &dev_attr_delay_off); if (rc) goto err_out_delayon; - led_cdev->trigger_data = (void *)1; + /* If there is hardware support for blinking, start one + * user friendly blink rate chosen by the driver. + */ + if (led_cdev->blink_set) + led_cdev->blink_set(led_cdev, + &timer_data->delay_on, &timer_data->delay_off); return; err_out_delayon: device_remove_file(led_cdev->dev, &dev_attr_delay_on); +err_out: + led_cdev->trigger_data = NULL; + kfree(timer_data); } static void timer_trig_deactivate(struct led_classdev *led_cdev) { - if (led_cdev->trigger_data) { + struct timer_trig_data *timer_data = led_cdev->trigger_data; + unsigned long on = 0, off = 0; + + if (timer_data) { device_remove_file(led_cdev->dev, &dev_attr_delay_on); device_remove_file(led_cdev->dev, &dev_attr_delay_off); + del_timer_sync(&timer_data->timer); + kfree(timer_data); } - /* Stop blinking */ - led_brightness_set(led_cdev, LED_OFF); + /* If there is hardware support for blinking, stop it */ + if (led_cdev->blink_set) + led_cdev->blink_set(led_cdev, &on, &off); } static struct led_trigger timer_led_trigger = { diff --git a/trunk/drivers/macintosh/adb-iop.c b/trunk/drivers/macintosh/adb-iop.c index f5f4da3d0b67..444696625171 100644 --- a/trunk/drivers/macintosh/adb-iop.c +++ b/trunk/drivers/macintosh/adb-iop.c @@ -80,7 +80,7 @@ static void adb_iop_end_req(struct adb_request *req, int state) static void adb_iop_complete(struct iop_msg *msg) { struct adb_request *req; - unsigned long flags; + uint flags; local_irq_save(flags); @@ -103,7 +103,7 @@ static void adb_iop_listen(struct iop_msg *msg) { struct adb_iopmsg *amsg = (struct adb_iopmsg *) msg->message; struct adb_request *req; - unsigned long flags; + uint flags; #ifdef DEBUG_ADB_IOP int i; #endif diff --git a/trunk/drivers/misc/apds9802als.c b/trunk/drivers/misc/apds9802als.c index 0ed09358027e..f9b91ba8900c 100644 --- a/trunk/drivers/misc/apds9802als.c +++ b/trunk/drivers/misc/apds9802als.c @@ -123,7 +123,7 @@ static ssize_t als_sensing_range_store(struct device *dev, { struct i2c_client *client = to_i2c_client(dev); struct als_data *data = i2c_get_clientdata(client); - int ret_val; + unsigned int ret_val; unsigned long val; if (strict_strtoul(buf, 10, &val)) diff --git a/trunk/drivers/misc/bh1770glc.c b/trunk/drivers/misc/bh1770glc.c index d79a972f2c79..cee632e645e1 100644 --- a/trunk/drivers/misc/bh1770glc.c +++ b/trunk/drivers/misc/bh1770glc.c @@ -649,7 +649,7 @@ static ssize_t bh1770_power_state_store(struct device *dev, { struct bh1770_chip *chip = dev_get_drvdata(dev); unsigned long value; - ssize_t ret; + size_t ret; if (strict_strtoul(buf, 0, &value)) return -EINVAL; @@ -659,12 +659,8 @@ static ssize_t bh1770_power_state_store(struct device *dev, pm_runtime_get_sync(dev); ret = bh1770_lux_rate(chip, chip->lux_rate_index); - if (ret < 0) { - pm_runtime_put(dev); - goto leave; - } + ret |= bh1770_lux_interrupt_control(chip, BH1770_ENABLE); - ret = bh1770_lux_interrupt_control(chip, BH1770_ENABLE); if (ret < 0) { pm_runtime_put(dev); goto leave; diff --git a/trunk/drivers/misc/isl29020.c b/trunk/drivers/misc/isl29020.c index ca47e6285075..34fe835921c4 100644 --- a/trunk/drivers/misc/isl29020.c +++ b/trunk/drivers/misc/isl29020.c @@ -87,7 +87,7 @@ static ssize_t als_sensing_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); - int ret_val; + unsigned int ret_val; unsigned long val; if (strict_strtoul(buf, 10, &val)) @@ -106,8 +106,6 @@ static ssize_t als_sensing_range_store(struct device *dev, val = 4; ret_val = i2c_smbus_read_byte_data(client, 0x00); - if (ret_val < 0) - return ret_val; ret_val &= 0xFC; /*reset the bit before setting them */ ret_val |= val - 1; diff --git a/trunk/drivers/net/wireless/rt2x00/Kconfig b/trunk/drivers/net/wireless/rt2x00/Kconfig index 4396d4b9bfb9..eea1ef2f502b 100644 --- a/trunk/drivers/net/wireless/rt2x00/Kconfig +++ b/trunk/drivers/net/wireless/rt2x00/Kconfig @@ -221,6 +221,9 @@ config RT2X00_LIB_LEDS boolean default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n) +comment "rt2x00 leds support disabled due to modularized LEDS_CLASS and built-in rt2x00" + depends on RT2X00_LIB=y && LEDS_CLASS=m + config RT2X00_LIB_DEBUGFS bool "Ralink debugfs support" depends on RT2X00_LIB && MAC80211_DEBUGFS diff --git a/trunk/drivers/rapidio/rio.c b/trunk/drivers/rapidio/rio.c index 7b5080c45569..68cf0c99138a 100644 --- a/trunk/drivers/rapidio/rio.c +++ b/trunk/drivers/rapidio/rio.c @@ -1159,11 +1159,11 @@ int __devinit rio_init_mports(void) list_for_each_entry(port, &rio_mports, node) { if (!request_mem_region(port->iores.start, - resource_size(&port->iores), + port->iores.end - port->iores.start, port->name)) { printk(KERN_ERR "RIO: Error requesting master port region 0x%016llx-0x%016llx\n", - (u64)port->iores.start, (u64)port->iores.end); + (u64)port->iores.start, (u64)port->iores.end - 1); rc = -ENOMEM; goto out; } diff --git a/trunk/drivers/video/backlight/adp8860_bl.c b/trunk/drivers/video/backlight/adp8860_bl.c index 734c650a47c4..3ec24609151e 100644 --- a/trunk/drivers/video/backlight/adp8860_bl.c +++ b/trunk/drivers/video/backlight/adp8860_bl.c @@ -502,10 +502,8 @@ static ssize_t adp8860_bl_l1_daylight_max_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct adp8860_bl *data = dev_get_drvdata(dev); - int ret = strict_strtoul(buf, 10, &data->cached_daylight_max); - if (ret) - return ret; + strict_strtoul(buf, 10, &data->cached_daylight_max); return adp8860_store(dev, buf, count, ADP8860_BLMX1); } static DEVICE_ATTR(l1_daylight_max, 0664, adp8860_bl_l1_daylight_max_show, @@ -616,7 +614,7 @@ static ssize_t adp8860_bl_ambient_light_zone_store(struct device *dev, if (val == 0) { /* Enable automatic ambient light sensing */ adp8860_set_bits(data->client, ADP8860_MDCR, CMP_AUTOEN); - } else if ((val > 0) && (val <= 3)) { + } else if ((val > 0) && (val < 6)) { /* Disable automatic ambient light sensing */ adp8860_clr_bits(data->client, ADP8860_MDCR, CMP_AUTOEN); @@ -624,7 +622,7 @@ static ssize_t adp8860_bl_ambient_light_zone_store(struct device *dev, mutex_lock(&data->lock); adp8860_read(data->client, ADP8860_CFGR, ®_val); reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT); - reg_val |= (val - 1) << CFGR_BLV_SHIFT; + reg_val |= val << CFGR_BLV_SHIFT; adp8860_write(data->client, ADP8860_CFGR, reg_val); mutex_unlock(&data->lock); } diff --git a/trunk/drivers/video/backlight/l4f00242t03.c b/trunk/drivers/video/backlight/l4f00242t03.c index c67801e57aaf..9093ef0fa869 100644 --- a/trunk/drivers/video/backlight/l4f00242t03.c +++ b/trunk/drivers/video/backlight/l4f00242t03.c @@ -78,7 +78,7 @@ static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power) const u16 slpin = 0x10; const u16 disoff = 0x28; - if (power <= FB_BLANK_NORMAL) { + if (power) { if (priv->lcd_on) return 0; diff --git a/trunk/drivers/video/backlight/lms283gf05.c b/trunk/drivers/video/backlight/lms283gf05.c index 5d3cf33953ac..abc43a0eb97d 100644 --- a/trunk/drivers/video/backlight/lms283gf05.c +++ b/trunk/drivers/video/backlight/lms283gf05.c @@ -129,7 +129,7 @@ static int lms283gf05_power_set(struct lcd_device *ld, int power) struct spi_device *spi = st->spi; struct lms283gf05_pdata *pdata = spi->dev.platform_data; - if (power <= FB_BLANK_NORMAL) { + if (power) { if (pdata) lms283gf05_reset(pdata->reset_gpio, pdata->reset_inverted); diff --git a/trunk/drivers/video/backlight/mbp_nvidia_bl.c b/trunk/drivers/video/backlight/mbp_nvidia_bl.c index 1485f7345f49..9fb533f6373e 100644 --- a/trunk/drivers/video/backlight/mbp_nvidia_bl.c +++ b/trunk/drivers/video/backlight/mbp_nvidia_bl.c @@ -335,24 +335,6 @@ static const struct dmi_system_id __initdata mbp_device_table[] = { }, .driver_data = (void *)&nvidia_chipset_data, }, - { - .callback = mbp_dmi_match, - .ident = "MacBookAir 3,1", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3,1"), - }, - .driver_data = (void *)&nvidia_chipset_data, - }, - { - .callback = mbp_dmi_match, - .ident = "MacBookAir 3,2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3,2"), - }, - .driver_data = (void *)&nvidia_chipset_data, - }, { } }; diff --git a/trunk/drivers/video/backlight/pwm_bl.c b/trunk/drivers/video/backlight/pwm_bl.c index 21866ec69656..550443518891 100644 --- a/trunk/drivers/video/backlight/pwm_bl.c +++ b/trunk/drivers/video/backlight/pwm_bl.c @@ -25,7 +25,6 @@ struct pwm_bl_data { struct pwm_device *pwm; struct device *dev; unsigned int period; - unsigned int lth_brightness; int (*notify)(struct device *, int brightness); }; @@ -49,9 +48,7 @@ static int pwm_backlight_update_status(struct backlight_device *bl) pwm_config(pb->pwm, 0, pb->period); pwm_disable(pb->pwm); } else { - brightness = pb->lth_brightness + - (brightness * (pb->period - pb->lth_brightness) / max); - pwm_config(pb->pwm, brightness, pb->period); + pwm_config(pb->pwm, brightness * pb->period / max, pb->period); pwm_enable(pb->pwm); } return 0; @@ -95,8 +92,6 @@ static int pwm_backlight_probe(struct platform_device *pdev) pb->period = data->pwm_period_ns; pb->notify = data->notify; - pb->lth_brightness = data->lth_brightness * - (data->pwm_period_ns / data->max_brightness); pb->dev = &pdev->dev; pb->pwm = pwm_request(data->pwm_id, "backlight"); diff --git a/trunk/drivers/video/backlight/s6e63m0.c b/trunk/drivers/video/backlight/s6e63m0.c index 5927db0da999..a3128c9cb7ad 100644 --- a/trunk/drivers/video/backlight/s6e63m0.c +++ b/trunk/drivers/video/backlight/s6e63m0.c @@ -729,10 +729,10 @@ static ssize_t s6e63m0_sysfs_show_gamma_table(struct device *dev, return strlen(buf); } -static DEVICE_ATTR(gamma_table, 0444, +static DEVICE_ATTR(gamma_table, 0644, s6e63m0_sysfs_show_gamma_table, NULL); -static int __devinit s6e63m0_probe(struct spi_device *spi) +static int __init s6e63m0_probe(struct spi_device *spi) { int ret = 0; struct s6e63m0 *lcd = NULL; @@ -829,9 +829,6 @@ static int __devexit s6e63m0_remove(struct spi_device *spi) struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); s6e63m0_power(lcd, FB_BLANK_POWERDOWN); - device_remove_file(&spi->dev, &dev_attr_gamma_table); - device_remove_file(&spi->dev, &dev_attr_gamma_mode); - backlight_device_unregister(lcd->bd); lcd_device_unregister(lcd->ld); kfree(lcd); diff --git a/trunk/fs/hugetlbfs/inode.c b/trunk/fs/hugetlbfs/inode.c index a5fe68189eed..d6cfac1f0a40 100644 --- a/trunk/fs/hugetlbfs/inode.c +++ b/trunk/fs/hugetlbfs/inode.c @@ -932,7 +932,8 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag, if (creat_flags == HUGETLB_SHMFS_INODE && !can_do_hugetlb_shm()) { *user = current_user(); if (user_shm_lock(size, *user)) { - printk_once(KERN_WARNING "Using mlock ulimits for SHM_HUGETLB is deprecated\n"); + WARN_ONCE(1, + "Using mlock ulimits for SHM_HUGETLB deprecated\n"); } else { *user = NULL; return ERR_PTR(-EPERM); diff --git a/trunk/fs/locks.c b/trunk/fs/locks.c index 0e62dd35d088..65765cb6afed 100644 --- a/trunk/fs/locks.c +++ b/trunk/fs/locks.c @@ -1504,8 +1504,9 @@ static int do_fcntl_delete_lease(struct file *filp) static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) { - struct file_lock *fl, *ret; + struct file_lock *fl; struct fasync_struct *new; + struct inode *inode = filp->f_path.dentry->d_inode; int error; fl = lease_alloc(filp, arg); @@ -1517,16 +1518,13 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) locks_free_lock(fl); return -ENOMEM; } - ret = fl; lock_flocks(); - error = __vfs_setlease(filp, arg, &ret); + error = __vfs_setlease(filp, arg, &fl); if (error) { unlock_flocks(); locks_free_lock(fl); goto out_free_fasync; } - if (ret != fl) - locks_free_lock(fl); /* * fasync_insert_entry() returns the old entry if any. @@ -1534,10 +1532,17 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg) * inserted it into the fasync list. Clear new so that * we don't release it here. */ - if (!fasync_insert_entry(fd, filp, &ret->fl_fasync, new)) + if (!fasync_insert_entry(fd, filp, &fl->fl_fasync, new)) new = NULL; - error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); + if (error < 0) { + /* remove lease just inserted by setlease */ + fl->fl_type = F_UNLCK | F_INPROGRESS; + fl->fl_break_time = jiffies - 10; + time_out_leases(inode); + } else { + error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); + } unlock_flocks(); out_free_fasync: diff --git a/trunk/fs/nfsd/nfs4state.c b/trunk/fs/nfsd/nfs4state.c index ad2bfa68d534..f1e5ec6b5105 100644 --- a/trunk/fs/nfsd/nfs4state.c +++ b/trunk/fs/nfsd/nfs4state.c @@ -673,17 +673,16 @@ static void nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses) spin_unlock(&clp->cl_lock); } -static int nfsd4_register_conn(struct nfsd4_conn *conn) +static void nfsd4_register_conn(struct nfsd4_conn *conn) { conn->cn_xpt_user.callback = nfsd4_conn_lost; - return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); + register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); } static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) { struct nfsd4_conn *conn; u32 flags = NFS4_CDFC4_FORE; - int ret; if (ses->se_flags & SESSION4_BACK_CHAN) flags |= NFS4_CDFC4_BACK; @@ -691,10 +690,7 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) if (!conn) return nfserr_jukebox; nfsd4_hash_conn(conn, ses); - ret = nfsd4_register_conn(conn); - if (ret) - /* oops; xprt is already down: */ - nfsd4_conn_lost(&conn->cn_xpt_user); + nfsd4_register_conn(conn); return nfs_ok; } @@ -1648,7 +1644,6 @@ static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_sessi { struct nfs4_client *clp = ses->se_client; struct nfsd4_conn *c; - int ret; spin_lock(&clp->cl_lock); c = __nfsd4_find_conn(new->cn_xprt, ses); @@ -1659,10 +1654,7 @@ static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_sessi } __nfsd4_hash_conn(new, ses); spin_unlock(&clp->cl_lock); - ret = nfsd4_register_conn(new); - if (ret) - /* oops; xprt is already down: */ - nfsd4_conn_lost(&new->cn_xpt_user); + nfsd4_register_conn(new); return; } diff --git a/trunk/fs/xfs/linux-2.6/xfs_aops.c b/trunk/fs/xfs/linux-2.6/xfs_aops.c index 7d287afccde5..c9af48fffcd7 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_aops.c +++ b/trunk/fs/xfs/linux-2.6/xfs_aops.c @@ -1111,12 +1111,11 @@ xfs_vm_writepage( uptodate = 0; /* - * set_page_dirty dirties all buffers in a page, independent - * of their state. The dirty state however is entirely - * meaningless for holes (!mapped && uptodate), so skip - * buffers covering holes here. + * A hole may still be marked uptodate because discard_buffer + * leaves the flag set. */ if (!buffer_mapped(bh) && buffer_uptodate(bh)) { + ASSERT(!buffer_dirty(bh)); imap_valid = 0; continue; } diff --git a/trunk/fs/xfs/linux-2.6/xfs_buf.c b/trunk/fs/xfs/linux-2.6/xfs_buf.c index aa1d353def29..63fd2c07cb57 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_buf.c +++ b/trunk/fs/xfs/linux-2.6/xfs_buf.c @@ -1781,6 +1781,7 @@ xfs_buf_delwri_split( INIT_LIST_HEAD(list); spin_lock(dwlk); list_for_each_entry_safe(bp, n, dwq, b_list) { + trace_xfs_buf_delwri_split(bp, _RET_IP_); ASSERT(bp->b_flags & XBF_DELWRI); if (!XFS_BUF_ISPINNED(bp) && !xfs_buf_cond_lock(bp)) { @@ -1794,7 +1795,6 @@ xfs_buf_delwri_split( _XBF_RUN_QUEUES); bp->b_flags |= XBF_WRITE; list_move_tail(&bp->b_list, list); - trace_xfs_buf_delwri_split(bp, _RET_IP_); } else skipped++; } diff --git a/trunk/fs/xfs/linux-2.6/xfs_ioctl.c b/trunk/fs/xfs/linux-2.6/xfs_ioctl.c index ad442d9e392e..2ea238f6d38e 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/trunk/fs/xfs/linux-2.6/xfs_ioctl.c @@ -416,7 +416,7 @@ xfs_attrlist_by_handle( if (IS_ERR(dentry)) return PTR_ERR(dentry); - kbuf = kzalloc(al_hreq.buflen, GFP_KERNEL); + kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL); if (!kbuf) goto out_dput; diff --git a/trunk/fs/xfs/linux-2.6/xfs_iops.c b/trunk/fs/xfs/linux-2.6/xfs_iops.c index 94d5fd6a2973..96107efc0c61 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_iops.c +++ b/trunk/fs/xfs/linux-2.6/xfs_iops.c @@ -762,8 +762,7 @@ xfs_setup_inode( inode->i_state = I_NEW; inode_sb_list_add(inode); - /* make the inode look hashed for the writeback code */ - hlist_add_fake(&inode->i_hash); + insert_inode_hash(inode); inode->i_mode = ip->i_d.di_mode; inode->i_nlink = ip->i_d.di_nlink; diff --git a/trunk/fs/xfs/linux-2.6/xfs_super.c b/trunk/fs/xfs/linux-2.6/xfs_super.c index 064f964d4f3c..9f3a78fe6ae4 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_super.c +++ b/trunk/fs/xfs/linux-2.6/xfs_super.c @@ -353,6 +353,9 @@ xfs_parseargs( mp->m_qflags &= ~XFS_OQUOTA_ENFD; } else if (!strcmp(this_char, MNTOPT_DELAYLOG)) { mp->m_flags |= XFS_MOUNT_DELAYLOG; + cmn_err(CE_WARN, + "Enabling EXPERIMENTAL delayed logging feature " + "- use at your own risk.\n"); } else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) { mp->m_flags &= ~XFS_MOUNT_DELAYLOG; } else if (!strcmp(this_char, "ihashsize")) { diff --git a/trunk/fs/xfs/linux-2.6/xfs_sync.c b/trunk/fs/xfs/linux-2.6/xfs_sync.c index afb0d7cfad1c..37d33254981d 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_sync.c +++ b/trunk/fs/xfs/linux-2.6/xfs_sync.c @@ -853,7 +853,6 @@ xfs_reclaim_inodes_ag( if (trylock) { if (!mutex_trylock(&pag->pag_ici_reclaim_lock)) { skipped++; - xfs_perag_put(pag); continue; } first_index = pag->pag_ici_reclaim_cursor; diff --git a/trunk/fs/xfs/xfs_filestream.c b/trunk/fs/xfs/xfs_filestream.c index 9124425b7f2f..9b715dce5699 100644 --- a/trunk/fs/xfs/xfs_filestream.c +++ b/trunk/fs/xfs/xfs_filestream.c @@ -744,15 +744,9 @@ xfs_filestream_new_ag( * If the file's parent directory is known, take its iolock in exclusive * mode to prevent two sibling files from racing each other to migrate * themselves and their parent to different AGs. - * - * Note that we lock the parent directory iolock inside the child - * iolock here. That's fine as we never hold both parent and child - * iolock in any other place. This is different from the ilock, - * which requires locking of the child after the parent for namespace - * operations. */ if (pip) - xfs_ilock(pip, XFS_IOLOCK_EXCL | XFS_IOLOCK_PARENT); + xfs_ilock(pip, XFS_IOLOCK_EXCL); /* * A new AG needs to be found for the file. If the file's parent diff --git a/trunk/fs/xfs/xfs_mount.c b/trunk/fs/xfs/xfs_mount.c index 19e9dfa1c254..b1498ab5a399 100644 --- a/trunk/fs/xfs/xfs_mount.c +++ b/trunk/fs/xfs/xfs_mount.c @@ -275,7 +275,6 @@ xfs_free_perag( pag = radix_tree_delete(&mp->m_perag_tree, agno); spin_unlock(&mp->m_perag_lock); ASSERT(pag); - ASSERT(atomic_read(&pag->pag_ref) == 0); call_rcu(&pag->rcu_head, __xfs_free_perag); } } diff --git a/trunk/fs/xfs/xfs_quota.h b/trunk/fs/xfs/xfs_quota.h index 9bb6eda4cd21..e0e64b113bd6 100644 --- a/trunk/fs/xfs/xfs_quota.h +++ b/trunk/fs/xfs/xfs_quota.h @@ -346,17 +346,8 @@ xfs_qm_vop_dqalloc(struct xfs_inode *ip, uid_t uid, gid_t gid, prid_t prid, #define xfs_trans_mod_dquot_byino(tp, ip, fields, delta) #define xfs_trans_apply_dquot_deltas(tp) #define xfs_trans_unreserve_and_mod_dquots(tp) -static inline int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp, - struct xfs_inode *ip, long nblks, long ninos, uint flags) -{ - return 0; -} -static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp, - struct xfs_mount *mp, struct xfs_dquot *udqp, - struct xfs_dquot *gdqp, long nblks, long nions, uint flags) -{ - return 0; -} +#define xfs_trans_reserve_quota_nblks(tp, ip, nblks, ninos, flags) (0) +#define xfs_trans_reserve_quota_bydquots(tp, mp, u, g, nb, ni, fl) (0) #define xfs_qm_vop_create_dqattach(tp, ip, u, g) #define xfs_qm_vop_rename_dqattach(it) (0) #define xfs_qm_vop_chown(tp, ip, old, new) (NULL) @@ -366,14 +357,11 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp, #define xfs_qm_dqdetach(ip) #define xfs_qm_dqrele(d) #define xfs_qm_statvfs(ip, s) -static inline int xfs_qm_sync(struct xfs_mount *mp, int flags) -{ - return 0; -} +#define xfs_qm_sync(mp, fl) (0) #define xfs_qm_newmount(mp, a, b) (0) #define xfs_qm_mount_quotas(mp) #define xfs_qm_unmount(mp) -#define xfs_qm_unmount_quotas(mp) +#define xfs_qm_unmount_quotas(mp) (0) #endif /* CONFIG_XFS_QUOTA */ #define xfs_trans_unreserve_quota_nblks(tp, ip, nblks, ninos, flags) \ diff --git a/trunk/include/drm/ttm/ttm_bo_api.h b/trunk/include/drm/ttm/ttm_bo_api.h index beafc156a535..5afa5b52063e 100644 --- a/trunk/include/drm/ttm/ttm_bo_api.h +++ b/trunk/include/drm/ttm/ttm_bo_api.h @@ -432,10 +432,6 @@ extern void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo); * together with the @destroy function, * enables driver-specific objects derived from a ttm_buffer_object. * On successful return, the object kref and list_kref are set to 1. - * If a failure occurs, the function will call the @destroy function, or - * kfree() if @destroy is NULL. Thus, after a failure, dereferencing @bo is - * illegal and will likely cause memory corruption. - * * Returns * -ENOMEM: Out of memory. * -EINVAL: Invalid placement flags. diff --git a/trunk/include/drm/ttm/ttm_bo_driver.h b/trunk/include/drm/ttm/ttm_bo_driver.h index 8e0c848326b6..d01b4ddbdc56 100644 --- a/trunk/include/drm/ttm/ttm_bo_driver.h +++ b/trunk/include/drm/ttm/ttm_bo_driver.h @@ -206,84 +206,14 @@ struct ttm_tt { struct ttm_mem_type_manager; struct ttm_mem_type_manager_func { - /** - * struct ttm_mem_type_manager member init - * - * @man: Pointer to a memory type manager. - * @p_size: Implementation dependent, but typically the size of the - * range to be managed in pages. - * - * Called to initialize a private range manager. The function is - * expected to initialize the man::priv member. - * Returns 0 on success, negative error code on failure. - */ int (*init)(struct ttm_mem_type_manager *man, unsigned long p_size); - - /** - * struct ttm_mem_type_manager member takedown - * - * @man: Pointer to a memory type manager. - * - * Called to undo the setup done in init. All allocated resources - * should be freed. - */ int (*takedown)(struct ttm_mem_type_manager *man); - - /** - * struct ttm_mem_type_manager member get_node - * - * @man: Pointer to a memory type manager. - * @bo: Pointer to the buffer object we're allocating space for. - * @placement: Placement details. - * @mem: Pointer to a struct ttm_mem_reg to be filled in. - * - * This function should allocate space in the memory type managed - * by @man. Placement details if - * applicable are given by @placement. If successful, - * @mem::mm_node should be set to a non-null value, and - * @mem::start should be set to a value identifying the beginning - * of the range allocated, and the function should return zero. - * If the memory region accomodate the buffer object, @mem::mm_node - * should be set to NULL, and the function should return 0. - * If a system error occured, preventing the request to be fulfilled, - * the function should return a negative error code. - * - * Note that @mem::mm_node will only be dereferenced by - * struct ttm_mem_type_manager functions and optionally by the driver, - * which has knowledge of the underlying type. - * - * This function may not be called from within atomic context, so - * an implementation can and must use either a mutex or a spinlock to - * protect any data structures managing the space. - */ int (*get_node)(struct ttm_mem_type_manager *man, struct ttm_buffer_object *bo, struct ttm_placement *placement, struct ttm_mem_reg *mem); - - /** - * struct ttm_mem_type_manager member put_node - * - * @man: Pointer to a memory type manager. - * @mem: Pointer to a struct ttm_mem_reg to be filled in. - * - * This function frees memory type resources previously allocated - * and that are identified by @mem::mm_node and @mem::start. May not - * be called from within atomic context. - */ void (*put_node)(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem); - - /** - * struct ttm_mem_type_manager member debug - * - * @man: Pointer to a memory type manager. - * @prefix: Prefix to be used in printout to identify the caller. - * - * This function is called to print out the state of the memory - * type manager to aid debugging of out-of-memory conditions. - * It may not be called from within atomic context. - */ void (*debug)(struct ttm_mem_type_manager *man, const char *prefix); }; @@ -301,13 +231,14 @@ struct ttm_mem_type_manager { uint64_t size; uint32_t available_caching; uint32_t default_caching; - const struct ttm_mem_type_manager_func *func; - void *priv; /* - * Protected by the global->lru_lock. + * Protected by the bdev->lru_lock. + * TODO: Consider one lru_lock per ttm_mem_type_manager. + * Plays ill with list removal, though. */ - + const struct ttm_mem_type_manager_func *func; + void *priv; struct list_head lru; }; diff --git a/trunk/include/linux/atomic.h b/trunk/include/linux/atomic.h deleted file mode 100644 index 96c038e43d66..000000000000 --- a/trunk/include/linux/atomic.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _LINUX_ATOMIC_H -#define _LINUX_ATOMIC_H -#include - -/** - * atomic_inc_not_zero_hint - increment if not null - * @v: pointer of type atomic_t - * @hint: probable value of the atomic before the increment - * - * This version of atomic_inc_not_zero() gives a hint of probable - * value of the atomic. This helps processor to not read the memory - * before doing the atomic read/modify/write cycle, lowering - * number of bus transactions on some arches. - * - * Returns: 0 if increment was not done, 1 otherwise. - */ -#ifndef atomic_inc_not_zero_hint -static inline int atomic_inc_not_zero_hint(atomic_t *v, int hint) -{ - int val, c = hint; - - /* sanity test, should be removed by compiler if hint is a constant */ - if (!hint) - return atomic_inc_not_zero(v); - - do { - val = atomic_cmpxchg(v, c, c + 1); - if (val == c) - return 1; - c = val; - } while (c); - - return 0; -} -#endif - -#endif /* _LINUX_ATOMIC_H */ diff --git a/trunk/include/linux/highmem.h b/trunk/include/linux/highmem.h index b676c585574e..e9138198e823 100644 --- a/trunk/include/linux/highmem.h +++ b/trunk/include/linux/highmem.h @@ -5,7 +5,6 @@ #include #include #include -#include #include diff --git a/trunk/include/linux/kernel.h b/trunk/include/linux/kernel.h index fc3da9e4da19..b526947bdf48 100644 --- a/trunk/include/linux/kernel.h +++ b/trunk/include/linux/kernel.h @@ -293,7 +293,6 @@ extern bool printk_timed_ratelimit(unsigned long *caller_jiffies, unsigned int interval_msec); extern int printk_delay_msec; -extern int dmesg_restrict; /* * Print a one-time message (analogous to WARN_ONCE() et al): diff --git a/trunk/include/linux/leds-lp5521.h b/trunk/include/linux/leds-lp5521.h deleted file mode 100644 index 38368d785f08..000000000000 --- a/trunk/include/linux/leds-lp5521.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * LP5521 LED chip driver. - * - * Copyright (C) 2010 Nokia Corporation - * - * Contact: Samu Onkalo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#ifndef __LINUX_LP5521_H -#define __LINUX_LP5521_H - -/* See Documentation/leds/leds-lp5521.txt */ - -struct lp5521_led_config { - u8 chan_nr; - u8 led_current; /* mA x10, 0 if led is not connected */ - u8 max_current; -}; - -#define LP5521_CLOCK_AUTO 0 -#define LP5521_CLOCK_INT 1 -#define LP5521_CLOCK_EXT 2 - -struct lp5521_platform_data { - struct lp5521_led_config *led_config; - u8 num_channels; - u8 clock_mode; - int (*setup_resources)(void); - void (*release_resources)(void); - void (*enable)(bool state); -}; - -#endif /* __LINUX_LP5521_H */ diff --git a/trunk/include/linux/leds-lp5523.h b/trunk/include/linux/leds-lp5523.h deleted file mode 100644 index 796747637b80..000000000000 --- a/trunk/include/linux/leds-lp5523.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * LP5523 LED Driver - * - * Copyright (C) 2010 Nokia Corporation - * - * Contact: Samu Onkalo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#ifndef __LINUX_LP5523_H -#define __LINUX_LP5523_H - -/* See Documentation/leds/leds-lp5523.txt */ - -struct lp5523_led_config { - u8 chan_nr; - u8 led_current; /* mA x10, 0 if led is not connected */ - u8 max_current; -}; - -#define LP5523_CLOCK_AUTO 0 -#define LP5523_CLOCK_INT 1 -#define LP5523_CLOCK_EXT 2 - -struct lp5523_platform_data { - struct lp5523_led_config *led_config; - u8 num_channels; - u8 clock_mode; - int (*setup_resources)(void); - void (*release_resources)(void); - void (*enable)(bool state); -}; - -#endif /* __LINUX_LP5523_H */ diff --git a/trunk/include/linux/leds.h b/trunk/include/linux/leds.h index 0f19df9e37b0..ba6986a11663 100644 --- a/trunk/include/linux/leds.h +++ b/trunk/include/linux/leds.h @@ -15,7 +15,6 @@ #include #include #include -#include struct device; /* @@ -46,14 +45,10 @@ struct led_classdev { /* Get LED brightness level */ enum led_brightness (*brightness_get)(struct led_classdev *led_cdev); - /* - * Activate hardware accelerated blink, delays are in milliseconds - * and if both are zero then a sensible default should be chosen. - * The call should adjust the timings in that case and if it can't - * match the values specified exactly. - * Deactivate blinking again when the brightness is set to a fixed - * value via the brightness_set() callback. - */ + /* Activate hardware accelerated blink, delays are in + * miliseconds and if none is provided then a sensible default + * should be chosen. The call can adjust the timings if it can't + * match the values specified exactly. */ int (*blink_set)(struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off); @@ -62,10 +57,6 @@ struct led_classdev { struct list_head node; /* LED Device list */ const char *default_trigger; /* Trigger to use */ - unsigned long blink_delay_on, blink_delay_off; - struct timer_list blink_timer; - int blink_brightness; - #ifdef CONFIG_LEDS_TRIGGERS /* Protects the trigger data below */ struct rw_semaphore trigger_lock; @@ -82,36 +73,6 @@ extern void led_classdev_unregister(struct led_classdev *led_cdev); extern void led_classdev_suspend(struct led_classdev *led_cdev); extern void led_classdev_resume(struct led_classdev *led_cdev); -/** - * led_blink_set - set blinking with software fallback - * @led_cdev: the LED to start blinking - * @delay_on: the time it should be on (in ms) - * @delay_off: the time it should ble off (in ms) - * - * This function makes the LED blink, attempting to use the - * hardware acceleration if possible, but falling back to - * software blinking if there is no hardware blinking or if - * the LED refuses the passed values. - * - * Note that if software blinking is active, simply calling - * led_cdev->brightness_set() will not stop the blinking, - * use led_classdev_brightness_set() instead. - */ -extern void led_blink_set(struct led_classdev *led_cdev, - unsigned long *delay_on, - unsigned long *delay_off); -/** - * led_brightness_set - set LED brightness - * @led_cdev: the LED to set - * @brightness: the brightness to set it to - * - * Set an LED's brightness, and, if necessary, cancel the - * software blink timer that implements blinking when the - * hardware doesn't. - */ -extern void led_brightness_set(struct led_classdev *led_cdev, - enum led_brightness brightness); - /* * LED Triggers */ diff --git a/trunk/include/linux/pwm_backlight.h b/trunk/include/linux/pwm_backlight.h index e031e1a486d9..01b3d759f1fc 100644 --- a/trunk/include/linux/pwm_backlight.h +++ b/trunk/include/linux/pwm_backlight.h @@ -8,7 +8,6 @@ struct platform_pwm_backlight_data { int pwm_id; unsigned int max_brightness; unsigned int dft_brightness; - unsigned int lth_brightness; unsigned int pwm_period_ns; int (*init)(struct device *dev); int (*notify)(struct device *dev, int brightness); diff --git a/trunk/include/linux/radix-tree.h b/trunk/include/linux/radix-tree.h index ab2baa5c4884..a39cbed9ee17 100644 --- a/trunk/include/linux/radix-tree.h +++ b/trunk/include/linux/radix-tree.h @@ -34,13 +34,19 @@ * needed for RCU lookups (because root->height is unreliable). The only * time callers need worry about this is when doing a lookup_slot under * RCU. - * - * Indirect pointer in fact is also used to tag the last pointer of a node - * when it is shrunk, before we rcu free the node. See shrink code for - * details. */ #define RADIX_TREE_INDIRECT_PTR 1 +#define RADIX_TREE_RETRY ((void *)-1UL) + +static inline void *radix_tree_ptr_to_indirect(void *ptr) +{ + return (void *)((unsigned long)ptr | RADIX_TREE_INDIRECT_PTR); +} +static inline void *radix_tree_indirect_to_ptr(void *ptr) +{ + return (void *)((unsigned long)ptr & ~RADIX_TREE_INDIRECT_PTR); +} #define radix_tree_indirect_to_ptr(ptr) \ radix_tree_indirect_to_ptr((void __force *)(ptr)) @@ -134,29 +140,16 @@ do { \ * removed. * * For use with radix_tree_lookup_slot(). Caller must hold tree at least read - * locked across slot lookup and dereference. Not required if write lock is - * held (ie. items cannot be concurrently inserted). - * - * radix_tree_deref_retry must be used to confirm validity of the pointer if - * only the read lock is held. + * locked across slot lookup and dereference. More likely, will be used with + * radix_tree_replace_slot(), as well, so caller will hold tree write locked. */ static inline void *radix_tree_deref_slot(void **pslot) { - return rcu_dereference(*pslot); + void *ret = rcu_dereference(*pslot); + if (unlikely(radix_tree_is_indirect_ptr(ret))) + ret = RADIX_TREE_RETRY; + return ret; } - -/** - * radix_tree_deref_retry - check radix_tree_deref_slot - * @arg: pointer returned by radix_tree_deref_slot - * Returns: 0 if retry is not required, otherwise retry is required - * - * radix_tree_deref_retry must be used with radix_tree_deref_slot. - */ -static inline int radix_tree_deref_retry(void *arg) -{ - return unlikely((unsigned long)arg & RADIX_TREE_INDIRECT_PTR); -} - /** * radix_tree_replace_slot - replace item in a slot * @pslot: pointer to slot, returned by radix_tree_lookup_slot diff --git a/trunk/include/linux/resource.h b/trunk/include/linux/resource.h index d01c96c1966e..88d36f9145ba 100644 --- a/trunk/include/linux/resource.h +++ b/trunk/include/linux/resource.h @@ -2,7 +2,6 @@ #define _LINUX_RESOURCE_H #include -#include /* * Resource control/accounting header file for linux diff --git a/trunk/include/linux/sunrpc/svc_xprt.h b/trunk/include/linux/sunrpc/svc_xprt.h index aea0d438e3c7..bbdb680ffbe9 100644 --- a/trunk/include/linux/sunrpc/svc_xprt.h +++ b/trunk/include/linux/sunrpc/svc_xprt.h @@ -82,28 +82,18 @@ struct svc_xprt { struct net *xpt_net; }; -static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u) +static inline void register_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u) { spin_lock(&xpt->xpt_lock); - list_del_init(&u->list); + list_add(&u->list, &xpt->xpt_users); spin_unlock(&xpt->xpt_lock); } -static inline int register_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u) +static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u) { spin_lock(&xpt->xpt_lock); - if (test_bit(XPT_CLOSE, &xpt->xpt_flags)) { - /* - * The connection is about to be deleted soon (or, - * worse, may already be deleted--in which case we've - * already notified the xpt_users). - */ - spin_unlock(&xpt->xpt_lock); - return -ENOTCONN; - } - list_add(&u->list, &xpt->xpt_users); + list_del_init(&u->list); spin_unlock(&xpt->xpt_lock); - return 0; } int svc_reg_xprt_class(struct svc_xprt_class *); diff --git a/trunk/kernel/latencytop.c b/trunk/kernel/latencytop.c index 17110a4a4fc2..877fb306d415 100644 --- a/trunk/kernel/latencytop.c +++ b/trunk/kernel/latencytop.c @@ -194,7 +194,14 @@ __account_scheduler_latency(struct task_struct *tsk, int usecs, int inter) account_global_scheduler_latency(tsk, &lat); - for (i = 0; i < tsk->latency_record_count; i++) { + /* + * short term hack; if we're > 32 we stop; future we recycle: + */ + tsk->latency_record_count++; + if (tsk->latency_record_count >= LT_SAVECOUNT) + goto out_unlock; + + for (i = 0; i < LT_SAVECOUNT; i++) { struct latency_record *mylat; int same = 1; @@ -220,14 +227,8 @@ __account_scheduler_latency(struct task_struct *tsk, int usecs, int inter) } } - /* - * short term hack; if we're > 32 we stop; future we recycle: - */ - if (tsk->latency_record_count >= LT_SAVECOUNT) - goto out_unlock; - /* Allocated a new one: */ - i = tsk->latency_record_count++; + i = tsk->latency_record_count; memcpy(&tsk->latency_record[i], &lat, sizeof(struct latency_record)); out_unlock: diff --git a/trunk/kernel/printk.c b/trunk/kernel/printk.c index 38e7d5868d60..b2ebaee8c377 100644 --- a/trunk/kernel/printk.c +++ b/trunk/kernel/printk.c @@ -261,12 +261,6 @@ static inline void boot_delay_msec(void) } #endif -#ifdef CONFIG_SECURITY_DMESG_RESTRICT -int dmesg_restrict = 1; -#else -int dmesg_restrict; -#endif - int do_syslog(int type, char __user *buf, int len, bool from_file) { unsigned i, j, limit, count; diff --git a/trunk/kernel/range.c b/trunk/kernel/range.c index 37fa9b99ad58..471b66acabb5 100644 --- a/trunk/kernel/range.c +++ b/trunk/kernel/range.c @@ -119,7 +119,7 @@ static int cmp_range(const void *x1, const void *x2) int clean_sort_range(struct range *range, int az) { - int i, j, k = az - 1, nr_range = az; + int i, j, k = az - 1, nr_range = 0; for (i = 0; i < k; i++) { if (range[i].end) diff --git a/trunk/kernel/sysctl.c b/trunk/kernel/sysctl.c index b65bf634035e..c33a1edb799f 100644 --- a/trunk/kernel/sysctl.c +++ b/trunk/kernel/sysctl.c @@ -703,15 +703,6 @@ static struct ctl_table kern_table[] = { .extra2 = &ten_thousand, }, #endif - { - .procname = "dmesg_restrict", - .data = &dmesg_restrict, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec_minmax, - .extra1 = &zero, - .extra2 = &one, - }, { .procname = "ngroups_max", .data = &ngroups_max, diff --git a/trunk/lib/radix-tree.c b/trunk/lib/radix-tree.c index 5086bb962b4d..6f412ab4c24f 100644 --- a/trunk/lib/radix-tree.c +++ b/trunk/lib/radix-tree.c @@ -82,16 +82,6 @@ struct radix_tree_preload { }; static DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 0, }; -static inline void *ptr_to_indirect(void *ptr) -{ - return (void *)((unsigned long)ptr | RADIX_TREE_INDIRECT_PTR); -} - -static inline void *indirect_to_ptr(void *ptr) -{ - return (void *)((unsigned long)ptr & ~RADIX_TREE_INDIRECT_PTR); -} - static inline gfp_t root_gfp_mask(struct radix_tree_root *root) { return root->gfp_mask & __GFP_BITS_MASK; @@ -275,7 +265,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) return -ENOMEM; /* Increase the height. */ - node->slots[0] = indirect_to_ptr(root->rnode); + node->slots[0] = radix_tree_indirect_to_ptr(root->rnode); /* Propagate the aggregated tag info into the new root */ for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { @@ -286,7 +276,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) newheight = root->height+1; node->height = newheight; node->count = 1; - node = ptr_to_indirect(node); + node = radix_tree_ptr_to_indirect(node); rcu_assign_pointer(root->rnode, node); root->height = newheight; } while (height > root->height); @@ -319,7 +309,7 @@ int radix_tree_insert(struct radix_tree_root *root, return error; } - slot = indirect_to_ptr(root->rnode); + slot = radix_tree_indirect_to_ptr(root->rnode); height = root->height; shift = (height-1) * RADIX_TREE_MAP_SHIFT; @@ -335,7 +325,8 @@ int radix_tree_insert(struct radix_tree_root *root, rcu_assign_pointer(node->slots[offset], slot); node->count++; } else - rcu_assign_pointer(root->rnode, ptr_to_indirect(slot)); + rcu_assign_pointer(root->rnode, + radix_tree_ptr_to_indirect(slot)); } /* Go a level down */ @@ -383,7 +374,7 @@ static void *radix_tree_lookup_element(struct radix_tree_root *root, return NULL; return is_slot ? (void *)&root->rnode : node; } - node = indirect_to_ptr(node); + node = radix_tree_indirect_to_ptr(node); height = node->height; if (index > radix_tree_maxindex(height)) @@ -402,7 +393,7 @@ static void *radix_tree_lookup_element(struct radix_tree_root *root, height--; } while (height > 0); - return is_slot ? (void *)slot : indirect_to_ptr(node); + return is_slot ? (void *)slot:node; } /** @@ -464,7 +455,7 @@ void *radix_tree_tag_set(struct radix_tree_root *root, height = root->height; BUG_ON(index > radix_tree_maxindex(height)); - slot = indirect_to_ptr(root->rnode); + slot = radix_tree_indirect_to_ptr(root->rnode); shift = (height - 1) * RADIX_TREE_MAP_SHIFT; while (height > 0) { @@ -518,7 +509,7 @@ void *radix_tree_tag_clear(struct radix_tree_root *root, shift = (height - 1) * RADIX_TREE_MAP_SHIFT; pathp->node = NULL; - slot = indirect_to_ptr(root->rnode); + slot = radix_tree_indirect_to_ptr(root->rnode); while (height > 0) { int offset; @@ -588,7 +579,7 @@ int radix_tree_tag_get(struct radix_tree_root *root, if (!radix_tree_is_indirect_ptr(node)) return (index == 0); - node = indirect_to_ptr(node); + node = radix_tree_indirect_to_ptr(node); height = node->height; if (index > radix_tree_maxindex(height)) @@ -675,7 +666,7 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root, } shift = (height - 1) * RADIX_TREE_MAP_SHIFT; - slot = indirect_to_ptr(root->rnode); + slot = radix_tree_indirect_to_ptr(root->rnode); /* * we fill the path from (root->height - 2) to 0, leaving the index at @@ -906,7 +897,7 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results, results[0] = node; return 1; } - node = indirect_to_ptr(node); + node = radix_tree_indirect_to_ptr(node); max_index = radix_tree_maxindex(node->height); @@ -925,8 +916,7 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results, slot = *(((void ***)results)[ret + i]); if (!slot) continue; - results[ret + nr_found] = - indirect_to_ptr(rcu_dereference_raw(slot)); + results[ret + nr_found] = rcu_dereference_raw(slot); nr_found++; } ret += nr_found; @@ -975,7 +965,7 @@ radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results, results[0] = (void **)&root->rnode; return 1; } - node = indirect_to_ptr(node); + node = radix_tree_indirect_to_ptr(node); max_index = radix_tree_maxindex(node->height); @@ -1100,7 +1090,7 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, results[0] = node; return 1; } - node = indirect_to_ptr(node); + node = radix_tree_indirect_to_ptr(node); max_index = radix_tree_maxindex(node->height); @@ -1119,8 +1109,7 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, slot = *(((void ***)results)[ret + i]); if (!slot) continue; - results[ret + nr_found] = - indirect_to_ptr(rcu_dereference_raw(slot)); + results[ret + nr_found] = rcu_dereference_raw(slot); nr_found++; } ret += nr_found; @@ -1170,7 +1159,7 @@ radix_tree_gang_lookup_tag_slot(struct radix_tree_root *root, void ***results, results[0] = (void **)&root->rnode; return 1; } - node = indirect_to_ptr(node); + node = radix_tree_indirect_to_ptr(node); max_index = radix_tree_maxindex(node->height); @@ -1206,7 +1195,7 @@ static inline void radix_tree_shrink(struct radix_tree_root *root) void *newptr; BUG_ON(!radix_tree_is_indirect_ptr(to_free)); - to_free = indirect_to_ptr(to_free); + to_free = radix_tree_indirect_to_ptr(to_free); /* * The candidate node has more than one child, or its child @@ -1219,39 +1208,16 @@ static inline void radix_tree_shrink(struct radix_tree_root *root) /* * We don't need rcu_assign_pointer(), since we are simply - * moving the node from one part of the tree to another: if it - * was safe to dereference the old pointer to it + * moving the node from one part of the tree to another. If + * it was safe to dereference the old pointer to it * (to_free->slots[0]), it will be safe to dereference the new - * one (root->rnode) as far as dependent read barriers go. + * one (root->rnode). */ newptr = to_free->slots[0]; if (root->height > 1) - newptr = ptr_to_indirect(newptr); + newptr = radix_tree_ptr_to_indirect(newptr); root->rnode = newptr; root->height--; - - /* - * We have a dilemma here. The node's slot[0] must not be - * NULLed in case there are concurrent lookups expecting to - * find the item. However if this was a bottom-level node, - * then it may be subject to the slot pointer being visible - * to callers dereferencing it. If item corresponding to - * slot[0] is subsequently deleted, these callers would expect - * their slot to become empty sooner or later. - * - * For example, lockless pagecache will look up a slot, deref - * the page pointer, and if the page is 0 refcount it means it - * was concurrently deleted from pagecache so try the deref - * again. Fortunately there is already a requirement for logic - * to retry the entire slot lookup -- the indirect pointer - * problem (replacing direct root node with an indirect pointer - * also results in a stale slot). So tag the slot as indirect - * to force callers to retry. - */ - if (root->height == 0) - *((unsigned long *)&to_free->slots[0]) |= - RADIX_TREE_INDIRECT_PTR; - radix_tree_node_free(to_free); } } @@ -1288,7 +1254,7 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) root->rnode = NULL; goto out; } - slot = indirect_to_ptr(slot); + slot = radix_tree_indirect_to_ptr(slot); shift = (height - 1) * RADIX_TREE_MAP_SHIFT; pathp->node = NULL; @@ -1330,7 +1296,8 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) radix_tree_node_free(to_free); if (pathp->node->count) { - if (pathp->node == indirect_to_ptr(root->rnode)) + if (pathp->node == + radix_tree_indirect_to_ptr(root->rnode)) radix_tree_shrink(root); goto out; } diff --git a/trunk/mm/filemap.c b/trunk/mm/filemap.c index ea89840fc65f..61ba5e405791 100644 --- a/trunk/mm/filemap.c +++ b/trunk/mm/filemap.c @@ -644,9 +644,7 @@ struct page *find_get_page(struct address_space *mapping, pgoff_t offset) pagep = radix_tree_lookup_slot(&mapping->page_tree, offset); if (pagep) { page = radix_tree_deref_slot(pagep); - if (unlikely(!page)) - goto out; - if (radix_tree_deref_retry(page)) + if (unlikely(!page || page == RADIX_TREE_RETRY)) goto repeat; if (!page_cache_get_speculative(page)) @@ -662,7 +660,6 @@ struct page *find_get_page(struct address_space *mapping, pgoff_t offset) goto repeat; } } -out: rcu_read_unlock(); return page; @@ -780,11 +777,12 @@ unsigned find_get_pages(struct address_space *mapping, pgoff_t start, page = radix_tree_deref_slot((void **)pages[i]); if (unlikely(!page)) continue; - if (radix_tree_deref_retry(page)) { - if (ret) - start = pages[ret-1]->index; + /* + * this can only trigger if nr_found == 1, making livelock + * a non issue. + */ + if (unlikely(page == RADIX_TREE_RETRY)) goto restart; - } if (!page_cache_get_speculative(page)) goto repeat; @@ -832,7 +830,11 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index, page = radix_tree_deref_slot((void **)pages[i]); if (unlikely(!page)) continue; - if (radix_tree_deref_retry(page)) + /* + * this can only trigger if nr_found == 1, making livelock + * a non issue. + */ + if (unlikely(page == RADIX_TREE_RETRY)) goto restart; if (page->mapping == NULL || page->index != index) @@ -885,7 +887,11 @@ unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index, page = radix_tree_deref_slot((void **)pages[i]); if (unlikely(!page)) continue; - if (radix_tree_deref_retry(page)) + /* + * this can only trigger if nr_found == 1, making livelock + * a non issue. + */ + if (unlikely(page == RADIX_TREE_RETRY)) goto restart; if (!page_cache_get_speculative(page)) @@ -1023,9 +1029,6 @@ static void do_generic_file_read(struct file *filp, loff_t *ppos, goto page_not_up_to_date; if (!trylock_page(page)) goto page_not_up_to_date; - /* Did it get truncated before we got the lock? */ - if (!page->mapping) - goto page_not_up_to_date_locked; if (!mapping->a_ops->is_partially_uptodate(page, desc, offset)) goto page_not_up_to_date_locked; diff --git a/trunk/mm/memcontrol.c b/trunk/mm/memcontrol.c index 2efa8ea07ff7..9a99cfaf0a19 100644 --- a/trunk/mm/memcontrol.c +++ b/trunk/mm/memcontrol.c @@ -4208,17 +4208,15 @@ static struct mem_cgroup *mem_cgroup_alloc(void) memset(mem, 0, size); mem->stat = alloc_percpu(struct mem_cgroup_stat_cpu); - if (!mem->stat) - goto out_free; + if (!mem->stat) { + if (size < PAGE_SIZE) + kfree(mem); + else + vfree(mem); + mem = NULL; + } spin_lock_init(&mem->pcp_counter_lock); return mem; - -out_free: - if (size < PAGE_SIZE) - kfree(mem); - else - vfree(mem); - return NULL; } /* diff --git a/trunk/mm/vmscan.c b/trunk/mm/vmscan.c index d31d7ce52c0e..b8a6fdc21312 100644 --- a/trunk/mm/vmscan.c +++ b/trunk/mm/vmscan.c @@ -913,7 +913,7 @@ static unsigned long shrink_page_list(struct list_head *page_list, * back off and wait for congestion to clear because further reclaim * will encounter the same problem */ - if (nr_dirty == nr_congested && nr_dirty != 0) + if (nr_dirty == nr_congested) zone_set_flag(zone, ZONE_CONGESTED); free_page_list(&free_pages); diff --git a/trunk/security/Kconfig b/trunk/security/Kconfig index e80da955e687..bd72ae623494 100644 --- a/trunk/security/Kconfig +++ b/trunk/security/Kconfig @@ -39,18 +39,6 @@ config KEYS_DEBUG_PROC_KEYS If you are unsure as to whether this is required, answer N. -config SECURITY_DMESG_RESTRICT - bool "Restrict unprivileged access to the kernel syslog" - default n - help - This enforces restrictions on unprivileged users reading the kernel - syslog via dmesg(8). - - If this option is not selected, no restrictions will be enforced - unless the dmesg_restrict sysctl is explicitly set to (1). - - If you are unsure how to answer this question, answer N. - config SECURITY bool "Enable different security models" depends on SYSFS diff --git a/trunk/security/apparmor/lsm.c b/trunk/security/apparmor/lsm.c index b7106f192b75..cf1de4462ccd 100644 --- a/trunk/security/apparmor/lsm.c +++ b/trunk/security/apparmor/lsm.c @@ -922,7 +922,7 @@ static int __init apparmor_init(void) error = register_security(&apparmor_ops); if (error) { AA_ERROR("Unable to register AppArmor\n"); - goto set_init_cxt_out; + goto register_security_out; } /* Report that AppArmor successfully initialized */ @@ -936,9 +936,6 @@ static int __init apparmor_init(void) return error; -set_init_cxt_out: - aa_free_task_context(current->real_cred->security); - register_security_out: aa_free_root_ns(); @@ -947,6 +944,7 @@ static int __init apparmor_init(void) apparmor_enabled = 0; return error; + } security_initcall(apparmor_init); diff --git a/trunk/security/apparmor/policy.c b/trunk/security/apparmor/policy.c index 4f0eadee78b8..52cc865f1464 100644 --- a/trunk/security/apparmor/policy.c +++ b/trunk/security/apparmor/policy.c @@ -306,7 +306,7 @@ static struct aa_namespace *alloc_namespace(const char *prefix, return ns; fail_unconfined: - kzfree(ns->base.hname); + kzfree(ns->base.name); fail_ns: kzfree(ns); return NULL; diff --git a/trunk/security/commoncap.c b/trunk/security/commoncap.c index 04b80f9912bf..5e632b4857e4 100644 --- a/trunk/security/commoncap.c +++ b/trunk/security/commoncap.c @@ -895,8 +895,6 @@ int cap_syslog(int type, bool from_file) { if (type != SYSLOG_ACTION_OPEN && from_file) return 0; - if (dmesg_restrict && !capable(CAP_SYS_ADMIN)) - return -EPERM; if ((type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER) && !capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/trunk/tools/perf/util/ui/util.c b/trunk/tools/perf/util/ui/util.c index 9706d9d40279..056c69521a38 100644 --- a/trunk/tools/perf/util/ui/util.c +++ b/trunk/tools/perf/util/ui/util.c @@ -104,9 +104,10 @@ int ui__help_window(const char *text) return rc; } +static const char yes[] = "Yes", no[] = "No"; + bool ui__dialog_yesno(const char *msg) { /* newtWinChoice should really be accepting const char pointers... */ - char yes[] = "Yes", no[] = "No"; - return newtWinChoice(NULL, yes, no, (char *)msg) == 1; + return newtWinChoice(NULL, (char *)yes, (char *)no, (char *)msg) == 1; }