1. 04 2月, 2011 1 次提交
  2. 02 11月, 2010 1 次提交
  3. 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
  4. 17 12月, 2009 2 次提交
  5. 09 12月, 2009 1 次提交
    • F
      spi: fix spidev compilation failure when VERBOSE is defined · 41df70d9
      Florian Fainelli 提交于
      When VERBOSE is defined in the spidev module, the compilation
      will throw an error on 'spi' not being defined:
      
      CC [M]  drivers/spi/spidev.o
      drivers/spi/spidev.c: In function 'spidev_message':
      drivers/spi/spidev.c:266: error: 'spi' undeclared (first use in this function)
      drivers/spi/spidev.c:266: error: (Each undeclared identifier is reported only once
      drivers/spi/spidev.c:266: error: for each function it appears in.)
      
      instead of using spi-> we should actually use spidev->spi.
      This patch fixes the build failure.
      Signed-off-by: NFlorian Fainelli <ffainelli@freebox.fr>
      Signed-off-by: NGrant Likely <grant.likely@secretlab.ca>
      41df70d9
  6. 04 12月, 2009 1 次提交
  7. 14 10月, 2009 1 次提交
  8. 02 10月, 2009 1 次提交
  9. 23 9月, 2009 1 次提交
  10. 01 7月, 2009 1 次提交
    • D
      spi: new spi->mode bits · b55f627f
      David Brownell 提交于
      Add two new spi_device.mode bits to accomodate more protocol options, and
      pass them through to usermode drivers:
      
       * SPI_NO_CS ... a second 3-wire variant, where the chipselect
         line is removed instead of a data line; transfers are still
         full duplex.
      
         This obviously has STRONG protocol implications since the
         chipselect transitions can't be used to synchronize state
         transitions with the SPI master.
      
       * SPI_READY ... defines open drain signal that's pulled low
         to pause the clock.  This defines a 5-wire variant (normal
         4-wire SPI plus READY) and two 4-wire variants (READY plus
         each of the 3-wire flavors).
      
         Such hardware flow control can be a big win.  There are ADC
         converters and flash chips that expose READY signals, but not
         many host controllers support it today.
      
      The spi_bitbang code should be changed to use SPI_NO_CS instead of its
      current nonportable hack.  That's a mode most hardware can easily support
      (unlike SPI_READY).
      Signed-off-by: NDavid Brownell <dbrownell@users.sourceforge.net>
      Cc: "Paulraj, Sandeep" <s-paulraj@ti.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      b55f627f
  11. 02 12月, 2008 1 次提交
    • W
      spi: avoid spidev crash when device is removed · aaacf4bb
      Wolfgang Ocker 提交于
      I saw a kernel oops in spidev_remove() when a spidev device was registered
      and I unloaded the SPI master driver:
      
      Unable to handle kernel paging request for data at address 0x00000004
      Faulting instruction address: 0xc01c0c50
      Oops: Kernel access of bad area, sig: 11 [#1]
      CDSPR
      Modules linked in: spi_ppc4xx(-)
      NIP: c01c0c50 LR: c01bf9e4 CTR: c01c0c34
      REGS: cec89c30 TRAP: 0300   Not tainted  (2.6.27.3izt)
      MSR: 00021000 <ME>  CR: 24000228  XER: 20000007
      DEAR: 00000004, ESR: 00800000
      TASK = cf889040[2070] 'rmmod' THREAD: cec88000
      GPR00: 00000000 cec89ce0 cf889040 cec8e000 00000004 cec8e000 ffffffff 00000000
      GPR08: 0000001c c0336380 00000000 c01c0c34 00000001 1001a338 100e0000 100df49c
      GPR16: 100b54c0 100df49c 100ddd20 100f05a8 100b5340 100efd68 00000000 00000000
      GPR24: 100ec008 100f0428 c0327788 c0327794 cec8e0ac cec8e000 c0336380 00000000
      NIP [c01c0c50] spidev_remove+0x1c/0xe4
      LR [c01bf9e4] spi_drv_remove+0x2c/0x3c
      Call Trace:
      [cec89d00] [c01bf9e4] spi_drv_remove+0x2c/0x3c
      [cec89d10] [c01859a0] __device_release_driver+0x78/0xb4
      [cec89d20] [c0185ab0] device_release_driver+0x28/0x44
      [cec89d40] [c0184be8] bus_remove_device+0xac/0xd8
      [cec89d60] [c0183094] device_del+0x100/0x194
      [cec89d80] [c0183140] device_unregister+0x18/0x30
      [cec89da0] [c01bf30c] __unregister+0x20/0x34
      [cec89db0] [c0182778] device_for_each_child+0x38/0x74
      [cec89de0] [c01bf2d0] spi_unregister_master+0x28/0x44
      [cec89e00] [c01bfeac] spi_bitbang_stop+0x1c/0x58
      [cec89e20] [d908a5e0] spi_ppc4xx_of_remove+0x24/0x7c [spi_ppc4xx]
      [...]
      
      IMHO a call to spi_set_drvdata() is missing in spidev_probe(). The patch
      below helped.
      Signed-off-by: NWolfgang Ocker <weo@reccoware.de>
      Signed-off-by: NDavid Brownell <dbrownell@users.sourceforge.net>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      aaacf4bb
  12. 17 10月, 2008 1 次提交
  13. 25 7月, 2008 1 次提交
  14. 22 7月, 2008 1 次提交
  15. 05 7月, 2008 1 次提交
    • S
      spi: fix the read path in spidev · 4b1295b0
      Sebastian Siewior 提交于
      This got broken by the recent "fix rmmod $spi_driver while spidev-user is
      active".  I tested the rmmod & write path but didn't check the read path.
      I am sorry.  The read logic changed and spidev_sync_read() +
      spidev_sync_write() do not return zero on success anymore but the number
      of bytes that has been transfered over the bus.  This patch changes the
      logic and copy_to_user() gets called again.
      
      The write path returns the number of bytes which are written to the
      underlying device what may be less than the requested size.  This patch
      makes the same change to the read path or else we request a read of 20
      bytes, get 10, don't call copy to user and report to the user that we read
      10 bytes.
      
      [akpm@linux-foundation.org: remove test of known-to-be-zero local]
      Signed-off-by: NSebastian Siewior <bigeasy@linutronix.de>
      Acked-by: NDavid Brownell <dbrownell@users.sourceforge.net>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      4b1295b0
  16. 21 6月, 2008 1 次提交
  17. 07 6月, 2008 1 次提交
  18. 25 5月, 2008 1 次提交
  19. 29 10月, 2007 1 次提交
    • A
      fix abuses of ptrdiff_t · 142956af
      Al Viro 提交于
      Use of ptrdiff_t in places like
      
      -                       if (!access_ok(VERIFY_WRITE, u_tmp->rx_buf, u_tmp->len))
      +                       if (!access_ok(VERIFY_WRITE, (u8 __user *)
      +                                               (ptrdiff_t) u_tmp->rx_buf,
      +                                               u_tmp->len))
      
      is wrong; for one thing, it's a bad C (it's what uintptr_t is for; in general
      we are not even promised that ptrdiff_t is large enough to hold a pointer,
      just enough to hold a difference between two pointers within the same object).
      For another, it confuses the fsck out of sparse.
      
      Use unsigned long or uintptr_t instead.  There are several places misusing
      ptrdiff_t; fixed.
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      142956af
  20. 12 8月, 2007 1 次提交
  21. 01 8月, 2007 1 次提交
  22. 18 7月, 2007 1 次提交
  23. 24 5月, 2007 2 次提交
  24. 17 5月, 2007 1 次提交
  25. 09 5月, 2007 1 次提交