1. 16 11月, 2010 1 次提交
  2. 15 10月, 2010 1 次提交
    • A
      llseek: automatically add .llseek fop · 6038f373
      Arnd Bergmann 提交于
      All file_operations should get a .llseek operation so we can make
      nonseekable_open the default for future file operations without a
      .llseek pointer.
      
      The three cases that we can automatically detect are no_llseek, seq_lseek
      and default_llseek. For cases where we can we can automatically prove that
      the file offset is always ignored, we use noop_llseek, which maintains
      the current behavior of not returning an error from a seek.
      
      New drivers should normally not use noop_llseek but instead use no_llseek
      and call nonseekable_open at open time.  Existing drivers can be converted
      to do the same when the maintainer knows for certain that no user code
      relies on calling seek on the device file.
      
      The generated code is often incorrectly indented and right now contains
      comments that clarify for each added line why a specific variant was
      chosen. In the version that gets submitted upstream, the comments will
      be gone and I will manually fix the indentation, because there does not
      seem to be a way to do that using coccinelle.
      
      Some amount of new code is currently sitting in linux-next that should get
      the same modifications, which I will do at the end of the merge window.
      
      Many thanks to Julia Lawall for helping me learn to write a semantic
      patch that does all this.
      
      ===== begin semantic patch =====
      // This adds an llseek= method to all file operations,
      // as a preparation for making no_llseek the default.
      //
      // The rules are
      // - use no_llseek explicitly if we do nonseekable_open
      // - use seq_lseek for sequential files
      // - use default_llseek if we know we access f_pos
      // - use noop_llseek if we know we don't access f_pos,
      //   but we still want to allow users to call lseek
      //
      @ open1 exists @
      identifier nested_open;
      @@
      nested_open(...)
      {
      <+...
      nonseekable_open(...)
      ...+>
      }
      
      @ open exists@
      identifier open_f;
      identifier i, f;
      identifier open1.nested_open;
      @@
      int open_f(struct inode *i, struct file *f)
      {
      <+...
      (
      nonseekable_open(...)
      |
      nested_open(...)
      )
      ...+>
      }
      
      @ read disable optional_qualifier exists @
      identifier read_f;
      identifier f, p, s, off;
      type ssize_t, size_t, loff_t;
      expression E;
      identifier func;
      @@
      ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off)
      {
      <+...
      (
         *off = E
      |
         *off += E
      |
         func(..., off, ...)
      |
         E = *off
      )
      ...+>
      }
      
      @ read_no_fpos disable optional_qualifier exists @
      identifier read_f;
      identifier f, p, s, off;
      type ssize_t, size_t, loff_t;
      @@
      ssize_t read_f(struct file *f, char *p, size_t s, loff_t *off)
      {
      ... when != off
      }
      
      @ write @
      identifier write_f;
      identifier f, p, s, off;
      type ssize_t, size_t, loff_t;
      expression E;
      identifier func;
      @@
      ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off)
      {
      <+...
      (
        *off = E
      |
        *off += E
      |
        func(..., off, ...)
      |
        E = *off
      )
      ...+>
      }
      
      @ write_no_fpos @
      identifier write_f;
      identifier f, p, s, off;
      type ssize_t, size_t, loff_t;
      @@
      ssize_t write_f(struct file *f, const char *p, size_t s, loff_t *off)
      {
      ... when != off
      }
      
      @ fops0 @
      identifier fops;
      @@
      struct file_operations fops = {
       ...
      };
      
      @ has_llseek depends on fops0 @
      identifier fops0.fops;
      identifier llseek_f;
      @@
      struct file_operations fops = {
      ...
       .llseek = llseek_f,
      ...
      };
      
      @ has_read depends on fops0 @
      identifier fops0.fops;
      identifier read_f;
      @@
      struct file_operations fops = {
      ...
       .read = read_f,
      ...
      };
      
      @ has_write depends on fops0 @
      identifier fops0.fops;
      identifier write_f;
      @@
      struct file_operations fops = {
      ...
       .write = write_f,
      ...
      };
      
      @ has_open depends on fops0 @
      identifier fops0.fops;
      identifier open_f;
      @@
      struct file_operations fops = {
      ...
       .open = open_f,
      ...
      };
      
      // use no_llseek if we call nonseekable_open
      ////////////////////////////////////////////
      @ nonseekable1 depends on !has_llseek && has_open @
      identifier fops0.fops;
      identifier nso ~= "nonseekable_open";
      @@
      struct file_operations fops = {
      ...  .open = nso, ...
      +.llseek = no_llseek, /* nonseekable */
      };
      
      @ nonseekable2 depends on !has_llseek @
      identifier fops0.fops;
      identifier open.open_f;
      @@
      struct file_operations fops = {
      ...  .open = open_f, ...
      +.llseek = no_llseek, /* open uses nonseekable */
      };
      
      // use seq_lseek for sequential files
      /////////////////////////////////////
      @ seq depends on !has_llseek @
      identifier fops0.fops;
      identifier sr ~= "seq_read";
      @@
      struct file_operations fops = {
      ...  .read = sr, ...
      +.llseek = seq_lseek, /* we have seq_read */
      };
      
      // use default_llseek if there is a readdir
      ///////////////////////////////////////////
      @ fops1 depends on !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
      identifier fops0.fops;
      identifier readdir_e;
      @@
      // any other fop is used that changes pos
      struct file_operations fops = {
      ... .readdir = readdir_e, ...
      +.llseek = default_llseek, /* readdir is present */
      };
      
      // use default_llseek if at least one of read/write touches f_pos
      /////////////////////////////////////////////////////////////////
      @ fops2 depends on !fops1 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
      identifier fops0.fops;
      identifier read.read_f;
      @@
      // read fops use offset
      struct file_operations fops = {
      ... .read = read_f, ...
      +.llseek = default_llseek, /* read accesses f_pos */
      };
      
      @ fops3 depends on !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
      identifier fops0.fops;
      identifier write.write_f;
      @@
      // write fops use offset
      struct file_operations fops = {
      ... .write = write_f, ...
      +	.llseek = default_llseek, /* write accesses f_pos */
      };
      
      // Use noop_llseek if neither read nor write accesses f_pos
      ///////////////////////////////////////////////////////////
      
      @ fops4 depends on !fops1 && !fops2 && !fops3 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
      identifier fops0.fops;
      identifier read_no_fpos.read_f;
      identifier write_no_fpos.write_f;
      @@
      // write fops use offset
      struct file_operations fops = {
      ...
       .write = write_f,
       .read = read_f,
      ...
      +.llseek = noop_llseek, /* read and write both use no f_pos */
      };
      
      @ depends on has_write && !has_read && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
      identifier fops0.fops;
      identifier write_no_fpos.write_f;
      @@
      struct file_operations fops = {
      ... .write = write_f, ...
      +.llseek = noop_llseek, /* write uses no f_pos */
      };
      
      @ depends on has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
      identifier fops0.fops;
      identifier read_no_fpos.read_f;
      @@
      struct file_operations fops = {
      ... .read = read_f, ...
      +.llseek = noop_llseek, /* read uses no f_pos */
      };
      
      @ depends on !has_read && !has_write && !fops1 && !fops2 && !has_llseek && !nonseekable1 && !nonseekable2 && !seq @
      identifier fops0.fops;
      @@
      struct file_operations fops = {
      ...
      +.llseek = noop_llseek, /* no read or write fn */
      };
      ===== End semantic patch =====
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      Cc: Julia Lawall <julia@diku.dk>
      Cc: Christoph Hellwig <hch@infradead.org>
      6038f373
  3. 16 9月, 2010 1 次提交
    • A
      mac: autoconvert trivial BKL users to private mutex · d851b6e0
      Arnd Bergmann 提交于
      All these files use the big kernel lock in a trivial
      way to serialize their private file operations,
      typically resulting from an earlier semi-automatic
      pushdown from VFS.
      
      None of these drivers appears to want to lock against
      other code, and they all use the BKL as the top-level
      lock in their file operations, meaning that there
      is no lock-order inversion problem.
      
      Consequently, we can remove the BKL completely,
      replacing it with a per-file mutex in every case.
      Using a scripted approach means we can avoid
      typos.
      
      file=$1
      name=$2
      if grep -q lock_kernel ${file} ; then
          if grep -q 'include.*linux.mutex.h' ${file} ; then
                  sed -i '/include.*<linux\/smp_lock.h>/d' ${file}
          else
                  sed -i 's/include.*<linux\/smp_lock.h>.*$/include <linux\/mutex.h>/g' ${file}
          fi
          sed -i ${file} \
              -e "/^#include.*linux.mutex.h/,$ {
                      1,/^\(static\|int\|long\)/ {
                           /^\(static\|int\|long\)/istatic DEFINE_MUTEX(${name}_mutex);
      
      } }"  \
          -e "s/\(un\)*lock_kernel\>[ ]*()/mutex_\1lock(\&${name}_mutex)/g" \
          -e '/[      ]*cycle_kernel_lock();/d'
      else
          sed -i -e '/include.*\<smp_lock.h\>/d' ${file}  \
                      -e '/cycle_kernel_lock()/d'
      fi
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
      Cc: linuxppc-dev@ozlabs.org
      d851b6e0
  4. 24 8月, 2010 1 次提交
  5. 29 7月, 2010 1 次提交
  6. 17 5月, 2010 1 次提交
  7. 09 2月, 2010 1 次提交
  8. 08 12月, 2009 1 次提交
  9. 14 10月, 2009 1 次提交
    • B
      powerpc/pmac: Fix issues with sleep on some powerbooks · 11a50873
      Benjamin Herrenschmidt 提交于
      Since the change of how interrupts are disabled during suspend,
      certain PowerBook models started exhibiting various issues during
      suspend or resume from sleep.
      
      I finally tracked it down to the code that runs various "platform"
      functions (kind of little scripts extracted from the device-tree),
      which uses our i2c and PMU drivers expecting interrutps to work,
      and at a time where with the new scheme, they have been disabled.
      
      This causes timeouts internally which for some reason results in
      the PMU being unable to see the trackpad, among other issues, really
      it depends on the machine. Most of the time, we fail to properly adjust
      some clocks for suspend/resume so the results are not always
      predictable.
      
      This patch fixes it by using IRQF_TIMER for both the PMU and the I2C
      interrupts. I prefer doing it this way than moving the call sites since
      I really want those platform functions to still be called after all
      drivers (and before sysdevs).
      
      We also do a slight cleanup to via-pmu.c driver to make sure the
      ADB autopoll mask is handled correctly when doing bus resets
      Signed-off-by: NBenjamin Herrenschmidt <benh@kernel.crashing.org>
      11a50873
  10. 21 12月, 2008 1 次提交
  11. 03 7月, 2008 1 次提交
  12. 13 3月, 2008 1 次提交
    • G
      [POWERPC] Fix build of modular drivers/macintosh/apm_emu.c · 620a2459
      Guido Guenther 提交于
      Currently, if drivers/macintosh/apm_emu is a module and the config
      doesn't have CONFIG_SUSPEND we get:
      
      ERROR: "pmu_batteries" [drivers/macintosh/apm_emu.ko] undefined!
      ERROR: "pmu_battery_count" [drivers/macintosh/apm_emu.ko] undefined!
      ERROR: "pmu_power_flags" [drivers/macintosh/apm_emu.ko] undefined!
      
      on PPC32.  The variables aren't wrapped in '#if defined(CONFIG_SUSPEND)'
      so we probably shouldn't wrap the exports either.  This removes the
      CONFIG_SUSPEND part of the export, which fixes compilation on ppc32.
      Signed-off-by: NGuido Guenther <agx@sigxcpu.org>
      Signed-off-by: NPaul Mackerras <paulus@samba.org>
      620a2459
  13. 25 1月, 2008 1 次提交
  14. 21 12月, 2007 2 次提交
  15. 19 12月, 2007 3 次提交
    • J
      [POWERPC] powermac: Use generic suspend code · f91266ed
      Johannes Berg 提交于
      This adds platform_suspend_ops for PMU based machines, directly in
      the PMU driver.  This allows suspending via /sys/power/state
      on powerbooks.
      
      The patch also replaces the PMU ioctl with a simple call to
      pm_suspend(PM_SUSPEND_MEM).
      
      Additionally, it cleans up some debug code.
      Signed-off-by: NJohannes Berg <johannes@sipsolutions.net>
      Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
      Signed-off-by: NPaul Mackerras <paulus@samba.org>
      f91266ed
    • P
      [POWERPC] Fix sleep on powerbook 3400 · 887ef35a
      Paul Mackerras 提交于
      Sleep on the powerbook 3400 has been broken since the change that made
      powerbook_sleep_3400 call pmac_suspend_devices(), which disables
      interrupts.  There are a couple of loops in powerbook_sleep_3400 that
      depend on interrupts being enabled, and in fact it has to have
      interrupts enabled at the point of going to sleep since it is an
      interrupt from the PMU that wakes it up.
      
      This fixes it by using pmu_wait_complete() instead of a spinloop, and
      by explicitly enabling interrupts before putting the CPU into sleep
      mode (which is OK since all interrupts except the PMU interrupt have
      been disabled at the interrupt controller by this stage).
      
      This changes the logic so that it keeps putting the CPU into sleep mode
      until the completion of the interrupt transaction from the PMU that
      signals the end of sleep.  Also, we now call pmu_unlock() before sleep
      so that the via_pmu_interrupt() code can process the interrupt event
      from the PMU properly.
      
      Now that generic code saves and restores PCI state, it is no longer
      necessary to do that here.  Thus pbook_pci_save/restore and related
      functions are no longer necessary, so this removes them.
      
      Lastly, this moves the ioremap of the memory controller to init code
      rather than doing it on every sleep/wakeup cycle.
      Signed-off-by: NPaul Mackerras <paulus@samba.org>
      887ef35a
    • J
      [POWERPC] via-pmu: Kill sleep notifiers completely · b819a9bf
      Johannes Berg 提交于
      This kills off the remnants of the old sleep notifiers now that they
      are no longer used.
      Signed-off-by: NJohannes Berg <johannes@sipsolutions.net>
      Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
      Signed-off-by: NPaul Mackerras <paulus@samba.org>
      b819a9bf
  16. 18 12月, 2007 1 次提交
  17. 03 12月, 2007 2 次提交
  18. 20 10月, 2007 1 次提交
  19. 25 8月, 2007 1 次提交
    • O
      [POWERPC] Fix undefined reference to device_power_up/resume · e120e8d0
      Olaf Hering 提交于
      Current Linus tree fails to link on pmac32:
      
      drivers/built-in.o: In function `pmac_wakeup_devices':
      via-pmu.c:(.text+0x5bab4): undefined reference to `device_power_up'
      via-pmu.c:(.text+0x5bb08): undefined reference to `device_resume'
      drivers/built-in.o: In function `pmac_suspend_devices':
      via-pmu.c:(.text+0x5c260): undefined reference to `device_power_down'
      via-pmu.c:(.text+0x5c27c): undefined reference to `device_resume'
      make[1]: *** [.tmp_vmlinux1] Error 1
      
      changing CONFIG_PM > CONFIG_PM_SLEEP leads to:
      
      drivers/built-in.o: In function `pmu_led_set':
      via-pmu-led.c:(.text+0x5cdca): undefined reference to `pmu_sys_suspended'
      via-pmu-led.c:(.text+0x5cdce): undefined reference to `pmu_sys_suspended'
      drivers/built-in.o: In function `pmu_req_done':
      via-pmu-led.c:(.text+0x5ce3e): undefined reference to `pmu_sys_suspended'
      via-pmu-led.c:(.text+0x5ce42): undefined reference to `pmu_sys_suspended'
      drivers/built-in.o: In function `adb_init':
      (.init.text+0x4c5c): undefined reference to `pmu_register_sleep_notifier'
      make[1]: *** [.tmp_vmlinux1] Error 1
      
      So change even more places from PM to PM_SLEEP to allow linking.
      Signed-off-by: NOlaf Hering <olaf@aepfle.de>
      Signed-off-by: NPaul Mackerras <paulus@samba.org>
      e120e8d0
  20. 17 8月, 2007 1 次提交
  21. 08 5月, 2007 1 次提交
  22. 07 5月, 2007 1 次提交
  23. 27 4月, 2007 1 次提交
  24. 26 4月, 2007 1 次提交
  25. 24 4月, 2007 3 次提交
  26. 13 4月, 2007 1 次提交
  27. 26 3月, 2007 1 次提交
  28. 13 2月, 2007 3 次提交
  29. 12 2月, 2007 1 次提交
  30. 06 1月, 2007 1 次提交
  31. 08 12月, 2006 1 次提交
  32. 05 10月, 2006 1 次提交
    • D
      IRQ: Maintain regs pointer globally rather than passing to IRQ handlers · 7d12e780
      David Howells 提交于
      Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
      of passing regs around manually through all ~1800 interrupt handlers in the
      Linux kernel.
      
      The regs pointer is used in few places, but it potentially costs both stack
      space and code to pass it around.  On the FRV arch, removing the regs parameter
      from all the genirq function results in a 20% speed up of the IRQ exit path
      (ie: from leaving timer_interrupt() to leaving do_IRQ()).
      
      Where appropriate, an arch may override the generic storage facility and do
      something different with the variable.  On FRV, for instance, the address is
      maintained in GR28 at all times inside the kernel as part of general exception
      handling.
      
      Having looked over the code, it appears that the parameter may be handed down
      through up to twenty or so layers of functions.  Consider a USB character
      device attached to a USB hub, attached to a USB controller that posts its
      interrupts through a cascaded auxiliary interrupt controller.  A character
      device driver may want to pass regs to the sysrq handler through the input
      layer which adds another few layers of parameter passing.
      
      I've build this code with allyesconfig for x86_64 and i386.  I've runtested the
      main part of the code on FRV and i386, though I can't test most of the drivers.
      I've also done partial conversion for powerpc and MIPS - these at least compile
      with minimal configurations.
      
      This will affect all archs.  Mostly the changes should be relatively easy.
      Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
      
      	struct pt_regs *old_regs = set_irq_regs(regs);
      
      And put the old one back at the end:
      
      	set_irq_regs(old_regs);
      
      Don't pass regs through to generic_handle_irq() or __do_IRQ().
      
      In timer_interrupt(), this sort of change will be necessary:
      
      	-	update_process_times(user_mode(regs));
      	-	profile_tick(CPU_PROFILING, regs);
      	+	update_process_times(user_mode(get_irq_regs()));
      	+	profile_tick(CPU_PROFILING);
      
      I'd like to move update_process_times()'s use of get_irq_regs() into itself,
      except that i386, alone of the archs, uses something other than user_mode().
      
      Some notes on the interrupt handling in the drivers:
      
       (*) input_dev() is now gone entirely.  The regs pointer is no longer stored in
           the input_dev struct.
      
       (*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking.  It does
           something different depending on whether it's been supplied with a regs
           pointer or not.
      
       (*) Various IRQ handler function pointers have been moved to type
           irq_handler_t.
      Signed-Off-By: NDavid Howells <dhowells@redhat.com>
      (cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
      7d12e780