Browse Source

Merge tag 'char-misc-3.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char/misc updates from Greg KH:
 "Here's the big char/misc driver tree merge for 3.11-rc1

  A variety of different driver patches here.  All of these have been in
  linux-next for a while, and the networking patches were acked-by David
  Miller, as it made sense for those patches to come through this tree"

* tag 'char-misc-3.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (102 commits)
  Revert "char: misc: assign file->private_data in all cases"
  drivers: uio_pdrv_genirq: Use of_match_ptr() macro
  mei: check whether hw start has succeeded
  mei: check if the hardware reset succeeded
  mei: mei_cl_connect: don't multiply the timeout twice
  mei: do not override a client writing state when buffering
  mei: move mei_cl_irq_write_complete to client.c
  UIO: Fix concurrency issue
  drivers: uio_dmem_genirq: Use of_match_ptr() macro
  char: misc: assign file->private_data in all cases
  drivers: hv: allocate synic structures before hv_synic_init()
  drivers: hv: check interrupt mask before read_index
  vme: vme_tsi148.c: fix error return code in tsi148_probe()
  FMC: fix error handling in probe() function
  fmc: avoid readl/writel namespace conflict
  FMC: NULL dereference on allocation failure
  UIO: fix uio_pdrv_genirq with device tree but no interrupt
  UIO: allow binding uio_pdrv_genirq.c to devices using command line option
  FMC: add a char-device mezzanine driver
  FMC: add a driver to write mezzanine EEPROM
  ...
Linus Torvalds 12 years ago
parent
commit
fe3c22bd5c
100 changed files with 4550 additions and 841 deletions
  1. 2 0
      Documentation/00-INDEX
  2. 19 0
      Documentation/devicetree/bindings/ata/atmel-at91_cf.txt
  3. 15 0
      Documentation/devicetree/bindings/extcon/extcon-twl.txt
  4. 156 0
      Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt
  5. 38 0
      Documentation/fmc/00-INDEX
  6. 47 0
      Documentation/fmc/API.txt
  7. 88 0
      Documentation/fmc/FMC-and-SDB.txt
  8. 311 0
      Documentation/fmc/carrier.txt
  9. 64 0
      Documentation/fmc/fmc-chardev.txt
  10. 36 0
      Documentation/fmc/fmc-fakedev.txt
  11. 17 0
      Documentation/fmc/fmc-trivial.txt
  12. 125 0
      Documentation/fmc/fmc-write-eeprom.txt
  13. 168 0
      Documentation/fmc/identifiers.txt
  14. 123 0
      Documentation/fmc/mezzanine.txt
  15. 56 0
      Documentation/fmc/parameters.txt
  16. 2 2
      Documentation/w1/w1.generic
  17. 10 0
      MAINTAINERS
  18. 2 0
      drivers/Kconfig
  19. 1 0
      drivers/Makefile
  20. 3 3
      drivers/char/hpet.c
  21. 3 3
      drivers/char/ipmi/ipmi_poweroff.c
  22. 1 1
      drivers/char/mem.c
  23. 1 1
      drivers/char/mspec.c
  24. 4 4
      drivers/char/random.c
  25. 3 3
      drivers/char/rtc.c
  26. 8 2
      drivers/char/xilinx_hwicap/xilinx_hwicap.h
  27. 7 0
      drivers/extcon/Kconfig
  28. 1 0
      drivers/extcon/Makefile
  29. 3 22
      drivers/extcon/extcon-class.c
  30. 246 0
      drivers/extcon/extcon-palmas.c
  31. 51 0
      drivers/fmc/Kconfig
  32. 13 0
      drivers/fmc/Makefile
  33. 202 0
      drivers/fmc/fmc-chardev.c
  34. 296 0
      drivers/fmc/fmc-core.c
  35. 100 0
      drivers/fmc/fmc-dump.c
  36. 355 0
      drivers/fmc/fmc-fakedev.c
  37. 114 0
      drivers/fmc/fmc-match.c
  38. 266 0
      drivers/fmc/fmc-sdb.c
  39. 107 0
      drivers/fmc/fmc-trivial.c
  40. 176 0
      drivers/fmc/fmc-write-eeprom.c
  41. 82 0
      drivers/fmc/fru-parse.c
  42. 46 4
      drivers/hv/channel.c
  43. 115 4
      drivers/hv/channel_mgmt.c
  44. 14 0
      drivers/hv/connection.c
  45. 53 32
      drivers/hv/hv.c
  46. 4 0
      drivers/hv/hyperv_vmbus.h
  47. 7 5
      drivers/hv/ring_buffer.c
  48. 7 3
      drivers/hv/vmbus_drv.c
  49. 10 0
      drivers/memory/Kconfig
  50. 1 0
      drivers/memory/Makefile
  51. 340 0
      drivers/memory/mvebu-devbus.c
  52. 4 1
      drivers/memory/tegra20-mc.c
  53. 6 3
      drivers/memory/tegra30-mc.c
  54. 1 0
      drivers/misc/Kconfig
  55. 1 1
      drivers/misc/ad525x_dpot.c
  56. 3 2
      drivers/misc/apds9802als.c
  57. 24 13
      drivers/misc/apds990x.c
  58. 1 4
      drivers/misc/arm-charlcd.c
  59. 38 21
      drivers/misc/bh1770glc.c
  60. 1 1
      drivers/misc/bh1780gli.c
  61. 8 6
      drivers/misc/carma/carma-fpga-program.c
  62. 4 4
      drivers/misc/carma/carma-fpga.c
  63. 15 29
      drivers/misc/eeprom/at24.c
  64. 8 17
      drivers/misc/eeprom/at25.c
  65. 50 138
      drivers/misc/ep93xx_pwm.c
  66. 3 2
      drivers/misc/hmc6352.c
  67. 20 4
      drivers/misc/isl29003.c
  68. 4 2
      drivers/misc/isl29020.c
  69. 4 2
      drivers/misc/lis3lv02d/lis3lv02d.c
  70. 3 3
      drivers/misc/mei/amthif.c
  71. 89 3
      drivers/misc/mei/client.c
  72. 4 0
      drivers/misc/mei/client.h
  73. 32 5
      drivers/misc/mei/hbm.c
  74. 1 1
      drivers/misc/mei/hbm.h
  75. 2 1
      drivers/misc/mei/hw-me.c
  76. 14 4
      drivers/misc/mei/init.c
  77. 58 147
      drivers/misc/mei/interrupt.c
  78. 13 36
      drivers/misc/mei/main.c
  79. 7 22
      drivers/misc/mei/mei_dev.h
  80. 0 19
      drivers/misc/mei/pci-me.c
  81. 0 6
      drivers/misc/mei/wd.c
  82. 19 25
      drivers/misc/pch_phub.c
  83. 5 9
      drivers/misc/sgi-gru/gruprocfs.c
  84. 47 22
      drivers/misc/spear13xx_pcie_gadget.c
  85. 3 6
      drivers/misc/sram.c
  86. 3 3
      drivers/misc/ti-st/st_kim.c
  87. 4 2
      drivers/misc/ti_dac7512.c
  88. 2 2
      drivers/misc/tsl2550.c
  89. 1 0
      drivers/net/netconsole.c
  90. 2 2
      drivers/pcmcia/Kconfig
  91. 88 88
      drivers/pcmcia/at91_cf.c
  92. 2 0
      drivers/pcmcia/pd6729.c
  93. 1 13
      drivers/uio/uio_aec.c
  94. 1 13
      drivers/uio/uio_cif.c
  95. 1 3
      drivers/uio/uio_dmem_genirq.c
  96. 1 13
      drivers/uio/uio_netx.c
  97. 2 15
      drivers/uio/uio_pci_generic.c
  98. 29 25
      drivers/uio/uio_pdrv_genirq.c
  99. 1 1
      drivers/uio/uio_pruss.c
  100. 1 13
      drivers/uio/uio_sercos3.c

+ 2 - 0
Documentation/00-INDEX

@@ -187,6 +187,8 @@ firmware_class/
 	- request_firmware() hotplug interface info.
 flexible-arrays.txt
 	- how to make use of flexible sized arrays in linux
+fmc/
+	- information about the FMC bus abstraction
 frv/
 	- Fujitsu FR-V Linux documentation.
 futex-requeue-pi.txt

+ 19 - 0
Documentation/devicetree/bindings/ata/atmel-at91_cf.txt

@@ -0,0 +1,19 @@
+Atmel AT91RM9200 CompactFlash
+
+Required properties:
+- compatible : "atmel,at91rm9200-cf".
+- reg : should specify localbus address and size used.
+- gpios : specifies the gpio pins to control the CF device. Detect
+  and reset gpio's are mandatory while irq and vcc gpio's are
+  optional and may be set to 0 if not present.
+
+Example:
+compact-flash@50000000 {
+	compatible = "atmel,at91rm9200-cf";
+	reg = <0x50000000 0x30000000>;
+	gpios = <&pioC 13 0	/* irq */
+		 &pioC 15 0 	/* detect */
+		 0		/* vcc */
+		 &pioC  5 0	/* reset */
+		>;
+};

+ 15 - 0
Documentation/devicetree/bindings/extcon/extcon-twl.txt

@@ -0,0 +1,15 @@
+EXTCON FOR TWL CHIPS
+
+PALMAS USB COMPARATOR
+Required Properties:
+ - compatible : Should be "ti,palmas-usb" or "ti,twl6035-usb"
+ - vbus-supply : phandle to the regulator device tree node.
+
+Optional Properties:
+ - ti,wakeup : To enable the wakeup comparator in probe
+
+palmas-usb {
+       compatible = "ti,twl6035-usb", "ti,palmas-usb";
+       vbus-supply = <&smps10_reg>;
+       ti,wakeup;
+};

+ 156 - 0
Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt

@@ -0,0 +1,156 @@
+Device tree bindings for MVEBU Device Bus controllers
+
+The Device Bus controller available in some Marvell's SoC allows to control
+different types of standard memory and I/O devices such as NOR, NAND, and FPGA.
+The actual devices are instantiated from the child nodes of a Device Bus node.
+
+Required properties:
+
+ - compatible:          Currently only Armada 370/XP SoC are supported,
+                        with this compatible string:
+
+                        marvell,mvebu-devbus
+
+ - reg:                 A resource specifier for the register space.
+                        This is the base address of a chip select within
+			the controller's register space.
+                        (see the example below)
+
+ - #address-cells:      Must be set to 1
+ - #size-cells:         Must be set to 1
+ - ranges:              Must be set up to reflect the memory layout with four
+                        integer values for each chip-select line in use:
+                        0 <physical address of mapping> <size>
+
+Mandatory timing properties for child nodes:
+
+Read parameters:
+
+ - devbus,turn-off-ps:  Defines the time during which the controller does not
+                        drive the AD bus after the completion of a device read.
+                        This prevents contentions on the Device Bus after a read
+                        cycle from a slow device.
+
+ - devbus,bus-width:    Defines the bus width (e.g. <16>)
+
+ - devbus,badr-skew-ps: Defines the time delay from from A[2:0] toggle,
+                        to read data sample. This parameter is useful for
+                        synchronous pipelined devices, where the address
+                        precedes the read data by one or two cycles.
+
+ - devbus,acc-first-ps: Defines the time delay from the negation of
+                        ALE[0] to the cycle that the first read data is sampled
+                        by the controller.
+
+ - devbus,acc-next-ps:  Defines the time delay between the cycle that
+                        samples data N and the cycle that samples data N+1
+                        (in burst accesses).
+
+ - devbus,rd-setup-ps:  Defines the time delay between DEV_CSn assertion to
+			DEV_OEn assertion. If set to 0 (default),
+                        DEV_OEn and DEV_CSn are asserted at the same cycle.
+                        This parameter has no affect on <acc-first-ps> parameter
+                        (no affect on first data sample). Set <rd-setup-ps>
+                        to a value smaller than <acc-first-ps>.
+
+ - devbus,rd-hold-ps:   Defines the time between the last data sample to the
+			de-assertion of DEV_CSn. If set to 0 (default),
+			DEV_OEn and DEV_CSn are de-asserted at the same cycle
+			(the cycle of the last data sample).
+                        This parameter has no affect on DEV_OEn de-assertion.
+                        DEV_OEn is always de-asserted the next cycle after
+                        last data sampled. Also this parameter has no
+                        affect on <turn-off-ps> parameter.
+                        Set <rd-hold-ps> to a value smaller than <turn-off-ps>.
+
+Write parameters:
+
+ - devbus,ale-wr-ps:    Defines the time delay from the ALE[0] negation cycle
+			to the DEV_WEn assertion.
+
+ - devbus,wr-low-ps:    Defines the time during which DEV_WEn is active.
+                        A[2:0] and Data are kept valid as long as DEV_WEn
+                        is active. This parameter defines the setup time of
+                        address and data to DEV_WEn rise.
+
+ - devbus,wr-high-ps:   Defines the time during which DEV_WEn is kept
+                        inactive (high) between data beats of a burst write.
+                        DEV_A[2:0] and Data are kept valid (do not toggle) for
+                        <wr-high-ps> - <tick> ps.
+			This parameter defines the hold time of address and
+			data after DEV_WEn rise.
+
+ - devbus,sync-enable: Synchronous device enable.
+                       1: True
+                       0: False
+
+An example for an Armada XP GP board, with a 16 MiB NOR device as child
+is showed below. Note that the Device Bus driver is in charge of allocating
+the mbus address decoding window for each of its child devices.
+The window is created using the chip select specified in the child
+device node together with the base address and size specified in the ranges
+property. For instance, in the example below the allocated decoding window
+will start at base address 0xf0000000, with a size 0x1000000 (16 MiB)
+for chip select 0 (a.k.a DEV_BOOTCS).
+
+This address window handling is done in this mvebu-devbus only as a temporary
+solution. It will be removed when the support for mbus device tree binding is
+added.
+
+The reg property implicitly specifies the chip select as this:
+
+  0x10400: DEV_BOOTCS
+  0x10408: DEV_CS0
+  0x10410: DEV_CS1
+  0x10418: DEV_CS2
+  0x10420: DEV_CS3
+
+Example:
+
+	devbus-bootcs@d0010400 {
+		status = "okay";
+		ranges = <0 0xf0000000 0x1000000>; /* @addr 0xf0000000, size 0x1000000 */
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* Device Bus parameters are required */
+
+		/* Read parameters */
+		devbus,bus-width    = <8>;
+		devbus,turn-off-ps  = <60000>;
+		devbus,badr-skew-ps = <0>;
+		devbus,acc-first-ps = <124000>;
+		devbus,acc-next-ps  = <248000>;
+		devbus,rd-setup-ps  = <0>;
+		devbus,rd-hold-ps   = <0>;
+
+		/* Write parameters */
+		devbus,sync-enable = <0>;
+		devbus,wr-high-ps  = <60000>;
+		devbus,wr-low-ps   = <60000>;
+		devbus,ale-wr-ps   = <60000>;
+
+		flash@0 {
+			compatible = "cfi-flash";
+
+			/* 16 MiB */
+			reg = <0 0x1000000>;
+			bank-width = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			/*
+			 * We split the 16 MiB in two partitions,
+			 * just as an example.
+			 */
+			partition@0 {
+				label = "First";
+				reg = <0 0x800000>;
+			};
+
+			partition@800000 {
+				label = "Second";
+				reg = <0x800000 0x800000>;
+			};
+		};
+	};

+ 38 - 0
Documentation/fmc/00-INDEX

@@ -0,0 +1,38 @@
+
+Documentation in this directory comes from sections of the manual we
+wrote for the externally-developed fmc-bus package. The complete
+manual as of today (2013-02) is available in PDF format at
+http://www.ohwr.org/projects/fmc-bus/files
+
+00-INDEX
+	- this file.
+
+FMC-and-SDB.txt
+	- What are FMC and SDB, basic concepts for this framework
+
+API.txt
+	- The functions that are exported by the bus driver
+
+parameters.txt
+	- The module parameters
+
+carrier.txt
+	- writing a carrier (a device)
+
+mezzanine.txt
+	- writing code for your mezzanine (a driver)
+
+identifiers.txt
+	- how identification and matching works
+
+fmc-fakedev.txt
+	- about drivers/fmc/fmc-fakedev.ko
+
+fmc-trivial.txt
+	- about drivers/fmc/fmc-trivial.ko
+
+fmc-write-eeprom.txt
+	- about drivers/fmc/fmc-write-eeprom.ko
+
+fmc-chardev.txt
+	- about drivers/fmc/fmc-chardev.ko

+ 47 - 0
Documentation/fmc/API.txt

@@ -0,0 +1,47 @@
+Functions Exported by fmc.ko
+****************************
+
+The FMC core exports the usual 4 functions that are needed for a bus to
+work, and a few more:
+
+        int fmc_driver_register(struct fmc_driver *drv);
+        void fmc_driver_unregister(struct fmc_driver *drv);
+        int fmc_device_register(struct fmc_device *fmc);
+        void fmc_device_unregister(struct fmc_device *fmc);
+
+        int fmc_device_register_n(struct fmc_device **fmc, int n);
+        void fmc_device_unregister_n(struct fmc_device **fmc, int n);
+
+        uint32_t fmc_readl(struct fmc_device *fmc, int offset);
+        void fmc_writel(struct fmc_device *fmc, uint32_t val, int off);
+        void *fmc_get_drvdata(struct fmc_device *fmc);
+        void fmc_set_drvdata(struct fmc_device *fmc, void *data);
+
+        int fmc_reprogram(struct fmc_device *f, struct fmc_driver *d, char *gw,
+                          int sdb_entry);
+
+The data structure that describe a device is detailed in *note FMC
+Device::, the one that describes a driver is detailed in *note FMC
+Driver::.  Please note that structures of type fmc_device must be
+allocated by the caller, but must not be released after unregistering.
+The fmc-bus itself takes care of releasing the structure when their use
+count reaches zero - actually, the device model does that in lieu of us.
+
+The functions to register and unregister n devices are meant to be used
+by carriers that host more than one mezzanine. The devices must all be
+registered at the same time because if the FPGA is reprogrammed, all
+devices in the array are affected. Usually, the driver matching the
+first device will reprogram the FPGA, so other devices must know they
+are already driven by a reprogrammed FPGA.
+
+If a carrier hosts slots that are driven by different FPGA devices, it
+should register as a group only mezzanines that are driven by the same
+FPGA, for the reason outlined above.
+
+Finally, the fmc_reprogram function calls the reprogram method (see
+*note The API Offered by Carriers:: and also scans the memory area for
+an SDB tree. You can pass -1 as sdb_entry to disable such scan.
+Otherwise, the function fails if no tree is found at the specified
+entry point.  The function is meant to factorize common code, and by
+the time you read this it is already used by the spec-sw and fine-delay
+modules.

+ 88 - 0
Documentation/fmc/FMC-and-SDB.txt

@@ -0,0 +1,88 @@
+
+FMC (FPGA Mezzanine Card) is the standard we use for our I/O devices,
+in the context of White Rabbit and related hardware.
+
+In our I/O environments we need to write drivers for each mezzanine
+card, and such drivers must work regardless of the carrier being used.
+To achieve this, we abstract the FMC interface.
+
+We have a carrier for PCI-E called SPEC and one for VME called SVEC,
+but more are planned.  Also, we support stand-alone devices (usually
+plugged on a SPEC card), controlled through Etherbone, developed by GSI.
+
+Code and documentation for the FMC bus was born as part of the spec-sw
+project, but now it lives in its own project. Other projects, i.e.
+software support for the various carriers, should include this as a
+submodule.
+
+The most up to date version of code and documentation is always
+available from the repository you can clone from:
+
+        git://ohwr.org/fmc-projects/fmc-bus.git (read-only)
+        git@ohwr.org:fmc-projects/fmc-bus.git (read-write for developers)
+
+Selected versions of the documentation, as well as complete tar
+archives for selected revisions are placed to the Files section of the
+project: `http://www.ohwr.org/projects/fmc-bus/files'
+
+
+What is FMC
+***********
+
+FMC, as said, stands for "FPGA Mezzanine Card". It is a standard
+developed by the VME consortium called VITA (VMEbus International Trade
+Association and ratified by ANSI, the American National Standard
+Institute.  The official documentation is called "ANSI-VITA 57.1".
+
+The FMC card is an almost square PCB, around 70x75 millimeters, that is
+called mezzanine in this document.  It usually lives plugged into
+another PCB for power supply and control; such bigger circuit board is
+called carrier from now on, and a single carrier may host more than one
+mezzanine.
+
+In the typical application the mezzanine is mostly analog while the
+carrier is mostly digital, and hosts an FPGA that must be configured to
+match the specific mezzanine and the desired application. Thus, you may
+need to load different FPGA images to drive different instances of the
+same mezzanine.
+
+FMC, as such, is not a bus in the usual meaning of the term, because
+most carriers have only one connector, and carriers with several
+connectors have completely separate electrical connections to them.
+This package, however, implements a bus as a software abstraction.
+
+
+What is SDB
+***********
+
+SDB (Self Describing Bus) is a set of data structures that we use for
+enumerating the internal structure of an FPGA image. We also use it as
+a filesystem inside the FMC EEPROM.
+
+SDB is not mandatory for use of this FMC kernel bus, but if you have SDB
+this package can make good use of it.  SDB itself is developed in the
+fpga-config-space OHWR project. The link to the repository is
+`git://ohwr.org/hdl-core-lib/fpga-config-space.git' and what is used in
+this project lives in the sdbfs subdirectory in there.
+
+SDB support for FMC is described in *note FMC Identification:: and
+*note SDB Support::
+
+
+SDB Support
+***********
+
+The fmc.ko bus driver exports a few functions to help drivers taking
+advantage of the SDB information that may be present in your own FPGA
+memory image.
+
+The module exports the following functions, in the special header
+<linux/fmc-sdb.h>. The linux/ prefix in the name is there because we
+plan to submit it upstream in the future, and don't want to force
+changes on our drivers if that happens.
+
+         int fmc_scan_sdb_tree(struct fmc_device *fmc, unsigned long address);
+         void fmc_show_sdb_tree(struct fmc_device *fmc);
+         signed long fmc_find_sdb_device(struct sdb_array *tree, uint64_t vendor,
+                                         uint32_t device, unsigned long *sz);
+         int fmc_free_sdb_tree(struct fmc_device *fmc);

+ 311 - 0
Documentation/fmc/carrier.txt

@@ -0,0 +1,311 @@
+FMC Device
+**********
+
+Within the Linux bus framework, the FMC device is created and
+registered by the carrier driver. For example, the PCI driver for the
+SPEC card fills a data structure for each SPEC that it drives, and
+registers an associated FMC device for each card.  The SVEC driver can
+do exactly the same for the VME carrier (actually, it should do it
+twice, because the SVEC carries two FMC mezzanines).  Similarly, an
+Etherbone driver will be able to register its own FMC devices, offering
+communication primitives through frame exchange.
+
+The contents of the EEPROM within the FMC are used for identification
+purposes, i.e. for matching the device with its own driver. For this
+reason the device structure includes a complete copy of the EEPROM
+(actually, the carrier driver may choose whether or not to return it -
+for example we most likely won't have the whole EEPROM available for
+Etherbone devices.
+
+The following listing shows the current structure defining a device.
+Please note that all the machinery is in place but some details may
+still change in the future.  For this reason, there is a version field
+at the beginning of the structure.  As usual, the minor number will
+change for compatible changes (like a new flag) and the major number
+will increase when an incompatible change happens (for example, a
+change in layout of some fmc data structures).  Device writers should
+just set it to the value FMC_VERSION, and be ready to get back -EINVAL
+at registration time.
+
+     struct fmc_device {
+             unsigned long version;
+             unsigned long flags;
+             struct module *owner;           /* char device must pin it */
+             struct fmc_fru_id id;           /* for EEPROM-based match */
+             struct fmc_operations *op;      /* carrier-provided */
+             int irq;                        /* according to host bus. 0 == none */
+             int eeprom_len;                 /* Usually 8kB, may be less */
+             int eeprom_addr;                /* 0x50, 0x52 etc */
+             uint8_t *eeprom;                /* Full contents or leading part */
+             char *carrier_name;             /* "SPEC" or similar, for special use */
+             void *carrier_data;             /* "struct spec *" or equivalent */
+             __iomem void *fpga_base;        /* May be NULL (Etherbone) */
+             __iomem void *slot_base;        /* Set by the driver */
+             struct fmc_device **devarray;   /* Allocated by the bus */
+             int slot_id;                    /* Index in the slot array */
+             int nr_slots;                   /* Number of slots in this carrier */
+             unsigned long memlen;           /* Used for the char device */
+             struct device dev;              /* For Linux use */
+             struct device *hwdev;           /* The underlying hardware device */
+             unsigned long sdbfs_entry;
+             struct sdb_array *sdb;
+             uint32_t device_id;             /* Filled by the device */
+             char *mezzanine_name;           /* Defaults to ``fmc'' */
+             void *mezzanine_data;
+     };
+
+The meaning of most fields is summarized in the code comment above.
+
+The following fields must be filled by the carrier driver before
+registration:
+
+   * version: must be set to FMC_VERSION.
+
+   * owner: set to MODULE_OWNER.
+
+   * op: the operations to act on the device.
+
+   * irq: number for the mezzanine; may be zero.
+
+   * eeprom_len: length of the following array.
+
+   * eeprom_addr: 0x50 for first mezzanine and so on.
+
+   * eeprom: the full content of the I2C EEPROM.
+
+   * carrier_name.
+
+   * carrier_data: a unique pointer for the carrier.
+
+   * fpga_base: the I/O memory address (may be NULL).
+
+   * slot_id: the index of this slot (starting from zero).
+
+   * memlen: if fpga_base is valid, the length of I/O memory.
+
+   * hwdev: to be used in some dev_err() calls.
+
+   * device_id: a slot-specific unique integer number.
+
+
+Please note that the carrier should read its own EEPROM memory before
+registering the device, as well as fill all other fields listed above.
+
+The following fields should not be assigned, because they are filled
+later by either the bus or the device driver:
+
+   * flags.
+
+   * fru_id: filled by the bus, parsing the eeprom.
+
+   * slot_base: filled and used by the driver, if useful to it.
+
+   * devarray: an array og all mezzanines driven by a singe FPGA.
+
+   * nr_slots: set by the core at registration time.
+
+   * dev: used by Linux.
+
+   * sdb: FPGA contents, scanned according to driver's directions.
+
+   * sdbfs_entry: SDB entry point in EEPROM: autodetected.
+
+   * mezzanine_data: available for the driver.
+
+   * mezzanine_name: filled by fmc-bus during identification.
+
+
+Note: mezzanine_data may be redundant, because Linux offers the drvdata
+approach, so the field may be removed in later versions of this bus
+implementation.
+
+As I write this, she SPEC carrier is already completely functional in
+the fmc-bus environment, and is a good reference to look at.
+
+
+The API Offered by Carriers
+===========================
+
+The carrier provides a number of methods by means of the
+`fmc_operations' structure, which currently is defined like this
+(again, it is a moving target, please refer to the header rather than
+this document):
+
+     struct fmc_operations {
+             uint32_t (*readl)(struct fmc_device *fmc, int offset);
+             void (*writel)(struct fmc_device *fmc, uint32_t value, int offset);
+             int (*reprogram)(struct fmc_device *f, struct fmc_driver *d, char *gw);
+             int (*validate)(struct fmc_device *fmc, struct fmc_driver *drv);
+             int (*irq_request)(struct fmc_device *fmc, irq_handler_t h,
+                                char *name, int flags);
+             void (*irq_ack)(struct fmc_device *fmc);
+             int (*irq_free)(struct fmc_device *fmc);
+             int (*gpio_config)(struct fmc_device *fmc, struct fmc_gpio *gpio,
+                                int ngpio);
+             int (*read_ee)(struct fmc_device *fmc, int pos, void *d, int l);
+             int (*write_ee)(struct fmc_device *fmc, int pos, const void *d, int l);
+     };
+
+The individual methods perform the following tasks:
+
+`readl'
+`writel'
+     These functions access FPGA registers by whatever means the
+     carrier offers. They are not expected to fail, and most of the time
+     they will just make a memory access to the host bus. If the
+     carrier provides a fpga_base pointer, the driver may use direct
+     access through that pointer. For this reason the header offers the
+     inline functions fmc_readl and fmc_writel that access fpga_base if
+     the respective method is NULL. A driver that wants to be portable
+     and efficient should use fmc_readl and fmc_writel.  For Etherbone,
+     or other non-local carriers, error-management is still to be
+     defined.
+
+`validate'
+     Module parameters are used to manage different applications for
+     two or more boards of the same kind. Validation is based on the
+     busid module parameter, if provided, and returns the matching
+     index in the associated array. See *note Module Parameters:: in in
+     doubt. If no match is found, `-ENOENT' is returned; if the user
+     didn't pass `busid=', all devices will pass validation.  The value
+     returned by the validate method can be used as index into other
+     parameters (for example, some drivers use the `lm32=' parameter in
+     this way). Such "generic parameters" are documented in *note
+     Module Parameters::, below. The validate method is used by
+     `fmc-trivial.ko', described in *note fmc-trivial::.
+
+`reprogram'
+     The carrier enumerates FMC devices by loading a standard (or
+     golden) FPGA binary that allows EEPROM access. Each driver, then,
+     will need to reprogram the FPGA by calling this function.  If the
+     name argument is NULL, the carrier should reprogram the golden
+     binary. If the gateware name has been overridden through module
+     parameters (in a carrier-specific way) the file loaded will match
+     the parameters. Per-device gateware names can be specified using
+     the `gateware=' parameter, see *note Module Parameters::.  Note:
+     Clients should call rhe new helper, fmc_reprogram, which both
+     calls this method and parse the SDB tree of the FPGA.
+
+`irq_request'
+`irq_ack'
+`irq_free'
+     Interrupt management is carrier-specific, so it is abstracted as
+     operations. The interrupt number is listed in the device
+     structure, and for the mezzanine driver the number is only
+     informative.  The handler will receive the fmc pointer as dev_id;
+     the flags argument is passed to the Linux request_irq function,
+     but fmc-specific flags may be added in the future. You'll most
+     likely want to pass the `IRQF_SHARED' flag.
+
+`gpio_config'
+     The method allows to configure a GPIO pin in the carrier, and read
+     its current value if it is configured as input. See *note The GPIO
+     Abstraction:: for details.
+
+`read_ee'
+`write_ee'
+     Read or write the EEPROM. The functions are expected to be only
+     called before reprogramming and the carrier should refuse them
+     with `ENODEV' after reprogramming.  The offset is expected to be
+     within 8kB (the current size), but addresses up to 1MB are
+     reserved to fit bigger I2C devices in the future. Carriers may
+     offer access to other internal flash memories using these same
+     methods: for example the SPEC driver may define that its carrier
+     I2C memory is seen at offset 1M and the internal SPI flash is seen
+     at offset 16M.  This multiplexing of several flash memories in the
+     same address space is is carrier-specific and should only be used
+     by a driver that has verified the `carrier_name' field.
+
+
+
+The GPIO Abstraction
+====================
+
+Support for GPIO pins in the fmc-bus environment is not very
+straightforward and deserves special discussion.
+
+While the general idea of a carrier-independent driver seems to fly,
+configuration of specific signals within the carrier needs at least
+some knowledge of the carrier itself.  For this reason, the specific
+driver can request to configure carrier-specific GPIO pins, numbered
+from 0 to at most 4095.  Configuration is performed by passing a
+pointer to an array of struct fmc_gpio items, as well as the length of
+the array. This is the data structure:
+
+        struct fmc_gpio {
+                char *carrier_name;
+                int gpio;
+                int _gpio;      /* internal use by the carrier */
+                int mode;       /* GPIOF_DIR_OUT etc, from <linux/gpio.h> */
+                int irqmode;    /* IRQF_TRIGGER_LOW and so on */
+        };
+
+By specifying a carrier_name for each pin, the driver may access
+different pins in different carriers.  The gpio_config method is
+expected to return the number of pins successfully configured, ignoring
+requests for other carriers. However, if no pin is configured (because
+no structure at all refers to the current carrier_name), the operation
+returns an error so the caller will know that it is running under a
+yet-unsupported carrier.
+
+So, for example, a driver that has been developed and tested on both
+the SPEC and the SVEC may request configuration of two different GPIO
+pins, and expect one such configuration to succeed - if none succeeds
+it most likely means that the current carrier is a still-unknown one.
+
+If, however, your GPIO pin has a specific known role, you can pass a
+special number in the gpio field, using one of the following macros:
+
+        #define FMC_GPIO_RAW(x)         (x)             /* 4096 of them */
+        #define FMC_GPIO_IRQ(x)         ((x) + 0x1000)  /*  256 of them */
+        #define FMC_GPIO_LED(x)         ((x) + 0x1100)  /*  256 of them */
+        #define FMC_GPIO_KEY(x)         ((x) + 0x1200)  /*  256 of them */
+        #define FMC_GPIO_TP(x)          ((x) + 0x1300)  /*  256 of them */
+        #define FMC_GPIO_USER(x)        ((x) + 0x1400)  /*  256 of them */
+
+Use of virtual GPIO numbers (anything but FMC_GPIO_RAW) is allowed
+provided the carrier_name field in the data structure is left
+unspecified (NULL). Each carrier is responsible for providing a mapping
+between virtual and physical GPIO numbers. The carrier may then use the
+_gpio field to cache the result of this mapping.
+
+All carriers must map their I/O lines to the sets above starting from
+zero.  The SPEC, for example, maps interrupt pins 0 and 1, and test
+points 0 through 3 (even if the test points on the PCB are called
+5,6,7,8).
+
+If, for example, a driver requires a free LED and a test point (for a
+scope probe to be plugged at some point during development) it may ask
+for FMC_GPIO_LED(0) and FMC_GPIO_TP(0). Each carrier will provide
+suitable GPIO pins.  Clearly, the person running the drivers will know
+the order used by the specific carrier driver in assigning leds and
+testpoints, so to make a carrier-dependent use of the diagnostic tools.
+
+In theory, some form of autodetection should be possible: a driver like
+the wr-nic (which uses IRQ(1) on the SPEC card) should configure
+IRQ(0), make a test with software-generated interrupts and configure
+IRQ(1) if the test fails. This probing step should be used because even
+if the wr-nic gateware is known to use IRQ1 on the SPEC, the driver
+should be carrier-independent and thus use IRQ(0) as a first bet -
+actually, the knowledge that IRQ0 may fail is carrier-dependent
+information, but using it doesn't make the driver unsuitable for other
+carriers.
+
+The return value of gpio_config is defined as follows:
+
+   * If no pin in the array can be used by the carrier, `-ENODEV'.
+
+   * If at least one virtual GPIO number cannot be mapped, `-ENOENT'.
+
+   * On success, 0 or positive. The value returned is the number of
+     high input bits (if no input is configured, the value for success
+     is 0).
+
+While I admit the procedure is not completely straightforward, it
+allows configuration, input and output with a single carrier operation.
+Given the typical use case of FMC devices, GPIO operations are not
+expected to ever by in hot paths, and GPIO access so fare has only been
+used to configure the interrupt pin, mode and polarity. Especially
+reading inputs is not expected to be common. If your device has GPIO
+capabilities in the hot path, you should consider using the kernel's
+GPIO mechanisms.

+ 64 - 0
Documentation/fmc/fmc-chardev.txt

@@ -0,0 +1,64 @@
+fmc-chardev
+===========
+
+This is a simple generic driver, that allows user access by means of a
+character device (actually, one for each mezzanine it takes hold of).
+
+The char device is created as a misc device. Its name in /dev (as
+created by udev) is the same name as the underlying FMC device. Thus,
+the name can be a silly fmc-0000 look-alike if the device has no
+identifiers nor bus_id, a more specific fmc-0400 if the device has a
+bus-specific address but no associated name, or something like
+fdelay-0400 if the FMC core can rely on both a mezzanine name and a bus
+address.
+
+Currently the driver only supports read and write: you can lseek to the
+desired address and read or write a register.
+
+The driver assumes all registers are 32-bit in size, and only accepts a
+single read or write per system call. However, as a result of Unix read
+and write semantics, users can simply fread or fwrite bigger areas in
+order to dump or store bigger memory areas.
+
+There is currently no support for mmap, user-space interrupt management
+and DMA buffers. They may be added in later versions, if the need
+arises.
+
+The example below shows raw access to a SPEC card programmed with its
+golden FPGA file, that features an SDB structure at offset 256 - i.e.
+64 words.  The mezzanine's EEPROM in this case is not programmed, so the
+default name is fmc-<bus><devfn>, and there are two cards in the system:
+
+  spusa.root# insmod fmc-chardev.ko
+  [ 1073.339332] spec 0000:02:00.0: Driver has no ID: matches all
+  [ 1073.345051] spec 0000:02:00.0: Created misc device "fmc-0200"
+  [ 1073.350821] spec 0000:04:00.0: Driver has no ID: matches all
+  [ 1073.356525] spec 0000:04:00.0: Created misc device "fmc-0400"
+  spusa.root# ls -l /dev/fmc*
+  crw------- 1 root root 10, 58 Nov 20 19:23 /dev/fmc-0200
+  crw------- 1 root root 10, 57 Nov 20 19:23 /dev/fmc-0400
+  spusa.root# dd bs=4 skip=64 count=1 if=/dev/fmc-0200 2> /dev/null | od -t x1z
+  0000000 2d 42 44 53                                      >-BDS<
+  0000004
+
+The simple program tools/fmc-mem in this package can access an FMC char
+device and read or write a word or a whole area.  Actually, the program
+is not specific to FMC at all, it just uses lseek, read and write.
+
+Its first argument is the device name, the second the offset, the third
+(if any) the value to write and the optional last argument that must
+begin with "+" is the number of bytes to read or write.  In case of
+repeated reading data is written to stdout; repeated writes read from
+stdin and the value argument is ignored.
+
+The following examples show reading the SDB magic number and the first
+SDB record from a SPEC device programmed with its golden image:
+
+     spusa.root# ./fmc-mem /dev/fmc-0200 100
+     5344422d
+     spusa.root# ./fmc-mem /dev/fmc-0200 100 +40 | od -Ax -t x1z
+     000000 2d 42 44 53 00 01 02 00 00 00 00 00 00 00 00 00  >-BDS............<
+     000010 00 00 00 00 ff 01 00 00 00 00 00 00 51 06 00 00  >............Q...<
+     000020 c9 42 a5 e6 02 00 00 00 11 05 12 20 2d 34 42 57  >.B......... -4BW<
+     000030 73 6f 72 43 72 61 62 73 49 53 47 2d 00 20 20 20  >sorCrabsISG-.   <
+     000040

+ 36 - 0
Documentation/fmc/fmc-fakedev.txt

@@ -0,0 +1,36 @@
+fmc-fakedev
+===========
+
+This package includes a software-only device, called fmc-fakedev, which
+is able to register up to 4 mezzanines (by default it registers one).
+Unlike the SPEC driver, which creates an FMC device for each PCI cards
+it manages, this module creates a single instance of its set of
+mezzanines.
+
+It is meant as the simplest possible example of how a driver should be
+written, and it includes a fake EEPROM image (built using the tools
+described in *note FMC Identification::),, which by default is
+replicated for each fake mezzanine.
+
+You can also use this device to verify the match algorithms, by asking
+it to test your own EEPROM image. You can provide the image by means of
+the eeprom= module parameter: the new EEPROM image is loaded, as usual,
+by means of the firmware loader.  This example shows the defaults and a
+custom EEPROM image:
+
+     spusa.root# insmod fmc-fakedev.ko
+     [   99.971247]  fake-fmc-carrier: mezzanine 0
+     [   99.975393]       Manufacturer: fake-vendor
+     [   99.979624]       Product name: fake-design-for-testing
+     spusa.root# rmmod fmc-fakedev
+     spusa.root# insmod fmc-fakedev.ko eeprom=fdelay-eeprom.bin
+     [  121.447464]  fake-fmc-carrier: Mezzanine 0: eeprom "fdelay-eeprom.bin"
+     [  121.462725]  fake-fmc-carrier: mezzanine 0
+     [  121.466858]       Manufacturer: CERN
+     [  121.470477]       Product name: FmcDelay1ns4cha
+     spusa.root# rmmod fmc-fakedev
+
+After loading the device, you can use the write_ee method do modify its
+own internal fake EEPROM: whenever the image is overwritten starting at
+offset 0, the module will unregister and register again the FMC device.
+This is shown in fmc-write-eeprom.txt

+ 17 - 0
Documentation/fmc/fmc-trivial.txt

@@ -0,0 +1,17 @@
+fmc-trivial
+===========
+
+The simple module fmc-trivial is just a simple client that registers an
+interrupt handler. I used it to verify the basic mechanism of the FMC
+bus and how interrupts worked.
+
+The module implements the generic FMC parameters, so it can program a
+different gateware file in each card. The whole list of parameters it
+accepts are:
+
+`busid='
+`gateware='
+     Generic parameters. See mezzanine.txt
+
+
+This driver is worth reading, in my opinion.

+ 125 - 0
Documentation/fmc/fmc-write-eeprom.txt

@@ -0,0 +1,125 @@
+fmc-write-eeprom
+================
+
+This module is designed to load a binary file from /lib/firmware and to
+write it to the internal EEPROM of the mezzanine card. This driver uses
+the `busid' generic parameter.
+
+Overwriting the EEPROM is not something you should do daily, and it is
+expected to only happen during manufacturing. For this reason, the
+module makes it unlikely for the random user to change a working EEPROM.
+
+The module takes the following measures:
+
+   * It accepts a `file=' argument (within /lib/firmware) and if no
+     such argument is received, it doesn't write anything to EEPROM
+     (i.e. there is no default file name).
+
+   * If the file name ends with `.bin' it is written verbatim starting
+     at offset 0.
+
+   * If the file name ends with `.tlv' it is interpreted as
+     type-length-value (i.e., it allows writev(2)-like operation).
+
+   * If the file name doesn't match any of the patterns above, it is
+     ignored and no write is performed.
+
+   * Only cards listed with `busid=' are written to. If no busid is
+     specified, no programming is done (and the probe function of the
+     driver will fail).
+
+
+Each TLV tuple is formatted in this way: the header is 5 bytes,
+followed by data. The first byte is `w' for write, the next two bytes
+represent the address, in little-endian byte order, and the next two
+represent the data length, in little-endian order. The length does not
+include the header (it is the actual number of bytes to be written).
+
+This is a real example: that writes 5 bytes at position 0x110:
+
+        spusa.root# od -t x1 -Ax /lib/firmware/try.tlv
+        000000 77 10 01 05 00 30 31 32 33 34
+        00000a
+        spusa.root# insmod /tmp/fmc-write-eeprom.ko busid=0x0200 file=try.tlv
+        [19983.391498] spec 0000:03:00.0: write 5 bytes at 0x0110
+        [19983.414615] spec 0000:03:00.0: write_eeprom: success
+
+Please note that you'll most likely want to use SDBFS to build your
+EEPROM image, at least if your mezzanines are being used in the White
+Rabbit environment. For this reason the TLV format is not expected to
+be used much and is not expected to be developed further.
+
+If you want to try reflashing fake EEPROM devices, you can use the
+fmc-fakedev.ko module (see *note fmc-fakedev::).  Whenever you change
+the image starting at offset 0, it will deregister and register again
+after two seconds.  Please note, however, that if fmc-write-eeprom is
+still loaded, the system will associate it to the new device, which
+will be reprogrammed and thus will be unloaded after two seconds.  The
+following example removes the module after it reflashed fakedev the
+first time.
+
+     spusa.root# insmod fmc-fakedev.ko
+        [   72.984733]  fake-fmc: Manufacturer: fake-vendor
+        [   72.989434]  fake-fmc: Product name: fake-design-for-testing
+        spusa.root# insmod fmc-write-eeprom.ko busid=0 file=fdelay-eeprom.bin; \
+            rmmod fmc-write-eeprom
+        [  130.874098]  fake-fmc: Matching a generic driver (no ID)
+        [  130.887845]  fake-fmc: programming 6155 bytes
+        [  130.894567]  fake-fmc: write_eeprom: success
+        [  132.895794]  fake-fmc: Manufacturer: CERN
+        [  132.899872]  fake-fmc: Product name: FmcDelay1ns4cha
+
+
+Writing to the EEPROM
+=====================
+
+Once you have created a binary file for your EEPROM, you can write it
+to the storage medium using the fmc-write-eeprom (See *note
+fmc-write-eeprom::, while relying on a carrier driver.  The procedure
+here shown here uses the SPEC driver
+(`http://www.ohwr.org/projects/spec-sw').
+
+The example assumes no driver is already loaded (actually, I unloaded
+them by hand as everything loads automatically at boot time after you
+installed the modules), and shows kernel messages together with
+commands. Here the prompt is spusa.root# and two SPEC cards are plugged
+in the system.
+
+     spusa.root# insmod fmc.ko
+     spusa.root# insmod spec.ko
+     [13972.382818] spec 0000:02:00.0:  probe for device 0002:0000
+     [13972.392773] spec 0000:02:00.0: got file "fmc/spec-init.bin", 1484404 (0x16a674) bytes
+     [13972.591388] spec 0000:02:00.0: FPGA programming successful
+     [13972.883011] spec 0000:02:00.0: EEPROM has no FRU information
+     [13972.888719] spec 0000:02:00.0: No device_id filled, using index
+     [13972.894676] spec 0000:02:00.0: No mezzanine_name found
+     [13972.899863] /home/rubini/wip/spec-sw/kernel/spec-gpio.c - spec_gpio_init
+     [13972.906578] spec 0000:04:00.0:  probe for device 0004:0000
+     [13972.916509] spec 0000:04:00.0: got file "fmc/spec-init.bin", 1484404 (0x16a674) bytes
+     [13973.115096] spec 0000:04:00.0: FPGA programming successful
+     [13973.401798] spec 0000:04:00.0: EEPROM has no FRU information
+     [13973.407474] spec 0000:04:00.0: No device_id filled, using index
+     [13973.413417] spec 0000:04:00.0: No mezzanine_name found
+     [13973.418600] /home/rubini/wip/spec-sw/kernel/spec-gpio.c - spec_gpio_init
+     spusa.root# ls /sys/bus/fmc/devices
+     fmc-0000  fmc-0001
+     spusa.root# insmod fmc-write-eeprom.ko busid=0x0200 file=fdelay-eeprom.bin
+     [14103.966259] spec 0000:02:00.0: Matching an generic driver (no ID)
+     [14103.975519] spec 0000:02:00.0: programming 6155 bytes
+     [14126.373762] spec 0000:02:00.0: write_eeprom: success
+     [14126.378770] spec 0000:04:00.0: Matching an generic driver (no ID)
+     [14126.384903] spec 0000:04:00.0: fmc_write_eeprom: no filename given: not programming
+     [14126.392600] fmc_write_eeprom: probe of fmc-0001 failed with error -2
+
+Reading back the EEPROM
+=======================
+
+In order to read back the binary content of the EEPROM of your
+mezzanine device, the bus creates a read-only sysfs file called eeprom
+for each mezzanine it knows about:
+
+   spusa.root# cd /sys/bus/fmc/devices; ls -l */eeprom
+   -r--r--r-- 1 root root 8192 Apr  9 16:53 FmcDelay1ns4cha-f001/eeprom
+   -r--r--r-- 1 root root 8192 Apr  9 17:19 fake-design-for-testing-f002/eeprom
+   -r--r--r-- 1 root root 8192 Apr  9 17:19 fake-design-for-testing-f003/eeprom
+   -r--r--r-- 1 root root 8192 Apr  9 17:19 fmc-f004/eeprom

+ 168 - 0
Documentation/fmc/identifiers.txt

@@ -0,0 +1,168 @@
+FMC Identification
+******************
+
+The FMC standard requires every compliant mezzanine to carry
+identification information in an I2C EEPROM.  The information must be
+laid out according to the "IPMI Platform Management FRU Information",
+where IPMI is a lie I'd better not expand, and FRU means "Field
+Replaceable Unit".
+
+The FRU information is an intricate unreadable binary blob that must
+live at offset 0 of the EEPROM, and typically extends for a few hundred
+bytes. The standard allows the application to use all the remaining
+storage area of the EEPROM as it wants.
+
+This chapter explains how to create your own EEPROM image and how to
+write it in your mezzanine, as well as how devices and drivers are
+paired at run time.  EEPROM programming uses tools that are part of this
+package and SDB (part of the fpga-config-space package).
+
+The first sections are only interesting for manufacturers who need to
+write the EEPROM. If you are just a software developer writing an FMC
+device or driver, you may jump straight to *note SDB Support::.
+
+
+Building the FRU Structure
+==========================
+
+If you want to know the internals of the FRU structure and despair, you
+can retrieve the document from
+`http://download.intel.com/design/servers/ipmi/FRU1011.pdf' .  The
+standard is awful and difficult without reason, so we only support the
+minimum mandatory subset - we create a simple structure and parse it
+back at run time, but we are not able to either generate or parse more
+arcane features like non-english languages and 6-bit text.  If you need
+more items of the FRU standard for your boards, please submit patches.
+
+This package includes the Python script that Matthieu Cattin wrote to
+generate the FRU binary blob, based on an helper libipmi by Manohar
+Vanga and Matthieu himself.  I changed the test script to receive
+parameters from the command line or from the environment (the command
+line takes precedence)
+
+To make a long story short, in order to build a standard-compliant
+binary file to be burned in your EEPROM, you need the following items:
+
+        Environment    Opt     Official Name          Default
+---------------------------------------------------------------------
+        FRU_VENDOR     -v      "Board Manufacturer"   fmc-example
+        FRU_NAME       -n      "Board Product Name"   mezzanine
+        FRU_SERIAL     -s      `Board Serial Number"  0001
+        FRU_PART       -p      "Board Part Number"    sample-part
+        FRU_OUTPUT     -o      not applicable         /dev/stdout
+
+The "Official Name" above is what you find in the FRU official
+documentation, chapter 11, page 7 ("Board Info Area Format").  The
+output option is used to save the generated binary to a specific file
+name instead of stdout.
+
+You can pass the items to the FRU generator either in the environment
+or on the command line.  This package has currently no support for
+specifying power consumption or such stuff, but I plan to add it as
+soon as I find some time for that.
+
+FIXME: consumption etc for FRU are here or in PTS?
+
+The following example creates a binary image for a specific board:
+
+        ./tools/fru-generator -v CERN -n FmcAdc100m14b4cha \
+               -s HCCFFIA___-CR000003 -p EDA-02063-V5-0 > eeprom.bin
+
+The following example shows a script that builds several binary EEPROM
+images for a series of boards, changing the serial number for each of
+them. The script uses a mix of environment variables and command line
+options, and uses the same string patterns shown above.
+
+        #!/bin/sh
+
+        export FRU_VENDOR="CERN"
+        export FRU_NAME="FmcAdc100m14b4cha"
+        export FRU_PART="EDA-02063-V5-0"
+
+        serial="HCCFFIA___-CR"
+
+        for number in $(seq 1 50); do
+           # build number-string "ns"
+           ns="$(printf %06d $number)"
+           ./fru-generator -s "${serial}${ns}" > eeprom-${ns}.bin
+        done
+
+
+Using SDB-FS in the EEPROM
+==========================
+
+If you want to use SDB as a filesystem in the EEPROM device within the
+mezzanine, you should create one such filesystem using gensdbfs, from
+the fpga-config-space package on OHWR.
+
+By using an SBD filesystem you can cluster several files in a single
+EEPROM, so both the host system and a soft-core running in the FPGA (if
+any) can access extra production-time information.
+
+We chose to use SDB as a storage filesystem because the format is very
+simple, and both the host system and the soft-core will likely already
+include support code for such format. The SDB library offered by the
+fpga-config-space is less than 1kB under LM32, so it proves quite up to
+the task.
+
+The SDB entry point (which acts as a directory listing) cannot live at
+offset zero in the flash device, because the FRU information must live
+there.  To avoid wasting precious storage space while still allowing
+for more-than-minimal FRU structures, the fmc.ko will look for the SDB
+record at address 256, 512 and 1024.
+
+In order to generate the complete EEPROM image you'll need a
+configuration file for gensdbfs: you tell the program where to place
+the sdb entry point, and you must force the FRU data file to be placed
+at the beginning of the storage device. If needed, you can also place
+other files at a special offset (we sometimes do it for backward
+compatibility with drivers we wrote before implementing SDB for flash
+memory).
+
+The directory tools/sdbfs of this package includes a well-commented
+example that you may want to use as a starting point (the comments are
+in the file called -SDB-CONFIG-).  Reading documentation for gensdbfs
+is a suggested first step anyways.
+
+This package (generic FMC bus support) only accesses two files in the
+EEPROM: the FRU information, at offset zero, with a suggested filename
+of IPMI-FRU and the short name for the mezzanine, in a file called
+name. The IPMI-FRU name is not mandatory, but a strongly suggested
+choice; the name filename is mandatory, because this is the preferred
+short name used by the FMC core.  For example, a name of "fdelay" may
+supplement a Product Name like "FmcDelay1ns4cha" - exactly as
+demonstrated in `tools/sdbfs'.
+
+Note: SDB access to flash memory is not yet supported, so the short
+name currently in use is just the "Product Name" FRU string.
+
+The example in tools/sdbfs includes an extra file, that is needed by
+the fine-delay driver, and must live at a known address of 0x1800.  By
+running gensdbfs on that directory you can output your binary EEPROM
+image (here below spusa$ is the shell prompt):
+
+        spusa$ ../fru-generator -v CERN -n FmcDelay1ns4cha -s proto-0 \
+                      -p EDA-02267-V3 > IPMI-FRU
+        spusa$ ls -l
+        total 16
+        -rw-rw-r-- 1 rubini staff 975 Nov 19 18:08 --SDB-CONFIG--
+        -rw-rw-r-- 1 rubini staff 216 Nov 19 18:13 IPMI-FRU
+        -rw-rw-r-- 1 rubini staff  11 Nov 19 18:04 fd-calib
+        -rw-rw-r-- 1 rubini staff   7 Nov 19 18:04 name
+        spusa$ sudo gensdbfs . /lib/firmware/fdelay-eeprom.bin
+        spusa$ sdb-read -l -e 0x100 /lib/firmware/fdelay-eeprom.bin
+        /home/rubini/wip/sdbfs/userspace/sdb-read: listing format is to be defined
+        46696c6544617461:2e202020  00000100-000018ff .
+        46696c6544617461:6e616d65  00000200-00000206 name
+        46696c6544617461:66642d63  00001800-000018ff fd-calib
+        46696c6544617461:49504d49  00000000-000000d7 IPMI-FRU
+        spusa$ ../fru-dump /lib/firmware/fdelay-eeprom.bin
+        /lib/firmware/fdelay-eeprom.bin: manufacturer: CERN
+        /lib/firmware/fdelay-eeprom.bin: product-name: FmcDelay1ns4cha
+        /lib/firmware/fdelay-eeprom.bin: serial-number: proto-0
+        /lib/firmware/fdelay-eeprom.bin: part-number: EDA-02267-V3
+
+As expected, the output file is both a proper sdbfs object and an IPMI
+FRU information blob. The fd-calib file lives at offset 0x1800 and is
+over-allocated to 256 bytes, according to the configuration file for
+gensdbfs.

+ 123 - 0
Documentation/fmc/mezzanine.txt

@@ -0,0 +1,123 @@
+FMC Driver
+**********
+
+An FMC driver is concerned with the specific mezzanine and associated
+gateware. As such, it is expected to be independent of the carrier
+being used: it will perform I/O accesses only by means of
+carrier-provided functions.
+
+The matching between device and driver is based on the content of the
+EEPROM (as mandated by the FMC standard) or by the actual cores
+configured in the FPGA; the latter technique is used when the FPGA is
+already programmed when the device is registered to the bus core.
+
+In some special cases it is possible for a driver to directly access
+FPGA registers, by means of the `fpga_base' field of the device
+structure. This may be needed for high-bandwidth peripherals like fast
+ADC cards. If the device module registered a remote device (for example
+by means of Etherbone), the `fpga_base' pointer will be NULL.
+Therefore, drivers must be ready to deal with NULL base pointers, and
+fail gracefully.  Most driver, however, are not expected to access the
+pointer directly but run fmc_readl and fmc_writel instead, which will
+work in any case.
+
+In even more special cases, the driver may access carrier-specific
+functionality: the `carrier_name' string allows the driver to check
+which is the current carrier and make use of the `carrier_data'
+pointer.  We chose to use carrier names rather than numeric identifiers
+for greater flexibility, but also to avoid a central registry within
+the `fmc.h' file - we hope other users will exploit our framework with
+their own carriers.  An example use of carrier names is in GPIO setup
+(see *note The GPIO Abstraction::), although the name match is not
+expected to be performed by the driver.  If you depend on specific
+carriers, please check the carrier name and fail gracefully if your
+driver finds it is running in a yet-unknown-to-it environment.
+
+
+ID Table
+========
+
+Like most other Linux drivers, and FMC driver must list all the devices
+which it is able to drive.  This is usually done by means of a device
+table, but in FMC we can match hardware based either on the contents of
+their EEPROM or on the actual FPGA cores that can be enumerated.
+Therefore, we have two tables of identifiers.
+
+Matching of FRU information depends on two names, the manufacturer (or
+vendor) and the device (see *note FMC Identification::); for
+flexibility during production (i.e. before writing to the EEPROM) the
+bus supports a catch-all driver that specifies NULL strings. For this
+reason, the table is specified as pointer-and-length, not a a
+null-terminated array - the entry with NULL names can be a valid entry.
+
+Matching on FPGA cores depends on two numeric fields: the 64-bit vendor
+number and the 32-bit device number. Support for matching based on
+class is not yet implemented.  Each device is expected to be uniquely
+identified by an array of cores (it matches if all of the cores are
+instantiated), and for consistency the list is passed as
+pointer-and-length.  Several similar devices can be driven by the same
+driver, and thus the driver specifies and array of such arrays.
+
+The complete set of involved data structures is thus the following:
+
+        struct fmc_fru_id { char *manufacturer; char *product_name; };
+        struct fmc_sdb_one_id { uint64_t vendor; uint32_t device; };
+        struct fmc_sdb_id { struct fmc_sdb_one_id *cores; int cores_nr; };
+
+        struct fmc_device_id {
+                struct fmc_fru_id *fru_id; int fru_id_nr;
+                struct fmc_sdb_id *sdb_id; int sdb_id_nr;
+        };
+
+A better reference, with full explanation, is the <linux/fmc.h> header.
+
+
+Module Parameters
+=================
+
+Most of the FMC drivers need the same set of kernel parameters. This
+package includes support to implement common parameters by means of
+fields in the `fmc_driver' structure and simple macro definitions.
+
+The parameters are carrier-specific, in that they rely on the busid
+concept, that varies among carriers. For the SPEC, the identifier is a
+PCI bus and devfn number, 16 bits wide in total; drivers for other
+carriers will most likely offer something similar but not identical,
+and some code duplication is unavoidable.
+
+This is the list of parameters that are common to several modules to
+see how they are actually used, please look at spec-trivial.c.
+
+`busid='
+     This is an array of integers, listing carrier-specific
+     identification numbers. For PIC, for example, `0x0400' represents
+     bus 4, slot 0.  If any such ID is specified, the driver will only
+     accept to drive cards that appear in the list (even if the FMC ID
+     matches). This is accomplished by the validate carrier method.
+
+`gateware='
+     The argument is an array of strings. If no busid= is specified,
+     the first string of gateware= is used for all cards; otherwise the
+     identifiers and gateware names are paired one by one, in the order
+     specified.
+
+`show_sdb='
+     For modules supporting it, this parameter asks to show the SDB
+     internal structure by means of kernel messages. It is disabled by
+     default because those lines tend to hide more important messages,
+     if you look at the system console while loading the drivers.
+     Note: the parameter is being obsoleted, because fmc.ko itself now
+     supports dump_sdb= that applies to every client driver.
+
+
+For example, if you are using the trivial driver to load two different
+gateware files to two different cards, you can use the following
+parameters to load different binaries to the cards, after looking up
+the PCI identifiers. This has been tested with a SPEC carrier.
+
+        insmod fmc-trivial.ko \
+                              busid=0x0200,0x0400 \
+                              gateware=fmc/fine-delay.bin,fmc/simple-dio.bin
+
+Please note that not all sub-modules support all of those parameters.
+You can use modinfo to check what is supported by each module.

+ 56 - 0
Documentation/fmc/parameters.txt

@@ -0,0 +1,56 @@
+Module Parameters in fmc.ko
+***************************
+
+The core driver receives two module parameters, meant to help debugging
+client modules. Both parameters can be modified by writing to
+/sys/module/fmc/parameters/, because they are used when client drivers
+are devices are registered, not when fmc.ko is loaded.
+
+`dump_eeprom='
+     If not zero, the parameter asks the bus controller to dump the
+     EEPROM of any device that is registered, using printk.
+
+`dump_sdb='
+     If not zero, the parameter prints the SDB tree of every FPGA it is
+     loaded by fmc_reprogram(). If greater than one, it asks to dump
+     the binary content of SDB records.  This currently only dumps the
+     top-level SDB array, though.
+
+
+EEPROM dumping avoids repeating lines, since most of the contents is
+usually empty and all bits are one or zero. This is an example of the
+output:
+
+        [ 6625.850480] spec 0000:02:00.0: FPGA programming successful
+        [ 6626.139949] spec 0000:02:00.0: Manufacturer: CERN
+        [ 6626.144666] spec 0000:02:00.0: Product name: FmcDelay1ns4cha
+        [ 6626.150370] FMC: mezzanine 0: 0000:02:00.0 on SPEC
+        [ 6626.155179] FMC: dumping eeprom 0x2000 (8192) bytes
+        [ 6626.160087] 0000: 01 00 00 01  00 0b 00 f3  01 0a 00 a5  85 87 c4 43
+        [ 6626.167069] 0010: 45 52 4e cf  46 6d 63 44  65 6c 61 79  31 6e 73 34
+        [ 6626.174019] 0020: 63 68 61 c7  70 72 6f 74  6f 2d 30 cc  45 44 41 2d
+        [ 6626.180975] 0030: 30 32 32 36  37 2d 56 33  da 32 30 31  32 2d 31 31
+        [...]
+        [ 6626.371366] 0200: 66 64 65 6c  61 79 0a 00  00 00 00 00  00 00 00 00
+        [ 6626.378359] 0210: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00
+        [ 6626.385361] [...]
+        [ 6626.387308] 1800: 70 6c 61 63  65 68 6f 6c  64 65 72 ff  ff ff ff ff
+        [ 6626.394259] 1810: ff ff ff ff  ff ff ff ff  ff ff ff ff  ff ff ff ff
+        [ 6626.401250] [...]
+
+The dump of SDB looks like the following; the example shows the simple
+golden gateware for the SPEC card, removing the leading timestamps to
+fit the page:
+
+        spec 0000:02:00.0: SDB: 00000651:e6a542c9 WB4-Crossbar-GSI
+        spec 0000:02:00.0: SDB: 0000ce42:ff07fc47 WR-Periph-Syscon (00000000-000000ff)
+        FMC: mezzanine 0: 0000:02:00.0 on SPEC
+        FMC: poor dump of sdb first level:
+        0000: 53 44 42 2d  00 02 01 00  00 00 00 00  00 00 00 00
+        0010: 00 00 00 00  00 00 01 ff  00 00 00 00  00 00 06 51
+        0020: e6 a5 42 c9  00 00 00 02  20 12 05 11  57 42 34 2d
+        0030: 43 72 6f 73  73 62 61 72  2d 47 53 49  20 20 20 00
+        0040: 00 00 01 01  00 00 00 07  00 00 00 00  00 00 00 00
+        0050: 00 00 00 00  00 00 00 ff  00 00 00 00  00 00 ce 42
+        0060: ff 07 fc 47  00 00 00 01  20 12 03 05  57 52 2d 50
+        0070: 65 72 69 70  68 2d 53 79  73 63 6f 6e  20 20 20 01

+ 2 - 2
Documentation/w1/w1.generic

@@ -25,8 +25,8 @@ When a w1 master driver registers with the w1 subsystem, the following occurs:
  - sysfs entries for that w1 master are created
  - the w1 bus is periodically searched for new slave devices
 
-When a device is found on the bus, w1 core checks if driver for its family is
-loaded. If so, the family driver is attached to the slave.
+When a device is found on the bus, w1 core tries to load the driver for its family
+and check if it is loaded. If so, the family driver is attached to the slave.
 If there is no driver for the family, default one is assigned, which allows to perform
 almost any kind of operations. Each logical operation is a transaction
 in nature, which can contain several (two or one) low-level operations.

+ 10 - 0
MAINTAINERS

@@ -3309,6 +3309,15 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/floppy.git
 S:	Odd fixes
 F:	drivers/block/floppy.c
 
+FMC SUBSYSTEM
+M:	Alessandro Rubini <rubini@gnudd.com>
+W:	http://www.ohwr.org/projects/fmc-bus
+S:	Supported
+F:	drivers/fmc/
+F:	include/linux/fmc*.h
+F:	include/linux/ipmi-fru.h
+K:	fmc_d.*register
+
 FPU EMULATOR
 M:	Bill Metzenthen <billm@melbpc.org.au>
 W:	http://floatingpoint.sourceforge.net/emulator/index.html
@@ -7667,6 +7676,7 @@ STABLE BRANCH
 M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:	stable@vger.kernel.org
 S:	Supported
+F:	Documentation/stable_kernel_rules.txt
 
 STAGING SUBSYSTEM
 M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>

+ 2 - 0
drivers/Kconfig

@@ -166,4 +166,6 @@ source "drivers/ipack/Kconfig"
 
 source "drivers/reset/Kconfig"
 
+source "drivers/fmc/Kconfig"
+
 endmenu

+ 1 - 0
drivers/Makefile

@@ -152,3 +152,4 @@ obj-$(CONFIG_IIO)		+= iio/
 obj-$(CONFIG_VME_BUS)		+= vme/
 obj-$(CONFIG_IPACK_BUS)		+= ipack/
 obj-$(CONFIG_NTB)		+= ntb/
+obj-$(CONFIG_FMC)		+= fmc/

+ 3 - 3
drivers/char/hpet.c

@@ -725,7 +725,7 @@ static int hpet_is_known(struct hpet_data *hdp)
 	return 0;
 }
 
-static ctl_table hpet_table[] = {
+static struct ctl_table hpet_table[] = {
 	{
 	 .procname = "max-user-freq",
 	 .data = &hpet_max_freq,
@@ -736,7 +736,7 @@ static ctl_table hpet_table[] = {
 	{}
 };
 
-static ctl_table hpet_root[] = {
+static struct ctl_table hpet_root[] = {
 	{
 	 .procname = "hpet",
 	 .maxlen = 0,
@@ -746,7 +746,7 @@ static ctl_table hpet_root[] = {
 	{}
 };
 
-static ctl_table dev_root[] = {
+static struct ctl_table dev_root[] = {
 	{
 	 .procname = "dev",
 	 .maxlen = 0,

+ 3 - 3
drivers/char/ipmi/ipmi_poweroff.c

@@ -659,7 +659,7 @@ static struct ipmi_smi_watcher smi_watcher = {
 #ifdef CONFIG_PROC_FS
 #include <linux/sysctl.h>
 
-static ctl_table ipmi_table[] = {
+static struct ctl_table ipmi_table[] = {
 	{ .procname	= "poweroff_powercycle",
 	  .data		= &poweroff_powercycle,
 	  .maxlen	= sizeof(poweroff_powercycle),
@@ -668,14 +668,14 @@ static ctl_table ipmi_table[] = {
 	{ }
 };
 
-static ctl_table ipmi_dir_table[] = {
+static struct ctl_table ipmi_dir_table[] = {
 	{ .procname	= "ipmi",
 	  .mode		= 0555,
 	  .child	= ipmi_table },
 	{ }
 };
 
-static ctl_table ipmi_root_table[] = {
+static struct ctl_table ipmi_root_table[] = {
 	{ .procname	= "dev",
 	  .mode		= 0555,
 	  .child	= ipmi_dir_table },

+ 1 - 1
drivers/char/mem.c

@@ -745,7 +745,7 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig)
 		offset += file->f_pos;
 	case SEEK_SET:
 		/* to avoid userland mistaking f_pos=-9 as -EBADF=-9 */
-		if ((unsigned long long)offset >= ~0xFFFULL) {
+		if (IS_ERR_VALUE((unsigned long long)offset)) {
 			ret = -EOVERFLOW;
 			break;
 		}

+ 1 - 1
drivers/char/mspec.c

@@ -267,7 +267,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma,
 	if ((vma->vm_flags & VM_WRITE) == 0)
 		return -EPERM;
 
-	pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+	pages = vma_pages(vma);
 	vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
 	if (vdata_size <= PAGE_SIZE)
 		vdata = kzalloc(vdata_size, GFP_KERNEL);

+ 4 - 4
drivers/char/random.c

@@ -1381,10 +1381,10 @@ static char sysctl_bootid[16];
  * as an ASCII string in the standard UUID format.  If accesses via the
  * sysctl system call, it is returned as 16 bytes of binary data.
  */
-static int proc_do_uuid(ctl_table *table, int write,
+static int proc_do_uuid(struct ctl_table *table, int write,
 			void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-	ctl_table fake_table;
+	struct ctl_table fake_table;
 	unsigned char buf[64], tmp_uuid[16], *uuid;
 
 	uuid = table->data;
@@ -1409,8 +1409,8 @@ static int proc_do_uuid(ctl_table *table, int write,
 }
 
 static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
-extern ctl_table random_table[];
-ctl_table random_table[] = {
+extern struct ctl_table random_table[];
+struct ctl_table random_table[] = {
 	{
 		.procname	= "poolsize",
 		.data		= &sysctl_poolsize,

+ 3 - 3
drivers/char/rtc.c

@@ -280,7 +280,7 @@ static irqreturn_t rtc_interrupt(int irq, void *dev_id)
 /*
  * sysctl-tuning infrastructure.
  */
-static ctl_table rtc_table[] = {
+static struct ctl_table rtc_table[] = {
 	{
 		.procname	= "max-user-freq",
 		.data		= &rtc_max_user_freq,
@@ -291,7 +291,7 @@ static ctl_table rtc_table[] = {
 	{ }
 };
 
-static ctl_table rtc_root[] = {
+static struct ctl_table rtc_root[] = {
 	{
 		.procname	= "rtc",
 		.mode		= 0555,
@@ -300,7 +300,7 @@ static ctl_table rtc_root[] = {
 	{ }
 };
 
-static ctl_table dev_root[] = {
+static struct ctl_table dev_root[] = {
 	{
 		.procname	= "dev",
 		.mode		= 0555,

+ 8 - 2
drivers/char/xilinx_hwicap/xilinx_hwicap.h

@@ -37,7 +37,7 @@
 #include <linux/cdev.h>
 #include <linux/platform_device.h>
 
-#include <asm/io.h>
+#include <linux/io.h>
 
 struct hwicap_drvdata {
 	u32 write_buffer_in_use;  /* Always in [0,3] */
@@ -85,7 +85,13 @@ struct hwicap_driver_config {
 	void (*reset)(struct hwicap_drvdata *drvdata);
 };
 
-/* Number of times to poll the done regsiter */
+/* Number of times to poll the done register. This has to be large
+ * enough to allow an entire configuration to complete. If an entire
+ * page (4kb) is configured at once, that could take up to 4k cycles
+ * with a byte-wide icap interface. In most cases, this driver is
+ * used with a much smaller fifo, but this should be sufficient in the
+ * worst case.
+ */
 #define XHI_MAX_RETRIES     5000
 
 /************ Constant Definitions *************/

+ 7 - 0
drivers/extcon/Kconfig

@@ -53,4 +53,11 @@ config EXTCON_ARIZONA
 	  with Wolfson Arizona devices. These are audio CODECs with
 	  advanced audio accessory detection support.
 
+config EXTCON_PALMAS
+	tristate "Palmas USB EXTCON support"
+	depends on MFD_PALMAS
+	help
+	  Say Y here to enable support for USB peripheral and USB host
+	  detection by palmas usb.
+
 endif # MULTISTATE_SWITCH

+ 1 - 0
drivers/extcon/Makefile

@@ -8,3 +8,4 @@ obj-$(CONFIG_EXTCON_ADC_JACK)	+= extcon-adc-jack.o
 obj-$(CONFIG_EXTCON_MAX77693)	+= extcon-max77693.o
 obj-$(CONFIG_EXTCON_MAX8997)	+= extcon-max8997.o
 obj-$(CONFIG_EXTCON_ARIZONA)	+= extcon-arizona.o
+obj-$(CONFIG_EXTCON_PALMAS)	+= extcon-palmas.o

+ 3 - 22
drivers/extcon/extcon-class.c

@@ -185,26 +185,6 @@ static ssize_t cable_state_show(struct device *dev,
 					       cable->cable_index));
 }
 
-static ssize_t cable_state_store(struct device *dev,
-				 struct device_attribute *attr, const char *buf,
-				 size_t count)
-{
-	struct extcon_cable *cable = container_of(attr, struct extcon_cable,
-						  attr_state);
-	int ret, state;
-
-	ret = sscanf(buf, "%d", &state);
-	if (ret == 0)
-		ret = -EINVAL;
-	else
-		ret = extcon_set_cable_state_(cable->edev, cable->cable_index,
-					      state);
-
-	if (ret < 0)
-		return ret;
-	return count;
-}
-
 /**
  * extcon_update_state() - Update the cable attach states of the extcon device
  *			only for the masked bits.
@@ -501,6 +481,7 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
 		return -ENODEV;
 	}
 }
+EXPORT_SYMBOL_GPL(extcon_register_interest);
 
 /**
  * extcon_unregister_interest() - Unregister the notifier registered by
@@ -515,6 +496,7 @@ int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
 
 	return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb);
 }
+EXPORT_SYMBOL_GPL(extcon_unregister_interest);
 
 /**
  * extcon_register_notifier() - Register a notifiee to get notified by
@@ -665,9 +647,8 @@ int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
 
 			sysfs_attr_init(&cable->attr_state.attr);
 			cable->attr_state.attr.name = "state";
-			cable->attr_state.attr.mode = 0644;
+			cable->attr_state.attr.mode = 0444;
 			cable->attr_state.show = cable_state_show;
-			cable->attr_state.store = cable_state_store;
 		}
 	}
 

+ 246 - 0
drivers/extcon/extcon-palmas.c

@@ -0,0 +1,246 @@
+/*
+ * Palmas USB transceiver driver
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * Based on twl6030_usb.c
+ *
+ * Author: Hema HK <hemahk@ti.com>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/mfd/palmas.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+static const char *palmas_extcon_cable[] = {
+	[0] = "USB",
+	[1] = "USB-HOST",
+	NULL,
+};
+
+static const int mutually_exclusive[] = {0x3, 0x0};
+
+static void palmas_usb_wakeup(struct palmas *palmas, int enable)
+{
+	if (enable)
+		palmas_write(palmas, PALMAS_USB_OTG_BASE, PALMAS_USB_WAKEUP,
+			PALMAS_USB_WAKEUP_ID_WK_UP_COMP);
+	else
+		palmas_write(palmas, PALMAS_USB_OTG_BASE, PALMAS_USB_WAKEUP, 0);
+}
+
+static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb)
+{
+	struct palmas_usb *palmas_usb = _palmas_usb;
+	unsigned int vbus_line_state;
+
+	palmas_read(palmas_usb->palmas, PALMAS_INTERRUPT_BASE,
+		PALMAS_INT3_LINE_STATE, &vbus_line_state);
+
+	if (vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS) {
+		if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) {
+			palmas_usb->linkstat = PALMAS_USB_STATE_VBUS;
+			extcon_set_cable_state(&palmas_usb->edev, "USB", true);
+		} else {
+			dev_dbg(palmas_usb->dev,
+				"Spurious connect event detected\n");
+		}
+	} else if (!(vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS)) {
+		if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) {
+			palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
+			extcon_set_cable_state(&palmas_usb->edev, "USB", false);
+		} else {
+			dev_dbg(palmas_usb->dev,
+				"Spurious disconnect event detected\n");
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb)
+{
+	unsigned int set;
+	struct palmas_usb *palmas_usb = _palmas_usb;
+
+	palmas_read(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+		PALMAS_USB_ID_INT_LATCH_SET, &set);
+
+	if (set & PALMAS_USB_ID_INT_SRC_ID_GND) {
+		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+			PALMAS_USB_ID_INT_EN_HI_SET,
+			PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
+		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+			PALMAS_USB_ID_INT_EN_HI_CLR,
+			PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND);
+		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+			PALMAS_USB_ID_INT_LATCH_CLR,
+			PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND);
+		palmas_usb->linkstat = PALMAS_USB_STATE_ID;
+		extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true);
+	} else if (set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) {
+		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+			PALMAS_USB_ID_INT_EN_HI_SET,
+			PALMAS_USB_ID_INT_EN_HI_SET_ID_GND);
+		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+			PALMAS_USB_ID_INT_EN_HI_CLR,
+			PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT);
+		palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+			PALMAS_USB_ID_INT_LATCH_CLR,
+			PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT);
+		palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT;
+		extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void palmas_enable_irq(struct palmas_usb *palmas_usb)
+{
+	palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+		PALMAS_USB_VBUS_CTRL_SET,
+		PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP);
+
+	palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+		PALMAS_USB_ID_CTRL_SET, PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP);
+
+	palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+		PALMAS_USB_ID_INT_EN_HI_SET,
+		PALMAS_USB_ID_INT_EN_HI_SET_ID_GND);
+
+	palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb);
+
+	/* cold plug for host mode needs this delay */
+	msleep(30);
+	palmas_id_irq_handler(palmas_usb->id_irq, palmas_usb);
+}
+
+static int palmas_usb_probe(struct platform_device *pdev)
+{
+	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
+	struct palmas_usb_platform_data	*pdata = pdev->dev.platform_data;
+	struct device_node *node = pdev->dev.of_node;
+	struct palmas_usb *palmas_usb;
+	int status;
+
+	if (node && !pdata) {
+		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+
+		if (!pdata)
+			return -ENOMEM;
+
+		pdata->wakeup = of_property_read_bool(node, "ti,wakeup");
+	} else if (!pdata) {
+		return -EINVAL;
+	}
+
+	palmas_usb = devm_kzalloc(&pdev->dev, sizeof(*palmas_usb), GFP_KERNEL);
+	if (!palmas_usb)
+		return -ENOMEM;
+
+	palmas->usb = palmas_usb;
+	palmas_usb->palmas = palmas;
+
+	palmas_usb->dev	 = &pdev->dev;
+
+	palmas_usb->id_otg_irq = regmap_irq_get_virq(palmas->irq_data,
+						PALMAS_ID_OTG_IRQ);
+	palmas_usb->id_irq = regmap_irq_get_virq(palmas->irq_data,
+						PALMAS_ID_IRQ);
+	palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data,
+						PALMAS_VBUS_OTG_IRQ);
+	palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data,
+						PALMAS_VBUS_IRQ);
+
+	palmas_usb_wakeup(palmas, pdata->wakeup);
+
+	platform_set_drvdata(pdev, palmas_usb);
+
+	palmas_usb->edev.name = "palmas-usb";
+	palmas_usb->edev.supported_cable = palmas_extcon_cable;
+	palmas_usb->edev.mutually_exclusive = mutually_exclusive;
+
+	status = extcon_dev_register(&palmas_usb->edev, palmas_usb->dev);
+	if (status) {
+		dev_err(&pdev->dev, "failed to register extcon device\n");
+		return status;
+	}
+
+	status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->id_irq,
+			NULL, palmas_id_irq_handler,
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			"palmas_usb_id", palmas_usb);
+	if (status < 0) {
+		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
+					palmas_usb->id_irq, status);
+		goto fail_extcon;
+	}
+
+	status = devm_request_threaded_irq(palmas_usb->dev,
+			palmas_usb->vbus_irq, NULL, palmas_vbus_irq_handler,
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			"palmas_usb_vbus", palmas_usb);
+	if (status < 0) {
+		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
+					palmas_usb->vbus_irq, status);
+		goto fail_extcon;
+	}
+
+	palmas_enable_irq(palmas_usb);
+
+	return 0;
+
+fail_extcon:
+	extcon_dev_unregister(&palmas_usb->edev);
+
+	return status;
+}
+
+static int palmas_usb_remove(struct platform_device *pdev)
+{
+	struct palmas_usb *palmas_usb = platform_get_drvdata(pdev);
+
+	extcon_dev_unregister(&palmas_usb->edev);
+
+	return 0;
+}
+
+static struct of_device_id of_palmas_match_tbl[] = {
+	{ .compatible = "ti,palmas-usb", },
+	{ .compatible = "ti,twl6035-usb", },
+	{ /* end */ }
+};
+
+static struct platform_driver palmas_usb_driver = {
+	.probe = palmas_usb_probe,
+	.remove = palmas_usb_remove,
+	.driver = {
+		.name = "palmas-usb",
+		.of_match_table = of_palmas_match_tbl,
+		.owner = THIS_MODULE,
+	},
+};
+
+module_platform_driver(palmas_usb_driver);
+
+MODULE_ALIAS("platform:palmas-usb");
+MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
+MODULE_DESCRIPTION("Palmas USB transceiver driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, of_palmas_match_tbl);

+ 51 - 0
drivers/fmc/Kconfig

@@ -0,0 +1,51 @@
+#
+# FMC (ANSI-VITA 57.1) bus support
+#
+
+menuconfig FMC
+	tristate "FMC support"
+	help
+
+	  FMC (FPGA Mezzanine Carrier) is a mechanical and electrical
+	  standard for mezzanine cards that plug into a carrier board.
+	  This kernel subsystem supports the matching between carrier
+	  and mezzanine based on identifiers stored in the internal I2C
+	  EEPROM, as well as having carrier-independent drivers.
+
+	  The framework was born outside of the kernel and at this time
+	  the off-tree code base is more complete.  Code and documentation
+	  is at git://ohwr.org/fmc-projects/fmc-bus.git .
+
+if FMC
+
+config FMC_FAKEDEV
+	tristate "FMC fake device (software testing)"
+	help
+	  This is a fake carrier, bringing a default EEPROM content
+	  that can be rewritten at run time and usef for matching
+	  mezzanines.
+
+config FMC_TRIVIAL
+	tristate "FMC trivial mezzanine driver (software testing)"
+	help
+	  This is a fake mezzanine driver, to show how FMC works and test it.
+	  The driver also handles interrupts (we used it with a real carrier
+	  before the mezzanines were produced)
+
+config FMC_WRITE_EEPROM
+	tristate "FMC mezzanine driver to write I2C EEPROM"
+	help
+	  This driver matches every mezzanine device and can write the
+	  internal EEPROM of the PCB, using the firmware loader to get
+	  its binary and the function carrier->reprogram to actually do it.
+	  It is useful when the mezzanines are produced.
+
+config FMC_CHARDEV
+	tristate "FMC mezzanine driver that registers a char device"
+	help
+	  This driver matches every mezzanine device and allows user
+	  space to read and write registers using a char device. It
+	  can be used to write user-space drivers, or just get
+	  aquainted with a mezzanine before writing its specific driver.
+
+endif # FMC

+ 13 - 0
drivers/fmc/Makefile

@@ -0,0 +1,13 @@
+
+obj-$(CONFIG_FMC) += fmc.o
+
+fmc-y = fmc-core.o
+fmc-y += fmc-match.o
+fmc-y += fmc-sdb.o
+fmc-y += fru-parse.o
+fmc-y += fmc-dump.o
+
+obj-$(CONFIG_FMC_FAKEDEV) += fmc-fakedev.o
+obj-$(CONFIG_FMC_TRIVIAL) += fmc-trivial.o
+obj-$(CONFIG_FMC_WRITE_EEPROM) += fmc-write-eeprom.o
+obj-$(CONFIG_FMC_CHARDEV) += fmc-chardev.o

+ 202 - 0
drivers/fmc/fmc-chardev.c

@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2012 CERN (www.cern.ch)
+ * Author: Alessandro Rubini <rubini@gnudd.com>
+ *
+ * Released according to the GNU GPL, version 2 or any later version.
+ *
+ * This work is part of the White Rabbit project, a research effort led
+ * by CERN, the European Institute for Nuclear Research.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/spinlock.h>
+#include <linux/fmc.h>
+#include <linux/uaccess.h>
+
+static LIST_HEAD(fc_devices);
+static DEFINE_SPINLOCK(fc_lock);
+
+struct fc_instance {
+	struct list_head list;
+	struct fmc_device *fmc;
+	struct miscdevice misc;
+};
+
+/* at open time, we must identify our device */
+static int fc_open(struct inode *ino, struct file *f)
+{
+	struct fmc_device *fmc;
+	struct fc_instance *fc;
+	int minor = iminor(ino);
+
+	list_for_each_entry(fc, &fc_devices, list)
+		if (fc->misc.minor == minor)
+			break;
+	if (fc->misc.minor != minor)
+		return -ENODEV;
+	fmc = fc->fmc;
+	if (try_module_get(fmc->owner) == 0)
+		return -ENODEV;
+
+	f->private_data = fmc;
+	return 0;
+}
+
+static int fc_release(struct inode *ino, struct file *f)
+{
+	struct fmc_device *fmc = f->private_data;
+	module_put(fmc->owner);
+	return 0;
+}
+
+/* read and write are simple after the default llseek has been used */
+static ssize_t fc_read(struct file *f, char __user *buf, size_t count,
+		       loff_t *offp)
+{
+	struct fmc_device *fmc = f->private_data;
+	unsigned long addr;
+	uint32_t val;
+
+	if (count < sizeof(val))
+		return -EINVAL;
+	count = sizeof(val);
+
+	addr = *offp;
+	if (addr > fmc->memlen)
+		return -ESPIPE; /* Illegal seek */
+	val = fmc_readl(fmc, addr);
+	if (copy_to_user(buf, &val, count))
+		return -EFAULT;
+	*offp += count;
+	return count;
+}
+
+static ssize_t fc_write(struct file *f, const char __user *buf, size_t count,
+			loff_t *offp)
+{
+	struct fmc_device *fmc = f->private_data;
+	unsigned long addr;
+	uint32_t val;
+
+	if (count < sizeof(val))
+		return -EINVAL;
+	count = sizeof(val);
+
+	addr = *offp;
+	if (addr > fmc->memlen)
+		return -ESPIPE; /* Illegal seek */
+	if (copy_from_user(&val, buf, count))
+		return -EFAULT;
+	fmc_writel(fmc, val, addr);
+	*offp += count;
+	return count;
+}
+
+static const struct file_operations fc_fops = {
+	.owner = THIS_MODULE,
+	.open = fc_open,
+	.release = fc_release,
+	.llseek = generic_file_llseek,
+	.read = fc_read,
+	.write = fc_write,
+};
+
+
+/* Device part .. */
+static int fc_probe(struct fmc_device *fmc);
+static int fc_remove(struct fmc_device *fmc);
+
+static struct fmc_driver fc_drv = {
+	.version = FMC_VERSION,
+	.driver.name = KBUILD_MODNAME,
+	.probe = fc_probe,
+	.remove = fc_remove,
+	/* no table: we want to match everything */
+};
+
+/* We accept the generic busid parameter */
+FMC_PARAM_BUSID(fc_drv);
+
+/* probe and remove must allocate and release a misc device */
+static int fc_probe(struct fmc_device *fmc)
+{
+	int ret;
+	int index = 0;
+
+	struct fc_instance *fc;
+
+	if (fmc->op->validate)
+		index = fmc->op->validate(fmc, &fc_drv);
+	if (index < 0)
+		return -EINVAL; /* not our device: invalid */
+
+	/* Create a char device: we want to create it anew */
+	fc = kzalloc(sizeof(*fc), GFP_KERNEL);
+	if (!fc)
+		return -ENOMEM;
+	fc->fmc = fmc;
+	fc->misc.minor = MISC_DYNAMIC_MINOR;
+	fc->misc.fops = &fc_fops;
+	fc->misc.name = kstrdup(dev_name(&fmc->dev), GFP_KERNEL);
+
+	spin_lock(&fc_lock);
+	ret = misc_register(&fc->misc);
+	if (ret < 0)
+		goto err_unlock;
+	list_add(&fc->list, &fc_devices);
+	spin_unlock(&fc_lock);
+	dev_info(&fc->fmc->dev, "Created misc device \"%s\"\n",
+		 fc->misc.name);
+	return 0;
+
+err_unlock:
+	spin_unlock(&fc_lock);
+	kfree(fc->misc.name);
+	kfree(fc);
+	return ret;
+}
+
+static int fc_remove(struct fmc_device *fmc)
+{
+	struct fc_instance *fc;
+
+	list_for_each_entry(fc, &fc_devices, list)
+		if (fc->fmc == fmc)
+			break;
+	if (fc->fmc != fmc) {
+		dev_err(&fmc->dev, "remove called but not found\n");
+		return -ENODEV;
+	}
+
+	spin_lock(&fc_lock);
+	list_del(&fc->list);
+	misc_deregister(&fc->misc);
+	kfree(fc->misc.name);
+	kfree(fc);
+	spin_unlock(&fc_lock);
+
+	return 0;
+}
+
+
+static int fc_init(void)
+{
+	int ret;
+
+	ret = fmc_driver_register(&fc_drv);
+	return ret;
+}
+
+static void fc_exit(void)
+{
+	fmc_driver_unregister(&fc_drv);
+}
+
+module_init(fc_init);
+module_exit(fc_exit);
+
+MODULE_LICENSE("GPL");

+ 296 - 0
drivers/fmc/fmc-core.c

@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2012 CERN (www.cern.ch)
+ * Author: Alessandro Rubini <rubini@gnudd.com>
+ *
+ * Released according to the GNU GPL, version 2 or any later version.
+ *
+ * This work is part of the White Rabbit project, a research effort led
+ * by CERN, the European Institute for Nuclear Research.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/fmc.h>
+
+static int fmc_check_version(unsigned long version, const char *name)
+{
+	if (__FMC_MAJOR(version) != FMC_MAJOR) {
+		pr_err("%s: \"%s\" has wrong major (has %li, expected %i)\n",
+		       __func__, name, __FMC_MAJOR(version), FMC_MAJOR);
+		return -EINVAL;
+	}
+
+	if (__FMC_MINOR(version) != FMC_MINOR)
+		pr_info("%s: \"%s\" has wrong minor (has %li, expected %i)\n",
+		       __func__, name, __FMC_MINOR(version), FMC_MINOR);
+	return 0;
+}
+
+static int fmc_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	/* struct fmc_device *fdev = to_fmc_device(dev); */
+
+	/* FIXME: The MODALIAS */
+	add_uevent_var(env, "MODALIAS=%s", "fmc");
+	return 0;
+}
+
+static int fmc_probe(struct device *dev)
+{
+	struct fmc_driver *fdrv = to_fmc_driver(dev->driver);
+	struct fmc_device *fdev = to_fmc_device(dev);
+
+	return fdrv->probe(fdev);
+}
+
+static int fmc_remove(struct device *dev)
+{
+	struct fmc_driver *fdrv = to_fmc_driver(dev->driver);
+	struct fmc_device *fdev = to_fmc_device(dev);
+
+	return fdrv->remove(fdev);
+}
+
+static void fmc_shutdown(struct device *dev)
+{
+	/* not implemented but mandatory */
+}
+
+static struct bus_type fmc_bus_type = {
+	.name = "fmc",
+	.match = fmc_match,
+	.uevent = fmc_uevent,
+	.probe = fmc_probe,
+	.remove = fmc_remove,
+	.shutdown = fmc_shutdown,
+};
+
+static void fmc_release(struct device *dev)
+{
+	struct fmc_device *fmc = container_of(dev, struct fmc_device, dev);
+
+	kfree(fmc);
+}
+
+/*
+ * The eeprom is exported in sysfs, through a binary attribute
+ */
+
+static ssize_t fmc_read_eeprom(struct file *file, struct kobject *kobj,
+			   struct bin_attribute *bin_attr,
+			   char *buf, loff_t off, size_t count)
+{
+	struct device *dev;
+	struct fmc_device *fmc;
+	int eelen;
+
+	dev = container_of(kobj, struct device, kobj);
+	fmc = container_of(dev, struct fmc_device, dev);
+	eelen = fmc->eeprom_len;
+	if (off > eelen)
+		return -ESPIPE;
+	if (off == eelen)
+		return 0; /* EOF */
+	if (off + count > eelen)
+		count = eelen - off;
+	memcpy(buf, fmc->eeprom + off, count);
+	return count;
+}
+
+static struct bin_attribute fmc_eeprom_attr = {
+	.attr = { .name = "eeprom", .mode = S_IRUGO, },
+	.size = 8192, /* more or less standard */
+	.read = fmc_read_eeprom,
+};
+
+/*
+ * Functions for client modules follow
+ */
+
+int fmc_driver_register(struct fmc_driver *drv)
+{
+	if (fmc_check_version(drv->version, drv->driver.name))
+		return -EINVAL;
+	drv->driver.bus = &fmc_bus_type;
+	return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL(fmc_driver_register);
+
+void fmc_driver_unregister(struct fmc_driver *drv)
+{
+	driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(fmc_driver_unregister);
+
+/*
+ * When a device set is registered, all eeproms must be read
+ * and all FRUs must be parsed
+ */
+int fmc_device_register_n(struct fmc_device **devs, int n)
+{
+	struct fmc_device *fmc, **devarray;
+	uint32_t device_id;
+	int i, ret = 0;
+
+	if (n < 1)
+		return 0;
+
+	/* Check the version of the first data structure (function prints) */
+	if (fmc_check_version(devs[0]->version, devs[0]->carrier_name))
+		return -EINVAL;
+
+	devarray = kmemdup(devs, n * sizeof(*devs), GFP_KERNEL);
+	if (!devarray)
+		return -ENOMEM;
+
+	/* Make all other checks before continuing, for all devices */
+	for (i = 0; i < n; i++) {
+		fmc = devarray[i];
+		if (!fmc->hwdev) {
+			pr_err("%s: device nr. %i has no hwdev pointer\n",
+			       __func__, i);
+			ret = -EINVAL;
+			break;
+		}
+		if (fmc->flags == FMC_DEVICE_NO_MEZZANINE) {
+			dev_info(fmc->hwdev, "absent mezzanine in slot %d\n",
+				 fmc->slot_id);
+			continue;
+		}
+		if (!fmc->eeprom) {
+			dev_err(fmc->hwdev, "no eeprom provided for slot %i\n",
+				fmc->slot_id);
+			ret = -EINVAL;
+		}
+		if (!fmc->eeprom_addr) {
+			dev_err(fmc->hwdev, "no eeprom_addr for slot %i\n",
+				fmc->slot_id);
+			ret = -EINVAL;
+		}
+		if (!fmc->carrier_name || !fmc->carrier_data ||
+		    !fmc->device_id) {
+			dev_err(fmc->hwdev,
+				"deivce nr %i: carrier name, "
+				"data or dev_id not set\n", i);
+			ret = -EINVAL;
+		}
+		if (ret)
+			break;
+
+	}
+	if (ret) {
+		kfree(devarray);
+		return ret;
+	}
+
+	/* Validation is ok. Now init and register the devices */
+	for (i = 0; i < n; i++) {
+		fmc = devarray[i];
+
+		if (fmc->flags == FMC_DEVICE_NO_MEZZANINE)
+			continue; /* dev_info already done above */
+
+		fmc->nr_slots = n; /* each slot must know how many are there */
+		fmc->devarray = devarray;
+
+		device_initialize(&fmc->dev);
+		fmc->dev.release = fmc_release;
+		fmc->dev.parent = fmc->hwdev;
+
+		/* Fill the identification stuff (may fail) */
+		fmc_fill_id_info(fmc);
+
+		fmc->dev.bus = &fmc_bus_type;
+
+		/* Name from mezzanine info or carrier info. Or 0,1,2.. */
+		device_id = fmc->device_id;
+		if (!fmc->mezzanine_name)
+			dev_set_name(&fmc->dev, "fmc-%04x", device_id);
+		else
+			dev_set_name(&fmc->dev, "%s-%04x", fmc->mezzanine_name,
+				     device_id);
+		ret = device_add(&fmc->dev);
+		if (ret < 0) {
+			dev_err(fmc->hwdev, "Slot %i: Failed in registering "
+				"\"%s\"\n", fmc->slot_id, fmc->dev.kobj.name);
+			goto out;
+		}
+		ret = sysfs_create_bin_file(&fmc->dev.kobj, &fmc_eeprom_attr);
+		if (ret < 0) {
+			dev_err(&fmc->dev, "Failed in registering eeprom\n");
+			goto out1;
+		}
+		/* This device went well, give information to the user */
+		fmc_dump_eeprom(fmc);
+		fmc_dump_sdb(fmc);
+	}
+	return 0;
+
+out1:
+	device_del(&fmc->dev);
+out:
+	fmc_free_id_info(fmc);
+	put_device(&fmc->dev);
+
+	kfree(devarray);
+	for (i--; i >= 0; i--) {
+		sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr);
+		device_del(&devs[i]->dev);
+		fmc_free_id_info(devs[i]);
+		put_device(&devs[i]->dev);
+	}
+	return ret;
+
+}
+EXPORT_SYMBOL(fmc_device_register_n);
+
+int fmc_device_register(struct fmc_device *fmc)
+{
+	return fmc_device_register_n(&fmc, 1);
+}
+EXPORT_SYMBOL(fmc_device_register);
+
+void fmc_device_unregister_n(struct fmc_device **devs, int n)
+{
+	int i;
+
+	if (n < 1)
+		return;
+
+	/* Free devarray first, not used by the later loop */
+	kfree(devs[0]->devarray);
+
+	for (i = 0; i < n; i++) {
+		if (devs[i]->flags == FMC_DEVICE_NO_MEZZANINE)
+			continue;
+		sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr);
+		device_del(&devs[i]->dev);
+		fmc_free_id_info(devs[i]);
+		put_device(&devs[i]->dev);
+	}
+}
+EXPORT_SYMBOL(fmc_device_unregister_n);
+
+void fmc_device_unregister(struct fmc_device *fmc)
+{
+	fmc_device_unregister_n(&fmc, 1);
+}
+EXPORT_SYMBOL(fmc_device_unregister);
+
+/* Init and exit are trivial */
+static int fmc_init(void)
+{
+	return bus_register(&fmc_bus_type);
+}
+
+static void fmc_exit(void)
+{
+	bus_unregister(&fmc_bus_type);
+}
+
+module_init(fmc_init);
+module_exit(fmc_exit);
+
+MODULE_LICENSE("GPL");

+ 100 - 0
drivers/fmc/fmc-dump.c

@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 CERN (www.cern.ch)
+ * Author: Alessandro Rubini <rubini@gnudd.com>
+ *
+ * Released according to the GNU GPL, version 2 or any later version.
+ *
+ * This work is part of the White Rabbit project, a research effort led
+ * by CERN, the European Institute for Nuclear Research.
+ */
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/fmc.h>
+#include <linux/fmc-sdb.h>
+
+static int fmc_must_dump_eeprom;
+module_param_named(dump_eeprom, fmc_must_dump_eeprom, int, 0644);
+static int fmc_must_dump_sdb;
+module_param_named(dump_sdb, fmc_must_dump_sdb, int, 0644);
+
+#define LINELEN 16
+
+/* Dumping 8k takes oh so much: avoid duplicate lines */
+static const uint8_t *dump_line(int addr, const uint8_t *line,
+				const uint8_t *prev)
+{
+	int i;
+
+	if (!prev || memcmp(line, prev, LINELEN)) {
+		pr_info("%04x: ", addr);
+		for (i = 0; i < LINELEN; ) {
+			printk(KERN_CONT "%02x", line[i]);
+			i++;
+			printk(i & 3 ? " " : i & (LINELEN - 1) ? "  " : "\n");
+		}
+		return line;
+	}
+	/* repeated line */
+	if (line == prev + LINELEN)
+		pr_info("[...]\n");
+	return prev;
+}
+
+void fmc_dump_eeprom(const struct fmc_device *fmc)
+{
+	const uint8_t *line, *prev;
+	int i;
+
+	if (!fmc_must_dump_eeprom)
+		return;
+
+	pr_info("FMC: %s (%s), slot %i, device %s\n", dev_name(fmc->hwdev),
+		fmc->carrier_name, fmc->slot_id, dev_name(&fmc->dev));
+	pr_info("FMC: dumping eeprom 0x%x (%i) bytes\n", fmc->eeprom_len,
+	       fmc->eeprom_len);
+
+	line = fmc->eeprom;
+	prev = NULL;
+	for (i = 0; i < fmc->eeprom_len; i += LINELEN, line += LINELEN)
+		prev = dump_line(i, line, prev);
+}
+
+void fmc_dump_sdb(const struct fmc_device *fmc)
+{
+	const uint8_t *line, *prev;
+	int i, len;
+
+	if (!fmc->sdb)
+		return;
+	if (!fmc_must_dump_sdb)
+		return;
+
+	/* If the argument is not-zero, do simple dump (== show) */
+	if (fmc_must_dump_sdb > 0)
+		fmc_show_sdb_tree(fmc);
+
+	if (fmc_must_dump_sdb == 1)
+		return;
+
+	/* If bigger than 1, dump it seriously, to help debugging */
+
+	/*
+	 * Here we should really use libsdbfs (which is designed to
+	 * work in kernel space as well) , but it doesn't support
+	 * directories yet, and it requires better intergration (it
+	 * should be used instead of fmc-specific code).
+	 *
+	 * So, lazily, just dump the top-level array
+	 */
+	pr_info("FMC: %s (%s), slot %i, device %s\n", dev_name(fmc->hwdev),
+		fmc->carrier_name, fmc->slot_id, dev_name(&fmc->dev));
+	pr_info("FMC: poor dump of sdb first level:\n");
+
+	len = fmc->sdb->len * sizeof(union sdb_record);
+	line = (void *)fmc->sdb->record;
+	prev = NULL;
+	for (i = 0; i < len; i += LINELEN, line += LINELEN)
+		prev = dump_line(i, line, prev);
+	return;
+}

+ 355 - 0
drivers/fmc/fmc-fakedev.c

@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2012 CERN (www.cern.ch)
+ * Author: Alessandro Rubini <rubini@gnudd.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * The software is provided "as is"; the copyright holders disclaim
+ * all warranties and liabilities, to the extent permitted by
+ * applicable law.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+#include <linux/workqueue.h>
+#include <linux/err.h>
+#include <linux/fmc.h>
+
+#define FF_EEPROM_SIZE		8192	/* The standard eeprom size */
+#define FF_MAX_MEZZANINES	4	/* Fakes a multi-mezzanine carrier */
+
+/* The user can pass up to 4 names of eeprom images to load */
+static char *ff_eeprom[FF_MAX_MEZZANINES];
+static int ff_nr_eeprom;
+module_param_array_named(eeprom, ff_eeprom, charp, &ff_nr_eeprom, 0444);
+
+/* The user can ask for a multi-mezzanine carrier, with the default eeprom */
+static int ff_nr_dev = 1;
+module_param_named(ndev, ff_nr_dev, int, 0444);
+
+
+/* Lazily, don't support the "standard" module parameters */
+
+/*
+ * Eeprom built from these commands:
+
+	../fru-generator -v fake-vendor -n fake-design-for-testing \
+		-s 01234 -p none > IPMI-FRU
+
+	gensdbfs . ../fake-eeprom.bin
+*/
+static char ff_eeimg[FF_MAX_MEZZANINES][FF_EEPROM_SIZE] = {
+	{
+	0x01, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x00, 0xf2, 0x01, 0x0b, 0x00, 0xb2,
+	0x86, 0x87, 0xcb, 0x66, 0x61, 0x6b, 0x65, 0x2d, 0x76, 0x65, 0x6e, 0x64,
+	0x6f, 0x72, 0xd7, 0x66, 0x61, 0x6b, 0x65, 0x2d, 0x64, 0x65, 0x73, 0x69,
+	0x67, 0x6e, 0x2d, 0x66, 0x6f, 0x72, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x69,
+	0x6e, 0x67, 0xc5, 0x30, 0x31, 0x32, 0x33, 0x34, 0xc4, 0x6e, 0x6f, 0x6e,
+	0x65, 0xda, 0x32, 0x30, 0x31, 0x32, 0x2d, 0x31, 0x31, 0x2d, 0x31, 0x39,
+	0x20, 0x32, 0x32, 0x3a, 0x34, 0x32, 0x3a, 0x33, 0x30, 0x2e, 0x30, 0x37,
+	0x34, 0x30, 0x35, 0x35, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87,
+	0x02, 0x02, 0x0d, 0xf7, 0xf8, 0x02, 0xb0, 0x04, 0x74, 0x04, 0xec, 0x04,
+	0x00, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x02, 0x02, 0x0d, 0x5c, 0x93, 0x01,
+	0x4a, 0x01, 0x39, 0x01, 0x5a, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x0b,
+	0x02, 0x02, 0x0d, 0x63, 0x8c, 0x00, 0xfa, 0x00, 0xed, 0x00, 0x06, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x01, 0x02, 0x0d, 0xfb, 0xf5, 0x05,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x02, 0x0d, 0xfc, 0xf4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0d, 0xfd, 0xf3, 0x03,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xfa, 0x82, 0x0b, 0xea, 0x8f, 0xa2, 0x12, 0x00, 0x00, 0x1e, 0x44, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x53, 0x44, 0x42, 0x2d, 0x00, 0x03, 0x01, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x01, 0xc4, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61,
+	0x2e, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+	0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc4, 0x46, 0x69, 0x6c, 0x65,
+	0x44, 0x61, 0x74, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf,
+	0x46, 0x69, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x49, 0x50, 0x4d, 0x49,
+	0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, 0x50, 0x4d, 0x49,
+	0x2d, 0x46, 0x52, 0x55, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x20, 0x01, 0x66, 0x61, 0x6b, 0x65, 0x0a,
+	},
+};
+
+struct ff_dev {
+	struct fmc_device *fmc[FF_MAX_MEZZANINES];
+	struct device dev;
+};
+
+static struct ff_dev *ff_current_dev; /* We have 1 carrier, 1 slot */
+
+static int ff_reprogram(struct fmc_device *fmc, struct fmc_driver *drv,
+			  char *gw)
+{
+	const struct firmware *fw;
+	int ret;
+
+	if (!gw) {
+		/* program golden: success */
+		fmc->flags &= ~FMC_DEVICE_HAS_CUSTOM;
+		fmc->flags |= FMC_DEVICE_HAS_GOLDEN;
+		return 0;
+	}
+
+	dev_info(&fmc->dev, "reprogramming with %s\n", gw);
+	ret = request_firmware(&fw, gw, &fmc->dev);
+	if (ret < 0) {
+		dev_warn(&fmc->dev, "request firmware \"%s\": error %i\n",
+			 gw, ret);
+		goto out;
+	}
+	fmc->flags &= ~FMC_DEVICE_HAS_GOLDEN;
+	fmc->flags |= FMC_DEVICE_HAS_CUSTOM;
+
+out:
+	release_firmware(fw);
+	return ret;
+}
+
+static int ff_irq_request(struct fmc_device *fmc, irq_handler_t handler,
+			    char *name, int flags)
+{
+	return -EOPNOTSUPP;
+}
+
+/* FIXME: should also have some fake FMC GPIO mapping */
+
+
+/*
+ * This work function is called when we changed the eeprom. It removes the
+ * current fmc device and registers a new one, with different identifiers.
+ */
+static struct ff_dev *ff_dev_create(void); /* defined later */
+
+static void ff_work_fn(struct work_struct *work)
+{
+	struct ff_dev *ff = ff_current_dev;
+	int ret;
+
+	fmc_device_unregister_n(ff->fmc, ff_nr_dev);
+	device_unregister(&ff->dev);
+	ff_current_dev = NULL;
+
+	ff = ff_dev_create();
+	if (IS_ERR(ff)) {
+		pr_warning("%s: can't re-create FMC devices\n", __func__);
+		return;
+	}
+	ret = fmc_device_register_n(ff->fmc, ff_nr_dev);
+	if (ret < 0) {
+		dev_warn(&ff->dev, "can't re-register FMC devices\n");
+		device_unregister(&ff->dev);
+		return;
+	}
+
+	ff_current_dev = ff;
+}
+
+static DECLARE_DELAYED_WORK(ff_work, ff_work_fn);
+
+
+/* low-level i2c */
+static int ff_eeprom_read(struct fmc_device *fmc, uint32_t offset,
+		void *buf, size_t size)
+{
+	if (offset > FF_EEPROM_SIZE)
+		return -EINVAL;
+	if (offset + size > FF_EEPROM_SIZE)
+		size = FF_EEPROM_SIZE - offset;
+	memcpy(buf, fmc->eeprom + offset, size);
+	return size;
+}
+
+static int ff_eeprom_write(struct fmc_device *fmc, uint32_t offset,
+		    const void *buf, size_t size)
+{
+	if (offset > FF_EEPROM_SIZE)
+		return -EINVAL;
+	if (offset + size > FF_EEPROM_SIZE)
+		size = FF_EEPROM_SIZE - offset;
+	dev_info(&fmc->dev, "write_eeprom: offset %i, size %zi\n",
+		 (int)offset, size);
+	memcpy(fmc->eeprom + offset, buf, size);
+	schedule_delayed_work(&ff_work, HZ * 2); /* remove, replug, in 2s */
+	return size;
+}
+
+/* i2c operations for fmc */
+static int ff_read_ee(struct fmc_device *fmc, int pos, void *data, int len)
+{
+	if (!(fmc->flags & FMC_DEVICE_HAS_GOLDEN))
+		return -EOPNOTSUPP;
+	return ff_eeprom_read(fmc, pos, data, len);
+}
+
+static int ff_write_ee(struct fmc_device *fmc, int pos,
+			 const void *data, int len)
+{
+	if (!(fmc->flags & FMC_DEVICE_HAS_GOLDEN))
+		return -EOPNOTSUPP;
+	return ff_eeprom_write(fmc, pos, data, len);
+}
+
+/* readl and writel do not do anything. Don't waste RAM with "base" */
+static uint32_t ff_readl(struct fmc_device *fmc, int offset)
+{
+	return 0;
+}
+
+static void ff_writel(struct fmc_device *fmc, uint32_t value, int offset)
+{
+	return;
+}
+
+/* validate is useful so fmc-write-eeprom will not reprogram every 2 seconds */
+static int ff_validate(struct fmc_device *fmc, struct fmc_driver *drv)
+{
+	int i;
+
+	if (!drv->busid_n)
+		return 0; /* everyhing is valid */
+	for (i = 0; i < drv->busid_n; i++)
+		if (drv->busid_val[i] == fmc->device_id)
+			return i;
+	return -ENOENT;
+}
+
+
+
+static struct fmc_operations ff_fmc_operations = {
+	.read32 =		ff_readl,
+	.write32 =		ff_writel,
+	.reprogram =		ff_reprogram,
+	.irq_request =		ff_irq_request,
+	.read_ee =		ff_read_ee,
+	.write_ee =		ff_write_ee,
+	.validate =		ff_validate,
+};
+
+/* This device is kmalloced: release it */
+static void ff_dev_release(struct device *dev)
+{
+	struct ff_dev *ff = container_of(dev, struct ff_dev, dev);
+	kfree(ff);
+}
+
+static struct fmc_device ff_template_fmc = {
+	.version = FMC_VERSION,
+	.owner = THIS_MODULE,
+	.carrier_name = "fake-fmc-carrier",
+	.device_id = 0xf001, /* fool */
+	.eeprom_len = sizeof(ff_eeimg[0]),
+	.memlen = 0x1000, /* 4k, to show something */
+	.op = &ff_fmc_operations,
+	.hwdev = NULL, /* filled at creation time */
+	.flags = FMC_DEVICE_HAS_GOLDEN,
+};
+
+static struct ff_dev *ff_dev_create(void)
+{
+	struct ff_dev *ff;
+	struct fmc_device *fmc;
+	int i, ret;
+
+	ff = kzalloc(sizeof(*ff), GFP_KERNEL);
+	if (!ff)
+		return ERR_PTR(-ENOMEM);
+	dev_set_name(&ff->dev, "fake-fmc-carrier");
+	ff->dev.release = ff_dev_release;
+
+	ret = device_register(&ff->dev);
+	if (ret < 0) {
+		put_device(&ff->dev);
+		return ERR_PTR(ret);
+	}
+
+	/* Create fmc structures that refer to this new "hw" device */
+	for (i = 0; i < ff_nr_dev; i++) {
+		fmc = kmemdup(&ff_template_fmc, sizeof(ff_template_fmc),
+			      GFP_KERNEL);
+		fmc->hwdev = &ff->dev;
+		fmc->carrier_data = ff;
+		fmc->nr_slots = ff_nr_dev;
+		/* the following fields are different for each slot */
+		fmc->eeprom = ff_eeimg[i];
+		fmc->eeprom_addr = 0x50 + 2 * i;
+		fmc->slot_id = i;
+		ff->fmc[i] = fmc;
+		/* increment the identifier, each must be different */
+		ff_template_fmc.device_id++;
+	}
+	return ff;
+}
+
+/* init and exit */
+static int ff_init(void)
+{
+	struct ff_dev *ff;
+	const struct firmware *fw;
+	int i, len, ret = 0;
+
+	/* Replicate the default eeprom for the max number of mezzanines */
+	for (i = 1; i < FF_MAX_MEZZANINES; i++)
+		memcpy(ff_eeimg[i], ff_eeimg[0], sizeof(ff_eeimg[0]));
+
+	if (ff_nr_eeprom > ff_nr_dev)
+		ff_nr_dev = ff_nr_eeprom;
+
+	ff = ff_dev_create();
+	if (IS_ERR(ff))
+		return PTR_ERR(ff);
+
+	/* If the user passed "eeprom=" as a parameter, fetch them */
+	for (i = 0; i < ff_nr_eeprom; i++) {
+		if (!strlen(ff_eeprom[i]))
+			continue;
+		ret = request_firmware(&fw, ff_eeprom[i], &ff->dev);
+		if (ret < 0) {
+			dev_err(&ff->dev, "Mezzanine %i: can't load \"%s\" "
+				"(error %i)\n", i, ff_eeprom[i], -ret);
+		} else {
+			len = min_t(size_t, fw->size, (size_t)FF_EEPROM_SIZE);
+			memcpy(ff_eeimg[i], fw->data, len);
+			release_firmware(fw);
+			dev_info(&ff->dev, "Mezzanine %i: eeprom \"%s\"\n", i,
+				ff_eeprom[i]);
+		}
+	}
+
+	ret = fmc_device_register_n(ff->fmc, ff_nr_dev);
+	if (ret) {
+		device_unregister(&ff->dev);
+		return ret;
+	}
+	ff_current_dev = ff;
+	return ret;
+}
+
+static void ff_exit(void)
+{
+	if (ff_current_dev) {
+		fmc_device_unregister_n(ff_current_dev->fmc, ff_nr_dev);
+		device_unregister(&ff_current_dev->dev);
+	}
+	cancel_delayed_work_sync(&ff_work);
+}
+
+module_init(ff_init);
+module_exit(ff_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");

+ 114 - 0
drivers/fmc/fmc-match.c

@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2012 CERN (www.cern.ch)
+ * Author: Alessandro Rubini <rubini@gnudd.com>
+ *
+ * Released according to the GNU GPL, version 2 or any later version.
+ *
+ * This work is part of the White Rabbit project, a research effort led
+ * by CERN, the European Institute for Nuclear Research.
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fmc.h>
+#include <linux/ipmi-fru.h>
+
+/* The fru parser is both user and kernel capable: it needs alloc */
+void *fru_alloc(size_t size)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
+
+/* The actual match function */
+int fmc_match(struct device *dev, struct device_driver *drv)
+{
+	struct fmc_driver *fdrv = to_fmc_driver(drv);
+	struct fmc_device *fdev = to_fmc_device(dev);
+	struct fmc_fru_id *fid;
+	int i, matched = 0;
+
+	/* This currently only matches the EEPROM (FRU id) */
+	fid = fdrv->id_table.fru_id;
+	if (!fid) {
+		dev_warn(&fdev->dev, "Driver has no ID: matches all\n");
+		matched = 1;
+	} else {
+		if (!fdev->id.manufacturer || !fdev->id.product_name)
+			return 0; /* the device has no FRU information */
+		for (i = 0; i < fdrv->id_table.fru_id_nr; i++, fid++) {
+			if (fid->manufacturer &&
+			    strcmp(fid->manufacturer, fdev->id.manufacturer))
+				continue;
+			if (fid->product_name &&
+			    strcmp(fid->product_name, fdev->id.product_name))
+				continue;
+			matched = 1;
+			break;
+		}
+	}
+
+	/* FIXME: match SDB contents */
+	return matched;
+}
+
+/* This function creates ID info for a newly registered device */
+int fmc_fill_id_info(struct fmc_device *fmc)
+{
+	struct fru_common_header *h;
+	struct fru_board_info_area *bia;
+	int ret, allocated = 0;
+
+	/* If we know the eeprom length, try to read it off the device */
+	if (fmc->eeprom_len && !fmc->eeprom) {
+		fmc->eeprom = kzalloc(fmc->eeprom_len, GFP_KERNEL);
+		if (!fmc->eeprom)
+			return -ENOMEM;
+		allocated = 1;
+		ret = fmc->op->read_ee(fmc, 0, fmc->eeprom, fmc->eeprom_len);
+		if (ret < 0)
+			goto out;
+	}
+
+	/* If no eeprom, continue with other matches */
+	if (!fmc->eeprom)
+		return 0;
+
+	dev_info(fmc->hwdev, "mezzanine %i\n", fmc->slot_id); /* header */
+
+	/* So we have the eeprom: parse the FRU part (if any) */
+	h = (void *)fmc->eeprom;
+	if (h->format != 1) {
+		pr_info("      EEPROM has no FRU information\n");
+		goto out;
+	}
+	if (!fru_header_cksum_ok(h)) {
+		pr_info("      FRU: wrong header checksum\n");
+		goto out;
+	}
+	bia = fru_get_board_area(h);
+	if (!fru_bia_cksum_ok(bia)) {
+		pr_info("      FRU: wrong board area checksum\n");
+		goto out;
+	}
+	fmc->id.manufacturer = fru_get_board_manufacturer(h);
+	fmc->id.product_name = fru_get_product_name(h);
+	pr_info("      Manufacturer: %s\n", fmc->id.manufacturer);
+	pr_info("      Product name: %s\n", fmc->id.product_name);
+
+	/* Create the short name (FIXME: look in sdb as well) */
+	fmc->mezzanine_name = kstrdup(fmc->id.product_name, GFP_KERNEL);
+
+out:
+	if (allocated) {
+		kfree(fmc->eeprom);
+		fmc->eeprom = NULL;
+	}
+	return 0; /* no error: let other identification work */
+}
+
+/* Some ID data is allocated using fru_alloc() above, so release it */
+void fmc_free_id_info(struct fmc_device *fmc)
+{
+	kfree(fmc->mezzanine_name);
+	kfree(fmc->id.manufacturer);
+	kfree(fmc->id.product_name);
+}

+ 266 - 0
drivers/fmc/fmc-sdb.c

@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2012 CERN (www.cern.ch)
+ * Author: Alessandro Rubini <rubini@gnudd.com>
+ *
+ * Released according to the GNU GPL, version 2 or any later version.
+ *
+ * This work is part of the White Rabbit project, a research effort led
+ * by CERN, the European Institute for Nuclear Research.
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fmc.h>
+#include <linux/sdb.h>
+#include <linux/err.h>
+#include <linux/fmc-sdb.h>
+#include <asm/byteorder.h>
+
+static uint32_t __sdb_rd(struct fmc_device *fmc, unsigned long address,
+			int convert)
+{
+	uint32_t res = fmc_readl(fmc, address);
+	if (convert)
+		return __be32_to_cpu(res);
+	return res;
+}
+
+static struct sdb_array *__fmc_scan_sdb_tree(struct fmc_device *fmc,
+					     unsigned long sdb_addr,
+					     unsigned long reg_base, int level)
+{
+	uint32_t onew;
+	int i, j, n, convert = 0;
+	struct sdb_array *arr, *sub;
+
+	onew = fmc_readl(fmc, sdb_addr);
+	if (onew == SDB_MAGIC) {
+		/* Uh! If we are little-endian, we must convert */
+		if (SDB_MAGIC != __be32_to_cpu(SDB_MAGIC))
+			convert = 1;
+	} else if (onew == __be32_to_cpu(SDB_MAGIC)) {
+		/* ok, don't convert */
+	} else {
+		return ERR_PTR(-ENOENT);
+	}
+	/* So, the magic was there: get the count from offset 4*/
+	onew = __sdb_rd(fmc, sdb_addr + 4, convert);
+	n = __be16_to_cpu(*(uint16_t *)&onew);
+	arr = kzalloc(sizeof(*arr), GFP_KERNEL);
+	if (!arr)
+		return ERR_PTR(-ENOMEM);
+	arr->record = kzalloc(sizeof(arr->record[0]) * n, GFP_KERNEL);
+	arr->subtree = kzalloc(sizeof(arr->subtree[0]) * n, GFP_KERNEL);
+	if (!arr->record || !arr->subtree) {
+		kfree(arr->record);
+		kfree(arr->subtree);
+		kfree(arr);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	arr->len = n;
+	arr->level = level;
+	arr->fmc = fmc;
+	for (i = 0; i < n; i++) {
+		union  sdb_record *r;
+
+		for (j = 0; j < sizeof(arr->record[0]); j += 4) {
+			*(uint32_t *)((void *)(arr->record + i) + j) =
+				__sdb_rd(fmc, sdb_addr + (i * 64) + j, convert);
+		}
+		r = &arr->record[i];
+		arr->subtree[i] = ERR_PTR(-ENODEV);
+		if (r->empty.record_type == sdb_type_bridge) {
+			struct sdb_component *c = &r->bridge.sdb_component;
+			uint64_t subaddr = __be64_to_cpu(r->bridge.sdb_child);
+			uint64_t newbase = __be64_to_cpu(c->addr_first);
+
+			subaddr += reg_base;
+			newbase += reg_base;
+			sub = __fmc_scan_sdb_tree(fmc, subaddr, newbase,
+						  level + 1);
+			arr->subtree[i] = sub; /* may be error */
+			if (IS_ERR(sub))
+				continue;
+			sub->parent = arr;
+			sub->baseaddr = newbase;
+		}
+	}
+	return arr;
+}
+
+int fmc_scan_sdb_tree(struct fmc_device *fmc, unsigned long address)
+{
+	struct sdb_array *ret;
+	if (fmc->sdb)
+		return -EBUSY;
+	ret = __fmc_scan_sdb_tree(fmc, address, 0 /* regs */, 0);
+	if (IS_ERR(ret))
+		return PTR_ERR(ret);
+	fmc->sdb = ret;
+	return 0;
+}
+EXPORT_SYMBOL(fmc_scan_sdb_tree);
+
+static void __fmc_sdb_free(struct sdb_array *arr)
+{
+	int i, n;
+
+	if (!arr)
+		return;
+	n = arr->len;
+	for (i = 0; i < n; i++) {
+		if (IS_ERR(arr->subtree[i]))
+			continue;
+		__fmc_sdb_free(arr->subtree[i]);
+	}
+	kfree(arr->record);
+	kfree(arr->subtree);
+	kfree(arr);
+}
+
+int fmc_free_sdb_tree(struct fmc_device *fmc)
+{
+	__fmc_sdb_free(fmc->sdb);
+	fmc->sdb = NULL;
+	return 0;
+}
+EXPORT_SYMBOL(fmc_free_sdb_tree);
+
+/* This helper calls reprogram and inizialized sdb as well */
+int fmc_reprogram(struct fmc_device *fmc, struct fmc_driver *d, char *gw,
+			 int sdb_entry)
+{
+	int ret;
+
+	ret = fmc->op->reprogram(fmc, d, gw);
+	if (ret < 0)
+		return ret;
+	if (sdb_entry < 0)
+		return ret;
+
+	/* We are required to find SDB at a given offset */
+	ret = fmc_scan_sdb_tree(fmc, sdb_entry);
+	if (ret < 0) {
+		dev_err(&fmc->dev, "Can't find SDB at address 0x%x\n",
+			sdb_entry);
+		return -ENODEV;
+	}
+	fmc_dump_sdb(fmc);
+	return 0;
+}
+EXPORT_SYMBOL(fmc_reprogram);
+
+static void __fmc_show_sdb_tree(const struct fmc_device *fmc,
+				const struct sdb_array *arr)
+{
+	int i, j, n = arr->len, level = arr->level;
+	const struct sdb_array *ap;
+
+	for (i = 0; i < n; i++) {
+		unsigned long base;
+		union  sdb_record *r;
+		struct sdb_product *p;
+		struct sdb_component *c;
+		r = &arr->record[i];
+		c = &r->dev.sdb_component;
+		p = &c->product;
+		base = 0;
+		for (ap = arr; ap; ap = ap->parent)
+			base += ap->baseaddr;
+		dev_info(&fmc->dev, "SDB: ");
+
+		for (j = 0; j < level; j++)
+			printk(KERN_CONT "   ");
+		switch (r->empty.record_type) {
+		case sdb_type_interconnect:
+			printk(KERN_CONT "%08llx:%08x %.19s\n",
+			       __be64_to_cpu(p->vendor_id),
+			       __be32_to_cpu(p->device_id),
+			       p->name);
+			break;
+		case sdb_type_device:
+			printk(KERN_CONT "%08llx:%08x %.19s (%08llx-%08llx)\n",
+			       __be64_to_cpu(p->vendor_id),
+			       __be32_to_cpu(p->device_id),
+			       p->name,
+			       __be64_to_cpu(c->addr_first) + base,
+			       __be64_to_cpu(c->addr_last) + base);
+			break;
+		case sdb_type_bridge:
+			printk(KERN_CONT "%08llx:%08x %.19s (bridge: %08llx)\n",
+			       __be64_to_cpu(p->vendor_id),
+			       __be32_to_cpu(p->device_id),
+			       p->name,
+			       __be64_to_cpu(c->addr_first) + base);
+			if (IS_ERR(arr->subtree[i])) {
+				printk(KERN_CONT "(bridge error %li)\n",
+				       PTR_ERR(arr->subtree[i]));
+				break;
+			}
+			__fmc_show_sdb_tree(fmc, arr->subtree[i]);
+			break;
+		case sdb_type_integration:
+			printk(KERN_CONT "integration\n");
+			break;
+		case sdb_type_repo_url:
+			printk(KERN_CONT "repo-url\n");
+			break;
+		case sdb_type_synthesis:
+			printk(KERN_CONT "synthesis-info\n");
+			break;
+		case sdb_type_empty:
+			printk(KERN_CONT "empty\n");
+			break;
+		default:
+			printk(KERN_CONT "UNKNOWN TYPE 0x%02x\n",
+			       r->empty.record_type);
+			break;
+		}
+	}
+}
+
+void fmc_show_sdb_tree(const struct fmc_device *fmc)
+{
+	if (!fmc->sdb)
+		return;
+	__fmc_show_sdb_tree(fmc, fmc->sdb);
+}
+EXPORT_SYMBOL(fmc_show_sdb_tree);
+
+signed long fmc_find_sdb_device(struct sdb_array *tree,
+				uint64_t vid, uint32_t did, unsigned long *sz)
+{
+	signed long res = -ENODEV;
+	union  sdb_record *r;
+	struct sdb_product *p;
+	struct sdb_component *c;
+	int i, n = tree->len;
+	uint64_t last, first;
+
+	/* FIXME: what if the first interconnect is not at zero? */
+	for (i = 0; i < n; i++) {
+		r = &tree->record[i];
+		c = &r->dev.sdb_component;
+		p = &c->product;
+
+		if (!IS_ERR(tree->subtree[i]))
+			res = fmc_find_sdb_device(tree->subtree[i],
+						  vid, did, sz);
+		if (res >= 0)
+			return res + tree->baseaddr;
+		if (r->empty.record_type != sdb_type_device)
+			continue;
+		if (__be64_to_cpu(p->vendor_id) != vid)
+			continue;
+		if (__be32_to_cpu(p->device_id) != did)
+			continue;
+		/* found */
+		last = __be64_to_cpu(c->addr_last);
+		first = __be64_to_cpu(c->addr_first);
+		if (sz)
+			*sz = (typeof(*sz))(last + 1 - first);
+		return first + tree->baseaddr;
+	}
+	return res;
+}
+EXPORT_SYMBOL(fmc_find_sdb_device);

+ 107 - 0
drivers/fmc/fmc-trivial.c

@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2012 CERN (www.cern.ch)
+ * Author: Alessandro Rubini <rubini@gnudd.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * The software is provided "as is"; the copyright holders disclaim
+ * all warranties and liabilities, to the extent permitted by
+ * applicable law.
+ */
+
+/* A trivial fmc driver that can load a gateware file and reports interrupts */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/fmc.h>
+
+static struct fmc_driver t_drv; /* initialized later */
+
+static irqreturn_t t_handler(int irq, void *dev_id)
+{
+	struct fmc_device *fmc = dev_id;
+
+	fmc->op->irq_ack(fmc);
+	dev_info(&fmc->dev, "received irq %i\n", irq);
+	return IRQ_HANDLED;
+}
+
+static struct fmc_gpio t_gpio[] = {
+	{
+		.gpio = FMC_GPIO_IRQ(0),
+		.mode = GPIOF_DIR_IN,
+		.irqmode = IRQF_TRIGGER_RISING,
+	}, {
+		.gpio = FMC_GPIO_IRQ(1),
+		.mode = GPIOF_DIR_IN,
+		.irqmode = IRQF_TRIGGER_RISING,
+	}
+};
+
+static int t_probe(struct fmc_device *fmc)
+{
+	int ret;
+	int index = 0;
+
+	if (fmc->op->validate)
+		index = fmc->op->validate(fmc, &t_drv);
+	if (index < 0)
+		return -EINVAL; /* not our device: invalid */
+
+	ret = fmc->op->irq_request(fmc, t_handler, "fmc-trivial", IRQF_SHARED);
+	if (ret < 0)
+		return ret;
+	/* ignore error code of call below, we really don't care */
+	fmc->op->gpio_config(fmc, t_gpio, ARRAY_SIZE(t_gpio));
+
+	/* Reprogram, if asked to. ESRCH == no filename specified */
+	ret = -ESRCH;
+	if (fmc->op->reprogram)
+		ret = fmc->op->reprogram(fmc, &t_drv, "");
+	if (ret == -ESRCH)
+		ret = 0;
+	if (ret < 0)
+		fmc->op->irq_free(fmc);
+
+	/* FIXME: reprogram LM32 too */
+	return ret;
+}
+
+static int t_remove(struct fmc_device *fmc)
+{
+	fmc->op->irq_free(fmc);
+	return 0;
+}
+
+static struct fmc_driver t_drv = {
+	.version = FMC_VERSION,
+	.driver.name = KBUILD_MODNAME,
+	.probe = t_probe,
+	.remove = t_remove,
+	/* no table, as the current match just matches everything */
+};
+
+ /* We accept the generic parameters */
+FMC_PARAM_BUSID(t_drv);
+FMC_PARAM_GATEWARE(t_drv);
+
+static int t_init(void)
+{
+	int ret;
+
+	ret = fmc_driver_register(&t_drv);
+	return ret;
+}
+
+static void t_exit(void)
+{
+	fmc_driver_unregister(&t_drv);
+}
+
+module_init(t_init);
+module_exit(t_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");

+ 176 - 0
drivers/fmc/fmc-write-eeprom.c

@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2012 CERN (www.cern.ch)
+ * Author: Alessandro Rubini <rubini@gnudd.com>
+ *
+ * Released according to the GNU GPL, version 2 or any later version.
+ *
+ * This work is part of the White Rabbit project, a research effort led
+ * by CERN, the European Institute for Nuclear Research.
+ */
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/firmware.h>
+#include <linux/init.h>
+#include <linux/fmc.h>
+#include <asm/unaligned.h>
+
+/*
+ * This module uses the firmware loader to program the whole or part
+ * of the FMC eeprom. The meat is in the _run functions.  However, no
+ * default file name is provided, to avoid accidental mishaps. Also,
+ * you must pass the busid argument
+ */
+static struct fmc_driver fwe_drv;
+
+FMC_PARAM_BUSID(fwe_drv);
+
+/* The "file=" is like the generic "gateware=" used elsewhere */
+static char *fwe_file[FMC_MAX_CARDS];
+static int fwe_file_n;
+module_param_array_named(file, fwe_file, charp, &fwe_file_n, 444);
+
+static int fwe_run_tlv(struct fmc_device *fmc, const struct firmware *fw,
+	int write)
+{
+	const uint8_t *p = fw->data;
+	int len = fw->size;
+	uint16_t thislen, thisaddr;
+	int err;
+
+	/* format is: 'w' addr16 len16 data... */
+	while (len > 5) {
+		thisaddr = get_unaligned_le16(p+1);
+		thislen = get_unaligned_le16(p+3);
+		if (p[0] != 'w' || thislen + 5 > len) {
+			dev_err(&fmc->dev, "invalid tlv at offset %ti\n",
+				p - fw->data);
+			return -EINVAL;
+		}
+		err = 0;
+		if (write) {
+			dev_info(&fmc->dev, "write %i bytes at 0x%04x\n",
+				 thislen, thisaddr);
+			err = fmc->op->write_ee(fmc, thisaddr, p + 5, thislen);
+		}
+		if (err < 0) {
+			dev_err(&fmc->dev, "write failure @0x%04x\n",
+				thisaddr);
+			return err;
+		}
+		p += 5 + thislen;
+		len -= 5 + thislen;
+	}
+	if (write)
+		dev_info(&fmc->dev, "write_eeprom: success\n");
+	return 0;
+}
+
+static int fwe_run_bin(struct fmc_device *fmc, const struct firmware *fw)
+{
+	int ret;
+
+	dev_info(&fmc->dev, "programming %zi bytes\n", fw->size);
+	ret = fmc->op->write_ee(fmc, 0, (void *)fw->data, fw->size);
+	if (ret < 0) {
+		dev_info(&fmc->dev, "write_eeprom: error %i\n", ret);
+		return ret;
+	}
+	dev_info(&fmc->dev, "write_eeprom: success\n");
+	return 0;
+}
+
+static int fwe_run(struct fmc_device *fmc, const struct firmware *fw, char *s)
+{
+	char *last4 = s + strlen(s) - 4;
+	int err;
+
+	if (!strcmp(last4, ".bin"))
+		return fwe_run_bin(fmc, fw);
+	if (!strcmp(last4, ".tlv")) {
+		err = fwe_run_tlv(fmc, fw, 0);
+		if (!err)
+			err = fwe_run_tlv(fmc, fw, 1);
+		return err;
+	}
+	dev_err(&fmc->dev, "invalid file name \"%s\"\n", s);
+	return -EINVAL;
+}
+
+/*
+ * Programming is done at probe time. Morever, only those listed with
+ * busid= are programmed.
+ * card is probed for, only one is programmed. Unfortunately, it's
+ * difficult to know in advance when probing the first card if others
+ * are there.
+ */
+int fwe_probe(struct fmc_device *fmc)
+{
+	int err, index = 0;
+	const struct firmware *fw;
+	struct device *dev = &fmc->dev;
+	char *s;
+
+	if (!fwe_drv.busid_n) {
+		dev_err(dev, "%s: no busid passed, refusing all cards\n",
+			KBUILD_MODNAME);
+		return -ENODEV;
+	}
+	if (fmc->op->validate)
+		index = fmc->op->validate(fmc, &fwe_drv);
+	if (index < 0) {
+		pr_err("%s: refusing device \"%s\"\n", KBUILD_MODNAME,
+		       dev_name(dev));
+		return -ENODEV;
+	}
+	if (index >= fwe_file_n) {
+		pr_err("%s: no filename for device index %i\n",
+			KBUILD_MODNAME, index);
+		return -ENODEV;
+	}
+	s = fwe_file[index];
+	if (!s) {
+		pr_err("%s: no filename for \"%s\" not programming\n",
+		       KBUILD_MODNAME, dev_name(dev));
+		return -ENOENT;
+	}
+	err = request_firmware(&fw, s, dev);
+	if (err < 0) {
+		dev_err(&fmc->dev, "request firmware \"%s\": error %i\n",
+			s, err);
+		return err;
+	}
+	fwe_run(fmc, fw, s);
+	release_firmware(fw);
+	return 0;
+}
+
+int fwe_remove(struct fmc_device *fmc)
+{
+	return 0;
+}
+
+static struct fmc_driver fwe_drv = {
+	.version = FMC_VERSION,
+	.driver.name = KBUILD_MODNAME,
+	.probe = fwe_probe,
+	.remove = fwe_remove,
+	/* no table, as the current match just matches everything */
+};
+
+static int fwe_init(void)
+{
+	int ret;
+
+	ret = fmc_driver_register(&fwe_drv);
+	return ret;
+}
+
+static void fwe_exit(void)
+{
+	fmc_driver_unregister(&fwe_drv);
+}
+
+module_init(fwe_init);
+module_exit(fwe_exit);
+
+MODULE_LICENSE("GPL");

+ 82 - 0
drivers/fmc/fru-parse.c

@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 CERN (www.cern.ch)
+ * Author: Alessandro Rubini <rubini@gnudd.com>
+ *
+ * Released according to the GNU GPL, version 2 or any later version.
+ *
+ * This work is part of the White Rabbit project, a research effort led
+ * by CERN, the European Institute for Nuclear Research.
+ */
+#include <linux/ipmi-fru.h>
+
+/* Some internal helpers */
+static struct fru_type_length *
+__fru_get_board_tl(struct fru_common_header *header, int nr)
+{
+	struct fru_board_info_area *bia;
+	struct fru_type_length *tl;
+
+	bia = fru_get_board_area(header);
+	tl = bia->tl;
+	while (nr > 0 && !fru_is_eof(tl)) {
+		tl = fru_next_tl(tl);
+		nr--;
+	}
+	if (fru_is_eof(tl))
+		return NULL;
+	return tl;
+}
+
+static char *__fru_alloc_get_tl(struct fru_common_header *header, int nr)
+{
+	struct fru_type_length *tl;
+	char *res;
+	int len;
+
+	tl = __fru_get_board_tl(header, nr);
+	if (!tl)
+		return NULL;
+	len = fru_strlen(tl);
+	res = fru_alloc(fru_strlen(tl) + 1);
+	if (!res)
+		return NULL;
+	return fru_strcpy(res, tl);
+}
+
+/* Public checksum verifiers */
+int fru_header_cksum_ok(struct fru_common_header *header)
+{
+	uint8_t *ptr = (void *)header;
+	int i, sum;
+
+	for (i = sum = 0; i < sizeof(*header); i++)
+		sum += ptr[i];
+	return (sum & 0xff) == 0;
+}
+int fru_bia_cksum_ok(struct fru_board_info_area *bia)
+{
+	uint8_t *ptr = (void *)bia;
+	int i, sum;
+
+	for (i = sum = 0; i < 8 * bia->area_len; i++)
+		sum += ptr[i];
+	return (sum & 0xff) == 0;
+}
+
+/* Get various stuff, trivial */
+char *fru_get_board_manufacturer(struct fru_common_header *header)
+{
+	return __fru_alloc_get_tl(header, 0);
+}
+char *fru_get_product_name(struct fru_common_header *header)
+{
+	return __fru_alloc_get_tl(header, 1);
+}
+char *fru_get_serial_number(struct fru_common_header *header)
+{
+	return __fru_alloc_get_tl(header, 2);
+}
+char *fru_get_part_number(struct fru_common_header *header)
+{
+	return __fru_alloc_get_tl(header, 3);
+}

+ 46 - 4
drivers/hv/channel.c

@@ -116,6 +116,15 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 	unsigned long flags;
 	int ret, t, err = 0;
 
+	spin_lock_irqsave(&newchannel->sc_lock, flags);
+	if (newchannel->state == CHANNEL_OPEN_STATE) {
+		newchannel->state = CHANNEL_OPENING_STATE;
+	} else {
+		spin_unlock_irqrestore(&newchannel->sc_lock, flags);
+		return -EINVAL;
+	}
+	spin_unlock_irqrestore(&newchannel->sc_lock, flags);
+
 	newchannel->onchannel_callback = onchannelcallback;
 	newchannel->channel_callback_context = context;
 
@@ -216,6 +225,9 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 	list_del(&open_info->msglistentry);
 	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
+	if (err == 0)
+		newchannel->state = CHANNEL_OPENED_STATE;
+
 	kfree(open_info);
 	return err;
 
@@ -500,15 +512,14 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
 }
 EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
 
-/*
- * vmbus_close - Close the specified channel
- */
-void vmbus_close(struct vmbus_channel *channel)
+static void vmbus_close_internal(struct vmbus_channel *channel)
 {
 	struct vmbus_channel_close_channel *msg;
 	int ret;
 	unsigned long flags;
 
+	channel->state = CHANNEL_OPEN_STATE;
+	channel->sc_creation_callback = NULL;
 	/* Stop callback and cancel the timer asap */
 	spin_lock_irqsave(&channel->inbound_lock, flags);
 	channel->onchannel_callback = NULL;
@@ -538,6 +549,37 @@ void vmbus_close(struct vmbus_channel *channel)
 
 
 }
+
+/*
+ * vmbus_close - Close the specified channel
+ */
+void vmbus_close(struct vmbus_channel *channel)
+{
+	struct list_head *cur, *tmp;
+	struct vmbus_channel *cur_channel;
+
+	if (channel->primary_channel != NULL) {
+		/*
+		 * We will only close sub-channels when
+		 * the primary is closed.
+		 */
+		return;
+	}
+	/*
+	 * Close all the sub-channels first and then close the
+	 * primary channel.
+	 */
+	list_for_each_safe(cur, tmp, &channel->sc_list) {
+		cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
+		if (cur_channel->state != CHANNEL_OPENED_STATE)
+			continue;
+		vmbus_close_internal(cur_channel);
+	}
+	/*
+	 * Now close the primary.
+	 */
+	vmbus_close_internal(channel);
+}
 EXPORT_SYMBOL_GPL(vmbus_close);
 
 /**

+ 115 - 4
drivers/hv/channel_mgmt.c

@@ -115,6 +115,9 @@ static struct vmbus_channel *alloc_channel(void)
 		return NULL;
 
 	spin_lock_init(&channel->inbound_lock);
+	spin_lock_init(&channel->sc_lock);
+
+	INIT_LIST_HEAD(&channel->sc_list);
 
 	channel->controlwq = create_workqueue("hv_vmbus_ctl");
 	if (!channel->controlwq) {
@@ -166,6 +169,7 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
 						     struct vmbus_channel,
 						     work);
 	unsigned long flags;
+	struct vmbus_channel *primary_channel;
 	struct vmbus_channel_relid_released msg;
 
 	vmbus_device_unregister(channel->device_obj);
@@ -174,9 +178,16 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
 	msg.header.msgtype = CHANNELMSG_RELID_RELEASED;
 	vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released));
 
-	spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
-	list_del(&channel->listentry);
-	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+	if (channel->primary_channel == NULL) {
+		spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
+		list_del(&channel->listentry);
+		spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+	} else {
+		primary_channel = channel->primary_channel;
+		spin_lock_irqsave(&primary_channel->sc_lock, flags);
+		list_del(&channel->listentry);
+		spin_unlock_irqrestore(&primary_channel->sc_lock, flags);
+	}
 	free_channel(channel);
 }
 
@@ -228,6 +239,24 @@ static void vmbus_process_offer(struct work_struct *work)
 	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
 
 	if (!fnew) {
+		/*
+		 * Check to see if this is a sub-channel.
+		 */
+		if (newchannel->offermsg.offer.sub_channel_index != 0) {
+			/*
+			 * Process the sub-channel.
+			 */
+			newchannel->primary_channel = channel;
+			spin_lock_irqsave(&channel->sc_lock, flags);
+			list_add_tail(&newchannel->sc_list, &channel->sc_list);
+			spin_unlock_irqrestore(&channel->sc_lock, flags);
+			newchannel->state = CHANNEL_OPEN_STATE;
+			if (channel->sc_creation_callback != NULL)
+				channel->sc_creation_callback(newchannel);
+
+			return;
+		}
+
 		free_channel(newchannel);
 		return;
 	}
@@ -685,4 +714,86 @@ cleanup:
 	return ret;
 }
 
-/* eof */
+/*
+ * Retrieve the (sub) channel on which to send an outgoing request.
+ * When a primary channel has multiple sub-channels, we choose a
+ * channel whose VCPU binding is closest to the VCPU on which
+ * this call is being made.
+ */
+struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary)
+{
+	struct list_head *cur, *tmp;
+	int cur_cpu = hv_context.vp_index[smp_processor_id()];
+	struct vmbus_channel *cur_channel;
+	struct vmbus_channel *outgoing_channel = primary;
+	int cpu_distance, new_cpu_distance;
+
+	if (list_empty(&primary->sc_list))
+		return outgoing_channel;
+
+	list_for_each_safe(cur, tmp, &primary->sc_list) {
+		cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
+		if (cur_channel->state != CHANNEL_OPENED_STATE)
+			continue;
+
+		if (cur_channel->target_vp == cur_cpu)
+			return cur_channel;
+
+		cpu_distance = ((outgoing_channel->target_vp > cur_cpu) ?
+				(outgoing_channel->target_vp - cur_cpu) :
+				(cur_cpu - outgoing_channel->target_vp));
+
+		new_cpu_distance = ((cur_channel->target_vp > cur_cpu) ?
+				(cur_channel->target_vp - cur_cpu) :
+				(cur_cpu - cur_channel->target_vp));
+
+		if (cpu_distance < new_cpu_distance)
+			continue;
+
+		outgoing_channel = cur_channel;
+	}
+
+	return outgoing_channel;
+}
+EXPORT_SYMBOL_GPL(vmbus_get_outgoing_channel);
+
+static void invoke_sc_cb(struct vmbus_channel *primary_channel)
+{
+	struct list_head *cur, *tmp;
+	struct vmbus_channel *cur_channel;
+
+	if (primary_channel->sc_creation_callback == NULL)
+		return;
+
+	list_for_each_safe(cur, tmp, &primary_channel->sc_list) {
+		cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
+
+		primary_channel->sc_creation_callback(cur_channel);
+	}
+}
+
+void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel,
+				void (*sc_cr_cb)(struct vmbus_channel *new_sc))
+{
+	primary_channel->sc_creation_callback = sc_cr_cb;
+}
+EXPORT_SYMBOL_GPL(vmbus_set_sc_create_callback);
+
+bool vmbus_are_subchannels_present(struct vmbus_channel *primary)
+{
+	bool ret;
+
+	ret = !list_empty(&primary->sc_list);
+
+	if (ret) {
+		/*
+		 * Invoke the callback on sub-channel creation.
+		 * This will present a uniform interface to the
+		 * clients.
+		 */
+		invoke_sc_cb(primary);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_are_subchannels_present);

+ 14 - 0
drivers/hv/connection.c

@@ -246,12 +246,26 @@ struct vmbus_channel *relid2channel(u32 relid)
 	struct vmbus_channel *channel;
 	struct vmbus_channel *found_channel  = NULL;
 	unsigned long flags;
+	struct list_head *cur, *tmp;
+	struct vmbus_channel *cur_sc;
 
 	spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
 	list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
 		if (channel->offermsg.child_relid == relid) {
 			found_channel = channel;
 			break;
+		} else if (!list_empty(&channel->sc_list)) {
+			/*
+			 * Deal with sub-channels.
+			 */
+			list_for_each_safe(cur, tmp, &channel->sc_list) {
+				cur_sc = list_entry(cur, struct vmbus_channel,
+							sc_list);
+				if (cur_sc->offermsg.child_relid == relid) {
+					found_channel = cur_sc;
+					break;
+				}
+			}
 		}
 	}
 	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);

+ 53 - 32
drivers/hv/hv.c

@@ -265,6 +265,59 @@ u16 hv_signal_event(void *con_id)
 	return status;
 }
 
+
+int hv_synic_alloc(void)
+{
+	size_t size = sizeof(struct tasklet_struct);
+	int cpu;
+
+	for_each_online_cpu(cpu) {
+		hv_context.event_dpc[cpu] = kmalloc(size, GFP_ATOMIC);
+		if (hv_context.event_dpc[cpu] == NULL) {
+			pr_err("Unable to allocate event dpc\n");
+			goto err;
+		}
+		tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu);
+
+		hv_context.synic_message_page[cpu] =
+			(void *)get_zeroed_page(GFP_ATOMIC);
+
+		if (hv_context.synic_message_page[cpu] == NULL) {
+			pr_err("Unable to allocate SYNIC message page\n");
+			goto err;
+		}
+
+		hv_context.synic_event_page[cpu] =
+			(void *)get_zeroed_page(GFP_ATOMIC);
+
+		if (hv_context.synic_event_page[cpu] == NULL) {
+			pr_err("Unable to allocate SYNIC event page\n");
+			goto err;
+		}
+	}
+
+	return 0;
+err:
+	return -ENOMEM;
+}
+
+void hv_synic_free_cpu(int cpu)
+{
+	kfree(hv_context.event_dpc[cpu]);
+	if (hv_context.synic_message_page[cpu])
+		free_page((unsigned long)hv_context.synic_event_page[cpu]);
+	if (hv_context.synic_message_page[cpu])
+		free_page((unsigned long)hv_context.synic_message_page[cpu]);
+}
+
+void hv_synic_free(void)
+{
+	int cpu;
+
+	for_each_online_cpu(cpu)
+		hv_synic_free_cpu(cpu);
+}
+
 /*
  * hv_synic_init - Initialize the Synthethic Interrupt Controller.
  *
@@ -289,30 +342,6 @@ void hv_synic_init(void *arg)
 	/* Check the version */
 	rdmsrl(HV_X64_MSR_SVERSION, version);
 
-	hv_context.event_dpc[cpu] = kmalloc(sizeof(struct tasklet_struct),
-					    GFP_ATOMIC);
-	if (hv_context.event_dpc[cpu] == NULL) {
-		pr_err("Unable to allocate event dpc\n");
-		goto cleanup;
-	}
-	tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu);
-
-	hv_context.synic_message_page[cpu] =
-		(void *)get_zeroed_page(GFP_ATOMIC);
-
-	if (hv_context.synic_message_page[cpu] == NULL) {
-		pr_err("Unable to allocate SYNIC message page\n");
-		goto cleanup;
-	}
-
-	hv_context.synic_event_page[cpu] =
-		(void *)get_zeroed_page(GFP_ATOMIC);
-
-	if (hv_context.synic_event_page[cpu] == NULL) {
-		pr_err("Unable to allocate SYNIC event page\n");
-		goto cleanup;
-	}
-
 	/* Setup the Synic's message page */
 	rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64);
 	simp.simp_enabled = 1;
@@ -355,14 +384,6 @@ void hv_synic_init(void *arg)
 	rdmsrl(HV_X64_MSR_VP_INDEX, vp_index);
 	hv_context.vp_index[cpu] = (u32)vp_index;
 	return;
-
-cleanup:
-	if (hv_context.synic_event_page[cpu])
-		free_page((unsigned long)hv_context.synic_event_page[cpu]);
-
-	if (hv_context.synic_message_page[cpu])
-		free_page((unsigned long)hv_context.synic_message_page[cpu]);
-	return;
 }
 
 /*

+ 4 - 0
drivers/hv/hyperv_vmbus.h

@@ -527,6 +527,10 @@ extern int hv_post_message(union hv_connection_id connection_id,
 
 extern u16 hv_signal_event(void *con_id);
 
+extern int hv_synic_alloc(void);
+
+extern void hv_synic_free(void);
+
 extern void hv_synic_init(void *irqarg);
 
 extern void hv_synic_cleanup(void *arg);

+ 7 - 5
drivers/hv/ring_buffer.c

@@ -32,7 +32,7 @@
 void hv_begin_read(struct hv_ring_buffer_info *rbi)
 {
 	rbi->ring_buffer->interrupt_mask = 1;
-	smp_mb();
+	mb();
 }
 
 u32 hv_end_read(struct hv_ring_buffer_info *rbi)
@@ -41,7 +41,7 @@ u32 hv_end_read(struct hv_ring_buffer_info *rbi)
 	u32 write;
 
 	rbi->ring_buffer->interrupt_mask = 0;
-	smp_mb();
+	mb();
 
 	/*
 	 * Now check to see if the ring buffer is still empty.
@@ -71,10 +71,12 @@ u32 hv_end_read(struct hv_ring_buffer_info *rbi)
 
 static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi)
 {
-	smp_mb();
+	mb();
 	if (rbi->ring_buffer->interrupt_mask)
 		return false;
 
+	/* check interrupt_mask before read_index */
+	rmb();
 	/*
 	 * This is the only case we need to signal when the
 	 * ring transitions from being empty to non-empty.
@@ -442,7 +444,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
 					     sizeof(u64));
 
 	/* Issue a full memory barrier before updating the write index */
-	smp_mb();
+	mb();
 
 	/* Now, update the write location */
 	hv_set_next_write_location(outring_info, next_write_location);
@@ -549,7 +551,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer,
 	/* Make sure all reads are done before we update the read index since */
 	/* the writer may start writing to the read area once the read index */
 	/*is updated */
-	smp_mb();
+	mb();
 
 	/* Update the read index */
 	hv_set_next_read_location(inring_info, next_read_location);

+ 7 - 3
drivers/hv/vmbus_drv.c

@@ -434,7 +434,7 @@ static void vmbus_on_msg_dpc(unsigned long data)
 		 * will not deliver any more messages since there is
 		 * no empty slot
 		 */
-		smp_mb();
+		mb();
 
 		if (msg->header.message_flags.msg_pending) {
 			/*
@@ -563,6 +563,9 @@ static int vmbus_bus_init(int irq)
 	 */
 	hv_register_vmbus_handler(irq, vmbus_isr);
 
+	ret = hv_synic_alloc();
+	if (ret)
+		goto err_alloc;
 	/*
 	 * Initialize the per-cpu interrupt state and
 	 * connect to the host.
@@ -570,13 +573,14 @@ static int vmbus_bus_init(int irq)
 	on_each_cpu(hv_synic_init, NULL, 1);
 	ret = vmbus_connect();
 	if (ret)
-		goto err_irq;
+		goto err_alloc;
 
 	vmbus_request_offers();
 
 	return 0;
 
-err_irq:
+err_alloc:
+	hv_synic_free();
 	free_irq(irq, hv_acpi_dev);
 
 err_unregister:

+ 10 - 0
drivers/memory/Kconfig

@@ -20,6 +20,16 @@ config TI_EMIF
 	  parameters and other settings during frequency, voltage and
 	  temperature changes
 
+config MVEBU_DEVBUS
+	bool "Marvell EBU Device Bus Controller"
+	default y
+	depends on PLAT_ORION && OF
+	help
+	  This driver is for the Device Bus controller available in some
+	  Marvell EBU SoCs such as Discovery (mv78xx0), Orion (88f5xxx) and
+	  Armada 370 and Armada XP. This controller allows to handle flash
+	  devices such as NOR, NAND, SRAM, and FPGA.
+
 config TEGRA20_MC
 	bool "Tegra20 Memory Controller(MC) driver"
 	default y

+ 1 - 0
drivers/memory/Makefile

@@ -6,5 +6,6 @@ ifeq ($(CONFIG_DDR),y)
 obj-$(CONFIG_OF)		+= of_memory.o
 endif
 obj-$(CONFIG_TI_EMIF)		+= emif.o
+obj-$(CONFIG_MVEBU_DEVBUS)	+= mvebu-devbus.o
 obj-$(CONFIG_TEGRA20_MC)	+= tegra20-mc.o
 obj-$(CONFIG_TEGRA30_MC)	+= tegra30-mc.o

+ 340 - 0
drivers/memory/mvebu-devbus.c

@@ -0,0 +1,340 @@
+/*
+ * Marvell EBU SoC Device Bus Controller
+ * (memory controller for NOR/NAND/SRAM/FPGA devices)
+ *
+ * Copyright (C) 2013 Marvell
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/mbus.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+/* Register definitions */
+#define DEV_WIDTH_BIT		30
+#define BADR_SKEW_BIT		28
+#define RD_HOLD_BIT		23
+#define ACC_NEXT_BIT		17
+#define RD_SETUP_BIT		12
+#define ACC_FIRST_BIT		6
+
+#define SYNC_ENABLE_BIT		24
+#define WR_HIGH_BIT		16
+#define WR_LOW_BIT		8
+
+#define READ_PARAM_OFFSET	0x0
+#define WRITE_PARAM_OFFSET	0x4
+
+static const char * const devbus_wins[] = {
+	"devbus-boot",
+	"devbus-cs0",
+	"devbus-cs1",
+	"devbus-cs2",
+	"devbus-cs3",
+};
+
+struct devbus_read_params {
+	u32 bus_width;
+	u32 badr_skew;
+	u32 turn_off;
+	u32 acc_first;
+	u32 acc_next;
+	u32 rd_setup;
+	u32 rd_hold;
+};
+
+struct devbus_write_params {
+	u32 sync_enable;
+	u32 wr_high;
+	u32 wr_low;
+	u32 ale_wr;
+};
+
+struct devbus {
+	struct device *dev;
+	void __iomem *base;
+	unsigned long tick_ps;
+};
+
+static int get_timing_param_ps(struct devbus *devbus,
+			       struct device_node *node,
+			       const char *name,
+			       u32 *ticks)
+{
+	u32 time_ps;
+	int err;
+
+	err = of_property_read_u32(node, name, &time_ps);
+	if (err < 0) {
+		dev_err(devbus->dev, "%s has no '%s' property\n",
+			name, node->full_name);
+		return err;
+	}
+
+	*ticks = (time_ps + devbus->tick_ps - 1) / devbus->tick_ps;
+
+	dev_dbg(devbus->dev, "%s: %u ps -> 0x%x\n",
+		name, time_ps, *ticks);
+	return 0;
+}
+
+static int devbus_set_timing_params(struct devbus *devbus,
+				    struct device_node *node)
+{
+	struct devbus_read_params r;
+	struct devbus_write_params w;
+	u32 value;
+	int err;
+
+	dev_dbg(devbus->dev, "Setting timing parameter, tick is %lu ps\n",
+		devbus->tick_ps);
+
+	/* Get read timings */
+	err = of_property_read_u32(node, "devbus,bus-width", &r.bus_width);
+	if (err < 0) {
+		dev_err(devbus->dev,
+			"%s has no 'devbus,bus-width' property\n",
+			node->full_name);
+		return err;
+	}
+	/* Convert bit width to byte width */
+	r.bus_width /= 8;
+
+	err = get_timing_param_ps(devbus, node, "devbus,badr-skew-ps",
+				 &r.badr_skew);
+	if (err < 0)
+		return err;
+
+	err = get_timing_param_ps(devbus, node, "devbus,turn-off-ps",
+				 &r.turn_off);
+	if (err < 0)
+		return err;
+
+	err = get_timing_param_ps(devbus, node, "devbus,acc-first-ps",
+				 &r.acc_first);
+	if (err < 0)
+		return err;
+
+	err = get_timing_param_ps(devbus, node, "devbus,acc-next-ps",
+				 &r.acc_next);
+	if (err < 0)
+		return err;
+
+	err = get_timing_param_ps(devbus, node, "devbus,rd-setup-ps",
+				 &r.rd_setup);
+	if (err < 0)
+		return err;
+
+	err = get_timing_param_ps(devbus, node, "devbus,rd-hold-ps",
+				 &r.rd_hold);
+	if (err < 0)
+		return err;
+
+	/* Get write timings */
+	err = of_property_read_u32(node, "devbus,sync-enable",
+				  &w.sync_enable);
+	if (err < 0) {
+		dev_err(devbus->dev,
+			"%s has no 'devbus,sync-enable' property\n",
+			node->full_name);
+		return err;
+	}
+
+	err = get_timing_param_ps(devbus, node, "devbus,ale-wr-ps",
+				 &w.ale_wr);
+	if (err < 0)
+		return err;
+
+	err = get_timing_param_ps(devbus, node, "devbus,wr-low-ps",
+				 &w.wr_low);
+	if (err < 0)
+		return err;
+
+	err = get_timing_param_ps(devbus, node, "devbus,wr-high-ps",
+				 &w.wr_high);
+	if (err < 0)
+		return err;
+
+	/* Set read timings */
+	value = r.bus_width << DEV_WIDTH_BIT |
+		r.badr_skew << BADR_SKEW_BIT |
+		r.rd_hold   << RD_HOLD_BIT   |
+		r.acc_next  << ACC_NEXT_BIT  |
+		r.rd_setup  << RD_SETUP_BIT  |
+		r.acc_first << ACC_FIRST_BIT |
+		r.turn_off;
+
+	dev_dbg(devbus->dev, "read parameters register 0x%p = 0x%x\n",
+		devbus->base + READ_PARAM_OFFSET,
+		value);
+
+	writel(value, devbus->base + READ_PARAM_OFFSET);
+
+	/* Set write timings */
+	value = w.sync_enable  << SYNC_ENABLE_BIT |
+		w.wr_low       << WR_LOW_BIT      |
+		w.wr_high      << WR_HIGH_BIT     |
+		w.ale_wr;
+
+	dev_dbg(devbus->dev, "write parameters register: 0x%p = 0x%x\n",
+		devbus->base + WRITE_PARAM_OFFSET,
+		value);
+
+	writel(value, devbus->base + WRITE_PARAM_OFFSET);
+
+	return 0;
+}
+
+static int mvebu_devbus_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = pdev->dev.of_node;
+	struct device_node *parent;
+	struct devbus *devbus;
+	struct resource *res;
+	struct clk *clk;
+	unsigned long rate;
+	const __be32 *ranges;
+	int err, cs;
+	int addr_cells, p_addr_cells, size_cells;
+	int ranges_len, tuple_len;
+	u32 base, size;
+
+	devbus = devm_kzalloc(&pdev->dev, sizeof(struct devbus), GFP_KERNEL);
+	if (!devbus)
+		return -ENOMEM;
+
+	devbus->dev = dev;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	devbus->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(devbus->base))
+		return PTR_ERR(devbus->base);
+
+	clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+	clk_prepare_enable(clk);
+
+	/*
+	 * Obtain clock period in picoseconds,
+	 * we need this in order to convert timing
+	 * parameters from cycles to picoseconds.
+	 */
+	rate = clk_get_rate(clk) / 1000;
+	devbus->tick_ps = 1000000000 / rate;
+
+	/* Read the device tree node and set the new timing parameters */
+	err = devbus_set_timing_params(devbus, node);
+	if (err < 0)
+		return err;
+
+	/*
+	 * Allocate an address window for this device.
+	 * If the device probing fails, then we won't be able to
+	 * remove the allocated address decoding window.
+	 *
+	 * FIXME: This is only a temporary hack! We need to do this here
+	 * because we still don't have device tree bindings for mbus.
+	 * Once that support is added, we will declare these address windows
+	 * statically in the device tree, and remove the window configuration
+	 * from here.
+	 */
+
+	/*
+	 * Get the CS to choose the window string.
+	 * This is a bit hacky, but it will be removed once the
+	 * address windows are declared in the device tree.
+	 */
+	cs = (((unsigned long)devbus->base) % 0x400) / 8;
+
+	/*
+	 * Parse 'ranges' property to obtain a (base,size) window tuple.
+	 * This will be removed once the address windows
+	 * are declared in the device tree.
+	 */
+	parent = of_get_parent(node);
+	if (!parent)
+		return -EINVAL;
+
+	p_addr_cells = of_n_addr_cells(parent);
+	of_node_put(parent);
+
+	addr_cells = of_n_addr_cells(node);
+	size_cells = of_n_size_cells(node);
+	tuple_len = (p_addr_cells + addr_cells + size_cells) * sizeof(__be32);
+
+	ranges = of_get_property(node, "ranges", &ranges_len);
+	if (ranges == NULL || ranges_len != tuple_len)
+		return -EINVAL;
+
+	base = of_translate_address(node, ranges + addr_cells);
+	if (base == OF_BAD_ADDR)
+		return -EINVAL;
+	size = of_read_number(ranges + addr_cells + p_addr_cells, size_cells);
+
+	/*
+	 * Create an mbus address windows.
+	 * FIXME: Remove this, together with the above code, once the
+	 * address windows are declared in the device tree.
+	 */
+	err = mvebu_mbus_add_window(devbus_wins[cs], base, size);
+	if (err < 0)
+		return err;
+
+	/*
+	 * We need to create a child device explicitly from here to
+	 * guarantee that the child will be probed after the timing
+	 * parameters for the bus are written.
+	 */
+	err = of_platform_populate(node, NULL, NULL, dev);
+	if (err < 0) {
+		mvebu_mbus_del_window(base, size);
+		return err;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id mvebu_devbus_of_match[] = {
+	{ .compatible = "marvell,mvebu-devbus" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match);
+
+static struct platform_driver mvebu_devbus_driver = {
+	.probe		= mvebu_devbus_probe,
+	.driver		= {
+		.name	= "mvebu-devbus",
+		.owner	= THIS_MODULE,
+		.of_match_table = mvebu_devbus_of_match,
+	},
+};
+
+static int __init mvebu_devbus_init(void)
+{
+	return platform_driver_register(&mvebu_devbus_driver);
+}
+module_init(mvebu_devbus_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell EBU SoC Device Bus controller");

+ 4 - 1
drivers/memory/tegra20-mc.c

@@ -193,8 +193,11 @@ static irqreturn_t tegra20_mc_isr(int irq, void *data)
 	mask &= stat;
 	if (!mask)
 		return IRQ_NONE;
-	while ((bit = ffs(mask)) != 0)
+	while ((bit = ffs(mask)) != 0) {
 		tegra20_mc_decode(mc, bit - 1);
+		mask &= ~BIT(bit - 1);
+	}
+
 	mc_writel(mc, stat, MC_INTSTATUS);
 	return IRQ_HANDLED;
 }

+ 6 - 3
drivers/memory/tegra30-mc.c

@@ -218,7 +218,7 @@ static void tegra30_mc_decode(struct tegra30_mc *mc, int n)
 		return;
 	}
 
-	err = readl(mc + MC_ERR_STATUS);
+	err = mc_readl(mc, MC_ERR_STATUS);
 
 	type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT;
 	perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >>
@@ -235,7 +235,7 @@ static void tegra30_mc_decode(struct tegra30_mc *mc, int n)
 	if (cid < ARRAY_SIZE(tegra30_mc_client))
 		client = tegra30_mc_client[cid];
 
-	addr = readl(mc + MC_ERR_ADR);
+	addr = mc_readl(mc, MC_ERR_ADR);
 
 	dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n",
 			   mc_int_err[idx], err, addr, client,
@@ -313,8 +313,11 @@ static irqreturn_t tegra30_mc_isr(int irq, void *data)
 	mask &= stat;
 	if (!mask)
 		return IRQ_NONE;
-	while ((bit = ffs(mask)) != 0)
+	while ((bit = ffs(mask)) != 0) {
 		tegra30_mc_decode(mc, bit - 1);
+		mask &= ~BIT(bit - 1);
+	}
+
 	mc_writel(mc, stat, MC_INTSTATUS);
 	return IRQ_HANDLED;
 }

+ 1 - 0
drivers/misc/Kconfig

@@ -480,6 +480,7 @@ config BMP085_SPI
 
 config PCH_PHUB
 	tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB"
+	select GENERIC_NET_UTILS
 	depends on PCI
 	help
 	  This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of

+ 1 - 1
drivers/misc/ad525x_dpot.c

@@ -470,7 +470,7 @@ static ssize_t sysfs_set_reg(struct device *dev,
 		!test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask))
 		return -EPERM;
 
-	err = strict_strtoul(buf, 10, &value);
+	err = kstrtoul(buf, 10, &value);
 	if (err)
 		return err;
 

+ 3 - 2
drivers/misc/apds9802als.c

@@ -126,8 +126,9 @@ static ssize_t als_sensing_range_store(struct device *dev,
 	int ret_val;
 	unsigned long val;
 
-	if (strict_strtoul(buf, 10, &val))
-		return -EINVAL;
+	ret_val = kstrtoul(buf, 10, &val);
+	if (ret_val)
+		return ret_val;
 
 	if (val < 4096)
 		val = 1;

+ 24 - 13
drivers/misc/apds990x.c

@@ -696,9 +696,11 @@ static ssize_t apds990x_lux_calib_store(struct device *dev,
 {
 	struct apds990x_chip *chip = dev_get_drvdata(dev);
 	unsigned long value;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &value))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
 
 	chip->lux_calib = value;
 
@@ -759,8 +761,9 @@ static ssize_t apds990x_rate_store(struct device *dev,
 	unsigned long value;
 	int ret;
 
-	if (strict_strtoul(buf, 0, &value))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
 
 	mutex_lock(&chip->mutex);
 	ret = apds990x_set_arate(chip, value);
@@ -813,9 +816,11 @@ static ssize_t apds990x_prox_enable_store(struct device *dev,
 {
 	struct apds990x_chip *chip =  dev_get_drvdata(dev);
 	unsigned long value;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &value))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
 
 	mutex_lock(&chip->mutex);
 
@@ -892,11 +897,12 @@ static ssize_t apds990x_lux_thresh_below_show(struct device *dev,
 static ssize_t apds990x_set_lux_thresh(struct apds990x_chip *chip, u32 *target,
 				const char *buf)
 {
-	int ret = 0;
 	unsigned long thresh;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &thresh))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &thresh);
+	if (ret)
+		return ret;
 
 	if (thresh > APDS_RANGE)
 		return -EINVAL;
@@ -957,9 +963,11 @@ static ssize_t apds990x_prox_threshold_store(struct device *dev,
 {
 	struct apds990x_chip *chip =  dev_get_drvdata(dev);
 	unsigned long value;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &value))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
 
 	if ((value > APDS_RANGE) || (value == 0) ||
 		(value < APDS_PROX_HYSTERESIS))
@@ -990,9 +998,12 @@ static ssize_t apds990x_power_state_store(struct device *dev,
 {
 	struct apds990x_chip *chip =  dev_get_drvdata(dev);
 	unsigned long value;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
 
-	if (strict_strtoul(buf, 0, &value))
-		return -EINVAL;
 	if (value) {
 		pm_runtime_get_sync(dev);
 		mutex_lock(&chip->mutex);

+ 1 - 4
drivers/misc/arm-charlcd.c

@@ -291,7 +291,7 @@ static int __init charlcd_probe(struct platform_device *pdev)
 	lcd->virtbase = ioremap(lcd->phybase, lcd->physize);
 	if (!lcd->virtbase) {
 		ret = -ENOMEM;
-		goto out_no_remap;
+		goto out_no_memregion;
 	}
 
 	lcd->irq = platform_get_irq(pdev, 0);
@@ -320,8 +320,6 @@ static int __init charlcd_probe(struct platform_device *pdev)
 
 out_no_irq:
 	iounmap(lcd->virtbase);
-out_no_remap:
-	platform_set_drvdata(pdev, NULL);
 out_no_memregion:
 	release_mem_region(lcd->phybase, SZ_4K);
 out_no_resource:
@@ -337,7 +335,6 @@ static int __exit charlcd_remove(struct platform_device *pdev)
 		free_irq(lcd->irq, lcd);
 		iounmap(lcd->virtbase);
 		release_mem_region(lcd->phybase, lcd->physize);
-		platform_set_drvdata(pdev, NULL);
 		kfree(lcd);
 	}
 

+ 38 - 21
drivers/misc/bh1770glc.c

@@ -651,8 +651,9 @@ static ssize_t bh1770_power_state_store(struct device *dev,
 	unsigned long value;
 	ssize_t ret;
 
-	if (strict_strtoul(buf, 0, &value))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
 
 	mutex_lock(&chip->mutex);
 	if (value) {
@@ -726,9 +727,11 @@ static ssize_t bh1770_prox_enable_store(struct device *dev,
 {
 	struct bh1770_chip *chip =  dev_get_drvdata(dev);
 	unsigned long value;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &value))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
 
 	mutex_lock(&chip->mutex);
 	/* Assume no proximity. Sensor will tell real state soon */
@@ -824,9 +827,11 @@ static ssize_t bh1770_set_prox_rate_above(struct device *dev,
 {
 	struct bh1770_chip *chip =  dev_get_drvdata(dev);
 	unsigned long value;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &value))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
 
 	mutex_lock(&chip->mutex);
 	chip->prox_rate_threshold = bh1770_prox_rate_validate(value);
@@ -840,9 +845,11 @@ static ssize_t bh1770_set_prox_rate_below(struct device *dev,
 {
 	struct bh1770_chip *chip =  dev_get_drvdata(dev);
 	unsigned long value;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &value))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
 
 	mutex_lock(&chip->mutex);
 	chip->prox_rate = bh1770_prox_rate_validate(value);
@@ -865,8 +872,10 @@ static ssize_t bh1770_set_prox_thres(struct device *dev,
 	unsigned long value;
 	int ret;
 
-	if (strict_strtoul(buf, 0, &value))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
+
 	if (value > BH1770_PROX_RANGE)
 		return -EINVAL;
 
@@ -893,9 +902,11 @@ static ssize_t bh1770_prox_persistence_store(struct device *dev,
 {
 	struct bh1770_chip *chip = dev_get_drvdata(dev);
 	unsigned long value;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &value))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
 
 	if (value > BH1770_PROX_MAX_PERSISTENCE)
 		return -EINVAL;
@@ -918,9 +929,11 @@ static ssize_t bh1770_prox_abs_thres_store(struct device *dev,
 {
 	struct bh1770_chip *chip = dev_get_drvdata(dev);
 	unsigned long value;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &value))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
 
 	if (value > BH1770_PROX_RANGE)
 		return -EINVAL;
@@ -963,9 +976,11 @@ static ssize_t bh1770_lux_calib_store(struct device *dev,
 	unsigned long value;
 	u32 old_calib;
 	u32 new_corr;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &value))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &value);
+	if (ret)
+		return ret;
 
 	mutex_lock(&chip->mutex);
 	old_calib = chip->lux_calib;
@@ -1012,8 +1027,9 @@ static ssize_t bh1770_set_lux_rate(struct device *dev,
 	unsigned long rate_hz;
 	int ret, i;
 
-	if (strict_strtoul(buf, 0, &rate_hz))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &rate_hz);
+	if (ret)
+		return ret;
 
 	for (i = 0; i < ARRAY_SIZE(lux_rates_hz) - 1; i++)
 		if (rate_hz >= lux_rates_hz[i])
@@ -1047,11 +1063,12 @@ static ssize_t bh1770_get_lux_thresh_below(struct device *dev,
 static ssize_t bh1770_set_lux_thresh(struct bh1770_chip *chip, u16 *target,
 				const char *buf)
 {
-	int ret = 0;
 	unsigned long thresh;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &thresh))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &thresh);
+	if (ret)
+		return ret;
 
 	if (thresh > BH1770_LUX_RANGE)
 		return -EINVAL;

+ 1 - 1
drivers/misc/bh1780gli.c

@@ -107,7 +107,7 @@ static ssize_t bh1780_store_power_state(struct device *dev,
 	unsigned long val;
 	int error;
 
-	error = strict_strtoul(buf, 0, &val);
+	error = kstrtoul(buf, 0, &val);
 	if (error)
 		return error;
 

+ 8 - 6
drivers/misc/carma/carma-fpga-program.c

@@ -830,8 +830,9 @@ static ssize_t penable_store(struct device *dev, struct device_attribute *attr,
 	unsigned long val;
 	int ret;
 
-	if (strict_strtoul(buf, 0, &val))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &val);
+	if (ret)
+		return ret;
 
 	if (val) {
 		ret = fpga_enable_power_supplies(priv);
@@ -859,8 +860,9 @@ static ssize_t program_store(struct device *dev, struct device_attribute *attr,
 	unsigned long val;
 	int ret;
 
-	if (strict_strtoul(buf, 0, &val))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &val);
+	if (ret)
+		return ret;
 
 	/* We can't have an image writer and be programming simultaneously */
 	if (mutex_lock_interruptible(&priv->lock))
@@ -919,7 +921,7 @@ static bool dma_filter(struct dma_chan *chan, void *data)
 
 static int fpga_of_remove(struct platform_device *op)
 {
-	struct fpga_dev *priv = dev_get_drvdata(&op->dev);
+	struct fpga_dev *priv = platform_get_drvdata(op);
 	struct device *this_device = priv->miscdev.this_device;
 
 	sysfs_remove_group(&this_device->kobj, &fpga_attr_group);
@@ -969,7 +971,7 @@ static int fpga_of_probe(struct platform_device *op)
 
 	kref_init(&priv->ref);
 
-	dev_set_drvdata(&op->dev, priv);
+	platform_set_drvdata(op, priv);
 	priv->dev = &op->dev;
 	mutex_init(&priv->lock);
 	init_completion(&priv->completion);

+ 4 - 4
drivers/misc/carma/carma-fpga.c

@@ -1002,10 +1002,10 @@ static ssize_t data_en_set(struct device *dev, struct device_attribute *attr,
 	unsigned long enable;
 	int ret;
 
-	ret = strict_strtoul(buf, 0, &enable);
+	ret = kstrtoul(buf, 0, &enable);
 	if (ret) {
 		dev_err(priv->dev, "unable to parse enable input\n");
-		return -EINVAL;
+		return ret;
 	}
 
 	/* protect against concurrent enable/disable */
@@ -1296,7 +1296,7 @@ static int data_of_probe(struct platform_device *op)
 		goto out_return;
 	}
 
-	dev_set_drvdata(&op->dev, priv);
+	platform_set_drvdata(op, priv);
 	priv->dev = &op->dev;
 	kref_init(&priv->ref);
 	mutex_init(&priv->mutex);
@@ -1400,7 +1400,7 @@ out_return:
 
 static int data_of_remove(struct platform_device *op)
 {
-	struct fpga_device *priv = dev_get_drvdata(&op->dev);
+	struct fpga_device *priv = platform_get_drvdata(op);
 	struct device *this_device = priv->miscdev.this_device;
 
 	/* remove all sysfs files, now the device cannot be re-enabled */

+ 15 - 29
drivers/misc/eeprom/at24.c

@@ -492,10 +492,9 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	if (client->dev.platform_data) {
 		chip = *(struct at24_platform_data *)client->dev.platform_data;
 	} else {
-		if (!id->driver_data) {
-			err = -ENODEV;
-			goto err_out;
-		}
+		if (!id->driver_data)
+			return -ENODEV;
+
 		magic = id->driver_data;
 		chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN));
 		magic >>= AT24_SIZE_BYTELEN;
@@ -519,8 +518,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 			"byte_len looks suspicious (no power of 2)!\n");
 	if (!chip.page_size) {
 		dev_err(&client->dev, "page_size must not be 0!\n");
-		err = -EINVAL;
-		goto err_out;
+		return -EINVAL;
 	}
 	if (!is_power_of_2(chip.page_size))
 		dev_warn(&client->dev,
@@ -528,10 +526,9 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 	/* Use I2C operations unless we're stuck with SMBus extensions. */
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-		if (chip.flags & AT24_FLAG_ADDR16) {
-			err = -EPFNOSUPPORT;
-			goto err_out;
-		}
+		if (chip.flags & AT24_FLAG_ADDR16)
+			return -EPFNOSUPPORT;
+
 		if (i2c_check_functionality(client->adapter,
 				I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
 			use_smbus = I2C_SMBUS_I2C_BLOCK_DATA;
@@ -542,8 +539,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 				I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
 			use_smbus = I2C_SMBUS_BYTE_DATA;
 		} else {
-			err = -EPFNOSUPPORT;
-			goto err_out;
+			return -EPFNOSUPPORT;
 		}
 	}
 
@@ -553,12 +549,10 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		num_addresses =	DIV_ROUND_UP(chip.byte_len,
 			(chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256);
 
-	at24 = kzalloc(sizeof(struct at24_data) +
+	at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) +
 		num_addresses * sizeof(struct i2c_client *), GFP_KERNEL);
-	if (!at24) {
-		err = -ENOMEM;
-		goto err_out;
-	}
+	if (!at24)
+		return -ENOMEM;
 
 	mutex_init(&at24->lock);
 	at24->use_smbus = use_smbus;
@@ -596,11 +590,10 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 			at24->write_max = write_max;
 
 			/* buffer (data + address at the beginning) */
-			at24->writebuf = kmalloc(write_max + 2, GFP_KERNEL);
-			if (!at24->writebuf) {
-				err = -ENOMEM;
-				goto err_struct;
-			}
+			at24->writebuf = devm_kzalloc(&client->dev,
+				write_max + 2, GFP_KERNEL);
+			if (!at24->writebuf)
+				return -ENOMEM;
 		} else {
 			dev_warn(&client->dev,
 				"cannot write due to controller restrictions.");
@@ -648,11 +641,6 @@ err_clients:
 		if (at24->client[i])
 			i2c_unregister_device(at24->client[i]);
 
-	kfree(at24->writebuf);
-err_struct:
-	kfree(at24);
-err_out:
-	dev_dbg(&client->dev, "probe error %d\n", err);
 	return err;
 }
 
@@ -667,8 +655,6 @@ static int at24_remove(struct i2c_client *client)
 	for (i = 1; i < at24->num_addresses; i++)
 		i2c_unregister_device(at24->client[i]);
 
-	kfree(at24->writebuf);
-	kfree(at24);
 	return 0;
 }
 

+ 8 - 17
drivers/misc/eeprom/at25.c

@@ -371,11 +371,10 @@ static int at25_probe(struct spi_device *spi)
 		if (np) {
 			err = at25_np_to_chip(&spi->dev, np, &chip);
 			if (err)
-				goto fail;
+				return err;
 		} else {
 			dev_err(&spi->dev, "Error: no chip description\n");
-			err = -ENODEV;
-			goto fail;
+			return -ENODEV;
 		}
 	} else
 		chip = *(struct spi_eeprom *)spi->dev.platform_data;
@@ -389,8 +388,7 @@ static int at25_probe(struct spi_device *spi)
 		addrlen = 3;
 	else {
 		dev_dbg(&spi->dev, "unsupported address type\n");
-		err = -EINVAL;
-		goto fail;
+		return -EINVAL;
 	}
 
 	/* Ping the chip ... the status register is pretty portable,
@@ -400,14 +398,12 @@ static int at25_probe(struct spi_device *spi)
 	sr = spi_w8r8(spi, AT25_RDSR);
 	if (sr < 0 || sr & AT25_SR_nRDY) {
 		dev_dbg(&spi->dev, "rdsr --> %d (%02x)\n", sr, sr);
-		err = -ENXIO;
-		goto fail;
+		return -ENXIO;
 	}
 
-	if (!(at25 = kzalloc(sizeof *at25, GFP_KERNEL))) {
-		err = -ENOMEM;
-		goto fail;
-	}
+	at25 = devm_kzalloc(&spi->dev, sizeof(struct at25_data), GFP_KERNEL);
+	if (!at25)
+		return -ENOMEM;
 
 	mutex_init(&at25->lock);
 	at25->chip = chip;
@@ -439,7 +435,7 @@ static int at25_probe(struct spi_device *spi)
 
 	err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin);
 	if (err)
-		goto fail;
+		return err;
 
 	if (chip.setup)
 		chip.setup(&at25->mem, chip.context);
@@ -453,10 +449,6 @@ static int at25_probe(struct spi_device *spi)
 		(chip.flags & EE_READONLY) ? " (readonly)" : "",
 		at25->chip.page_size);
 	return 0;
-fail:
-	dev_dbg(&spi->dev, "probe err %d\n", err);
-	kfree(at25);
-	return err;
 }
 
 static int at25_remove(struct spi_device *spi)
@@ -465,7 +457,6 @@ static int at25_remove(struct spi_device *spi)
 
 	at25 = spi_get_drvdata(spi);
 	sysfs_remove_bin_file(&spi->dev.kobj, &at25->bin);
-	kfree(at25);
 	return 0;
 }
 

+ 50 - 138
drivers/misc/ep93xx_pwm.c

@@ -39,63 +39,6 @@ struct ep93xx_pwm {
 	u32		duty_percent;
 };
 
-static inline void ep93xx_pwm_writel(struct ep93xx_pwm *pwm,
-		unsigned int val, unsigned int off)
-{
-	__raw_writel(val, pwm->mmio_base + off);
-}
-
-static inline unsigned int ep93xx_pwm_readl(struct ep93xx_pwm *pwm,
-		unsigned int off)
-{
-	return __raw_readl(pwm->mmio_base + off);
-}
-
-static inline void ep93xx_pwm_write_tc(struct ep93xx_pwm *pwm, u16 value)
-{
-	ep93xx_pwm_writel(pwm, value, EP93XX_PWMx_TERM_COUNT);
-}
-
-static inline u16 ep93xx_pwm_read_tc(struct ep93xx_pwm *pwm)
-{
-	return ep93xx_pwm_readl(pwm, EP93XX_PWMx_TERM_COUNT);
-}
-
-static inline void ep93xx_pwm_write_dc(struct ep93xx_pwm *pwm, u16 value)
-{
-	ep93xx_pwm_writel(pwm, value, EP93XX_PWMx_DUTY_CYCLE);
-}
-
-static inline void ep93xx_pwm_enable(struct ep93xx_pwm *pwm)
-{
-	ep93xx_pwm_writel(pwm, 0x1, EP93XX_PWMx_ENABLE);
-}
-
-static inline void ep93xx_pwm_disable(struct ep93xx_pwm *pwm)
-{
-	ep93xx_pwm_writel(pwm, 0x0, EP93XX_PWMx_ENABLE);
-}
-
-static inline int ep93xx_pwm_is_enabled(struct ep93xx_pwm *pwm)
-{
-	return ep93xx_pwm_readl(pwm, EP93XX_PWMx_ENABLE) & 0x1;
-}
-
-static inline void ep93xx_pwm_invert(struct ep93xx_pwm *pwm)
-{
-	ep93xx_pwm_writel(pwm, 0x1, EP93XX_PWMx_INVERT);
-}
-
-static inline void ep93xx_pwm_normal(struct ep93xx_pwm *pwm)
-{
-	ep93xx_pwm_writel(pwm, 0x0, EP93XX_PWMx_INVERT);
-}
-
-static inline int ep93xx_pwm_is_inverted(struct ep93xx_pwm *pwm)
-{
-	return ep93xx_pwm_readl(pwm, EP93XX_PWMx_INVERT) & 0x1;
-}
-
 /*
  * /sys/devices/platform/ep93xx-pwm.N
  *   /min_freq      read-only   minimum pwm output frequency
@@ -131,9 +74,9 @@ static ssize_t ep93xx_pwm_get_freq(struct device *dev,
 	struct platform_device *pdev = to_platform_device(dev);
 	struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
 
-	if (ep93xx_pwm_is_enabled(pwm)) {
+	if (readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1) {
 		unsigned long rate = clk_get_rate(pwm->clk);
-		u16 term = ep93xx_pwm_read_tc(pwm);
+		u16 term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
 
 		return sprintf(buf, "%ld\n", rate / (term + 1));
 	} else {
@@ -149,12 +92,12 @@ static ssize_t ep93xx_pwm_set_freq(struct device *dev,
 	long val;
 	int err;
 
-	err = strict_strtol(buf, 10, &val);
+	err = kstrtol(buf, 10, &val);
 	if (err)
 		return -EINVAL;
 
 	if (val == 0) {
-		ep93xx_pwm_disable(pwm);
+		writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE);
 	} else if (val <= (clk_get_rate(pwm->clk) / 2)) {
 		u32 term, duty;
 
@@ -164,20 +107,20 @@ static ssize_t ep93xx_pwm_set_freq(struct device *dev,
 		if (val < 1)
 			val = 1;
 
-		term = ep93xx_pwm_read_tc(pwm);
+		term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
 		duty = ((val + 1) * pwm->duty_percent / 100) - 1;
 
 		/* If pwm is running, order is important */
 		if (val > term) {
-			ep93xx_pwm_write_tc(pwm, val);
-			ep93xx_pwm_write_dc(pwm, duty);
+			writel(val, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
+			writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE);
 		} else {
-			ep93xx_pwm_write_dc(pwm, duty);
-			ep93xx_pwm_write_tc(pwm, val);
+			writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE);
+			writel(val, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
 		}
 
-		if (!ep93xx_pwm_is_enabled(pwm))
-			ep93xx_pwm_enable(pwm);
+		if (!readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1)
+			writel(0x1, pwm->mmio_base + EP93XX_PWMx_ENABLE);
 	} else {
 		return -EINVAL;
 	}
@@ -202,13 +145,15 @@ static ssize_t ep93xx_pwm_set_duty_percent(struct device *dev,
 	long val;
 	int err;
 
-	err = strict_strtol(buf, 10, &val);
+	err = kstrtol(buf, 10, &val);
 	if (err)
 		return -EINVAL;
 
 	if (val > 0 && val < 100) {
-		u32 term = ep93xx_pwm_read_tc(pwm);
-		ep93xx_pwm_write_dc(pwm, ((term + 1) * val / 100) - 1);
+		u32 term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
+		u32 duty = ((term + 1) * val / 100) - 1;
+
+		writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE);
 		pwm->duty_percent = val;
 		return count;
 	}
@@ -221,8 +166,9 @@ static ssize_t ep93xx_pwm_get_invert(struct device *dev,
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
+	int inverted = readl(pwm->mmio_base + EP93XX_PWMx_INVERT) & 0x1;
 
-	return sprintf(buf, "%d\n", ep93xx_pwm_is_inverted(pwm));
+	return sprintf(buf, "%d\n", inverted);
 }
 
 static ssize_t ep93xx_pwm_set_invert(struct device *dev,
@@ -233,14 +179,14 @@ static ssize_t ep93xx_pwm_set_invert(struct device *dev,
 	long val;
 	int err;
 
-	err = strict_strtol(buf, 10, &val);
+	err = kstrtol(buf, 10, &val);
 	if (err)
 		return -EINVAL;
 
 	if (val == 0)
-		ep93xx_pwm_normal(pwm);
+		writel(0x0, pwm->mmio_base + EP93XX_PWMx_INVERT);
 	else if (val == 1)
-		ep93xx_pwm_invert(pwm);
+		writel(0x1, pwm->mmio_base + EP93XX_PWMx_INVERT);
 	else
 		return -EINVAL;
 
@@ -269,89 +215,55 @@ static const struct attribute_group ep93xx_pwm_sysfs_files = {
 	.attrs	= ep93xx_pwm_attrs,
 };
 
-static int __init ep93xx_pwm_probe(struct platform_device *pdev)
+static int ep93xx_pwm_probe(struct platform_device *pdev)
 {
 	struct ep93xx_pwm *pwm;
 	struct resource *res;
-	int err;
+	int ret;
 
-	err = ep93xx_pwm_acquire_gpio(pdev);
-	if (err)
-		return err;
+	pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
+	if (!pwm)
+		return -ENOMEM;
 
-	pwm = kzalloc(sizeof(struct ep93xx_pwm), GFP_KERNEL);
-	if (!pwm) {
-		err = -ENOMEM;
-		goto fail_no_mem;
-	}
+	pwm->clk = devm_clk_get(&pdev->dev, "pwm_clk");
+	if (IS_ERR(pwm->clk))
+		return PTR_ERR(pwm->clk);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		err = -ENXIO;
-		goto fail_no_mem_resource;
-	}
-
-	res = request_mem_region(res->start, resource_size(res), pdev->name);
-	if (res == NULL) {
-		err = -EBUSY;
-		goto fail_no_mem_resource;
-	}
-
-	pwm->mmio_base = ioremap(res->start, resource_size(res));
-	if (pwm->mmio_base == NULL) {
-		err = -ENXIO;
-		goto fail_no_ioremap;
-	}
-
-	err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files);
-	if (err)
-		goto fail_no_sysfs;
-
-	pwm->clk = clk_get(&pdev->dev, "pwm_clk");
-	if (IS_ERR(pwm->clk)) {
-		err = PTR_ERR(pwm->clk);
-		goto fail_no_clk;
+	pwm->mmio_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pwm->mmio_base))
+		return PTR_ERR(pwm->mmio_base);
+
+	ret = ep93xx_pwm_acquire_gpio(pdev);
+	if (ret)
+		return ret;
+
+	ret = sysfs_create_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files);
+	if (ret) {
+		ep93xx_pwm_release_gpio(pdev);
+		return ret;
 	}
 
 	pwm->duty_percent = 50;
 
-	platform_set_drvdata(pdev, pwm);
-
 	/* disable pwm at startup. Avoids zero value. */
-	ep93xx_pwm_disable(pwm);
-	ep93xx_pwm_write_tc(pwm, EP93XX_PWM_MAX_COUNT);
-	ep93xx_pwm_write_dc(pwm, EP93XX_PWM_MAX_COUNT / 2);
+	writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE);
+	writel(EP93XX_PWM_MAX_COUNT, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT);
+	writel(EP93XX_PWM_MAX_COUNT/2, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE);
 
 	clk_enable(pwm->clk);
 
+	platform_set_drvdata(pdev, pwm);
 	return 0;
-
-fail_no_clk:
-	sysfs_remove_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files);
-fail_no_sysfs:
-	iounmap(pwm->mmio_base);
-fail_no_ioremap:
-	release_mem_region(res->start, resource_size(res));
-fail_no_mem_resource:
-	kfree(pwm);
-fail_no_mem:
-	ep93xx_pwm_release_gpio(pdev);
-	return err;
 }
 
-static int __exit ep93xx_pwm_remove(struct platform_device *pdev)
+static int ep93xx_pwm_remove(struct platform_device *pdev)
 {
 	struct ep93xx_pwm *pwm = platform_get_drvdata(pdev);
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	ep93xx_pwm_disable(pwm);
+	writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE);
 	clk_disable(pwm->clk);
-	clk_put(pwm->clk);
-	platform_set_drvdata(pdev, NULL);
 	sysfs_remove_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files);
-	iounmap(pwm->mmio_base);
-	release_mem_region(res->start, resource_size(res));
-	kfree(pwm);
 	ep93xx_pwm_release_gpio(pdev);
 
 	return 0;
@@ -362,10 +274,10 @@ static struct platform_driver ep93xx_pwm_driver = {
 		.name	= "ep93xx-pwm",
 		.owner	= THIS_MODULE,
 	},
-	.remove		= __exit_p(ep93xx_pwm_remove),
+	.probe		= ep93xx_pwm_probe,
+	.remove		= ep93xx_pwm_remove,
 };
-
-module_platform_driver_probe(ep93xx_pwm_driver, ep93xx_pwm_probe);
+module_platform_driver(ep93xx_pwm_driver);
 
 MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>, "
 	      "H Hartley Sweeten <hsweeten@visionengravers.com>");

+ 3 - 2
drivers/misc/hmc6352.c

@@ -46,8 +46,9 @@ static int compass_store(struct device *dev, const char *buf, size_t count,
 	int ret;
 	unsigned long val;
 
-	if (strict_strtoul(buf, 10, &val))
-		return -EINVAL;
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
 	if (val >= strlen(map))
 		return -EINVAL;
 	mutex_lock(&compass_mutex);

+ 20 - 4
drivers/misc/isl29003.c

@@ -208,7 +208,11 @@ static ssize_t isl29003_store_range(struct device *dev,
 	unsigned long val;
 	int ret;
 
-	if ((strict_strtoul(buf, 10, &val) < 0) || (val > 3))
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	if (val > 3)
 		return -EINVAL;
 
 	ret = isl29003_set_range(client, val);
@@ -239,7 +243,11 @@ static ssize_t isl29003_store_resolution(struct device *dev,
 	unsigned long val;
 	int ret;
 
-	if ((strict_strtoul(buf, 10, &val) < 0) || (val > 3))
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	if (val > 3)
 		return -EINVAL;
 
 	ret = isl29003_set_resolution(client, val);
@@ -267,7 +275,11 @@ static ssize_t isl29003_store_mode(struct device *dev,
 	unsigned long val;
 	int ret;
 
-	if ((strict_strtoul(buf, 10, &val) < 0) || (val > 2))
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	if (val > 2)
 		return -EINVAL;
 
 	ret = isl29003_set_mode(client, val);
@@ -298,7 +310,11 @@ static ssize_t isl29003_store_power_state(struct device *dev,
 	unsigned long val;
 	int ret;
 
-	if ((strict_strtoul(buf, 10, &val) < 0) || (val > 1))
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	if (val > 1)
 		return -EINVAL;
 
 	ret = isl29003_set_power_state(client, val);

+ 4 - 2
drivers/misc/isl29020.c

@@ -90,8 +90,10 @@ static ssize_t als_sensing_range_store(struct device *dev,
 	int ret_val;
 	unsigned long val;
 
-	if (strict_strtoul(buf, 10, &val))
-		return -EINVAL;
+	ret_val = kstrtoul(buf, 10, &val);
+	if (ret_val)
+		return ret_val;
+
 	if (val < 1 || val > 64000)
 		return -EINVAL;
 

+ 4 - 2
drivers/misc/lis3lv02d/lis3lv02d.c

@@ -831,9 +831,11 @@ static ssize_t lis3lv02d_rate_set(struct device *dev,
 {
 	struct lis3lv02d *lis3 = dev_get_drvdata(dev);
 	unsigned long rate;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &rate))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &rate);
+	if (ret)
+		return ret;
 
 	lis3lv02d_sysfs_poweron(lis3);
 	if (lis3lv02d_set_odr(lis3, rate))

+ 3 - 3
drivers/misc/mei/amthif.c

@@ -443,11 +443,11 @@ unsigned int mei_amthif_poll(struct mei_device *dev,
  *
  * returns 0, OK; otherwise, error.
  */
-int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots,
-			struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
+int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
+				  s32 *slots, struct mei_cl_cb *cmpl_list)
 {
+	struct mei_device *dev = cl->dev;
 	struct mei_msg_hdr mei_hdr;
-	struct mei_cl *cl = cb->cl;
 	size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
 	u32 msg_slots = mei_data2slots(len);
 

+ 89 - 3
drivers/misc/mei/client.c

@@ -485,7 +485,6 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
 {
 	struct mei_device *dev;
 	struct mei_cl_cb *cb;
-	long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT);
 	int rets;
 
 	if (WARN_ON(!cl || !cl->dev))
@@ -518,7 +517,7 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
 	rets = wait_event_timeout(dev->wait_recvd_msg,
 				 (cl->state == MEI_FILE_CONNECTED ||
 				  cl->state == MEI_FILE_DISCONNECTED),
-				 timeout * HZ);
+				 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
 	mutex_lock(&dev->device_lock);
 
 	if (cl->state != MEI_FILE_CONNECTED) {
@@ -681,6 +680,68 @@ err:
 	return rets;
 }
 
+/**
+ * mei_cl_irq_write_complete - write a message to device
+ *	from the interrupt thread context
+ *
+ * @cl: client
+ * @cb: callback block.
+ * @slots: free slots.
+ * @cmpl_list: complete list.
+ *
+ * returns 0, OK; otherwise error.
+ */
+int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
+				     s32 *slots, struct mei_cl_cb *cmpl_list)
+{
+	struct mei_device *dev = cl->dev;
+	struct mei_msg_hdr mei_hdr;
+	size_t len = cb->request_buffer.size - cb->buf_idx;
+	u32 msg_slots = mei_data2slots(len);
+
+	mei_hdr.host_addr = cl->host_client_id;
+	mei_hdr.me_addr = cl->me_client_id;
+	mei_hdr.reserved = 0;
+
+	if (*slots >= msg_slots) {
+		mei_hdr.length = len;
+		mei_hdr.msg_complete = 1;
+	/* Split the message only if we can write the whole host buffer */
+	} else if (*slots == dev->hbuf_depth) {
+		msg_slots = *slots;
+		len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
+		mei_hdr.length = len;
+		mei_hdr.msg_complete = 0;
+	} else {
+		/* wait for next time the host buffer is empty */
+		return 0;
+	}
+
+	dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n",
+			cb->request_buffer.size, cb->buf_idx);
+	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr));
+
+	*slots -=  msg_slots;
+	if (mei_write_message(dev, &mei_hdr,
+			cb->request_buffer.data + cb->buf_idx)) {
+		cl->status = -ENODEV;
+		list_move_tail(&cb->list, &cmpl_list->list);
+		return -ENODEV;
+	}
+
+	cl->status = 0;
+	cl->writing_state = MEI_WRITING;
+	cb->buf_idx += mei_hdr.length;
+
+	if (mei_hdr.msg_complete) {
+		if (mei_cl_flow_ctrl_reduce(cl))
+			return -ENODEV;
+		list_move_tail(&cb->list, &dev->write_waiting_list.list);
+	}
+
+	return 0;
+}
+
 /**
  * mei_cl_write - submit a write cb to mei device
 	assumes device_lock is locked
@@ -723,7 +784,6 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 		cb->buf_idx = 0;
 		/* unseting complete will enqueue the cb for write */
 		mei_hdr.msg_complete = 0;
-		cl->writing_state = MEI_WRITING;
 		rets = buf->size;
 		goto out;
 	}
@@ -785,6 +845,32 @@ err:
 }
 
 
+/**
+ * mei_cl_complete - processes completed operation for a client
+ *
+ * @cl: private data of the file object.
+ * @cb: callback block.
+ */
+void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
+{
+	if (cb->fop_type == MEI_FOP_WRITE) {
+		mei_io_cb_free(cb);
+		cb = NULL;
+		cl->writing_state = MEI_WRITE_COMPLETE;
+		if (waitqueue_active(&cl->tx_wait))
+			wake_up_interruptible(&cl->tx_wait);
+
+	} else if (cb->fop_type == MEI_FOP_READ &&
+			MEI_READING == cl->reading_state) {
+		cl->reading_state = MEI_READ_COMPLETE;
+		if (waitqueue_active(&cl->rx_wait))
+			wake_up_interruptible(&cl->rx_wait);
+		else
+			mei_cl_bus_rx_event(cl);
+
+	}
+}
+
 
 /**
  * mei_cl_all_disconnect - disconnect forcefully all connected clients

+ 4 - 0
drivers/misc/mei/client.h

@@ -89,6 +89,10 @@ int mei_cl_disconnect(struct mei_cl *cl);
 int mei_cl_connect(struct mei_cl *cl, struct file *file);
 int mei_cl_read_start(struct mei_cl *cl, size_t length);
 int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking);
+int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
+				s32 *slots, struct mei_cl_cb *cmpl_list);
+
+void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb);
 
 void mei_host_client_init(struct work_struct *work);
 

+ 32 - 5
drivers/misc/mei/hbm.c

@@ -535,6 +535,20 @@ static void mei_hbm_fw_disconnect_req(struct mei_device *dev,
 }
 
 
+/**
+ * mei_hbm_version_is_supported - checks whether the driver can
+ *     support the hbm version of the device
+ *
+ * @dev: the device structure
+ * returns true if driver can support hbm version of the device
+ */
+bool mei_hbm_version_is_supported(struct mei_device *dev)
+{
+	return	(dev->version.major_version < HBM_MAJOR_VERSION) ||
+		(dev->version.major_version == HBM_MAJOR_VERSION &&
+		 dev->version.minor_version <= HBM_MINOR_VERSION);
+}
+
 /**
  * mei_hbm_dispatch - bottom half read routine after ISR to
  * handle the read bus message cmd processing.
@@ -562,9 +576,24 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 	switch (mei_msg->hbm_cmd) {
 	case HOST_START_RES_CMD:
 		version_res = (struct hbm_host_version_response *)mei_msg;
-		if (!version_res->host_version_supported) {
-			dev->version = version_res->me_max_version;
-			dev_dbg(&dev->pdev->dev, "version mismatch.\n");
+
+		dev_dbg(&dev->pdev->dev, "HBM VERSION: DRIVER=%02d:%02d DEVICE=%02d:%02d\n",
+				HBM_MAJOR_VERSION, HBM_MINOR_VERSION,
+				version_res->me_max_version.major_version,
+				version_res->me_max_version.minor_version);
+
+		if (version_res->host_version_supported) {
+			dev->version.major_version = HBM_MAJOR_VERSION;
+			dev->version.minor_version = HBM_MINOR_VERSION;
+		} else {
+			dev->version.major_version =
+				version_res->me_max_version.major_version;
+			dev->version.minor_version =
+				version_res->me_max_version.minor_version;
+		}
+
+		if (!mei_hbm_version_is_supported(dev)) {
+			dev_warn(&dev->pdev->dev, "hbm version mismatch: stopping the driver.\n");
 
 			dev->hbm_state = MEI_HBM_STOP;
 			mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr,
@@ -575,8 +604,6 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 			return;
 		}
 
-		dev->version.major_version = HBM_MAJOR_VERSION;
-		dev->version.minor_version = HBM_MINOR_VERSION;
 		if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
 		    dev->hbm_state == MEI_HBM_START) {
 			dev->init_clients_timer = 0;

+ 1 - 1
drivers/misc/mei/hbm.h

@@ -54,7 +54,7 @@ int mei_hbm_start_wait(struct mei_device *dev);
 int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl);
 int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl);
 int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl);
-
+bool mei_hbm_version_is_supported(struct mei_device *dev);
 
 #endif /* _MEI_HBM_H_ */
 

+ 2 - 1
drivers/misc/mei/hw-me.c

@@ -171,7 +171,7 @@ static void mei_me_hw_reset_release(struct mei_device *dev)
  * @dev: the device structure
  * @intr_enable: if interrupt should be enabled after reset.
  */
-static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
+static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 hcsr = mei_hcsr_read(hw);
@@ -191,6 +191,7 @@ static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
 		mei_me_hw_reset_release(dev);
 
 	dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", mei_hcsr_read(hw));
+	return 0;
 }
 
 /**

+ 14 - 4
drivers/misc/mei/init.c

@@ -106,8 +106,7 @@ int mei_start(struct mei_device *dev)
 		goto err;
 	}
 
-	if (dev->version.major_version != HBM_MAJOR_VERSION ||
-	    dev->version.minor_version != HBM_MINOR_VERSION) {
+	if (!mei_hbm_version_is_supported(dev)) {
 		dev_dbg(&dev->pdev->dev, "MEI start failed.\n");
 		goto err;
 	}
@@ -133,13 +132,19 @@ EXPORT_SYMBOL_GPL(mei_start);
 void mei_reset(struct mei_device *dev, int interrupts_enabled)
 {
 	bool unexpected;
+	int ret;
 
 	unexpected = (dev->dev_state != MEI_DEV_INITIALIZING &&
 			dev->dev_state != MEI_DEV_DISABLED &&
 			dev->dev_state != MEI_DEV_POWER_DOWN &&
 			dev->dev_state != MEI_DEV_POWER_UP);
 
-	mei_hw_reset(dev, interrupts_enabled);
+	ret = mei_hw_reset(dev, interrupts_enabled);
+	if (ret) {
+		dev_err(&dev->pdev->dev, "hw reset failed disabling the device\n");
+		interrupts_enabled = false;
+		dev->dev_state = MEI_DEV_DISABLED;
+	}
 
 	dev->hbm_state = MEI_HBM_IDLE;
 
@@ -176,7 +181,12 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
 		return;
 	}
 
-	mei_hw_start(dev);
+	ret = mei_hw_start(dev);
+	if (ret) {
+		dev_err(&dev->pdev->dev, "hw_start failed disabling the device\n");
+		dev->dev_state = MEI_DEV_DISABLED;
+		return;
+	}
 
 	dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
 	/* link is established * start sending messages.  */

+ 58 - 147
drivers/misc/mei/interrupt.c

@@ -30,32 +30,6 @@
 #include "client.h"
 
 
-/**
- * mei_cl_complete_handler - processes completed operation for a client
- *
- * @cl: private data of the file object.
- * @cb: callback block.
- */
-static void mei_cl_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb)
-{
-	if (cb->fop_type == MEI_FOP_WRITE) {
-		mei_io_cb_free(cb);
-		cb = NULL;
-		cl->writing_state = MEI_WRITE_COMPLETE;
-		if (waitqueue_active(&cl->tx_wait))
-			wake_up_interruptible(&cl->tx_wait);
-
-	} else if (cb->fop_type == MEI_FOP_READ &&
-			MEI_READING == cl->reading_state) {
-		cl->reading_state = MEI_READ_COMPLETE;
-		if (waitqueue_active(&cl->rx_wait))
-			wake_up_interruptible(&cl->rx_wait);
-		else
-			mei_cl_bus_rx_event(cl);
-
-	}
-}
-
 /**
  * mei_irq_compl_handler - dispatch complete handelers
  *	for the completed callbacks
@@ -78,7 +52,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list)
 		if (cl == &dev->iamthif_cl)
 			mei_amthif_complete(dev, cb);
 		else
-			mei_cl_complete_handler(cl, cb);
+			mei_cl_complete(cl, cb);
 	}
 }
 EXPORT_SYMBOL_GPL(mei_irq_compl_handler);
@@ -189,21 +163,21 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
 }
 
 /**
- * _mei_irq_thread_close - processes close related operation.
+ * mei_cl_irq_close - processes close related operation from
+ *	interrupt thread context - send disconnect request
  *
- * @dev: the device structure.
+ * @cl: client
+ * @cb: callback block.
  * @slots: free slots.
- * @cb_pos: callback block.
- * @cl: private data of the file object.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise, error.
  */
-static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
-				struct mei_cl_cb *cb_pos,
-				struct mei_cl *cl,
-				struct mei_cl_cb *cmpl_list)
+static int mei_cl_irq_close(struct mei_cl *cl, struct mei_cl_cb *cb,
+			s32 *slots, struct mei_cl_cb *cmpl_list)
 {
+	struct mei_device *dev = cl->dev;
+
 	u32 msg_slots =
 		mei_data2slots(sizeof(struct hbm_client_connect_request));
 
@@ -214,15 +188,15 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
 
 	if (mei_hbm_cl_disconnect_req(dev, cl)) {
 		cl->status = 0;
-		cb_pos->buf_idx = 0;
-		list_move_tail(&cb_pos->list, &cmpl_list->list);
+		cb->buf_idx = 0;
+		list_move_tail(&cb->list, &cmpl_list->list);
 		return -EIO;
 	}
 
 	cl->state = MEI_FILE_DISCONNECTING;
 	cl->status = 0;
-	cb_pos->buf_idx = 0;
-	list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
+	cb->buf_idx = 0;
+	list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
 	cl->timer_count = MEI_CONNECT_TIMEOUT;
 
 	return 0;
@@ -230,26 +204,26 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
 
 
 /**
- * _mei_irq_thread_read - processes read related operation.
+ * mei_cl_irq_close - processes client read related operation from the
+ *	interrupt thread context - request for flow control credits
  *
- * @dev: the device structure.
+ * @cl: client
+ * @cb: callback block.
  * @slots: free slots.
- * @cb_pos: callback block.
- * @cl: private data of the file object.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise, error.
  */
-static int _mei_irq_thread_read(struct mei_device *dev,	s32 *slots,
-			struct mei_cl_cb *cb_pos,
-			struct mei_cl *cl,
-			struct mei_cl_cb *cmpl_list)
+static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
+			   s32 *slots, struct mei_cl_cb *cmpl_list)
 {
+	struct mei_device *dev = cl->dev;
+
 	u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
 
 	if (*slots < msg_slots) {
 		/* return the cancel routine */
-		list_del(&cb_pos->list);
+		list_del(&cb->list);
 		return -EMSGSIZE;
 	}
 
@@ -257,38 +231,38 @@ static int _mei_irq_thread_read(struct mei_device *dev,	s32 *slots,
 
 	if (mei_hbm_cl_flow_control_req(dev, cl)) {
 		cl->status = -ENODEV;
-		cb_pos->buf_idx = 0;
-		list_move_tail(&cb_pos->list, &cmpl_list->list);
+		cb->buf_idx = 0;
+		list_move_tail(&cb->list, &cmpl_list->list);
 		return -ENODEV;
 	}
-	list_move_tail(&cb_pos->list, &dev->read_list.list);
+	list_move_tail(&cb->list, &dev->read_list.list);
 
 	return 0;
 }
 
 
 /**
- * _mei_irq_thread_ioctl - processes ioctl related operation.
+ * mei_cl_irq_ioctl - processes client ioctl related operation from the
+ *	interrupt thread context -   send connection request
  *
- * @dev: the device structure.
+ * @cl: client
+ * @cb: callback block.
  * @slots: free slots.
- * @cb_pos: callback block.
- * @cl: private data of the file object.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise, error.
  */
-static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
-			struct mei_cl_cb *cb_pos,
-			struct mei_cl *cl,
-			struct mei_cl_cb *cmpl_list)
+static int mei_cl_irq_ioctl(struct mei_cl *cl, struct mei_cl_cb *cb,
+			   s32 *slots, struct mei_cl_cb *cmpl_list)
 {
+	struct mei_device *dev = cl->dev;
+
 	u32 msg_slots =
 		mei_data2slots(sizeof(struct hbm_client_connect_request));
 
 	if (*slots < msg_slots) {
 		/* return the cancel routine */
-		list_del(&cb_pos->list);
+		list_del(&cb->list);
 		return -EMSGSIZE;
 	}
 
@@ -298,76 +272,17 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
 
 	if (mei_hbm_cl_connect_req(dev, cl)) {
 		cl->status = -ENODEV;
-		cb_pos->buf_idx = 0;
-		list_del(&cb_pos->list);
-		return -ENODEV;
-	} else {
-		list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
-		cl->timer_count = MEI_CONNECT_TIMEOUT;
-	}
-	return 0;
-}
-
-/**
- * mei_irq_thread_write_complete - write messages to device.
- *
- * @dev: the device structure.
- * @slots: free slots.
- * @cb: callback block.
- * @cmpl_list: complete list.
- *
- * returns 0, OK; otherwise, error.
- */
-static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
-			struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
-{
-	struct mei_msg_hdr mei_hdr;
-	struct mei_cl *cl = cb->cl;
-	size_t len = cb->request_buffer.size - cb->buf_idx;
-	u32 msg_slots = mei_data2slots(len);
-
-	mei_hdr.host_addr = cl->host_client_id;
-	mei_hdr.me_addr = cl->me_client_id;
-	mei_hdr.reserved = 0;
-
-	if (*slots >= msg_slots) {
-		mei_hdr.length = len;
-		mei_hdr.msg_complete = 1;
-	/* Split the message only if we can write the whole host buffer */
-	} else if (*slots == dev->hbuf_depth) {
-		msg_slots = *slots;
-		len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
-		mei_hdr.length = len;
-		mei_hdr.msg_complete = 0;
-	} else {
-		/* wait for next time the host buffer is empty */
-		return 0;
-	}
-
-	dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n",
-			cb->request_buffer.size, cb->buf_idx);
-	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr));
-
-	*slots -=  msg_slots;
-	if (mei_write_message(dev, &mei_hdr,
-			cb->request_buffer.data + cb->buf_idx)) {
-		cl->status = -ENODEV;
-		list_move_tail(&cb->list, &cmpl_list->list);
+		cb->buf_idx = 0;
+		list_del(&cb->list);
 		return -ENODEV;
 	}
 
-
-	cl->status = 0;
-	cb->buf_idx += mei_hdr.length;
-	if (mei_hdr.msg_complete) {
-		if (mei_cl_flow_ctrl_reduce(cl))
-			return -ENODEV;
-		list_move_tail(&cb->list, &dev->write_waiting_list.list);
-	}
-
+	list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
+	cl->timer_count = MEI_CONNECT_TIMEOUT;
 	return 0;
 }
 
+
 /**
  * mei_irq_read_handler - bottom half read routine after ISR to
  * handle the read processing.
@@ -481,7 +396,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 {
 
 	struct mei_cl *cl;
-	struct mei_cl_cb *pos = NULL, *next = NULL;
+	struct mei_cl_cb *cb, *next;
 	struct mei_cl_cb *list;
 	s32 slots;
 	int ret;
@@ -498,19 +413,19 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 	dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
 
 	list = &dev->write_waiting_list;
-	list_for_each_entry_safe(pos, next, &list->list, list) {
-		cl = pos->cl;
+	list_for_each_entry_safe(cb, next, &list->list, list) {
+		cl = cb->cl;
 		if (cl == NULL)
 			continue;
 
 		cl->status = 0;
-		list_del(&pos->list);
+		list_del(&cb->list);
 		if (MEI_WRITING == cl->writing_state &&
-		    pos->fop_type == MEI_FOP_WRITE &&
+		    cb->fop_type == MEI_FOP_WRITE &&
 		    cl != &dev->iamthif_cl) {
 			dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n");
 			cl->writing_state = MEI_WRITE_COMPLETE;
-			list_add_tail(&pos->list, &cmpl_list->list);
+			list_add_tail(&cb->list, &cmpl_list->list);
 		}
 		if (cl == &dev->iamthif_cl) {
 			dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
@@ -552,25 +467,23 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 
 	/* complete control write list CB */
 	dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
-	list_for_each_entry_safe(pos, next, &dev->ctrl_wr_list.list, list) {
-		cl = pos->cl;
+	list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) {
+		cl = cb->cl;
 		if (!cl) {
-			list_del(&pos->list);
+			list_del(&cb->list);
 			return -ENODEV;
 		}
-		switch (pos->fop_type) {
+		switch (cb->fop_type) {
 		case MEI_FOP_CLOSE:
 			/* send disconnect message */
-			ret = _mei_irq_thread_close(dev, &slots, pos,
-						cl, cmpl_list);
+			ret = mei_cl_irq_close(cl, cb, &slots, cmpl_list);
 			if (ret)
 				return ret;
 
 			break;
 		case MEI_FOP_READ:
 			/* send flow control message */
-			ret = _mei_irq_thread_read(dev, &slots, pos,
-						cl, cmpl_list);
+			ret = mei_cl_irq_read(cl, cb, &slots, cmpl_list);
 			if (ret)
 				return ret;
 
@@ -579,8 +492,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 			/* connect message */
 			if (mei_cl_is_other_connecting(cl))
 				continue;
-			ret = _mei_irq_thread_ioctl(dev, &slots, pos,
-						cl, cmpl_list);
+			ret = mei_cl_irq_ioctl(cl, cb, &slots, cmpl_list);
 			if (ret)
 				return ret;
 
@@ -593,8 +505,8 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 	}
 	/* complete  write list CB */
 	dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
-	list_for_each_entry_safe(pos, next, &dev->write_list.list, list) {
-		cl = pos->cl;
+	list_for_each_entry_safe(cb, next, &dev->write_list.list, list) {
+		cl = cb->cl;
 		if (cl == NULL)
 			continue;
 		if (mei_cl_flow_ctrl_creds(cl) <= 0) {
@@ -605,14 +517,13 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 		}
 
 		if (cl == &dev->iamthif_cl)
-			ret = mei_amthif_irq_write_complete(dev, &slots,
-							pos, cmpl_list);
+			ret = mei_amthif_irq_write_complete(cl, cb,
+						&slots, cmpl_list);
 		else
-			ret = mei_irq_thread_write_complete(dev, &slots, pos,
-						cmpl_list);
+			ret = mei_cl_irq_write_complete(cl, cb,
+						&slots, cmpl_list);
 		if (ret)
 			return ret;
-
 	}
 	return 0;
 }

+ 13 - 36
drivers/misc/mei/main.c

@@ -194,7 +194,6 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 	struct mei_cl_cb *cb_pos = NULL;
 	struct mei_cl_cb *cb = NULL;
 	struct mei_device *dev;
-	int i;
 	int rets;
 	int err;
 
@@ -210,38 +209,26 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 		goto out;
 	}
 
-	if ((cl->sm_state & MEI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) {
-		/* Do not allow to read watchdog client */
-		i = mei_me_cl_by_uuid(dev, &mei_wd_guid);
-		if (i >= 0) {
-			struct mei_me_client *me_client = &dev->me_clients[i];
-			if (cl->me_client_id == me_client->client_id) {
-				rets = -EBADF;
-				goto out;
-			}
-		}
-	} else {
-		cl->sm_state &= ~MEI_WD_STATE_INDEPENDENCE_MSG_SENT;
-	}
-
 	if (cl == &dev->iamthif_cl) {
 		rets = mei_amthif_read(dev, file, ubuf, length, offset);
 		goto out;
 	}
 
-	if (cl->read_cb && cl->read_cb->buf_idx > *offset) {
-		cb = cl->read_cb;
-		goto copy_buffer;
-	} else if (cl->read_cb && cl->read_cb->buf_idx > 0 &&
-		   cl->read_cb->buf_idx <= *offset) {
+	if (cl->read_cb) {
 		cb = cl->read_cb;
-		rets = 0;
-		goto free;
-	} else if ((!cl->read_cb || !cl->read_cb->buf_idx) && *offset > 0) {
-		/*Offset needs to be cleaned for contiguous reads*/
+		/* read what left */
+		if (cb->buf_idx > *offset)
+			goto copy_buffer;
+		/* offset is beyond buf_idx we have no more data return 0 */
+		if (cb->buf_idx > 0 && cb->buf_idx <= *offset) {
+			rets = 0;
+			goto free;
+		}
+		/* Offset needs to be cleaned for contiguous reads*/
+		if (cb->buf_idx == 0 && *offset > 0)
+			*offset = 0;
+	} else if (*offset > 0) {
 		*offset = 0;
-		rets = 0;
-		goto out;
 	}
 
 	err = mei_cl_read_start(cl, length);
@@ -420,16 +407,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 	if (rets)
 		goto out;
 
-	cl->sm_state = 0;
-	if (length == 4 &&
-	    ((memcmp(mei_wd_state_independence_msg[0],
-				 write_cb->request_buffer.data, 4) == 0) ||
-	     (memcmp(mei_wd_state_independence_msg[1],
-				 write_cb->request_buffer.data, 4) == 0) ||
-	     (memcmp(mei_wd_state_independence_msg[2],
-				 write_cb->request_buffer.data, 4) == 0)))
-		cl->sm_state |= MEI_WD_STATE_INDEPENDENCE_MSG_SENT;
-
 	if (cl == &dev->iamthif_cl) {
 		rets = mei_amthif_write(dev, write_cb);
 

+ 7 - 22
drivers/misc/mei/mei_dev.h

@@ -55,11 +55,6 @@ extern const uuid_le mei_amthif_guid;
  */
 extern const uuid_le mei_wd_guid;
 
-/*
- * Watchdog independence state message
- */
-extern const u8 mei_wd_state_independence_msg[3][4];
-
 /*
  * Number of Maximum MEI Clients
  */
@@ -201,7 +196,6 @@ struct mei_cl {
 	u8 timer_count;
 	enum mei_file_transaction_states reading_state;
 	enum mei_file_transaction_states writing_state;
-	int sm_state;
 	struct mei_cl_cb *read_cb;
 
 	/* MEI CL bus data */
@@ -239,7 +233,7 @@ struct mei_hw_ops {
 	bool (*host_is_ready) (struct mei_device *dev);
 
 	bool (*hw_is_ready) (struct mei_device *dev);
-	void (*hw_reset) (struct mei_device *dev, bool enable);
+	int (*hw_reset) (struct mei_device *dev, bool enable);
 	int  (*hw_start) (struct mei_device *dev);
 	void (*hw_config) (struct mei_device *dev);
 
@@ -502,8 +496,8 @@ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
 
 void mei_amthif_run_next_cmd(struct mei_device *dev);
 
-int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots,
-			struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list);
+int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
+				  s32 *slots, struct mei_cl_cb *cmpl_list);
 
 void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb);
 int mei_amthif_irq_read_msg(struct mei_device *dev,
@@ -522,15 +516,6 @@ void mei_nfc_host_exit(void);
  */
 extern const uuid_le mei_nfc_guid;
 
-int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots,
-			struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list);
-
-void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb);
-int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list,
-		struct mei_device *dev, struct mei_msg_hdr *mei_hdr);
-int mei_amthif_irq_read(struct mei_device *dev, s32 *slots);
-
-
 int mei_wd_send(struct mei_device *dev);
 int mei_wd_stop(struct mei_device *dev);
 int mei_wd_host_init(struct mei_device *dev);
@@ -554,14 +539,14 @@ static inline void mei_hw_config(struct mei_device *dev)
 {
 	dev->ops->hw_config(dev);
 }
-static inline void mei_hw_reset(struct mei_device *dev, bool enable)
+static inline int mei_hw_reset(struct mei_device *dev, bool enable)
 {
-	dev->ops->hw_reset(dev, enable);
+	return dev->ops->hw_reset(dev, enable);
 }
 
-static inline void mei_hw_start(struct mei_device *dev)
+static inline int mei_hw_start(struct mei_device *dev)
 {
-	dev->ops->hw_start(dev);
+	return dev->ops->hw_start(dev);
 }
 
 static inline void mei_clear_interrupts(struct mei_device *dev)

+ 0 - 19
drivers/misc/mei/pci-me.c

@@ -43,9 +43,6 @@
 #include "hw-me.h"
 #include "client.h"
 
-/* AMT device is a singleton on the platform */
-static struct pci_dev *mei_pdev;
-
 /* mei_pci_tbl - PCI Device ID Table */
 static DEFINE_PCI_DEVICE_TABLE(mei_me_pci_tbl) = {
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82946GZ)},
@@ -88,8 +85,6 @@ static DEFINE_PCI_DEVICE_TABLE(mei_me_pci_tbl) = {
 
 MODULE_DEVICE_TABLE(pci, mei_me_pci_tbl);
 
-static DEFINE_MUTEX(mei_mutex);
-
 /**
  * mei_quirk_probe - probe for devices that doesn't valid ME interface
  *
@@ -126,17 +121,12 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct mei_me_hw *hw;
 	int err;
 
-	mutex_lock(&mei_mutex);
 
 	if (!mei_me_quirk_probe(pdev, ent)) {
 		err = -ENODEV;
 		goto end;
 	}
 
-	if (mei_pdev) {
-		err = -EEXIST;
-		goto end;
-	}
 	/* enable pci dev */
 	err = pci_enable_device(pdev);
 	if (err) {
@@ -195,13 +185,10 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (err)
 		goto release_irq;
 
-	mei_pdev = pdev;
 	pci_set_drvdata(pdev, dev);
 
 	schedule_delayed_work(&dev->timer_work, HZ);
 
-	mutex_unlock(&mei_mutex);
-
 	pr_debug("initialization successful.\n");
 
 	return 0;
@@ -220,7 +207,6 @@ release_regions:
 disable_device:
 	pci_disable_device(pdev);
 end:
-	mutex_unlock(&mei_mutex);
 	dev_err(&pdev->dev, "initialization failed.\n");
 	return err;
 }
@@ -238,9 +224,6 @@ static void mei_me_remove(struct pci_dev *pdev)
 	struct mei_device *dev;
 	struct mei_me_hw *hw;
 
-	if (mei_pdev != pdev)
-		return;
-
 	dev = pci_get_drvdata(pdev);
 	if (!dev)
 		return;
@@ -251,8 +234,6 @@ static void mei_me_remove(struct pci_dev *pdev)
 	dev_err(&pdev->dev, "stop\n");
 	mei_stop(dev);
 
-	mei_pdev = NULL;
-
 	/* disable interrupts */
 	mei_disable_interrupts(dev);
 

+ 0 - 6
drivers/misc/mei/wd.c

@@ -31,12 +31,6 @@
 static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
 static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 };
 
-const u8 mei_wd_state_independence_msg[3][4] = {
-	{0x05, 0x02, 0x51, 0x10},
-	{0x05, 0x02, 0x52, 0x10},
-	{0x07, 0x02, 0x01, 0x10}
-};
-
 /*
  * AMT Watchdog Device
  */

+ 19 - 25
drivers/misc/pch_phub.c

@@ -633,17 +633,13 @@ static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr,
 static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
 			     const char *buf, size_t count)
 {
-	u8 mac[6];
+	u8 mac[ETH_ALEN];
 	ssize_t rom_size;
 	struct pch_phub_reg *chip = dev_get_drvdata(dev);
 
-	if (count != 18)
+	if (!mac_pton(buf, mac))
 		return -EINVAL;
 
-	sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
-		(u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3],
-		(u32 *)&mac[4], (u32 *)&mac[5]);
-
 	chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
 	if (!chip->pch_phub_extrom_base_address)
 		return -ENOMEM;
@@ -669,8 +665,6 @@ static struct bin_attribute pch_bin_attr = {
 static int pch_phub_probe(struct pci_dev *pdev,
 				    const struct pci_device_id *id)
 {
-	int retval;
-
 	int ret;
 	struct pch_phub_reg *chip;
 
@@ -713,13 +707,13 @@ static int pch_phub_probe(struct pci_dev *pdev,
 	if (id->driver_data == 1) { /* EG20T PCH */
 		const char *board_name;
 
-		retval = sysfs_create_file(&pdev->dev.kobj,
-					   &dev_attr_pch_mac.attr);
-		if (retval)
+		ret = sysfs_create_file(&pdev->dev.kobj,
+					&dev_attr_pch_mac.attr);
+		if (ret)
 			goto err_sysfs_create;
 
-		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
-		if (retval)
+		ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+		if (ret)
 			goto exit_bin_attr;
 
 		pch_phub_read_modify_write_reg(chip,
@@ -743,8 +737,8 @@ static int pch_phub_probe(struct pci_dev *pdev,
 		chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T;
 		chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T;
 	} else if (id->driver_data == 2) { /* ML7213 IOH */
-		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
-		if (retval)
+		ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+		if (ret)
 			goto err_sysfs_create;
 		/* set the prefech value
 		 * Device2(USB OHCI #1/ USB EHCI #1/ USB Device):a
@@ -766,12 +760,12 @@ static int pch_phub_probe(struct pci_dev *pdev,
 						 PCH_PHUB_ROM_START_ADDR_ML7223;
 		chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
 	} else if (id->driver_data == 4) { /* ML7223 IOH Bus-n*/
-		retval = sysfs_create_file(&pdev->dev.kobj,
-					   &dev_attr_pch_mac.attr);
-		if (retval)
+		ret = sysfs_create_file(&pdev->dev.kobj,
+					&dev_attr_pch_mac.attr);
+		if (ret)
 			goto err_sysfs_create;
-		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
-		if (retval)
+		ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+		if (ret)
 			goto exit_bin_attr;
 		/* set the prefech value
 		 * Device2(USB OHCI #0,1,2,3/ USB EHCI #0):a
@@ -783,13 +777,13 @@ static int pch_phub_probe(struct pci_dev *pdev,
 						 PCH_PHUB_ROM_START_ADDR_ML7223;
 		chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
 	} else if (id->driver_data == 5) { /* ML7831 */
-		retval = sysfs_create_file(&pdev->dev.kobj,
-					   &dev_attr_pch_mac.attr);
-		if (retval)
+		ret = sysfs_create_file(&pdev->dev.kobj,
+					&dev_attr_pch_mac.attr);
+		if (ret)
 			goto err_sysfs_create;
 
-		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
-		if (retval)
+		ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+		if (ret)
 			goto exit_bin_attr;
 
 		/* set the prefech value */

+ 5 - 9
drivers/misc/sgi-gru/gruprocfs.c

@@ -160,15 +160,11 @@ static int options_show(struct seq_file *s, void *p)
 static ssize_t options_write(struct file *file, const char __user *userbuf,
 			     size_t count, loff_t *data)
 {
-	char buf[20];
-
-	if (count >= sizeof(buf))
-		return -EINVAL;
-	if (copy_from_user(buf, userbuf, count))
-		return -EFAULT;
-	buf[count] = '\0';
-	if (strict_strtoul(buf, 0, &gru_options))
-		return -EINVAL;
+	int ret;
+
+	ret = kstrtoul_from_user(userbuf, count, 0, &gru_options);
+	if (ret)
+		return ret;
 
 	return count;
 }

+ 47 - 22
drivers/misc/spear13xx_pcie_gadget.c

@@ -316,8 +316,12 @@ static ssize_t pcie_gadget_store_no_of_msi(
 		struct spear_pcie_gadget_config *config,
 		const char *buf, size_t count)
 {
-	if (strict_strtoul(buf, 0, &config->requested_msi))
-		return -EINVAL;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &config->requested_msi);
+	if (ret)
+		return ret;
+
 	if (config->requested_msi > 32)
 		config->requested_msi = 32;
 
@@ -330,9 +334,11 @@ static ssize_t pcie_gadget_store_inta(
 {
 	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
 	ulong en;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &en))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &en);
+	if (ret)
+		return ret;
 
 	if (en)
 		writel(readl(&app_reg->app_ctrl_0) | (1 << SYS_INT_ID),
@@ -351,9 +357,11 @@ static ssize_t pcie_gadget_store_send_msi(
 	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
 	ulong vector;
 	u32 ven_msi;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &vector))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &vector);
+	if (ret)
+		return ret;
 
 	if (!config->configured_msi)
 		return -EINVAL;
@@ -395,9 +403,11 @@ static ssize_t pcie_gadget_store_vendor_id(
 		const char *buf, size_t count)
 {
 	ulong id;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &id))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &id);
+	if (ret)
+		return ret;
 
 	spear_dbi_write_reg(config, PCI_VENDOR_ID, 2, id);
 
@@ -420,9 +430,11 @@ static ssize_t pcie_gadget_store_device_id(
 		const char *buf, size_t count)
 {
 	ulong id;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &id))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &id);
+	if (ret)
+		return ret;
 
 	spear_dbi_write_reg(config, PCI_DEVICE_ID, 2, id);
 
@@ -443,9 +455,12 @@ static ssize_t pcie_gadget_store_bar0_size(
 	ulong size;
 	u32 pos, pos1;
 	u32 no_of_bit = 0;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &size);
+	if (ret)
+		return ret;
 
-	if (strict_strtoul(buf, 0, &size))
-		return -EINVAL;
 	/* min bar size is 256 */
 	if (size <= 0x100)
 		size = 0x100;
@@ -490,9 +505,11 @@ static ssize_t pcie_gadget_store_bar0_address(
 {
 	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
 	ulong address;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &address))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &address);
+	if (ret)
+		return ret;
 
 	address &= ~(config->bar0_size - 1);
 	if (config->va_bar0_address)
@@ -518,9 +535,11 @@ static ssize_t pcie_gadget_store_bar0_rw_offset(
 		const char *buf, size_t count)
 {
 	ulong offset;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &offset))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &offset);
+	if (ret)
+		return ret;
 
 	if (offset % 4)
 		return -EINVAL;
@@ -549,9 +568,11 @@ static ssize_t pcie_gadget_store_bar0_data(
 		const char *buf, size_t count)
 {
 	ulong data;
+	int ret;
 
-	if (strict_strtoul(buf, 0, &data))
-		return -EINVAL;
+	ret = kstrtoul(buf, 0, &data);
+	if (ret)
+		return ret;
 
 	if (!config->va_bar0_address)
 		return -ENOMEM;
@@ -776,7 +797,7 @@ static int spear_pcie_gadget_probe(struct platform_device *pdev)
 		goto err_iounmap_app;
 	}
 
-	dev_set_drvdata(&pdev->dev, target);
+	platform_set_drvdata(pdev, target);
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
@@ -814,9 +835,11 @@ static int spear_pcie_gadget_probe(struct platform_device *pdev)
 		clk = clk_get_sys("pcie1", NULL);
 		if (IS_ERR(clk)) {
 			pr_err("%s:couldn't get clk for pcie1\n", __func__);
+			status = PTR_ERR(clk);
 			goto err_irq;
 		}
-		if (clk_enable(clk)) {
+		status = clk_enable(clk);
+		if (status) {
 			pr_err("%s:couldn't enable clk for pcie1\n", __func__);
 			goto err_irq;
 		}
@@ -828,9 +851,11 @@ static int spear_pcie_gadget_probe(struct platform_device *pdev)
 		clk = clk_get_sys("pcie2", NULL);
 		if (IS_ERR(clk)) {
 			pr_err("%s:couldn't get clk for pcie2\n", __func__);
+			status = PTR_ERR(clk);
 			goto err_irq;
 		}
-		if (clk_enable(clk)) {
+		status = clk_enable(clk);
+		if (status) {
 			pr_err("%s:couldn't enable clk for pcie2\n", __func__);
 			goto err_irq;
 		}
@@ -863,7 +888,7 @@ static int spear_pcie_gadget_remove(struct platform_device *pdev)
 	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	irq = platform_get_irq(pdev, 0);
-	target = dev_get_drvdata(&pdev->dev);
+	target = platform_get_drvdata(pdev);
 	config = &target->config;
 
 	free_irq(irq, NULL);

+ 3 - 6
drivers/misc/sram.c

@@ -45,15 +45,12 @@ static int sram_probe(struct platform_device *pdev)
 	int ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -EINVAL;
+	virt_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(virt_base))
+		return PTR_ERR(virt_base);
 
 	size = resource_size(res);
 
-	virt_base = devm_request_and_ioremap(&pdev->dev, res);
-	if (!virt_base)
-		return -EADDRNOTAVAIL;
-
 	sram = devm_kzalloc(&pdev->dev, sizeof(*sram), GFP_KERNEL);
 	if (!sram)
 		return -ENOMEM;

+ 3 - 3
drivers/misc/ti-st/st_kim.c

@@ -680,7 +680,7 @@ void st_kim_ref(struct st_data_s **core_data, int id)
 		*core_data = NULL;
 		return;
 	}
-	kim_gdata = dev_get_drvdata(&pdev->dev);
+	kim_gdata = platform_get_drvdata(pdev);
 	*core_data = kim_gdata->core_data;
 }
 
@@ -735,7 +735,7 @@ static int kim_probe(struct platform_device *pdev)
 		pr_err("no mem to allocate");
 		return -ENOMEM;
 	}
-	dev_set_drvdata(&pdev->dev, kim_gdata);
+	platform_set_drvdata(pdev, kim_gdata);
 
 	err = st_core_init(&kim_gdata->core_data);
 	if (err != 0) {
@@ -810,7 +810,7 @@ static int kim_remove(struct platform_device *pdev)
 	struct ti_st_plat_data	*pdata = pdev->dev.platform_data;
 	struct kim_data_s	*kim_gdata;
 
-	kim_gdata = dev_get_drvdata(&pdev->dev);
+	kim_gdata = platform_get_drvdata(pdev);
 
 	/* Free the Bluetooth/FM/GPIO
 	 * nShutdown gpio from the system

+ 4 - 2
drivers/misc/ti_dac7512.c

@@ -33,9 +33,11 @@ static ssize_t dac7512_store_val(struct device *dev,
 	struct spi_device *spi = to_spi_device(dev);
 	unsigned char tmp[2];
 	unsigned long val;
+	int ret;
 
-	if (strict_strtoul(buf, 10, &val) < 0)
-		return -EINVAL;
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
 
 	tmp[0] = val >> 8;
 	tmp[1] = val & 0xff;

+ 2 - 2
drivers/misc/tsl2550.c

@@ -204,7 +204,7 @@ static ssize_t tsl2550_store_power_state(struct device *dev,
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int ret;
 
-	if (val < 0 || val > 1)
+	if (val > 1)
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
@@ -236,7 +236,7 @@ static ssize_t tsl2550_store_operating_mode(struct device *dev,
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int ret;
 
-	if (val < 0 || val > 1)
+	if (val > 1)
 		return -EINVAL;
 
 	if (data->power_state == 0)

+ 1 - 0
drivers/net/netconsole.c

@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 #include <linux/console.h>
 #include <linux/moduleparam.h>
+#include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/netpoll.h>
 #include <linux/inet.h>

+ 2 - 2
drivers/pcmcia/Kconfig

@@ -243,7 +243,7 @@ config PCMCIA_DEBUG
 
 config PCMCIA_PROBE
 	bool
-	default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X && !PARISC
+	default y if ISA && !ARCH_SA1100 && !PARISC
 
 config M32R_PCC
 	bool "M32R PCMCIA I/F"
@@ -288,7 +288,7 @@ config BFIN_CFPCMCIA
 
 config AT91_CF
 	tristate "AT91 CompactFlash Controller"
-	depends on PCMCIA && ARCH_AT91RM9200
+	depends on PCMCIA && ARCH_AT91
 	help
 	  Say Y here to support the CompactFlash controller on AT91 chips.
 	  Or choose M to compile the driver as a module named "at91_cf".

+ 88 - 88
drivers/pcmcia/at91_cf.c

@@ -18,13 +18,14 @@
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/platform_data/atmel.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 
 #include <pcmcia/ss.h>
 
-#include <mach/hardware.h>
-#include <asm/io.h>
-#include <asm/sizes.h>
-
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
@@ -41,8 +42,6 @@
 
 /*--------------------------------------------------------------------------*/
 
-static const char driver_name[] = "at91_cf";
-
 struct at91_cf_socket {
 	struct pcmcia_socket	socket;
 
@@ -76,7 +75,7 @@ static irqreturn_t at91_cf_irq(int irq, void *_cf)
 		/* kick pccard as needed */
 		if (present != cf->present) {
 			cf->present = present;
-			pr_debug("%s: card %s\n", driver_name,
+			dev_dbg(&cf->pdev->dev, "card %s\n",
 					present ? "present" : "gone");
 			pcmcia_parse_events(&cf->socket, SS_DETECT);
 		}
@@ -100,9 +99,9 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
 		int vcc	= gpio_is_valid(cf->board->vcc_pin);
 
 		*sp = SS_DETECT | SS_3VCARD;
-		if (!rdy || gpio_get_value(rdy))
+		if (!rdy || gpio_get_value(cf->board->irq_pin))
 			*sp |= SS_READY;
-		if (!vcc || gpio_get_value(vcc))
+		if (!vcc || gpio_get_value(cf->board->vcc_pin))
 			*sp |= SS_POWERON;
 	} else
 		*sp = 0;
@@ -120,22 +119,22 @@ at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
 	/* switch Vcc if needed and possible */
 	if (gpio_is_valid(cf->board->vcc_pin)) {
 		switch (s->Vcc) {
-			case 0:
-				gpio_set_value(cf->board->vcc_pin, 0);
-				break;
-			case 33:
-				gpio_set_value(cf->board->vcc_pin, 1);
-				break;
-			default:
-				return -EINVAL;
+		case 0:
+			gpio_set_value(cf->board->vcc_pin, 0);
+			break;
+		case 33:
+			gpio_set_value(cf->board->vcc_pin, 1);
+			break;
+		default:
+			return -EINVAL;
 		}
 	}
 
 	/* toggle reset if needed */
 	gpio_set_value(cf->board->rst_pin, s->flags & SS_RESET);
 
-	pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
-		driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
+	dev_dbg(&cf->pdev->dev, "Vcc %d, io_irq %d, flags %04x csc %04x\n",
+				s->Vcc, s->io_irq, s->flags, s->csc_mask);
 
 	return 0;
 }
@@ -171,10 +170,10 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
 	 */
 	if (!(io->flags & (MAP_16BIT | MAP_AUTOSZ))) {
 		csr |= AT91_SMC_DBW_8;
-		pr_debug("%s: 8bit i/o bus\n", driver_name);
+		dev_dbg(&cf->pdev->dev, "8bit i/o bus\n");
 	} else {
 		csr |= AT91_SMC_DBW_16;
-		pr_debug("%s: 16bit i/o bus\n", driver_name);
+		dev_dbg(&cf->pdev->dev, "16bit i/o bus\n");
 	}
 	at91_ramc_write(0, AT91_SMC_CSR(cf->board->chipselect), csr);
 
@@ -215,6 +214,37 @@ static struct pccard_operations at91_cf_ops = {
 
 /*--------------------------------------------------------------------------*/
 
+#if defined(CONFIG_OF)
+static const struct of_device_id at91_cf_dt_ids[] = {
+	{ .compatible = "atmel,at91rm9200-cf" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, at91_cf_dt_ids);
+
+static int at91_cf_dt_init(struct platform_device *pdev)
+{
+	struct at91_cf_data *board;
+
+	board = devm_kzalloc(&pdev->dev, sizeof(*board), GFP_KERNEL);
+	if (!board)
+		return -ENOMEM;
+
+	board->irq_pin = of_get_gpio(pdev->dev.of_node, 0);
+	board->det_pin = of_get_gpio(pdev->dev.of_node, 1);
+	board->vcc_pin = of_get_gpio(pdev->dev.of_node, 2);
+	board->rst_pin = of_get_gpio(pdev->dev.of_node, 3);
+
+	pdev->dev.platform_data = board;
+
+	return 0;
+}
+#else
+static int at91_cf_dt_init(struct platform_device *pdev)
+{
+	return -ENODEV;
+}
+#endif
+
 static int __init at91_cf_probe(struct platform_device *pdev)
 {
 	struct at91_cf_socket	*cf;
@@ -222,14 +252,22 @@ static int __init at91_cf_probe(struct platform_device *pdev)
 	struct resource		*io;
 	int			status;
 
-	if (!board || !gpio_is_valid(board->det_pin) || !gpio_is_valid(board->rst_pin))
+	if (!board) {
+		status = at91_cf_dt_init(pdev);
+		if (status)
+			return status;
+
+		board = pdev->dev.platform_data;
+	}
+
+	if (!gpio_is_valid(board->det_pin) || !gpio_is_valid(board->rst_pin))
 		return -ENODEV;
 
 	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!io)
 		return -ENODEV;
 
-	cf = kzalloc(sizeof *cf, GFP_KERNEL);
+	cf = devm_kzalloc(&pdev->dev, sizeof(*cf), GFP_KERNEL);
 	if (!cf)
 		return -ENOMEM;
 
@@ -239,22 +277,25 @@ static int __init at91_cf_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, cf);
 
 	/* must be a GPIO; ergo must trigger on both edges */
-	status = gpio_request(board->det_pin, "cf_det");
+	status = devm_gpio_request(&pdev->dev, board->det_pin, "cf_det");
 	if (status < 0)
-		goto fail0;
-	status = request_irq(gpio_to_irq(board->det_pin), at91_cf_irq, 0, driver_name, cf);
+		return status;
+
+	status = devm_request_irq(&pdev->dev, gpio_to_irq(board->det_pin),
+					at91_cf_irq, 0, "at91_cf detect", cf);
 	if (status < 0)
-		goto fail00;
+		return status;
+
 	device_init_wakeup(&pdev->dev, 1);
 
-	status = gpio_request(board->rst_pin, "cf_rst");
+	status = devm_gpio_request(&pdev->dev, board->rst_pin, "cf_rst");
 	if (status < 0)
 		goto fail0a;
 
 	if (gpio_is_valid(board->vcc_pin)) {
-		status = gpio_request(board->vcc_pin, "cf_vcc");
+		status = devm_gpio_request(&pdev->dev, board->vcc_pin, "cf_vcc");
 		if (status < 0)
-			goto fail0b;
+			goto fail0a;
 	}
 
 	/*
@@ -264,32 +305,33 @@ static int __init at91_cf_probe(struct platform_device *pdev)
 	 * (Note:  DK board doesn't wire the IRQ pin...)
 	 */
 	if (gpio_is_valid(board->irq_pin)) {
-		status = gpio_request(board->irq_pin, "cf_irq");
+		status = devm_gpio_request(&pdev->dev, board->irq_pin, "cf_irq");
 		if (status < 0)
-			goto fail0c;
-		status = request_irq(gpio_to_irq(board->irq_pin), at91_cf_irq,
-				IRQF_SHARED, driver_name, cf);
+			goto fail0a;
+
+		status = devm_request_irq(&pdev->dev, gpio_to_irq(board->irq_pin),
+					at91_cf_irq, IRQF_SHARED, "at91_cf", cf);
 		if (status < 0)
-			goto fail0d;
+			goto fail0a;
 		cf->socket.pci_irq = gpio_to_irq(board->irq_pin);
 	} else
 		cf->socket.pci_irq = nr_irqs + 1;
 
 	/* pcmcia layer only remaps "real" memory not iospace */
-	cf->socket.io_offset = (unsigned long)
-			ioremap(cf->phys_baseaddr + CF_IO_PHYS, SZ_2K);
+	cf->socket.io_offset = (unsigned long) devm_ioremap(&pdev->dev,
+					cf->phys_baseaddr + CF_IO_PHYS, SZ_2K);
 	if (!cf->socket.io_offset) {
 		status = -ENXIO;
-		goto fail1;
+		goto fail0a;
 	}
 
 	/* reserve chip-select regions */
-	if (!request_mem_region(io->start, resource_size(io), driver_name)) {
+	if (!devm_request_mem_region(&pdev->dev, io->start, resource_size(io), "at91_cf")) {
 		status = -ENXIO;
-		goto fail1;
+		goto fail0a;
 	}
 
-	pr_info("%s: irqs det #%d, io #%d\n", driver_name,
+	dev_info(&pdev->dev, "irqs det #%d, io #%d\n",
 		gpio_to_irq(board->det_pin), gpio_to_irq(board->irq_pin));
 
 	cf->socket.owner = THIS_MODULE;
@@ -303,55 +345,22 @@ static int __init at91_cf_probe(struct platform_device *pdev)
 
 	status = pcmcia_register_socket(&cf->socket);
 	if (status < 0)
-		goto fail2;
+		goto fail0a;
 
 	return 0;
 
-fail2:
-	release_mem_region(io->start, resource_size(io));
-fail1:
-	if (cf->socket.io_offset)
-		iounmap((void __iomem *) cf->socket.io_offset);
-	if (gpio_is_valid(board->irq_pin)) {
-		free_irq(gpio_to_irq(board->irq_pin), cf);
-fail0d:
-		gpio_free(board->irq_pin);
-	}
-fail0c:
-	if (gpio_is_valid(board->vcc_pin))
-		gpio_free(board->vcc_pin);
-fail0b:
-	gpio_free(board->rst_pin);
 fail0a:
 	device_init_wakeup(&pdev->dev, 0);
-	free_irq(gpio_to_irq(board->det_pin), cf);
-fail00:
-	gpio_free(board->det_pin);
-fail0:
-	kfree(cf);
 	return status;
 }
 
 static int __exit at91_cf_remove(struct platform_device *pdev)
 {
 	struct at91_cf_socket	*cf = platform_get_drvdata(pdev);
-	struct at91_cf_data	*board = cf->board;
-	struct resource		*io = cf->socket.io[0].res;
 
 	pcmcia_unregister_socket(&cf->socket);
-	release_mem_region(io->start, resource_size(io));
-	iounmap((void __iomem *) cf->socket.io_offset);
-	if (gpio_is_valid(board->irq_pin)) {
-		free_irq(gpio_to_irq(board->irq_pin), cf);
-		gpio_free(board->irq_pin);
-	}
-	if (gpio_is_valid(board->vcc_pin))
-		gpio_free(board->vcc_pin);
-	gpio_free(board->rst_pin);
 	device_init_wakeup(&pdev->dev, 0);
-	free_irq(gpio_to_irq(board->det_pin), cf);
-	gpio_free(board->det_pin);
-	kfree(cf);
+
 	return 0;
 }
 
@@ -391,8 +400,9 @@ static int at91_cf_resume(struct platform_device *pdev)
 
 static struct platform_driver at91_cf_driver = {
 	.driver = {
-		.name		= (char *) driver_name,
+		.name		= "at91_cf",
 		.owner		= THIS_MODULE,
+		.of_match_table = of_match_ptr(at91_cf_dt_ids),
 	},
 	.remove		= __exit_p(at91_cf_remove),
 	.suspend	= at91_cf_suspend,
@@ -401,17 +411,7 @@ static struct platform_driver at91_cf_driver = {
 
 /*--------------------------------------------------------------------------*/
 
-static int __init at91_cf_init(void)
-{
-	return platform_driver_probe(&at91_cf_driver, at91_cf_probe);
-}
-module_init(at91_cf_init);
-
-static void __exit at91_cf_exit(void)
-{
-	platform_driver_unregister(&at91_cf_driver);
-}
-module_exit(at91_cf_exit);
+module_platform_driver_probe(at91_cf_driver, at91_cf_probe);
 
 MODULE_DESCRIPTION("AT91 Compact Flash Driver");
 MODULE_AUTHOR("David Brownell");

+ 2 - 0
drivers/pcmcia/pd6729.c

@@ -644,6 +644,7 @@ static int pd6729_pci_probe(struct pci_dev *dev,
 	if (!pci_resource_start(dev, 0)) {
 		dev_warn(&dev->dev, "refusing to load the driver as the "
 			"io_base is NULL.\n");
+		ret = -ENOMEM;
 		goto err_out_disable;
 	}
 
@@ -673,6 +674,7 @@ static int pd6729_pci_probe(struct pci_dev *dev,
 	mask = pd6729_isa_scan();
 	if (irq_mode == 0 && mask == 0) {
 		dev_warn(&dev->dev, "no ISA interrupt is available.\n");
+		ret = -ENODEV;
 		goto err_out_free_res;
 	}
 

+ 1 - 13
drivers/uio/uio_aec.c

@@ -160,17 +160,5 @@ static struct pci_driver pci_driver = {
 	.remove = remove,
 };
 
-static int __init aectc_init(void)
-{
-	return pci_register_driver(&pci_driver);
-}
-
-static void __exit aectc_exit(void)
-{
-	pci_unregister_driver(&pci_driver);
-}
-
+module_pci_driver(pci_driver);
 MODULE_LICENSE("GPL");
-
-module_init(aectc_init);
-module_exit(aectc_exit);

+ 1 - 13
drivers/uio/uio_cif.c

@@ -135,19 +135,7 @@ static struct pci_driver hilscher_pci_driver = {
 	.remove = hilscher_pci_remove,
 };
 
-static int __init hilscher_init_module(void)
-{
-	return pci_register_driver(&hilscher_pci_driver);
-}
-
-static void __exit hilscher_exit_module(void)
-{
-	pci_unregister_driver(&hilscher_pci_driver);
-}
-
-module_init(hilscher_init_module);
-module_exit(hilscher_exit_module);
-
+module_pci_driver(hilscher_pci_driver);
 MODULE_DEVICE_TABLE(pci, hilscher_pci_ids);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger");

+ 1 - 3
drivers/uio/uio_dmem_genirq.c

@@ -336,8 +336,6 @@ static const struct of_device_id uio_of_genirq_match[] = {
 	{ /* empty for now */ },
 };
 MODULE_DEVICE_TABLE(of, uio_of_genirq_match);
-#else
-# define uio_of_genirq_match NULL
 #endif
 
 static struct platform_driver uio_dmem_genirq = {
@@ -347,7 +345,7 @@ static struct platform_driver uio_dmem_genirq = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
 		.pm = &uio_dmem_genirq_dev_pm_ops,
-		.of_match_table = uio_of_genirq_match,
+		.of_match_table = of_match_ptr(uio_of_genirq_match),
 	},
 };
 

+ 1 - 13
drivers/uio/uio_netx.c

@@ -174,19 +174,7 @@ static struct pci_driver netx_pci_driver = {
 	.remove = netx_pci_remove,
 };
 
-static int __init netx_init_module(void)
-{
-	return pci_register_driver(&netx_pci_driver);
-}
-
-static void __exit netx_exit_module(void)
-{
-	pci_unregister_driver(&netx_pci_driver);
-}
-
-module_init(netx_init_module);
-module_exit(netx_exit_module);
-
+module_pci_driver(netx_pci_driver);
 MODULE_DEVICE_TABLE(pci, netx_pci_ids);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Hans J. Koch, Manuel Traut");

+ 2 - 15
drivers/uio/uio_pci_generic.c

@@ -113,27 +113,14 @@ static void remove(struct pci_dev *pdev)
 	kfree(gdev);
 }
 
-static struct pci_driver driver = {
+static struct pci_driver uio_pci_driver = {
 	.name = "uio_pci_generic",
 	.id_table = NULL, /* only dynamic id's */
 	.probe = probe,
 	.remove = remove,
 };
 
-static int __init init(void)
-{
-	pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-	return pci_register_driver(&driver);
-}
-
-static void __exit cleanup(void)
-{
-	pci_unregister_driver(&driver);
-}
-
-module_init(init);
-module_exit(cleanup);
-
+module_pci_driver(uio_pci_driver);
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR(DRIVER_AUTHOR);

+ 29 - 25
drivers/uio/uio_pdrv_genirq.c

@@ -37,6 +37,11 @@ struct uio_pdrv_genirq_platdata {
 	struct platform_device *pdev;
 };
 
+/* Bits in uio_pdrv_genirq_platdata.flags */
+enum {
+	UIO_IRQ_DISABLED = 0,
+};
+
 static int uio_pdrv_genirq_open(struct uio_info *info, struct inode *inode)
 {
 	struct uio_pdrv_genirq_platdata *priv = info->priv;
@@ -63,8 +68,10 @@ static irqreturn_t uio_pdrv_genirq_handler(int irq, struct uio_info *dev_info)
 	 * remember the state so we can allow user space to enable it later.
 	 */
 
-	if (!test_and_set_bit(0, &priv->flags))
+	spin_lock(&priv->lock);
+	if (!__test_and_set_bit(UIO_IRQ_DISABLED, &priv->flags))
 		disable_irq_nosync(irq);
+	spin_unlock(&priv->lock);
 
 	return IRQ_HANDLED;
 }
@@ -78,16 +85,17 @@ static int uio_pdrv_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on)
 	 * in the interrupt controller, but keep track of the
 	 * state to prevent per-irq depth damage.
 	 *
-	 * Serialize this operation to support multiple tasks.
+	 * Serialize this operation to support multiple tasks and concurrency
+	 * with irq handler on SMP systems.
 	 */
 
 	spin_lock_irqsave(&priv->lock, flags);
 	if (irq_on) {
-		if (test_and_clear_bit(0, &priv->flags))
+		if (__test_and_clear_bit(UIO_IRQ_DISABLED, &priv->flags))
 			enable_irq(dev_info->irq);
 	} else {
-		if (!test_and_set_bit(0, &priv->flags))
-			disable_irq(dev_info->irq);
+		if (!__test_and_set_bit(UIO_IRQ_DISABLED, &priv->flags))
+			disable_irq_nosync(dev_info->irq);
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -103,24 +111,16 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
 	int i;
 
 	if (pdev->dev.of_node) {
-		int irq;
-
 		/* alloc uioinfo for one device */
 		uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL);
 		if (!uioinfo) {
 			ret = -ENOMEM;
 			dev_err(&pdev->dev, "unable to kmalloc\n");
-			goto bad2;
+			return ret;
 		}
 		uioinfo->name = pdev->dev.of_node->name;
 		uioinfo->version = "devicetree";
-
 		/* Multiple IRQs are not supported */
-		irq = platform_get_irq(pdev, 0);
-		if (irq == -ENXIO)
-			uioinfo->irq = UIO_IRQ_NONE;
-		else
-			uioinfo->irq = irq;
 	}
 
 	if (!uioinfo || !uioinfo->name || !uioinfo->version) {
@@ -148,12 +148,15 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
 
 	if (!uioinfo->irq) {
 		ret = platform_get_irq(pdev, 0);
-		if (ret < 0) {
+		uioinfo->irq = ret;
+		if (ret == -ENXIO && pdev->dev.of_node)
+			uioinfo->irq = UIO_IRQ_NONE;
+		else if (ret < 0) {
 			dev_err(&pdev->dev, "failed to get IRQ\n");
-			goto bad0;
+			goto bad1;
 		}
-		uioinfo->irq = ret;
 	}
+
 	uiomem = &uioinfo->mem[0];
 
 	for (i = 0; i < pdev->num_resources; ++i) {
@@ -206,19 +209,19 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
 	ret = uio_register_device(&pdev->dev, priv->uioinfo);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to register uio device\n");
-		goto bad1;
+		goto bad2;
 	}
 
 	platform_set_drvdata(pdev, priv);
 	return 0;
+ bad2:
+	pm_runtime_disable(&pdev->dev);
  bad1:
 	kfree(priv);
-	pm_runtime_disable(&pdev->dev);
  bad0:
 	/* kfree uioinfo for OF */
 	if (pdev->dev.of_node)
 		kfree(uioinfo);
- bad2:
 	return ret;
 }
 
@@ -263,12 +266,13 @@ static const struct dev_pm_ops uio_pdrv_genirq_dev_pm_ops = {
 };
 
 #ifdef CONFIG_OF
-static const struct of_device_id uio_of_genirq_match[] = {
-	{ /* empty for now */ },
+static struct of_device_id uio_of_genirq_match[] = {
+	{ /* This is filled with module_parm */ },
+	{ /* Sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, uio_of_genirq_match);
-#else
-# define uio_of_genirq_match NULL
+module_param_string(of_id, uio_of_genirq_match[0].compatible, 128, 0);
+MODULE_PARM_DESC(of_id, "Openfirmware id of the device to be handled by uio");
 #endif
 
 static struct platform_driver uio_pdrv_genirq = {
@@ -278,7 +282,7 @@ static struct platform_driver uio_pdrv_genirq = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
 		.pm = &uio_pdrv_genirq_dev_pm_ops,
-		.of_match_table = uio_of_genirq_match,
+		.of_match_table = of_match_ptr(uio_of_genirq_match),
 	},
 };
 

+ 1 - 1
drivers/uio/uio_pruss.c

@@ -136,9 +136,9 @@ static int pruss_probe(struct platform_device *dev)
 	gdev->pruss_clk = clk_get(&dev->dev, "pruss");
 	if (IS_ERR(gdev->pruss_clk)) {
 		dev_err(&dev->dev, "Failed to get clock\n");
+		ret = PTR_ERR(gdev->pruss_clk);
 		kfree(gdev->info);
 		kfree(gdev);
-		ret = PTR_ERR(gdev->pruss_clk);
 		return ret;
 	} else {
 		clk_enable(gdev->pruss_clk);

+ 1 - 13
drivers/uio/uio_sercos3.c

@@ -226,19 +226,7 @@ static struct pci_driver sercos3_pci_driver = {
 	.remove = sercos3_pci_remove,
 };
 
-static int __init sercos3_init_module(void)
-{
-	return pci_register_driver(&sercos3_pci_driver);
-}
-
-static void __exit sercos3_exit_module(void)
-{
-	pci_unregister_driver(&sercos3_pci_driver);
-}
-
-module_init(sercos3_init_module);
-module_exit(sercos3_exit_module);
-
+module_pci_driver(sercos3_pci_driver);
 MODULE_DESCRIPTION("UIO driver for the Automata Sercos III PCI card");
 MODULE_AUTHOR("John Ogness <john.ogness@linutronix.de>");
 MODULE_LICENSE("GPL v2");

Some files were not shown because too many files changed in this diff