diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 14:43:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 14:43:33 -0400 |
commit | fe3c22bd5cadd8e36977b218b27fbea821381ec8 (patch) | |
tree | cc4d4479a077c0db22e5de40d181ad6963fc3993 | |
parent | ce49b6289fa3878b190f15192e54bb23dca552b6 (diff) | |
parent | 380672698b8e64f0b5e418412b1ed370bd366428 (diff) |
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
...
130 files changed, 5322 insertions, 919 deletions
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 45b3df936d2f..0c4cc688e89a 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX | |||
@@ -187,6 +187,8 @@ firmware_class/ | |||
187 | - request_firmware() hotplug interface info. | 187 | - request_firmware() hotplug interface info. |
188 | flexible-arrays.txt | 188 | flexible-arrays.txt |
189 | - how to make use of flexible sized arrays in linux | 189 | - how to make use of flexible sized arrays in linux |
190 | fmc/ | ||
191 | - information about the FMC bus abstraction | ||
190 | frv/ | 192 | frv/ |
191 | - Fujitsu FR-V Linux documentation. | 193 | - Fujitsu FR-V Linux documentation. |
192 | futex-requeue-pi.txt | 194 | futex-requeue-pi.txt |
diff --git a/Documentation/devicetree/bindings/ata/atmel-at91_cf.txt b/Documentation/devicetree/bindings/ata/atmel-at91_cf.txt new file mode 100644 index 000000000000..c1d22b3ae134 --- /dev/null +++ b/Documentation/devicetree/bindings/ata/atmel-at91_cf.txt | |||
@@ -0,0 +1,19 @@ | |||
1 | Atmel AT91RM9200 CompactFlash | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "atmel,at91rm9200-cf". | ||
5 | - reg : should specify localbus address and size used. | ||
6 | - gpios : specifies the gpio pins to control the CF device. Detect | ||
7 | and reset gpio's are mandatory while irq and vcc gpio's are | ||
8 | optional and may be set to 0 if not present. | ||
9 | |||
10 | Example: | ||
11 | compact-flash@50000000 { | ||
12 | compatible = "atmel,at91rm9200-cf"; | ||
13 | reg = <0x50000000 0x30000000>; | ||
14 | gpios = <&pioC 13 0 /* irq */ | ||
15 | &pioC 15 0 /* detect */ | ||
16 | 0 /* vcc */ | ||
17 | &pioC 5 0 /* reset */ | ||
18 | >; | ||
19 | }; | ||
diff --git a/Documentation/devicetree/bindings/extcon/extcon-twl.txt b/Documentation/devicetree/bindings/extcon/extcon-twl.txt new file mode 100644 index 000000000000..58f531ab4df3 --- /dev/null +++ b/Documentation/devicetree/bindings/extcon/extcon-twl.txt | |||
@@ -0,0 +1,15 @@ | |||
1 | EXTCON FOR TWL CHIPS | ||
2 | |||
3 | PALMAS USB COMPARATOR | ||
4 | Required Properties: | ||
5 | - compatible : Should be "ti,palmas-usb" or "ti,twl6035-usb" | ||
6 | - vbus-supply : phandle to the regulator device tree node. | ||
7 | |||
8 | Optional Properties: | ||
9 | - ti,wakeup : To enable the wakeup comparator in probe | ||
10 | |||
11 | palmas-usb { | ||
12 | compatible = "ti,twl6035-usb", "ti,palmas-usb"; | ||
13 | vbus-supply = <&smps10_reg>; | ||
14 | ti,wakeup; | ||
15 | }; | ||
diff --git a/Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt b/Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt new file mode 100644 index 000000000000..653c90c34a71 --- /dev/null +++ b/Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt | |||
@@ -0,0 +1,156 @@ | |||
1 | Device tree bindings for MVEBU Device Bus controllers | ||
2 | |||
3 | The Device Bus controller available in some Marvell's SoC allows to control | ||
4 | different types of standard memory and I/O devices such as NOR, NAND, and FPGA. | ||
5 | The actual devices are instantiated from the child nodes of a Device Bus node. | ||
6 | |||
7 | Required properties: | ||
8 | |||
9 | - compatible: Currently only Armada 370/XP SoC are supported, | ||
10 | with this compatible string: | ||
11 | |||
12 | marvell,mvebu-devbus | ||
13 | |||
14 | - reg: A resource specifier for the register space. | ||
15 | This is the base address of a chip select within | ||
16 | the controller's register space. | ||
17 | (see the example below) | ||
18 | |||
19 | - #address-cells: Must be set to 1 | ||
20 | - #size-cells: Must be set to 1 | ||
21 | - ranges: Must be set up to reflect the memory layout with four | ||
22 | integer values for each chip-select line in use: | ||
23 | 0 <physical address of mapping> <size> | ||
24 | |||
25 | Mandatory timing properties for child nodes: | ||
26 | |||
27 | Read parameters: | ||
28 | |||
29 | - devbus,turn-off-ps: Defines the time during which the controller does not | ||
30 | drive the AD bus after the completion of a device read. | ||
31 | This prevents contentions on the Device Bus after a read | ||
32 | cycle from a slow device. | ||
33 | |||
34 | - devbus,bus-width: Defines the bus width (e.g. <16>) | ||
35 | |||
36 | - devbus,badr-skew-ps: Defines the time delay from from A[2:0] toggle, | ||
37 | to read data sample. This parameter is useful for | ||
38 | synchronous pipelined devices, where the address | ||
39 | precedes the read data by one or two cycles. | ||
40 | |||
41 | - devbus,acc-first-ps: Defines the time delay from the negation of | ||
42 | ALE[0] to the cycle that the first read data is sampled | ||
43 | by the controller. | ||
44 | |||
45 | - devbus,acc-next-ps: Defines the time delay between the cycle that | ||
46 | samples data N and the cycle that samples data N+1 | ||
47 | (in burst accesses). | ||
48 | |||
49 | - devbus,rd-setup-ps: Defines the time delay between DEV_CSn assertion to | ||
50 | DEV_OEn assertion. If set to 0 (default), | ||
51 | DEV_OEn and DEV_CSn are asserted at the same cycle. | ||
52 | This parameter has no affect on <acc-first-ps> parameter | ||
53 | (no affect on first data sample). Set <rd-setup-ps> | ||
54 | to a value smaller than <acc-first-ps>. | ||
55 | |||
56 | - devbus,rd-hold-ps: Defines the time between the last data sample to the | ||
57 | de-assertion of DEV_CSn. If set to 0 (default), | ||
58 | DEV_OEn and DEV_CSn are de-asserted at the same cycle | ||
59 | (the cycle of the last data sample). | ||
60 | This parameter has no affect on DEV_OEn de-assertion. | ||
61 | DEV_OEn is always de-asserted the next cycle after | ||
62 | last data sampled. Also this parameter has no | ||
63 | affect on <turn-off-ps> parameter. | ||
64 | Set <rd-hold-ps> to a value smaller than <turn-off-ps>. | ||
65 | |||
66 | Write parameters: | ||
67 | |||
68 | - devbus,ale-wr-ps: Defines the time delay from the ALE[0] negation cycle | ||
69 | to the DEV_WEn assertion. | ||
70 | |||
71 | - devbus,wr-low-ps: Defines the time during which DEV_WEn is active. | ||
72 | A[2:0] and Data are kept valid as long as DEV_WEn | ||
73 | is active. This parameter defines the setup time of | ||
74 | address and data to DEV_WEn rise. | ||
75 | |||
76 | - devbus,wr-high-ps: Defines the time during which DEV_WEn is kept | ||
77 | inactive (high) between data beats of a burst write. | ||
78 | DEV_A[2:0] and Data are kept valid (do not toggle) for | ||
79 | <wr-high-ps> - <tick> ps. | ||
80 | This parameter defines the hold time of address and | ||
81 | data after DEV_WEn rise. | ||
82 | |||
83 | - devbus,sync-enable: Synchronous device enable. | ||
84 | 1: True | ||
85 | 0: False | ||
86 | |||
87 | An example for an Armada XP GP board, with a 16 MiB NOR device as child | ||
88 | is showed below. Note that the Device Bus driver is in charge of allocating | ||
89 | the mbus address decoding window for each of its child devices. | ||
90 | The window is created using the chip select specified in the child | ||
91 | device node together with the base address and size specified in the ranges | ||
92 | property. For instance, in the example below the allocated decoding window | ||
93 | will start at base address 0xf0000000, with a size 0x1000000 (16 MiB) | ||
94 | for chip select 0 (a.k.a DEV_BOOTCS). | ||
95 | |||
96 | This address window handling is done in this mvebu-devbus only as a temporary | ||
97 | solution. It will be removed when the support for mbus device tree binding is | ||
98 | added. | ||
99 | |||
100 | The reg property implicitly specifies the chip select as this: | ||
101 | |||
102 | 0x10400: DEV_BOOTCS | ||
103 | 0x10408: DEV_CS0 | ||
104 | 0x10410: DEV_CS1 | ||
105 | 0x10418: DEV_CS2 | ||
106 | 0x10420: DEV_CS3 | ||
107 | |||
108 | Example: | ||
109 | |||
110 | devbus-bootcs@d0010400 { | ||
111 | status = "okay"; | ||
112 | ranges = <0 0xf0000000 0x1000000>; /* @addr 0xf0000000, size 0x1000000 */ | ||
113 | #address-cells = <1>; | ||
114 | #size-cells = <1>; | ||
115 | |||
116 | /* Device Bus parameters are required */ | ||
117 | |||
118 | /* Read parameters */ | ||
119 | devbus,bus-width = <8>; | ||
120 | devbus,turn-off-ps = <60000>; | ||
121 | devbus,badr-skew-ps = <0>; | ||
122 | devbus,acc-first-ps = <124000>; | ||
123 | devbus,acc-next-ps = <248000>; | ||
124 | devbus,rd-setup-ps = <0>; | ||
125 | devbus,rd-hold-ps = <0>; | ||
126 | |||
127 | /* Write parameters */ | ||
128 | devbus,sync-enable = <0>; | ||
129 | devbus,wr-high-ps = <60000>; | ||
130 | devbus,wr-low-ps = <60000>; | ||
131 | devbus,ale-wr-ps = <60000>; | ||
132 | |||
133 | flash@0 { | ||
134 | compatible = "cfi-flash"; | ||
135 | |||
136 | /* 16 MiB */ | ||
137 | reg = <0 0x1000000>; | ||
138 | bank-width = <2>; | ||
139 | #address-cells = <1>; | ||
140 | #size-cells = <1>; | ||
141 | |||
142 | /* | ||
143 | * We split the 16 MiB in two partitions, | ||
144 | * just as an example. | ||
145 | */ | ||
146 | partition@0 { | ||
147 | label = "First"; | ||
148 | reg = <0 0x800000>; | ||
149 | }; | ||
150 | |||
151 | partition@800000 { | ||
152 | label = "Second"; | ||
153 | reg = <0x800000 0x800000>; | ||
154 | }; | ||
155 | }; | ||
156 | }; | ||
diff --git a/Documentation/fmc/00-INDEX b/Documentation/fmc/00-INDEX new file mode 100644 index 000000000000..431c69570f43 --- /dev/null +++ b/Documentation/fmc/00-INDEX | |||
@@ -0,0 +1,38 @@ | |||
1 | |||
2 | Documentation in this directory comes from sections of the manual we | ||
3 | wrote for the externally-developed fmc-bus package. The complete | ||
4 | manual as of today (2013-02) is available in PDF format at | ||
5 | http://www.ohwr.org/projects/fmc-bus/files | ||
6 | |||
7 | 00-INDEX | ||
8 | - this file. | ||
9 | |||
10 | FMC-and-SDB.txt | ||
11 | - What are FMC and SDB, basic concepts for this framework | ||
12 | |||
13 | API.txt | ||
14 | - The functions that are exported by the bus driver | ||
15 | |||
16 | parameters.txt | ||
17 | - The module parameters | ||
18 | |||
19 | carrier.txt | ||
20 | - writing a carrier (a device) | ||
21 | |||
22 | mezzanine.txt | ||
23 | - writing code for your mezzanine (a driver) | ||
24 | |||
25 | identifiers.txt | ||
26 | - how identification and matching works | ||
27 | |||
28 | fmc-fakedev.txt | ||
29 | - about drivers/fmc/fmc-fakedev.ko | ||
30 | |||
31 | fmc-trivial.txt | ||
32 | - about drivers/fmc/fmc-trivial.ko | ||
33 | |||
34 | fmc-write-eeprom.txt | ||
35 | - about drivers/fmc/fmc-write-eeprom.ko | ||
36 | |||
37 | fmc-chardev.txt | ||
38 | - about drivers/fmc/fmc-chardev.ko | ||
diff --git a/Documentation/fmc/API.txt b/Documentation/fmc/API.txt new file mode 100644 index 000000000000..06b06b92c794 --- /dev/null +++ b/Documentation/fmc/API.txt | |||
@@ -0,0 +1,47 @@ | |||
1 | Functions Exported by fmc.ko | ||
2 | **************************** | ||
3 | |||
4 | The FMC core exports the usual 4 functions that are needed for a bus to | ||
5 | work, and a few more: | ||
6 | |||
7 | int fmc_driver_register(struct fmc_driver *drv); | ||
8 | void fmc_driver_unregister(struct fmc_driver *drv); | ||
9 | int fmc_device_register(struct fmc_device *fmc); | ||
10 | void fmc_device_unregister(struct fmc_device *fmc); | ||
11 | |||
12 | int fmc_device_register_n(struct fmc_device **fmc, int n); | ||
13 | void fmc_device_unregister_n(struct fmc_device **fmc, int n); | ||
14 | |||
15 | uint32_t fmc_readl(struct fmc_device *fmc, int offset); | ||
16 | void fmc_writel(struct fmc_device *fmc, uint32_t val, int off); | ||
17 | void *fmc_get_drvdata(struct fmc_device *fmc); | ||
18 | void fmc_set_drvdata(struct fmc_device *fmc, void *data); | ||
19 | |||
20 | int fmc_reprogram(struct fmc_device *f, struct fmc_driver *d, char *gw, | ||
21 | int sdb_entry); | ||
22 | |||
23 | The data structure that describe a device is detailed in *note FMC | ||
24 | Device::, the one that describes a driver is detailed in *note FMC | ||
25 | Driver::. Please note that structures of type fmc_device must be | ||
26 | allocated by the caller, but must not be released after unregistering. | ||
27 | The fmc-bus itself takes care of releasing the structure when their use | ||
28 | count reaches zero - actually, the device model does that in lieu of us. | ||
29 | |||
30 | The functions to register and unregister n devices are meant to be used | ||
31 | by carriers that host more than one mezzanine. The devices must all be | ||
32 | registered at the same time because if the FPGA is reprogrammed, all | ||
33 | devices in the array are affected. Usually, the driver matching the | ||
34 | first device will reprogram the FPGA, so other devices must know they | ||
35 | are already driven by a reprogrammed FPGA. | ||
36 | |||
37 | If a carrier hosts slots that are driven by different FPGA devices, it | ||
38 | should register as a group only mezzanines that are driven by the same | ||
39 | FPGA, for the reason outlined above. | ||
40 | |||
41 | Finally, the fmc_reprogram function calls the reprogram method (see | ||
42 | *note The API Offered by Carriers:: and also scans the memory area for | ||
43 | an SDB tree. You can pass -1 as sdb_entry to disable such scan. | ||
44 | Otherwise, the function fails if no tree is found at the specified | ||
45 | entry point. The function is meant to factorize common code, and by | ||
46 | the time you read this it is already used by the spec-sw and fine-delay | ||
47 | modules. | ||
diff --git a/Documentation/fmc/FMC-and-SDB.txt b/Documentation/fmc/FMC-and-SDB.txt new file mode 100644 index 000000000000..fa14e0b24521 --- /dev/null +++ b/Documentation/fmc/FMC-and-SDB.txt | |||
@@ -0,0 +1,88 @@ | |||
1 | |||
2 | FMC (FPGA Mezzanine Card) is the standard we use for our I/O devices, | ||
3 | in the context of White Rabbit and related hardware. | ||
4 | |||
5 | In our I/O environments we need to write drivers for each mezzanine | ||
6 | card, and such drivers must work regardless of the carrier being used. | ||
7 | To achieve this, we abstract the FMC interface. | ||
8 | |||
9 | We have a carrier for PCI-E called SPEC and one for VME called SVEC, | ||
10 | but more are planned. Also, we support stand-alone devices (usually | ||
11 | plugged on a SPEC card), controlled through Etherbone, developed by GSI. | ||
12 | |||
13 | Code and documentation for the FMC bus was born as part of the spec-sw | ||
14 | project, but now it lives in its own project. Other projects, i.e. | ||
15 | software support for the various carriers, should include this as a | ||
16 | submodule. | ||
17 | |||
18 | The most up to date version of code and documentation is always | ||
19 | available from the repository you can clone from: | ||
20 | |||
21 | git://ohwr.org/fmc-projects/fmc-bus.git (read-only) | ||
22 | git@ohwr.org:fmc-projects/fmc-bus.git (read-write for developers) | ||
23 | |||
24 | Selected versions of the documentation, as well as complete tar | ||
25 | archives for selected revisions are placed to the Files section of the | ||
26 | project: `http://www.ohwr.org/projects/fmc-bus/files' | ||
27 | |||
28 | |||
29 | What is FMC | ||
30 | *********** | ||
31 | |||
32 | FMC, as said, stands for "FPGA Mezzanine Card". It is a standard | ||
33 | developed by the VME consortium called VITA (VMEbus International Trade | ||
34 | Association and ratified by ANSI, the American National Standard | ||
35 | Institute. The official documentation is called "ANSI-VITA 57.1". | ||
36 | |||
37 | The FMC card is an almost square PCB, around 70x75 millimeters, that is | ||
38 | called mezzanine in this document. It usually lives plugged into | ||
39 | another PCB for power supply and control; such bigger circuit board is | ||
40 | called carrier from now on, and a single carrier may host more than one | ||
41 | mezzanine. | ||
42 | |||
43 | In the typical application the mezzanine is mostly analog while the | ||
44 | carrier is mostly digital, and hosts an FPGA that must be configured to | ||
45 | match the specific mezzanine and the desired application. Thus, you may | ||
46 | need to load different FPGA images to drive different instances of the | ||
47 | same mezzanine. | ||
48 | |||
49 | FMC, as such, is not a bus in the usual meaning of the term, because | ||
50 | most carriers have only one connector, and carriers with several | ||
51 | connectors have completely separate electrical connections to them. | ||
52 | This package, however, implements a bus as a software abstraction. | ||
53 | |||
54 | |||
55 | What is SDB | ||
56 | *********** | ||
57 | |||
58 | SDB (Self Describing Bus) is a set of data structures that we use for | ||
59 | enumerating the internal structure of an FPGA image. We also use it as | ||
60 | a filesystem inside the FMC EEPROM. | ||
61 | |||
62 | SDB is not mandatory for use of this FMC kernel bus, but if you have SDB | ||
63 | this package can make good use of it. SDB itself is developed in the | ||
64 | fpga-config-space OHWR project. The link to the repository is | ||
65 | `git://ohwr.org/hdl-core-lib/fpga-config-space.git' and what is used in | ||
66 | this project lives in the sdbfs subdirectory in there. | ||
67 | |||
68 | SDB support for FMC is described in *note FMC Identification:: and | ||
69 | *note SDB Support:: | ||
70 | |||
71 | |||
72 | SDB Support | ||
73 | *********** | ||
74 | |||
75 | The fmc.ko bus driver exports a few functions to help drivers taking | ||
76 | advantage of the SDB information that may be present in your own FPGA | ||
77 | memory image. | ||
78 | |||
79 | The module exports the following functions, in the special header | ||
80 | <linux/fmc-sdb.h>. The linux/ prefix in the name is there because we | ||
81 | plan to submit it upstream in the future, and don't want to force | ||
82 | changes on our drivers if that happens. | ||
83 | |||
84 | int fmc_scan_sdb_tree(struct fmc_device *fmc, unsigned long address); | ||
85 | void fmc_show_sdb_tree(struct fmc_device *fmc); | ||
86 | signed long fmc_find_sdb_device(struct sdb_array *tree, uint64_t vendor, | ||
87 | uint32_t device, unsigned long *sz); | ||
88 | int fmc_free_sdb_tree(struct fmc_device *fmc); | ||
diff --git a/Documentation/fmc/carrier.txt b/Documentation/fmc/carrier.txt new file mode 100644 index 000000000000..173f6d65c88d --- /dev/null +++ b/Documentation/fmc/carrier.txt | |||
@@ -0,0 +1,311 @@ | |||
1 | FMC Device | ||
2 | ********** | ||
3 | |||
4 | Within the Linux bus framework, the FMC device is created and | ||
5 | registered by the carrier driver. For example, the PCI driver for the | ||
6 | SPEC card fills a data structure for each SPEC that it drives, and | ||
7 | registers an associated FMC device for each card. The SVEC driver can | ||
8 | do exactly the same for the VME carrier (actually, it should do it | ||
9 | twice, because the SVEC carries two FMC mezzanines). Similarly, an | ||
10 | Etherbone driver will be able to register its own FMC devices, offering | ||
11 | communication primitives through frame exchange. | ||
12 | |||
13 | The contents of the EEPROM within the FMC are used for identification | ||
14 | purposes, i.e. for matching the device with its own driver. For this | ||
15 | reason the device structure includes a complete copy of the EEPROM | ||
16 | (actually, the carrier driver may choose whether or not to return it - | ||
17 | for example we most likely won't have the whole EEPROM available for | ||
18 | Etherbone devices. | ||
19 | |||
20 | The following listing shows the current structure defining a device. | ||
21 | Please note that all the machinery is in place but some details may | ||
22 | still change in the future. For this reason, there is a version field | ||
23 | at the beginning of the structure. As usual, the minor number will | ||
24 | change for compatible changes (like a new flag) and the major number | ||
25 | will increase when an incompatible change happens (for example, a | ||
26 | change in layout of some fmc data structures). Device writers should | ||
27 | just set it to the value FMC_VERSION, and be ready to get back -EINVAL | ||
28 | at registration time. | ||
29 | |||
30 | struct fmc_device { | ||
31 | unsigned long version; | ||
32 | unsigned long flags; | ||
33 | struct module *owner; /* char device must pin it */ | ||
34 | struct fmc_fru_id id; /* for EEPROM-based match */ | ||
35 | struct fmc_operations *op; /* carrier-provided */ | ||
36 | int irq; /* according to host bus. 0 == none */ | ||
37 | int eeprom_len; /* Usually 8kB, may be less */ | ||
38 | int eeprom_addr; /* 0x50, 0x52 etc */ | ||
39 | uint8_t *eeprom; /* Full contents or leading part */ | ||
40 | char *carrier_name; /* "SPEC" or similar, for special use */ | ||
41 | void *carrier_data; /* "struct spec *" or equivalent */ | ||
42 | __iomem void *fpga_base; /* May be NULL (Etherbone) */ | ||
43 | __iomem void *slot_base; /* Set by the driver */ | ||
44 | struct fmc_device **devarray; /* Allocated by the bus */ | ||
45 | int slot_id; /* Index in the slot array */ | ||
46 | int nr_slots; /* Number of slots in this carrier */ | ||
47 | unsigned long memlen; /* Used for the char device */ | ||
48 | struct device dev; /* For Linux use */ | ||
49 | struct device *hwdev; /* The underlying hardware device */ | ||
50 | unsigned long sdbfs_entry; | ||
51 | struct sdb_array *sdb; | ||
52 | uint32_t device_id; /* Filled by the device */ | ||
53 | char *mezzanine_name; /* Defaults to ``fmc'' */ | ||
54 | void *mezzanine_data; | ||
55 | }; | ||
56 | |||
57 | The meaning of most fields is summarized in the code comment above. | ||
58 | |||
59 | The following fields must be filled by the carrier driver before | ||
60 | registration: | ||
61 | |||
62 | * version: must be set to FMC_VERSION. | ||
63 | |||
64 | * owner: set to MODULE_OWNER. | ||
65 | |||
66 | * op: the operations to act on the device. | ||
67 | |||
68 | * irq: number for the mezzanine; may be zero. | ||
69 | |||
70 | * eeprom_len: length of the following array. | ||
71 | |||
72 | * eeprom_addr: 0x50 for first mezzanine and so on. | ||
73 | |||
74 | * eeprom: the full content of the I2C EEPROM. | ||
75 | |||
76 | * carrier_name. | ||
77 | |||
78 | * carrier_data: a unique pointer for the carrier. | ||
79 | |||
80 | * fpga_base: the I/O memory address (may be NULL). | ||
81 | |||
82 | * slot_id: the index of this slot (starting from zero). | ||
83 | |||
84 | * memlen: if fpga_base is valid, the length of I/O memory. | ||
85 | |||
86 | * hwdev: to be used in some dev_err() calls. | ||
87 | |||
88 | * device_id: a slot-specific unique integer number. | ||
89 | |||
90 | |||
91 | Please note that the carrier should read its own EEPROM memory before | ||
92 | registering the device, as well as fill all other fields listed above. | ||
93 | |||
94 | The following fields should not be assigned, because they are filled | ||
95 | later by either the bus or the device driver: | ||
96 | |||
97 | * flags. | ||
98 | |||
99 | * fru_id: filled by the bus, parsing the eeprom. | ||
100 | |||
101 | * slot_base: filled and used by the driver, if useful to it. | ||
102 | |||
103 | * devarray: an array og all mezzanines driven by a singe FPGA. | ||
104 | |||
105 | * nr_slots: set by the core at registration time. | ||
106 | |||
107 | * dev: used by Linux. | ||
108 | |||
109 | * sdb: FPGA contents, scanned according to driver's directions. | ||
110 | |||
111 | * sdbfs_entry: SDB entry point in EEPROM: autodetected. | ||
112 | |||
113 | * mezzanine_data: available for the driver. | ||
114 | |||
115 | * mezzanine_name: filled by fmc-bus during identification. | ||
116 | |||
117 | |||
118 | Note: mezzanine_data may be redundant, because Linux offers the drvdata | ||
119 | approach, so the field may be removed in later versions of this bus | ||
120 | implementation. | ||
121 | |||
122 | As I write this, she SPEC carrier is already completely functional in | ||
123 | the fmc-bus environment, and is a good reference to look at. | ||
124 | |||
125 | |||
126 | The API Offered by Carriers | ||
127 | =========================== | ||
128 | |||
129 | The carrier provides a number of methods by means of the | ||
130 | `fmc_operations' structure, which currently is defined like this | ||
131 | (again, it is a moving target, please refer to the header rather than | ||
132 | this document): | ||
133 | |||
134 | struct fmc_operations { | ||
135 | uint32_t (*readl)(struct fmc_device *fmc, int offset); | ||
136 | void (*writel)(struct fmc_device *fmc, uint32_t value, int offset); | ||
137 | int (*reprogram)(struct fmc_device *f, struct fmc_driver *d, char *gw); | ||
138 | int (*validate)(struct fmc_device *fmc, struct fmc_driver *drv); | ||
139 | int (*irq_request)(struct fmc_device *fmc, irq_handler_t h, | ||
140 | char *name, int flags); | ||
141 | void (*irq_ack)(struct fmc_device *fmc); | ||
142 | int (*irq_free)(struct fmc_device *fmc); | ||
143 | int (*gpio_config)(struct fmc_device *fmc, struct fmc_gpio *gpio, | ||
144 | int ngpio); | ||
145 | int (*read_ee)(struct fmc_device *fmc, int pos, void *d, int l); | ||
146 | int (*write_ee)(struct fmc_device *fmc, int pos, const void *d, int l); | ||
147 | }; | ||
148 | |||
149 | The individual methods perform the following tasks: | ||
150 | |||
151 | `readl' | ||
152 | `writel' | ||
153 | These functions access FPGA registers by whatever means the | ||
154 | carrier offers. They are not expected to fail, and most of the time | ||
155 | they will just make a memory access to the host bus. If the | ||
156 | carrier provides a fpga_base pointer, the driver may use direct | ||
157 | access through that pointer. For this reason the header offers the | ||
158 | inline functions fmc_readl and fmc_writel that access fpga_base if | ||
159 | the respective method is NULL. A driver that wants to be portable | ||
160 | and efficient should use fmc_readl and fmc_writel. For Etherbone, | ||
161 | or other non-local carriers, error-management is still to be | ||
162 | defined. | ||
163 | |||
164 | `validate' | ||
165 | Module parameters are used to manage different applications for | ||
166 | two or more boards of the same kind. Validation is based on the | ||
167 | busid module parameter, if provided, and returns the matching | ||
168 | index in the associated array. See *note Module Parameters:: in in | ||
169 | doubt. If no match is found, `-ENOENT' is returned; if the user | ||
170 | didn't pass `busid=', all devices will pass validation. The value | ||
171 | returned by the validate method can be used as index into other | ||
172 | parameters (for example, some drivers use the `lm32=' parameter in | ||
173 | this way). Such "generic parameters" are documented in *note | ||
174 | Module Parameters::, below. The validate method is used by | ||
175 | `fmc-trivial.ko', described in *note fmc-trivial::. | ||
176 | |||
177 | `reprogram' | ||
178 | The carrier enumerates FMC devices by loading a standard (or | ||
179 | golden) FPGA binary that allows EEPROM access. Each driver, then, | ||
180 | will need to reprogram the FPGA by calling this function. If the | ||
181 | name argument is NULL, the carrier should reprogram the golden | ||
182 | binary. If the gateware name has been overridden through module | ||
183 | parameters (in a carrier-specific way) the file loaded will match | ||
184 | the parameters. Per-device gateware names can be specified using | ||
185 | the `gateware=' parameter, see *note Module Parameters::. Note: | ||
186 | Clients should call rhe new helper, fmc_reprogram, which both | ||
187 | calls this method and parse the SDB tree of the FPGA. | ||
188 | |||
189 | `irq_request' | ||
190 | `irq_ack' | ||
191 | `irq_free' | ||
192 | Interrupt management is carrier-specific, so it is abstracted as | ||
193 | operations. The interrupt number is listed in the device | ||
194 | structure, and for the mezzanine driver the number is only | ||
195 | informative. The handler will receive the fmc pointer as dev_id; | ||
196 | the flags argument is passed to the Linux request_irq function, | ||
197 | but fmc-specific flags may be added in the future. You'll most | ||
198 | likely want to pass the `IRQF_SHARED' flag. | ||
199 | |||
200 | `gpio_config' | ||
201 | The method allows to configure a GPIO pin in the carrier, and read | ||
202 | its current value if it is configured as input. See *note The GPIO | ||
203 | Abstraction:: for details. | ||
204 | |||
205 | `read_ee' | ||
206 | `write_ee' | ||
207 | Read or write the EEPROM. The functions are expected to be only | ||
208 | called before reprogramming and the carrier should refuse them | ||
209 | with `ENODEV' after reprogramming. The offset is expected to be | ||
210 | within 8kB (the current size), but addresses up to 1MB are | ||
211 | reserved to fit bigger I2C devices in the future. Carriers may | ||
212 | offer access to other internal flash memories using these same | ||
213 | methods: for example the SPEC driver may define that its carrier | ||
214 | I2C memory is seen at offset 1M and the internal SPI flash is seen | ||
215 | at offset 16M. This multiplexing of several flash memories in the | ||
216 | same address space is is carrier-specific and should only be used | ||
217 | by a driver that has verified the `carrier_name' field. | ||
218 | |||
219 | |||
220 | |||
221 | The GPIO Abstraction | ||
222 | ==================== | ||
223 | |||
224 | Support for GPIO pins in the fmc-bus environment is not very | ||
225 | straightforward and deserves special discussion. | ||
226 | |||
227 | While the general idea of a carrier-independent driver seems to fly, | ||
228 | configuration of specific signals within the carrier needs at least | ||
229 | some knowledge of the carrier itself. For this reason, the specific | ||
230 | driver can request to configure carrier-specific GPIO pins, numbered | ||
231 | from 0 to at most 4095. Configuration is performed by passing a | ||
232 | pointer to an array of struct fmc_gpio items, as well as the length of | ||
233 | the array. This is the data structure: | ||
234 | |||
235 | struct fmc_gpio { | ||
236 | char *carrier_name; | ||
237 | int gpio; | ||
238 | int _gpio; /* internal use by the carrier */ | ||
239 | int mode; /* GPIOF_DIR_OUT etc, from <linux/gpio.h> */ | ||
240 | int irqmode; /* IRQF_TRIGGER_LOW and so on */ | ||
241 | }; | ||
242 | |||
243 | By specifying a carrier_name for each pin, the driver may access | ||
244 | different pins in different carriers. The gpio_config method is | ||
245 | expected to return the number of pins successfully configured, ignoring | ||
246 | requests for other carriers. However, if no pin is configured (because | ||
247 | no structure at all refers to the current carrier_name), the operation | ||
248 | returns an error so the caller will know that it is running under a | ||
249 | yet-unsupported carrier. | ||
250 | |||
251 | So, for example, a driver that has been developed and tested on both | ||
252 | the SPEC and the SVEC may request configuration of two different GPIO | ||
253 | pins, and expect one such configuration to succeed - if none succeeds | ||
254 | it most likely means that the current carrier is a still-unknown one. | ||
255 | |||
256 | If, however, your GPIO pin has a specific known role, you can pass a | ||
257 | special number in the gpio field, using one of the following macros: | ||
258 | |||
259 | #define FMC_GPIO_RAW(x) (x) /* 4096 of them */ | ||
260 | #define FMC_GPIO_IRQ(x) ((x) + 0x1000) /* 256 of them */ | ||
261 | #define FMC_GPIO_LED(x) ((x) + 0x1100) /* 256 of them */ | ||
262 | #define FMC_GPIO_KEY(x) ((x) + 0x1200) /* 256 of them */ | ||
263 | #define FMC_GPIO_TP(x) ((x) + 0x1300) /* 256 of them */ | ||
264 | #define FMC_GPIO_USER(x) ((x) + 0x1400) /* 256 of them */ | ||
265 | |||
266 | Use of virtual GPIO numbers (anything but FMC_GPIO_RAW) is allowed | ||
267 | provided the carrier_name field in the data structure is left | ||
268 | unspecified (NULL). Each carrier is responsible for providing a mapping | ||
269 | between virtual and physical GPIO numbers. The carrier may then use the | ||
270 | _gpio field to cache the result of this mapping. | ||
271 | |||
272 | All carriers must map their I/O lines to the sets above starting from | ||
273 | zero. The SPEC, for example, maps interrupt pins 0 and 1, and test | ||
274 | points 0 through 3 (even if the test points on the PCB are called | ||
275 | 5,6,7,8). | ||
276 | |||
277 | If, for example, a driver requires a free LED and a test point (for a | ||
278 | scope probe to be plugged at some point during development) it may ask | ||
279 | for FMC_GPIO_LED(0) and FMC_GPIO_TP(0). Each carrier will provide | ||
280 | suitable GPIO pins. Clearly, the person running the drivers will know | ||
281 | the order used by the specific carrier driver in assigning leds and | ||
282 | testpoints, so to make a carrier-dependent use of the diagnostic tools. | ||
283 | |||
284 | In theory, some form of autodetection should be possible: a driver like | ||
285 | the wr-nic (which uses IRQ(1) on the SPEC card) should configure | ||
286 | IRQ(0), make a test with software-generated interrupts and configure | ||
287 | IRQ(1) if the test fails. This probing step should be used because even | ||
288 | if the wr-nic gateware is known to use IRQ1 on the SPEC, the driver | ||
289 | should be carrier-independent and thus use IRQ(0) as a first bet - | ||
290 | actually, the knowledge that IRQ0 may fail is carrier-dependent | ||
291 | information, but using it doesn't make the driver unsuitable for other | ||
292 | carriers. | ||
293 | |||
294 | The return value of gpio_config is defined as follows: | ||
295 | |||
296 | * If no pin in the array can be used by the carrier, `-ENODEV'. | ||
297 | |||
298 | * If at least one virtual GPIO number cannot be mapped, `-ENOENT'. | ||
299 | |||
300 | * On success, 0 or positive. The value returned is the number of | ||
301 | high input bits (if no input is configured, the value for success | ||
302 | is 0). | ||
303 | |||
304 | While I admit the procedure is not completely straightforward, it | ||
305 | allows configuration, input and output with a single carrier operation. | ||
306 | Given the typical use case of FMC devices, GPIO operations are not | ||
307 | expected to ever by in hot paths, and GPIO access so fare has only been | ||
308 | used to configure the interrupt pin, mode and polarity. Especially | ||
309 | reading inputs is not expected to be common. If your device has GPIO | ||
310 | capabilities in the hot path, you should consider using the kernel's | ||
311 | GPIO mechanisms. | ||
diff --git a/Documentation/fmc/fmc-chardev.txt b/Documentation/fmc/fmc-chardev.txt new file mode 100644 index 000000000000..d9ccb278e597 --- /dev/null +++ b/Documentation/fmc/fmc-chardev.txt | |||
@@ -0,0 +1,64 @@ | |||
1 | fmc-chardev | ||
2 | =========== | ||
3 | |||
4 | This is a simple generic driver, that allows user access by means of a | ||
5 | character device (actually, one for each mezzanine it takes hold of). | ||
6 | |||
7 | The char device is created as a misc device. Its name in /dev (as | ||
8 | created by udev) is the same name as the underlying FMC device. Thus, | ||
9 | the name can be a silly fmc-0000 look-alike if the device has no | ||
10 | identifiers nor bus_id, a more specific fmc-0400 if the device has a | ||
11 | bus-specific address but no associated name, or something like | ||
12 | fdelay-0400 if the FMC core can rely on both a mezzanine name and a bus | ||
13 | address. | ||
14 | |||
15 | Currently the driver only supports read and write: you can lseek to the | ||
16 | desired address and read or write a register. | ||
17 | |||
18 | The driver assumes all registers are 32-bit in size, and only accepts a | ||
19 | single read or write per system call. However, as a result of Unix read | ||
20 | and write semantics, users can simply fread or fwrite bigger areas in | ||
21 | order to dump or store bigger memory areas. | ||
22 | |||
23 | There is currently no support for mmap, user-space interrupt management | ||
24 | and DMA buffers. They may be added in later versions, if the need | ||
25 | arises. | ||
26 | |||
27 | The example below shows raw access to a SPEC card programmed with its | ||
28 | golden FPGA file, that features an SDB structure at offset 256 - i.e. | ||
29 | 64 words. The mezzanine's EEPROM in this case is not programmed, so the | ||
30 | default name is fmc-<bus><devfn>, and there are two cards in the system: | ||
31 | |||
32 | spusa.root# insmod fmc-chardev.ko | ||
33 | [ 1073.339332] spec 0000:02:00.0: Driver has no ID: matches all | ||
34 | [ 1073.345051] spec 0000:02:00.0: Created misc device "fmc-0200" | ||
35 | [ 1073.350821] spec 0000:04:00.0: Driver has no ID: matches all | ||
36 | [ 1073.356525] spec 0000:04:00.0: Created misc device "fmc-0400" | ||
37 | spusa.root# ls -l /dev/fmc* | ||
38 | crw------- 1 root root 10, 58 Nov 20 19:23 /dev/fmc-0200 | ||
39 | crw------- 1 root root 10, 57 Nov 20 19:23 /dev/fmc-0400 | ||
40 | spusa.root# dd bs=4 skip=64 count=1 if=/dev/fmc-0200 2> /dev/null | od -t x1z | ||
41 | 0000000 2d 42 44 53 >-BDS< | ||
42 | 0000004 | ||
43 | |||
44 | The simple program tools/fmc-mem in this package can access an FMC char | ||
45 | device and read or write a word or a whole area. Actually, the program | ||
46 | is not specific to FMC at all, it just uses lseek, read and write. | ||
47 | |||
48 | Its first argument is the device name, the second the offset, the third | ||
49 | (if any) the value to write and the optional last argument that must | ||
50 | begin with "+" is the number of bytes to read or write. In case of | ||
51 | repeated reading data is written to stdout; repeated writes read from | ||
52 | stdin and the value argument is ignored. | ||
53 | |||
54 | The following examples show reading the SDB magic number and the first | ||
55 | SDB record from a SPEC device programmed with its golden image: | ||
56 | |||
57 | spusa.root# ./fmc-mem /dev/fmc-0200 100 | ||
58 | 5344422d | ||
59 | spusa.root# ./fmc-mem /dev/fmc-0200 100 +40 | od -Ax -t x1z | ||
60 | 000000 2d 42 44 53 00 01 02 00 00 00 00 00 00 00 00 00 >-BDS............< | ||
61 | 000010 00 00 00 00 ff 01 00 00 00 00 00 00 51 06 00 00 >............Q...< | ||
62 | 000020 c9 42 a5 e6 02 00 00 00 11 05 12 20 2d 34 42 57 >.B......... -4BW< | ||
63 | 000030 73 6f 72 43 72 61 62 73 49 53 47 2d 00 20 20 20 >sorCrabsISG-. < | ||
64 | 000040 | ||
diff --git a/Documentation/fmc/fmc-fakedev.txt b/Documentation/fmc/fmc-fakedev.txt new file mode 100644 index 000000000000..e85b74a4ae30 --- /dev/null +++ b/Documentation/fmc/fmc-fakedev.txt | |||
@@ -0,0 +1,36 @@ | |||
1 | fmc-fakedev | ||
2 | =========== | ||
3 | |||
4 | This package includes a software-only device, called fmc-fakedev, which | ||
5 | is able to register up to 4 mezzanines (by default it registers one). | ||
6 | Unlike the SPEC driver, which creates an FMC device for each PCI cards | ||
7 | it manages, this module creates a single instance of its set of | ||
8 | mezzanines. | ||
9 | |||
10 | It is meant as the simplest possible example of how a driver should be | ||
11 | written, and it includes a fake EEPROM image (built using the tools | ||
12 | described in *note FMC Identification::),, which by default is | ||
13 | replicated for each fake mezzanine. | ||
14 | |||
15 | You can also use this device to verify the match algorithms, by asking | ||
16 | it to test your own EEPROM image. You can provide the image by means of | ||
17 | the eeprom= module parameter: the new EEPROM image is loaded, as usual, | ||
18 | by means of the firmware loader. This example shows the defaults and a | ||
19 | custom EEPROM image: | ||
20 | |||
21 | spusa.root# insmod fmc-fakedev.ko | ||
22 | [ 99.971247] fake-fmc-carrier: mezzanine 0 | ||
23 | [ 99.975393] Manufacturer: fake-vendor | ||
24 | [ 99.979624] Product name: fake-design-for-testing | ||
25 | spusa.root# rmmod fmc-fakedev | ||
26 | spusa.root# insmod fmc-fakedev.ko eeprom=fdelay-eeprom.bin | ||
27 | [ 121.447464] fake-fmc-carrier: Mezzanine 0: eeprom "fdelay-eeprom.bin" | ||
28 | [ 121.462725] fake-fmc-carrier: mezzanine 0 | ||
29 | [ 121.466858] Manufacturer: CERN | ||
30 | [ 121.470477] Product name: FmcDelay1ns4cha | ||
31 | spusa.root# rmmod fmc-fakedev | ||
32 | |||
33 | After loading the device, you can use the write_ee method do modify its | ||
34 | own internal fake EEPROM: whenever the image is overwritten starting at | ||
35 | offset 0, the module will unregister and register again the FMC device. | ||
36 | This is shown in fmc-write-eeprom.txt | ||
diff --git a/Documentation/fmc/fmc-trivial.txt b/Documentation/fmc/fmc-trivial.txt new file mode 100644 index 000000000000..d1910bc67159 --- /dev/null +++ b/Documentation/fmc/fmc-trivial.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | fmc-trivial | ||
2 | =========== | ||
3 | |||
4 | The simple module fmc-trivial is just a simple client that registers an | ||
5 | interrupt handler. I used it to verify the basic mechanism of the FMC | ||
6 | bus and how interrupts worked. | ||
7 | |||
8 | The module implements the generic FMC parameters, so it can program a | ||
9 | different gateware file in each card. The whole list of parameters it | ||
10 | accepts are: | ||
11 | |||
12 | `busid=' | ||
13 | `gateware=' | ||
14 | Generic parameters. See mezzanine.txt | ||
15 | |||
16 | |||
17 | This driver is worth reading, in my opinion. | ||
diff --git a/Documentation/fmc/fmc-write-eeprom.txt b/Documentation/fmc/fmc-write-eeprom.txt new file mode 100644 index 000000000000..44a3bc678bf0 --- /dev/null +++ b/Documentation/fmc/fmc-write-eeprom.txt | |||
@@ -0,0 +1,125 @@ | |||
1 | fmc-write-eeprom | ||
2 | ================ | ||
3 | |||
4 | This module is designed to load a binary file from /lib/firmware and to | ||
5 | write it to the internal EEPROM of the mezzanine card. This driver uses | ||
6 | the `busid' generic parameter. | ||
7 | |||
8 | Overwriting the EEPROM is not something you should do daily, and it is | ||
9 | expected to only happen during manufacturing. For this reason, the | ||
10 | module makes it unlikely for the random user to change a working EEPROM. | ||
11 | |||
12 | The module takes the following measures: | ||
13 | |||
14 | * It accepts a `file=' argument (within /lib/firmware) and if no | ||
15 | such argument is received, it doesn't write anything to EEPROM | ||
16 | (i.e. there is no default file name). | ||
17 | |||
18 | * If the file name ends with `.bin' it is written verbatim starting | ||
19 | at offset 0. | ||
20 | |||
21 | * If the file name ends with `.tlv' it is interpreted as | ||
22 | type-length-value (i.e., it allows writev(2)-like operation). | ||
23 | |||
24 | * If the file name doesn't match any of the patterns above, it is | ||
25 | ignored and no write is performed. | ||
26 | |||
27 | * Only cards listed with `busid=' are written to. If no busid is | ||
28 | specified, no programming is done (and the probe function of the | ||
29 | driver will fail). | ||
30 | |||
31 | |||
32 | Each TLV tuple is formatted in this way: the header is 5 bytes, | ||
33 | followed by data. The first byte is `w' for write, the next two bytes | ||
34 | represent the address, in little-endian byte order, and the next two | ||
35 | represent the data length, in little-endian order. The length does not | ||
36 | include the header (it is the actual number of bytes to be written). | ||
37 | |||
38 | This is a real example: that writes 5 bytes at position 0x110: | ||
39 | |||
40 | spusa.root# od -t x1 -Ax /lib/firmware/try.tlv | ||
41 | 000000 77 10 01 05 00 30 31 32 33 34 | ||
42 | 00000a | ||
43 | spusa.root# insmod /tmp/fmc-write-eeprom.ko busid=0x0200 file=try.tlv | ||
44 | [19983.391498] spec 0000:03:00.0: write 5 bytes at 0x0110 | ||
45 | [19983.414615] spec 0000:03:00.0: write_eeprom: success | ||
46 | |||
47 | Please note that you'll most likely want to use SDBFS to build your | ||
48 | EEPROM image, at least if your mezzanines are being used in the White | ||
49 | Rabbit environment. For this reason the TLV format is not expected to | ||
50 | be used much and is not expected to be developed further. | ||
51 | |||
52 | If you want to try reflashing fake EEPROM devices, you can use the | ||
53 | fmc-fakedev.ko module (see *note fmc-fakedev::). Whenever you change | ||
54 | the image starting at offset 0, it will deregister and register again | ||
55 | after two seconds. Please note, however, that if fmc-write-eeprom is | ||
56 | still loaded, the system will associate it to the new device, which | ||
57 | will be reprogrammed and thus will be unloaded after two seconds. The | ||
58 | following example removes the module after it reflashed fakedev the | ||
59 | first time. | ||
60 | |||
61 | spusa.root# insmod fmc-fakedev.ko | ||
62 | [ 72.984733] fake-fmc: Manufacturer: fake-vendor | ||
63 | [ 72.989434] fake-fmc: Product name: fake-design-for-testing | ||
64 | spusa.root# insmod fmc-write-eeprom.ko busid=0 file=fdelay-eeprom.bin; \ | ||
65 | rmmod fmc-write-eeprom | ||
66 | [ 130.874098] fake-fmc: Matching a generic driver (no ID) | ||
67 | [ 130.887845] fake-fmc: programming 6155 bytes | ||
68 | [ 130.894567] fake-fmc: write_eeprom: success | ||
69 | [ 132.895794] fake-fmc: Manufacturer: CERN | ||
70 | [ 132.899872] fake-fmc: Product name: FmcDelay1ns4cha | ||
71 | |||
72 | |||
73 | Writing to the EEPROM | ||
74 | ===================== | ||
75 | |||
76 | Once you have created a binary file for your EEPROM, you can write it | ||
77 | to the storage medium using the fmc-write-eeprom (See *note | ||
78 | fmc-write-eeprom::, while relying on a carrier driver. The procedure | ||
79 | here shown here uses the SPEC driver | ||
80 | (`http://www.ohwr.org/projects/spec-sw'). | ||
81 | |||
82 | The example assumes no driver is already loaded (actually, I unloaded | ||
83 | them by hand as everything loads automatically at boot time after you | ||
84 | installed the modules), and shows kernel messages together with | ||
85 | commands. Here the prompt is spusa.root# and two SPEC cards are plugged | ||
86 | in the system. | ||
87 | |||
88 | spusa.root# insmod fmc.ko | ||
89 | spusa.root# insmod spec.ko | ||
90 | [13972.382818] spec 0000:02:00.0: probe for device 0002:0000 | ||
91 | [13972.392773] spec 0000:02:00.0: got file "fmc/spec-init.bin", 1484404 (0x16a674) bytes | ||
92 | [13972.591388] spec 0000:02:00.0: FPGA programming successful | ||
93 | [13972.883011] spec 0000:02:00.0: EEPROM has no FRU information | ||
94 | [13972.888719] spec 0000:02:00.0: No device_id filled, using index | ||
95 | [13972.894676] spec 0000:02:00.0: No mezzanine_name found | ||
96 | [13972.899863] /home/rubini/wip/spec-sw/kernel/spec-gpio.c - spec_gpio_init | ||
97 | [13972.906578] spec 0000:04:00.0: probe for device 0004:0000 | ||
98 | [13972.916509] spec 0000:04:00.0: got file "fmc/spec-init.bin", 1484404 (0x16a674) bytes | ||
99 | [13973.115096] spec 0000:04:00.0: FPGA programming successful | ||
100 | [13973.401798] spec 0000:04:00.0: EEPROM has no FRU information | ||
101 | [13973.407474] spec 0000:04:00.0: No device_id filled, using index | ||
102 | [13973.413417] spec 0000:04:00.0: No mezzanine_name found | ||
103 | [13973.418600] /home/rubini/wip/spec-sw/kernel/spec-gpio.c - spec_gpio_init | ||
104 | spusa.root# ls /sys/bus/fmc/devices | ||
105 | fmc-0000 fmc-0001 | ||
106 | spusa.root# insmod fmc-write-eeprom.ko busid=0x0200 file=fdelay-eeprom.bin | ||
107 | [14103.966259] spec 0000:02:00.0: Matching an generic driver (no ID) | ||
108 | [14103.975519] spec 0000:02:00.0: programming 6155 bytes | ||
109 | [14126.373762] spec 0000:02:00.0: write_eeprom: success | ||
110 | [14126.378770] spec 0000:04:00.0: Matching an generic driver (no ID) | ||
111 | [14126.384903] spec 0000:04:00.0: fmc_write_eeprom: no filename given: not programming | ||
112 | [14126.392600] fmc_write_eeprom: probe of fmc-0001 failed with error -2 | ||
113 | |||
114 | Reading back the EEPROM | ||
115 | ======================= | ||
116 | |||
117 | In order to read back the binary content of the EEPROM of your | ||
118 | mezzanine device, the bus creates a read-only sysfs file called eeprom | ||
119 | for each mezzanine it knows about: | ||
120 | |||
121 | spusa.root# cd /sys/bus/fmc/devices; ls -l */eeprom | ||
122 | -r--r--r-- 1 root root 8192 Apr 9 16:53 FmcDelay1ns4cha-f001/eeprom | ||
123 | -r--r--r-- 1 root root 8192 Apr 9 17:19 fake-design-for-testing-f002/eeprom | ||
124 | -r--r--r-- 1 root root 8192 Apr 9 17:19 fake-design-for-testing-f003/eeprom | ||
125 | -r--r--r-- 1 root root 8192 Apr 9 17:19 fmc-f004/eeprom | ||
diff --git a/Documentation/fmc/identifiers.txt b/Documentation/fmc/identifiers.txt new file mode 100644 index 000000000000..3bb577ff0d52 --- /dev/null +++ b/Documentation/fmc/identifiers.txt | |||
@@ -0,0 +1,168 @@ | |||
1 | FMC Identification | ||
2 | ****************** | ||
3 | |||
4 | The FMC standard requires every compliant mezzanine to carry | ||
5 | identification information in an I2C EEPROM. The information must be | ||
6 | laid out according to the "IPMI Platform Management FRU Information", | ||
7 | where IPMI is a lie I'd better not expand, and FRU means "Field | ||
8 | Replaceable Unit". | ||
9 | |||
10 | The FRU information is an intricate unreadable binary blob that must | ||
11 | live at offset 0 of the EEPROM, and typically extends for a few hundred | ||
12 | bytes. The standard allows the application to use all the remaining | ||
13 | storage area of the EEPROM as it wants. | ||
14 | |||
15 | This chapter explains how to create your own EEPROM image and how to | ||
16 | write it in your mezzanine, as well as how devices and drivers are | ||
17 | paired at run time. EEPROM programming uses tools that are part of this | ||
18 | package and SDB (part of the fpga-config-space package). | ||
19 | |||
20 | The first sections are only interesting for manufacturers who need to | ||
21 | write the EEPROM. If you are just a software developer writing an FMC | ||
22 | device or driver, you may jump straight to *note SDB Support::. | ||
23 | |||
24 | |||
25 | Building the FRU Structure | ||
26 | ========================== | ||
27 | |||
28 | If you want to know the internals of the FRU structure and despair, you | ||
29 | can retrieve the document from | ||
30 | `http://download.intel.com/design/servers/ipmi/FRU1011.pdf' . The | ||
31 | standard is awful and difficult without reason, so we only support the | ||
32 | minimum mandatory subset - we create a simple structure and parse it | ||
33 | back at run time, but we are not able to either generate or parse more | ||
34 | arcane features like non-english languages and 6-bit text. If you need | ||
35 | more items of the FRU standard for your boards, please submit patches. | ||
36 | |||
37 | This package includes the Python script that Matthieu Cattin wrote to | ||
38 | generate the FRU binary blob, based on an helper libipmi by Manohar | ||
39 | Vanga and Matthieu himself. I changed the test script to receive | ||
40 | parameters from the command line or from the environment (the command | ||
41 | line takes precedence) | ||
42 | |||
43 | To make a long story short, in order to build a standard-compliant | ||
44 | binary file to be burned in your EEPROM, you need the following items: | ||
45 | |||
46 | Environment Opt Official Name Default | ||
47 | --------------------------------------------------------------------- | ||
48 | FRU_VENDOR -v "Board Manufacturer" fmc-example | ||
49 | FRU_NAME -n "Board Product Name" mezzanine | ||
50 | FRU_SERIAL -s `Board Serial Number" 0001 | ||
51 | FRU_PART -p "Board Part Number" sample-part | ||
52 | FRU_OUTPUT -o not applicable /dev/stdout | ||
53 | |||
54 | The "Official Name" above is what you find in the FRU official | ||
55 | documentation, chapter 11, page 7 ("Board Info Area Format"). The | ||
56 | output option is used to save the generated binary to a specific file | ||
57 | name instead of stdout. | ||
58 | |||
59 | You can pass the items to the FRU generator either in the environment | ||
60 | or on the command line. This package has currently no support for | ||
61 | specifying power consumption or such stuff, but I plan to add it as | ||
62 | soon as I find some time for that. | ||
63 | |||
64 | FIXME: consumption etc for FRU are here or in PTS? | ||
65 | |||
66 | The following example creates a binary image for a specific board: | ||
67 | |||
68 | ./tools/fru-generator -v CERN -n FmcAdc100m14b4cha \ | ||
69 | -s HCCFFIA___-CR000003 -p EDA-02063-V5-0 > eeprom.bin | ||
70 | |||
71 | The following example shows a script that builds several binary EEPROM | ||
72 | images for a series of boards, changing the serial number for each of | ||
73 | them. The script uses a mix of environment variables and command line | ||
74 | options, and uses the same string patterns shown above. | ||
75 | |||
76 | #!/bin/sh | ||
77 | |||
78 | export FRU_VENDOR="CERN" | ||
79 | export FRU_NAME="FmcAdc100m14b4cha" | ||
80 | export FRU_PART="EDA-02063-V5-0" | ||
81 | |||
82 | serial="HCCFFIA___-CR" | ||
83 | |||
84 | for number in $(seq 1 50); do | ||
85 | # build number-string "ns" | ||
86 | ns="$(printf %06d $number)" | ||
87 | ./fru-generator -s "${serial}${ns}" > eeprom-${ns}.bin | ||
88 | done | ||
89 | |||
90 | |||
91 | Using SDB-FS in the EEPROM | ||
92 | ========================== | ||
93 | |||
94 | If you want to use SDB as a filesystem in the EEPROM device within the | ||
95 | mezzanine, you should create one such filesystem using gensdbfs, from | ||
96 | the fpga-config-space package on OHWR. | ||
97 | |||
98 | By using an SBD filesystem you can cluster several files in a single | ||
99 | EEPROM, so both the host system and a soft-core running in the FPGA (if | ||
100 | any) can access extra production-time information. | ||
101 | |||
102 | We chose to use SDB as a storage filesystem because the format is very | ||
103 | simple, and both the host system and the soft-core will likely already | ||
104 | include support code for such format. The SDB library offered by the | ||
105 | fpga-config-space is less than 1kB under LM32, so it proves quite up to | ||
106 | the task. | ||
107 | |||
108 | The SDB entry point (which acts as a directory listing) cannot live at | ||
109 | offset zero in the flash device, because the FRU information must live | ||
110 | there. To avoid wasting precious storage space while still allowing | ||
111 | for more-than-minimal FRU structures, the fmc.ko will look for the SDB | ||
112 | record at address 256, 512 and 1024. | ||
113 | |||
114 | In order to generate the complete EEPROM image you'll need a | ||
115 | configuration file for gensdbfs: you tell the program where to place | ||
116 | the sdb entry point, and you must force the FRU data file to be placed | ||
117 | at the beginning of the storage device. If needed, you can also place | ||
118 | other files at a special offset (we sometimes do it for backward | ||
119 | compatibility with drivers we wrote before implementing SDB for flash | ||
120 | memory). | ||
121 | |||
122 | The directory tools/sdbfs of this package includes a well-commented | ||
123 | example that you may want to use as a starting point (the comments are | ||
124 | in the file called -SDB-CONFIG-). Reading documentation for gensdbfs | ||
125 | is a suggested first step anyways. | ||
126 | |||
127 | This package (generic FMC bus support) only accesses two files in the | ||
128 | EEPROM: the FRU information, at offset zero, with a suggested filename | ||
129 | of IPMI-FRU and the short name for the mezzanine, in a file called | ||
130 | name. The IPMI-FRU name is not mandatory, but a strongly suggested | ||
131 | choice; the name filename is mandatory, because this is the preferred | ||
132 | short name used by the FMC core. For example, a name of "fdelay" may | ||
133 | supplement a Product Name like "FmcDelay1ns4cha" - exactly as | ||
134 | demonstrated in `tools/sdbfs'. | ||
135 | |||
136 | Note: SDB access to flash memory is not yet supported, so the short | ||
137 | name currently in use is just the "Product Name" FRU string. | ||
138 | |||
139 | The example in tools/sdbfs includes an extra file, that is needed by | ||
140 | the fine-delay driver, and must live at a known address of 0x1800. By | ||
141 | running gensdbfs on that directory you can output your binary EEPROM | ||
142 | image (here below spusa$ is the shell prompt): | ||
143 | |||
144 | spusa$ ../fru-generator -v CERN -n FmcDelay1ns4cha -s proto-0 \ | ||
145 | -p EDA-02267-V3 > IPMI-FRU | ||
146 | spusa$ ls -l | ||
147 | total 16 | ||
148 | -rw-rw-r-- 1 rubini staff 975 Nov 19 18:08 --SDB-CONFIG-- | ||
149 | -rw-rw-r-- 1 rubini staff 216 Nov 19 18:13 IPMI-FRU | ||
150 | -rw-rw-r-- 1 rubini staff 11 Nov 19 18:04 fd-calib | ||
151 | -rw-rw-r-- 1 rubini staff 7 Nov 19 18:04 name | ||
152 | spusa$ sudo gensdbfs . /lib/firmware/fdelay-eeprom.bin | ||
153 | spusa$ sdb-read -l -e 0x100 /lib/firmware/fdelay-eeprom.bin | ||
154 | /home/rubini/wip/sdbfs/userspace/sdb-read: listing format is to be defined | ||
155 | 46696c6544617461:2e202020 00000100-000018ff . | ||
156 | 46696c6544617461:6e616d65 00000200-00000206 name | ||
157 | 46696c6544617461:66642d63 00001800-000018ff fd-calib | ||
158 | 46696c6544617461:49504d49 00000000-000000d7 IPMI-FRU | ||
159 | spusa$ ../fru-dump /lib/firmware/fdelay-eeprom.bin | ||
160 | /lib/firmware/fdelay-eeprom.bin: manufacturer: CERN | ||
161 | /lib/firmware/fdelay-eeprom.bin: product-name: FmcDelay1ns4cha | ||
162 | /lib/firmware/fdelay-eeprom.bin: serial-number: proto-0 | ||
163 | /lib/firmware/fdelay-eeprom.bin: part-number: EDA-02267-V3 | ||
164 | |||
165 | As expected, the output file is both a proper sdbfs object and an IPMI | ||
166 | FRU information blob. The fd-calib file lives at offset 0x1800 and is | ||
167 | over-allocated to 256 bytes, according to the configuration file for | ||
168 | gensdbfs. | ||
diff --git a/Documentation/fmc/mezzanine.txt b/Documentation/fmc/mezzanine.txt new file mode 100644 index 000000000000..87910dbfc91e --- /dev/null +++ b/Documentation/fmc/mezzanine.txt | |||
@@ -0,0 +1,123 @@ | |||
1 | FMC Driver | ||
2 | ********** | ||
3 | |||
4 | An FMC driver is concerned with the specific mezzanine and associated | ||
5 | gateware. As such, it is expected to be independent of the carrier | ||
6 | being used: it will perform I/O accesses only by means of | ||
7 | carrier-provided functions. | ||
8 | |||
9 | The matching between device and driver is based on the content of the | ||
10 | EEPROM (as mandated by the FMC standard) or by the actual cores | ||
11 | configured in the FPGA; the latter technique is used when the FPGA is | ||
12 | already programmed when the device is registered to the bus core. | ||
13 | |||
14 | In some special cases it is possible for a driver to directly access | ||
15 | FPGA registers, by means of the `fpga_base' field of the device | ||
16 | structure. This may be needed for high-bandwidth peripherals like fast | ||
17 | ADC cards. If the device module registered a remote device (for example | ||
18 | by means of Etherbone), the `fpga_base' pointer will be NULL. | ||
19 | Therefore, drivers must be ready to deal with NULL base pointers, and | ||
20 | fail gracefully. Most driver, however, are not expected to access the | ||
21 | pointer directly but run fmc_readl and fmc_writel instead, which will | ||
22 | work in any case. | ||
23 | |||
24 | In even more special cases, the driver may access carrier-specific | ||
25 | functionality: the `carrier_name' string allows the driver to check | ||
26 | which is the current carrier and make use of the `carrier_data' | ||
27 | pointer. We chose to use carrier names rather than numeric identifiers | ||
28 | for greater flexibility, but also to avoid a central registry within | ||
29 | the `fmc.h' file - we hope other users will exploit our framework with | ||
30 | their own carriers. An example use of carrier names is in GPIO setup | ||
31 | (see *note The GPIO Abstraction::), although the name match is not | ||
32 | expected to be performed by the driver. If you depend on specific | ||
33 | carriers, please check the carrier name and fail gracefully if your | ||
34 | driver finds it is running in a yet-unknown-to-it environment. | ||
35 | |||
36 | |||
37 | ID Table | ||
38 | ======== | ||
39 | |||
40 | Like most other Linux drivers, and FMC driver must list all the devices | ||
41 | which it is able to drive. This is usually done by means of a device | ||
42 | table, but in FMC we can match hardware based either on the contents of | ||
43 | their EEPROM or on the actual FPGA cores that can be enumerated. | ||
44 | Therefore, we have two tables of identifiers. | ||
45 | |||
46 | Matching of FRU information depends on two names, the manufacturer (or | ||
47 | vendor) and the device (see *note FMC Identification::); for | ||
48 | flexibility during production (i.e. before writing to the EEPROM) the | ||
49 | bus supports a catch-all driver that specifies NULL strings. For this | ||
50 | reason, the table is specified as pointer-and-length, not a a | ||
51 | null-terminated array - the entry with NULL names can be a valid entry. | ||
52 | |||
53 | Matching on FPGA cores depends on two numeric fields: the 64-bit vendor | ||
54 | number and the 32-bit device number. Support for matching based on | ||
55 | class is not yet implemented. Each device is expected to be uniquely | ||
56 | identified by an array of cores (it matches if all of the cores are | ||
57 | instantiated), and for consistency the list is passed as | ||
58 | pointer-and-length. Several similar devices can be driven by the same | ||
59 | driver, and thus the driver specifies and array of such arrays. | ||
60 | |||
61 | The complete set of involved data structures is thus the following: | ||
62 | |||
63 | struct fmc_fru_id { char *manufacturer; char *product_name; }; | ||
64 | struct fmc_sdb_one_id { uint64_t vendor; uint32_t device; }; | ||
65 | struct fmc_sdb_id { struct fmc_sdb_one_id *cores; int cores_nr; }; | ||
66 | |||
67 | struct fmc_device_id { | ||
68 | struct fmc_fru_id *fru_id; int fru_id_nr; | ||
69 | struct fmc_sdb_id *sdb_id; int sdb_id_nr; | ||
70 | }; | ||
71 | |||
72 | A better reference, with full explanation, is the <linux/fmc.h> header. | ||
73 | |||
74 | |||
75 | Module Parameters | ||
76 | ================= | ||
77 | |||
78 | Most of the FMC drivers need the same set of kernel parameters. This | ||
79 | package includes support to implement common parameters by means of | ||
80 | fields in the `fmc_driver' structure and simple macro definitions. | ||
81 | |||
82 | The parameters are carrier-specific, in that they rely on the busid | ||
83 | concept, that varies among carriers. For the SPEC, the identifier is a | ||
84 | PCI bus and devfn number, 16 bits wide in total; drivers for other | ||
85 | carriers will most likely offer something similar but not identical, | ||
86 | and some code duplication is unavoidable. | ||
87 | |||
88 | This is the list of parameters that are common to several modules to | ||
89 | see how they are actually used, please look at spec-trivial.c. | ||
90 | |||
91 | `busid=' | ||
92 | This is an array of integers, listing carrier-specific | ||
93 | identification numbers. For PIC, for example, `0x0400' represents | ||
94 | bus 4, slot 0. If any such ID is specified, the driver will only | ||
95 | accept to drive cards that appear in the list (even if the FMC ID | ||
96 | matches). This is accomplished by the validate carrier method. | ||
97 | |||
98 | `gateware=' | ||
99 | The argument is an array of strings. If no busid= is specified, | ||
100 | the first string of gateware= is used for all cards; otherwise the | ||
101 | identifiers and gateware names are paired one by one, in the order | ||
102 | specified. | ||
103 | |||
104 | `show_sdb=' | ||
105 | For modules supporting it, this parameter asks to show the SDB | ||
106 | internal structure by means of kernel messages. It is disabled by | ||
107 | default because those lines tend to hide more important messages, | ||
108 | if you look at the system console while loading the drivers. | ||
109 | Note: the parameter is being obsoleted, because fmc.ko itself now | ||
110 | supports dump_sdb= that applies to every client driver. | ||
111 | |||
112 | |||
113 | For example, if you are using the trivial driver to load two different | ||
114 | gateware files to two different cards, you can use the following | ||
115 | parameters to load different binaries to the cards, after looking up | ||
116 | the PCI identifiers. This has been tested with a SPEC carrier. | ||
117 | |||
118 | insmod fmc-trivial.ko \ | ||
119 | busid=0x0200,0x0400 \ | ||
120 | gateware=fmc/fine-delay.bin,fmc/simple-dio.bin | ||
121 | |||
122 | Please note that not all sub-modules support all of those parameters. | ||
123 | You can use modinfo to check what is supported by each module. | ||
diff --git a/Documentation/fmc/parameters.txt b/Documentation/fmc/parameters.txt new file mode 100644 index 000000000000..59edf088e3a4 --- /dev/null +++ b/Documentation/fmc/parameters.txt | |||
@@ -0,0 +1,56 @@ | |||
1 | Module Parameters in fmc.ko | ||
2 | *************************** | ||
3 | |||
4 | The core driver receives two module parameters, meant to help debugging | ||
5 | client modules. Both parameters can be modified by writing to | ||
6 | /sys/module/fmc/parameters/, because they are used when client drivers | ||
7 | are devices are registered, not when fmc.ko is loaded. | ||
8 | |||
9 | `dump_eeprom=' | ||
10 | If not zero, the parameter asks the bus controller to dump the | ||
11 | EEPROM of any device that is registered, using printk. | ||
12 | |||
13 | `dump_sdb=' | ||
14 | If not zero, the parameter prints the SDB tree of every FPGA it is | ||
15 | loaded by fmc_reprogram(). If greater than one, it asks to dump | ||
16 | the binary content of SDB records. This currently only dumps the | ||
17 | top-level SDB array, though. | ||
18 | |||
19 | |||
20 | EEPROM dumping avoids repeating lines, since most of the contents is | ||
21 | usually empty and all bits are one or zero. This is an example of the | ||
22 | output: | ||
23 | |||
24 | [ 6625.850480] spec 0000:02:00.0: FPGA programming successful | ||
25 | [ 6626.139949] spec 0000:02:00.0: Manufacturer: CERN | ||
26 | [ 6626.144666] spec 0000:02:00.0: Product name: FmcDelay1ns4cha | ||
27 | [ 6626.150370] FMC: mezzanine 0: 0000:02:00.0 on SPEC | ||
28 | [ 6626.155179] FMC: dumping eeprom 0x2000 (8192) bytes | ||
29 | [ 6626.160087] 0000: 01 00 00 01 00 0b 00 f3 01 0a 00 a5 85 87 c4 43 | ||
30 | [ 6626.167069] 0010: 45 52 4e cf 46 6d 63 44 65 6c 61 79 31 6e 73 34 | ||
31 | [ 6626.174019] 0020: 63 68 61 c7 70 72 6f 74 6f 2d 30 cc 45 44 41 2d | ||
32 | [ 6626.180975] 0030: 30 32 32 36 37 2d 56 33 da 32 30 31 32 2d 31 31 | ||
33 | [...] | ||
34 | [ 6626.371366] 0200: 66 64 65 6c 61 79 0a 00 00 00 00 00 00 00 00 00 | ||
35 | [ 6626.378359] 0210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ||
36 | [ 6626.385361] [...] | ||
37 | [ 6626.387308] 1800: 70 6c 61 63 65 68 6f 6c 64 65 72 ff ff ff ff ff | ||
38 | [ 6626.394259] 1810: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff | ||
39 | [ 6626.401250] [...] | ||
40 | |||
41 | The dump of SDB looks like the following; the example shows the simple | ||
42 | golden gateware for the SPEC card, removing the leading timestamps to | ||
43 | fit the page: | ||
44 | |||
45 | spec 0000:02:00.0: SDB: 00000651:e6a542c9 WB4-Crossbar-GSI | ||
46 | spec 0000:02:00.0: SDB: 0000ce42:ff07fc47 WR-Periph-Syscon (00000000-000000ff) | ||
47 | FMC: mezzanine 0: 0000:02:00.0 on SPEC | ||
48 | FMC: poor dump of sdb first level: | ||
49 | 0000: 53 44 42 2d 00 02 01 00 00 00 00 00 00 00 00 00 | ||
50 | 0010: 00 00 00 00 00 00 01 ff 00 00 00 00 00 00 06 51 | ||
51 | 0020: e6 a5 42 c9 00 00 00 02 20 12 05 11 57 42 34 2d | ||
52 | 0030: 43 72 6f 73 73 62 61 72 2d 47 53 49 20 20 20 00 | ||
53 | 0040: 00 00 01 01 00 00 00 07 00 00 00 00 00 00 00 00 | ||
54 | 0050: 00 00 00 00 00 00 00 ff 00 00 00 00 00 00 ce 42 | ||
55 | 0060: ff 07 fc 47 00 00 00 01 20 12 03 05 57 52 2d 50 | ||
56 | 0070: 65 72 69 70 68 2d 53 79 73 63 6f 6e 20 20 20 01 | ||
diff --git a/Documentation/w1/w1.generic b/Documentation/w1/w1.generic index 212f4ac31c01..a31c5a242973 100644 --- a/Documentation/w1/w1.generic +++ b/Documentation/w1/w1.generic | |||
@@ -25,8 +25,8 @@ When a w1 master driver registers with the w1 subsystem, the following occurs: | |||
25 | - sysfs entries for that w1 master are created | 25 | - sysfs entries for that w1 master are created |
26 | - the w1 bus is periodically searched for new slave devices | 26 | - the w1 bus is periodically searched for new slave devices |
27 | 27 | ||
28 | When a device is found on the bus, w1 core checks if driver for its family is | 28 | When a device is found on the bus, w1 core tries to load the driver for its family |
29 | loaded. If so, the family driver is attached to the slave. | 29 | and check if it is loaded. If so, the family driver is attached to the slave. |
30 | If there is no driver for the family, default one is assigned, which allows to perform | 30 | If there is no driver for the family, default one is assigned, which allows to perform |
31 | almost any kind of operations. Each logical operation is a transaction | 31 | almost any kind of operations. Each logical operation is a transaction |
32 | in nature, which can contain several (two or one) low-level operations. | 32 | in nature, which can contain several (two or one) low-level operations. |
diff --git a/MAINTAINERS b/MAINTAINERS index 4f43ddf7350a..7fab3298d745 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3309,6 +3309,15 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/floppy.git | |||
3309 | S: Odd fixes | 3309 | S: Odd fixes |
3310 | F: drivers/block/floppy.c | 3310 | F: drivers/block/floppy.c |
3311 | 3311 | ||
3312 | FMC SUBSYSTEM | ||
3313 | M: Alessandro Rubini <rubini@gnudd.com> | ||
3314 | W: http://www.ohwr.org/projects/fmc-bus | ||
3315 | S: Supported | ||
3316 | F: drivers/fmc/ | ||
3317 | F: include/linux/fmc*.h | ||
3318 | F: include/linux/ipmi-fru.h | ||
3319 | K: fmc_d.*register | ||
3320 | |||
3312 | FPU EMULATOR | 3321 | FPU EMULATOR |
3313 | M: Bill Metzenthen <billm@melbpc.org.au> | 3322 | M: Bill Metzenthen <billm@melbpc.org.au> |
3314 | W: http://floatingpoint.sourceforge.net/emulator/index.html | 3323 | W: http://floatingpoint.sourceforge.net/emulator/index.html |
@@ -7667,6 +7676,7 @@ STABLE BRANCH | |||
7667 | M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 7676 | M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
7668 | L: stable@vger.kernel.org | 7677 | L: stable@vger.kernel.org |
7669 | S: Supported | 7678 | S: Supported |
7679 | F: Documentation/stable_kernel_rules.txt | ||
7670 | 7680 | ||
7671 | STAGING SUBSYSTEM | 7681 | STAGING SUBSYSTEM |
7672 | M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 7682 | M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
diff --git a/drivers/Kconfig b/drivers/Kconfig index 9953a42809ec..ae050b54c368 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
@@ -166,4 +166,6 @@ source "drivers/ipack/Kconfig" | |||
166 | 166 | ||
167 | source "drivers/reset/Kconfig" | 167 | source "drivers/reset/Kconfig" |
168 | 168 | ||
169 | source "drivers/fmc/Kconfig" | ||
170 | |||
169 | endmenu | 171 | endmenu |
diff --git a/drivers/Makefile b/drivers/Makefile index 130abc1dfd65..336b0ad0acd0 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -152,3 +152,4 @@ obj-$(CONFIG_IIO) += iio/ | |||
152 | obj-$(CONFIG_VME_BUS) += vme/ | 152 | obj-$(CONFIG_VME_BUS) += vme/ |
153 | obj-$(CONFIG_IPACK_BUS) += ipack/ | 153 | obj-$(CONFIG_IPACK_BUS) += ipack/ |
154 | obj-$(CONFIG_NTB) += ntb/ | 154 | obj-$(CONFIG_NTB) += ntb/ |
155 | obj-$(CONFIG_FMC) += fmc/ | ||
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index d784650d14f0..448ce5e29c56 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
@@ -725,7 +725,7 @@ static int hpet_is_known(struct hpet_data *hdp) | |||
725 | return 0; | 725 | return 0; |
726 | } | 726 | } |
727 | 727 | ||
728 | static ctl_table hpet_table[] = { | 728 | static struct ctl_table hpet_table[] = { |
729 | { | 729 | { |
730 | .procname = "max-user-freq", | 730 | .procname = "max-user-freq", |
731 | .data = &hpet_max_freq, | 731 | .data = &hpet_max_freq, |
@@ -736,7 +736,7 @@ static ctl_table hpet_table[] = { | |||
736 | {} | 736 | {} |
737 | }; | 737 | }; |
738 | 738 | ||
739 | static ctl_table hpet_root[] = { | 739 | static struct ctl_table hpet_root[] = { |
740 | { | 740 | { |
741 | .procname = "hpet", | 741 | .procname = "hpet", |
742 | .maxlen = 0, | 742 | .maxlen = 0, |
@@ -746,7 +746,7 @@ static ctl_table hpet_root[] = { | |||
746 | {} | 746 | {} |
747 | }; | 747 | }; |
748 | 748 | ||
749 | static ctl_table dev_root[] = { | 749 | static struct ctl_table dev_root[] = { |
750 | { | 750 | { |
751 | .procname = "dev", | 751 | .procname = "dev", |
752 | .maxlen = 0, | 752 | .maxlen = 0, |
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index 2efa176beab0..9f2e3be2c5b8 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c | |||
@@ -659,7 +659,7 @@ static struct ipmi_smi_watcher smi_watcher = { | |||
659 | #ifdef CONFIG_PROC_FS | 659 | #ifdef CONFIG_PROC_FS |
660 | #include <linux/sysctl.h> | 660 | #include <linux/sysctl.h> |
661 | 661 | ||
662 | static ctl_table ipmi_table[] = { | 662 | static struct ctl_table ipmi_table[] = { |
663 | { .procname = "poweroff_powercycle", | 663 | { .procname = "poweroff_powercycle", |
664 | .data = &poweroff_powercycle, | 664 | .data = &poweroff_powercycle, |
665 | .maxlen = sizeof(poweroff_powercycle), | 665 | .maxlen = sizeof(poweroff_powercycle), |
@@ -668,14 +668,14 @@ static ctl_table ipmi_table[] = { | |||
668 | { } | 668 | { } |
669 | }; | 669 | }; |
670 | 670 | ||
671 | static ctl_table ipmi_dir_table[] = { | 671 | static struct ctl_table ipmi_dir_table[] = { |
672 | { .procname = "ipmi", | 672 | { .procname = "ipmi", |
673 | .mode = 0555, | 673 | .mode = 0555, |
674 | .child = ipmi_table }, | 674 | .child = ipmi_table }, |
675 | { } | 675 | { } |
676 | }; | 676 | }; |
677 | 677 | ||
678 | static ctl_table ipmi_root_table[] = { | 678 | static struct ctl_table ipmi_root_table[] = { |
679 | { .procname = "dev", | 679 | { .procname = "dev", |
680 | .mode = 0555, | 680 | .mode = 0555, |
681 | .child = ipmi_dir_table }, | 681 | .child = ipmi_dir_table }, |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 1ccbe9482faa..2ca6d7844ad9 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -745,7 +745,7 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig) | |||
745 | offset += file->f_pos; | 745 | offset += file->f_pos; |
746 | case SEEK_SET: | 746 | case SEEK_SET: |
747 | /* to avoid userland mistaking f_pos=-9 as -EBADF=-9 */ | 747 | /* to avoid userland mistaking f_pos=-9 as -EBADF=-9 */ |
748 | if ((unsigned long long)offset >= ~0xFFFULL) { | 748 | if (IS_ERR_VALUE((unsigned long long)offset)) { |
749 | ret = -EOVERFLOW; | 749 | ret = -EOVERFLOW; |
750 | break; | 750 | break; |
751 | } | 751 | } |
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index e1f60f968fdd..f1d7fa45c275 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c | |||
@@ -267,7 +267,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, | |||
267 | if ((vma->vm_flags & VM_WRITE) == 0) | 267 | if ((vma->vm_flags & VM_WRITE) == 0) |
268 | return -EPERM; | 268 | return -EPERM; |
269 | 269 | ||
270 | pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; | 270 | pages = vma_pages(vma); |
271 | vdata_size = sizeof(struct vma_data) + pages * sizeof(long); | 271 | vdata_size = sizeof(struct vma_data) + pages * sizeof(long); |
272 | if (vdata_size <= PAGE_SIZE) | 272 | if (vdata_size <= PAGE_SIZE) |
273 | vdata = kzalloc(vdata_size, GFP_KERNEL); | 273 | vdata = kzalloc(vdata_size, GFP_KERNEL); |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 35487e8ded59..0d91fe52f3f5 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -1381,10 +1381,10 @@ static char sysctl_bootid[16]; | |||
1381 | * as an ASCII string in the standard UUID format. If accesses via the | 1381 | * as an ASCII string in the standard UUID format. If accesses via the |
1382 | * sysctl system call, it is returned as 16 bytes of binary data. | 1382 | * sysctl system call, it is returned as 16 bytes of binary data. |
1383 | */ | 1383 | */ |
1384 | static int proc_do_uuid(ctl_table *table, int write, | 1384 | static int proc_do_uuid(struct ctl_table *table, int write, |
1385 | void __user *buffer, size_t *lenp, loff_t *ppos) | 1385 | void __user *buffer, size_t *lenp, loff_t *ppos) |
1386 | { | 1386 | { |
1387 | ctl_table fake_table; | 1387 | struct ctl_table fake_table; |
1388 | unsigned char buf[64], tmp_uuid[16], *uuid; | 1388 | unsigned char buf[64], tmp_uuid[16], *uuid; |
1389 | 1389 | ||
1390 | uuid = table->data; | 1390 | uuid = table->data; |
@@ -1409,8 +1409,8 @@ static int proc_do_uuid(ctl_table *table, int write, | |||
1409 | } | 1409 | } |
1410 | 1410 | ||
1411 | static int sysctl_poolsize = INPUT_POOL_WORDS * 32; | 1411 | static int sysctl_poolsize = INPUT_POOL_WORDS * 32; |
1412 | extern ctl_table random_table[]; | 1412 | extern struct ctl_table random_table[]; |
1413 | ctl_table random_table[] = { | 1413 | struct ctl_table random_table[] = { |
1414 | { | 1414 | { |
1415 | .procname = "poolsize", | 1415 | .procname = "poolsize", |
1416 | .data = &sysctl_poolsize, | 1416 | .data = &sysctl_poolsize, |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 91470fdbab2a..c0cbbd429bdc 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -280,7 +280,7 @@ static irqreturn_t rtc_interrupt(int irq, void *dev_id) | |||
280 | /* | 280 | /* |
281 | * sysctl-tuning infrastructure. | 281 | * sysctl-tuning infrastructure. |
282 | */ | 282 | */ |
283 | static ctl_table rtc_table[] = { | 283 | static struct ctl_table rtc_table[] = { |
284 | { | 284 | { |
285 | .procname = "max-user-freq", | 285 | .procname = "max-user-freq", |
286 | .data = &rtc_max_user_freq, | 286 | .data = &rtc_max_user_freq, |
@@ -291,7 +291,7 @@ static ctl_table rtc_table[] = { | |||
291 | { } | 291 | { } |
292 | }; | 292 | }; |
293 | 293 | ||
294 | static ctl_table rtc_root[] = { | 294 | static struct ctl_table rtc_root[] = { |
295 | { | 295 | { |
296 | .procname = "rtc", | 296 | .procname = "rtc", |
297 | .mode = 0555, | 297 | .mode = 0555, |
@@ -300,7 +300,7 @@ static ctl_table rtc_root[] = { | |||
300 | { } | 300 | { } |
301 | }; | 301 | }; |
302 | 302 | ||
303 | static ctl_table dev_root[] = { | 303 | static struct ctl_table dev_root[] = { |
304 | { | 304 | { |
305 | .procname = "dev", | 305 | .procname = "dev", |
306 | .mode = 0555, | 306 | .mode = 0555, |
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h index d31ee23c9f13..38b145eaf24d 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h | |||
@@ -37,7 +37,7 @@ | |||
37 | #include <linux/cdev.h> | 37 | #include <linux/cdev.h> |
38 | #include <linux/platform_device.h> | 38 | #include <linux/platform_device.h> |
39 | 39 | ||
40 | #include <asm/io.h> | 40 | #include <linux/io.h> |
41 | 41 | ||
42 | struct hwicap_drvdata { | 42 | struct hwicap_drvdata { |
43 | u32 write_buffer_in_use; /* Always in [0,3] */ | 43 | u32 write_buffer_in_use; /* Always in [0,3] */ |
@@ -85,7 +85,13 @@ struct hwicap_driver_config { | |||
85 | void (*reset)(struct hwicap_drvdata *drvdata); | 85 | void (*reset)(struct hwicap_drvdata *drvdata); |
86 | }; | 86 | }; |
87 | 87 | ||
88 | /* Number of times to poll the done regsiter */ | 88 | /* Number of times to poll the done register. This has to be large |
89 | * enough to allow an entire configuration to complete. If an entire | ||
90 | * page (4kb) is configured at once, that could take up to 4k cycles | ||
91 | * with a byte-wide icap interface. In most cases, this driver is | ||
92 | * used with a much smaller fifo, but this should be sufficient in the | ||
93 | * worst case. | ||
94 | */ | ||
89 | #define XHI_MAX_RETRIES 5000 | 95 | #define XHI_MAX_RETRIES 5000 |
90 | 96 | ||
91 | /************ Constant Definitions *************/ | 97 | /************ Constant Definitions *************/ |
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index 3297301a42d4..63f454e20576 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig | |||
@@ -53,4 +53,11 @@ config EXTCON_ARIZONA | |||
53 | with Wolfson Arizona devices. These are audio CODECs with | 53 | with Wolfson Arizona devices. These are audio CODECs with |
54 | advanced audio accessory detection support. | 54 | advanced audio accessory detection support. |
55 | 55 | ||
56 | config EXTCON_PALMAS | ||
57 | tristate "Palmas USB EXTCON support" | ||
58 | depends on MFD_PALMAS | ||
59 | help | ||
60 | Say Y here to enable support for USB peripheral and USB host | ||
61 | detection by palmas usb. | ||
62 | |||
56 | endif # MULTISTATE_SWITCH | 63 | endif # MULTISTATE_SWITCH |
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index f98a3c4d46e0..540e2c3a4431 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile | |||
@@ -8,3 +8,4 @@ obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o | |||
8 | obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o | 8 | obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o |
9 | obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o | 9 | obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o |
10 | obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o | 10 | obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o |
11 | obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o | ||
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 60adc04b0561..8c69803558fe 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c | |||
@@ -185,26 +185,6 @@ static ssize_t cable_state_show(struct device *dev, | |||
185 | cable->cable_index)); | 185 | cable->cable_index)); |
186 | } | 186 | } |
187 | 187 | ||
188 | static ssize_t cable_state_store(struct device *dev, | ||
189 | struct device_attribute *attr, const char *buf, | ||
190 | size_t count) | ||
191 | { | ||
192 | struct extcon_cable *cable = container_of(attr, struct extcon_cable, | ||
193 | attr_state); | ||
194 | int ret, state; | ||
195 | |||
196 | ret = sscanf(buf, "%d", &state); | ||
197 | if (ret == 0) | ||
198 | ret = -EINVAL; | ||
199 | else | ||
200 | ret = extcon_set_cable_state_(cable->edev, cable->cable_index, | ||
201 | state); | ||
202 | |||
203 | if (ret < 0) | ||
204 | return ret; | ||
205 | return count; | ||
206 | } | ||
207 | |||
208 | /** | 188 | /** |
209 | * extcon_update_state() - Update the cable attach states of the extcon device | 189 | * extcon_update_state() - Update the cable attach states of the extcon device |
210 | * only for the masked bits. | 190 | * only for the masked bits. |
@@ -501,6 +481,7 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj, | |||
501 | return -ENODEV; | 481 | return -ENODEV; |
502 | } | 482 | } |
503 | } | 483 | } |
484 | EXPORT_SYMBOL_GPL(extcon_register_interest); | ||
504 | 485 | ||
505 | /** | 486 | /** |
506 | * extcon_unregister_interest() - Unregister the notifier registered by | 487 | * extcon_unregister_interest() - Unregister the notifier registered by |
@@ -515,6 +496,7 @@ int extcon_unregister_interest(struct extcon_specific_cable_nb *obj) | |||
515 | 496 | ||
516 | return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb); | 497 | return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb); |
517 | } | 498 | } |
499 | EXPORT_SYMBOL_GPL(extcon_unregister_interest); | ||
518 | 500 | ||
519 | /** | 501 | /** |
520 | * extcon_register_notifier() - Register a notifiee to get notified by | 502 | * 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) | |||
665 | 647 | ||
666 | sysfs_attr_init(&cable->attr_state.attr); | 648 | sysfs_attr_init(&cable->attr_state.attr); |
667 | cable->attr_state.attr.name = "state"; | 649 | cable->attr_state.attr.name = "state"; |
668 | cable->attr_state.attr.mode = 0644; | 650 | cable->attr_state.attr.mode = 0444; |
669 | cable->attr_state.show = cable_state_show; | 651 | cable->attr_state.show = cable_state_show; |
670 | cable->attr_state.store = cable_state_store; | ||
671 | } | 652 | } |
672 | } | 653 | } |
673 | 654 | ||
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c new file mode 100644 index 000000000000..b752a0ad7b63 --- /dev/null +++ b/drivers/extcon/extcon-palmas.c | |||
@@ -0,0 +1,246 @@ | |||
1 | /* | ||
2 | * Palmas USB transceiver driver | ||
3 | * | ||
4 | * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * Author: Graeme Gregory <gg@slimlogic.co.uk> | ||
11 | * Author: Kishon Vijay Abraham I <kishon@ti.com> | ||
12 | * | ||
13 | * Based on twl6030_usb.c | ||
14 | * | ||
15 | * Author: Hema HK <hemahk@ti.com> | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <linux/mfd/palmas.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/of_platform.h> | ||
30 | |||
31 | static const char *palmas_extcon_cable[] = { | ||
32 | [0] = "USB", | ||
33 | [1] = "USB-HOST", | ||
34 | NULL, | ||
35 | }; | ||
36 | |||
37 | static const int mutually_exclusive[] = {0x3, 0x0}; | ||
38 | |||
39 | static void palmas_usb_wakeup(struct palmas *palmas, int enable) | ||
40 | { | ||
41 | if (enable) | ||
42 | palmas_write(palmas, PALMAS_USB_OTG_BASE, PALMAS_USB_WAKEUP, | ||
43 | PALMAS_USB_WAKEUP_ID_WK_UP_COMP); | ||
44 | else | ||
45 | palmas_write(palmas, PALMAS_USB_OTG_BASE, PALMAS_USB_WAKEUP, 0); | ||
46 | } | ||
47 | |||
48 | static irqreturn_t palmas_vbus_irq_handler(int irq, void *_palmas_usb) | ||
49 | { | ||
50 | struct palmas_usb *palmas_usb = _palmas_usb; | ||
51 | unsigned int vbus_line_state; | ||
52 | |||
53 | palmas_read(palmas_usb->palmas, PALMAS_INTERRUPT_BASE, | ||
54 | PALMAS_INT3_LINE_STATE, &vbus_line_state); | ||
55 | |||
56 | if (vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS) { | ||
57 | if (palmas_usb->linkstat != PALMAS_USB_STATE_VBUS) { | ||
58 | palmas_usb->linkstat = PALMAS_USB_STATE_VBUS; | ||
59 | extcon_set_cable_state(&palmas_usb->edev, "USB", true); | ||
60 | } else { | ||
61 | dev_dbg(palmas_usb->dev, | ||
62 | "Spurious connect event detected\n"); | ||
63 | } | ||
64 | } else if (!(vbus_line_state & PALMAS_INT3_LINE_STATE_VBUS)) { | ||
65 | if (palmas_usb->linkstat == PALMAS_USB_STATE_VBUS) { | ||
66 | palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; | ||
67 | extcon_set_cable_state(&palmas_usb->edev, "USB", false); | ||
68 | } else { | ||
69 | dev_dbg(palmas_usb->dev, | ||
70 | "Spurious disconnect event detected\n"); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | return IRQ_HANDLED; | ||
75 | } | ||
76 | |||
77 | static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb) | ||
78 | { | ||
79 | unsigned int set; | ||
80 | struct palmas_usb *palmas_usb = _palmas_usb; | ||
81 | |||
82 | palmas_read(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
83 | PALMAS_USB_ID_INT_LATCH_SET, &set); | ||
84 | |||
85 | if (set & PALMAS_USB_ID_INT_SRC_ID_GND) { | ||
86 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
87 | PALMAS_USB_ID_INT_EN_HI_SET, | ||
88 | PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT); | ||
89 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
90 | PALMAS_USB_ID_INT_EN_HI_CLR, | ||
91 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND); | ||
92 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
93 | PALMAS_USB_ID_INT_LATCH_CLR, | ||
94 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND); | ||
95 | palmas_usb->linkstat = PALMAS_USB_STATE_ID; | ||
96 | extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true); | ||
97 | } else if (set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) { | ||
98 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
99 | PALMAS_USB_ID_INT_EN_HI_SET, | ||
100 | PALMAS_USB_ID_INT_EN_HI_SET_ID_GND); | ||
101 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
102 | PALMAS_USB_ID_INT_EN_HI_CLR, | ||
103 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT); | ||
104 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
105 | PALMAS_USB_ID_INT_LATCH_CLR, | ||
106 | PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT); | ||
107 | palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; | ||
108 | extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false); | ||
109 | } | ||
110 | |||
111 | return IRQ_HANDLED; | ||
112 | } | ||
113 | |||
114 | static void palmas_enable_irq(struct palmas_usb *palmas_usb) | ||
115 | { | ||
116 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
117 | PALMAS_USB_VBUS_CTRL_SET, | ||
118 | PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP); | ||
119 | |||
120 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
121 | PALMAS_USB_ID_CTRL_SET, PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP); | ||
122 | |||
123 | palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, | ||
124 | PALMAS_USB_ID_INT_EN_HI_SET, | ||
125 | PALMAS_USB_ID_INT_EN_HI_SET_ID_GND); | ||
126 | |||
127 | palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb); | ||
128 | |||
129 | /* cold plug for host mode needs this delay */ | ||
130 | msleep(30); | ||
131 | palmas_id_irq_handler(palmas_usb->id_irq, palmas_usb); | ||
132 | } | ||
133 | |||
134 | static int palmas_usb_probe(struct platform_device *pdev) | ||
135 | { | ||
136 | struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); | ||
137 | struct palmas_usb_platform_data *pdata = pdev->dev.platform_data; | ||
138 | struct device_node *node = pdev->dev.of_node; | ||
139 | struct palmas_usb *palmas_usb; | ||
140 | int status; | ||
141 | |||
142 | if (node && !pdata) { | ||
143 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
144 | |||
145 | if (!pdata) | ||
146 | return -ENOMEM; | ||
147 | |||
148 | pdata->wakeup = of_property_read_bool(node, "ti,wakeup"); | ||
149 | } else if (!pdata) { | ||
150 | return -EINVAL; | ||
151 | } | ||
152 | |||
153 | palmas_usb = devm_kzalloc(&pdev->dev, sizeof(*palmas_usb), GFP_KERNEL); | ||
154 | if (!palmas_usb) | ||
155 | return -ENOMEM; | ||
156 | |||
157 | palmas->usb = palmas_usb; | ||
158 | palmas_usb->palmas = palmas; | ||
159 | |||
160 | palmas_usb->dev = &pdev->dev; | ||
161 | |||
162 | palmas_usb->id_otg_irq = regmap_irq_get_virq(palmas->irq_data, | ||
163 | PALMAS_ID_OTG_IRQ); | ||
164 | palmas_usb->id_irq = regmap_irq_get_virq(palmas->irq_data, | ||
165 | PALMAS_ID_IRQ); | ||
166 | palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data, | ||
167 | PALMAS_VBUS_OTG_IRQ); | ||
168 | palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data, | ||
169 | PALMAS_VBUS_IRQ); | ||
170 | |||
171 | palmas_usb_wakeup(palmas, pdata->wakeup); | ||
172 | |||
173 | platform_set_drvdata(pdev, palmas_usb); | ||
174 | |||
175 | palmas_usb->edev.name = "palmas-usb"; | ||
176 | palmas_usb->edev.supported_cable = palmas_extcon_cable; | ||
177 | palmas_usb->edev.mutually_exclusive = mutually_exclusive; | ||
178 | |||
179 | status = extcon_dev_register(&palmas_usb->edev, palmas_usb->dev); | ||
180 | if (status) { | ||
181 | dev_err(&pdev->dev, "failed to register extcon device\n"); | ||
182 | return status; | ||
183 | } | ||
184 | |||
185 | status = devm_request_threaded_irq(palmas_usb->dev, palmas_usb->id_irq, | ||
186 | NULL, palmas_id_irq_handler, | ||
187 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
188 | "palmas_usb_id", palmas_usb); | ||
189 | if (status < 0) { | ||
190 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | ||
191 | palmas_usb->id_irq, status); | ||
192 | goto fail_extcon; | ||
193 | } | ||
194 | |||
195 | status = devm_request_threaded_irq(palmas_usb->dev, | ||
196 | palmas_usb->vbus_irq, NULL, palmas_vbus_irq_handler, | ||
197 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
198 | "palmas_usb_vbus", palmas_usb); | ||
199 | if (status < 0) { | ||
200 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | ||
201 | palmas_usb->vbus_irq, status); | ||
202 | goto fail_extcon; | ||
203 | } | ||
204 | |||
205 | palmas_enable_irq(palmas_usb); | ||
206 | |||
207 | return 0; | ||
208 | |||
209 | fail_extcon: | ||
210 | extcon_dev_unregister(&palmas_usb->edev); | ||
211 | |||
212 | return status; | ||
213 | } | ||
214 | |||
215 | static int palmas_usb_remove(struct platform_device *pdev) | ||
216 | { | ||
217 | struct palmas_usb *palmas_usb = platform_get_drvdata(pdev); | ||
218 | |||
219 | extcon_dev_unregister(&palmas_usb->edev); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static struct of_device_id of_palmas_match_tbl[] = { | ||
225 | { .compatible = "ti,palmas-usb", }, | ||
226 | { .compatible = "ti,twl6035-usb", }, | ||
227 | { /* end */ } | ||
228 | }; | ||
229 | |||
230 | static struct platform_driver palmas_usb_driver = { | ||
231 | .probe = palmas_usb_probe, | ||
232 | .remove = palmas_usb_remove, | ||
233 | .driver = { | ||
234 | .name = "palmas-usb", | ||
235 | .of_match_table = of_palmas_match_tbl, | ||
236 | .owner = THIS_MODULE, | ||
237 | }, | ||
238 | }; | ||
239 | |||
240 | module_platform_driver(palmas_usb_driver); | ||
241 | |||
242 | MODULE_ALIAS("platform:palmas-usb"); | ||
243 | MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); | ||
244 | MODULE_DESCRIPTION("Palmas USB transceiver driver"); | ||
245 | MODULE_LICENSE("GPL"); | ||
246 | MODULE_DEVICE_TABLE(of, of_palmas_match_tbl); | ||
diff --git a/drivers/fmc/Kconfig b/drivers/fmc/Kconfig new file mode 100644 index 000000000000..c01cf45bc3d8 --- /dev/null +++ b/drivers/fmc/Kconfig | |||
@@ -0,0 +1,51 @@ | |||
1 | # | ||
2 | # FMC (ANSI-VITA 57.1) bus support | ||
3 | # | ||
4 | |||
5 | menuconfig FMC | ||
6 | tristate "FMC support" | ||
7 | help | ||
8 | |||
9 | FMC (FPGA Mezzanine Carrier) is a mechanical and electrical | ||
10 | standard for mezzanine cards that plug into a carrier board. | ||
11 | This kernel subsystem supports the matching between carrier | ||
12 | and mezzanine based on identifiers stored in the internal I2C | ||
13 | EEPROM, as well as having carrier-independent drivers. | ||
14 | |||
15 | The framework was born outside of the kernel and at this time | ||
16 | the off-tree code base is more complete. Code and documentation | ||
17 | is at git://ohwr.org/fmc-projects/fmc-bus.git . | ||
18 | |||
19 | if FMC | ||
20 | |||
21 | config FMC_FAKEDEV | ||
22 | tristate "FMC fake device (software testing)" | ||
23 | help | ||
24 | This is a fake carrier, bringing a default EEPROM content | ||
25 | that can be rewritten at run time and usef for matching | ||
26 | mezzanines. | ||
27 | |||
28 | config FMC_TRIVIAL | ||
29 | tristate "FMC trivial mezzanine driver (software testing)" | ||
30 | help | ||
31 | This is a fake mezzanine driver, to show how FMC works and test it. | ||
32 | The driver also handles interrupts (we used it with a real carrier | ||
33 | before the mezzanines were produced) | ||
34 | |||
35 | config FMC_WRITE_EEPROM | ||
36 | tristate "FMC mezzanine driver to write I2C EEPROM" | ||
37 | help | ||
38 | This driver matches every mezzanine device and can write the | ||
39 | internal EEPROM of the PCB, using the firmware loader to get | ||
40 | its binary and the function carrier->reprogram to actually do it. | ||
41 | It is useful when the mezzanines are produced. | ||
42 | |||
43 | config FMC_CHARDEV | ||
44 | tristate "FMC mezzanine driver that registers a char device" | ||
45 | help | ||
46 | This driver matches every mezzanine device and allows user | ||
47 | space to read and write registers using a char device. It | ||
48 | can be used to write user-space drivers, or just get | ||
49 | aquainted with a mezzanine before writing its specific driver. | ||
50 | |||
51 | endif # FMC | ||
diff --git a/drivers/fmc/Makefile b/drivers/fmc/Makefile new file mode 100644 index 000000000000..b9452919739f --- /dev/null +++ b/drivers/fmc/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | |||
2 | obj-$(CONFIG_FMC) += fmc.o | ||
3 | |||
4 | fmc-y = fmc-core.o | ||
5 | fmc-y += fmc-match.o | ||
6 | fmc-y += fmc-sdb.o | ||
7 | fmc-y += fru-parse.o | ||
8 | fmc-y += fmc-dump.o | ||
9 | |||
10 | obj-$(CONFIG_FMC_FAKEDEV) += fmc-fakedev.o | ||
11 | obj-$(CONFIG_FMC_TRIVIAL) += fmc-trivial.o | ||
12 | obj-$(CONFIG_FMC_WRITE_EEPROM) += fmc-write-eeprom.o | ||
13 | obj-$(CONFIG_FMC_CHARDEV) += fmc-chardev.o | ||
diff --git a/drivers/fmc/fmc-chardev.c b/drivers/fmc/fmc-chardev.c new file mode 100644 index 000000000000..cc031db2d2a3 --- /dev/null +++ b/drivers/fmc/fmc-chardev.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 CERN (www.cern.ch) | ||
3 | * Author: Alessandro Rubini <rubini@gnudd.com> | ||
4 | * | ||
5 | * Released according to the GNU GPL, version 2 or any later version. | ||
6 | * | ||
7 | * This work is part of the White Rabbit project, a research effort led | ||
8 | * by CERN, the European Institute for Nuclear Research. | ||
9 | */ | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/list.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/fs.h> | ||
15 | #include <linux/miscdevice.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | #include <linux/fmc.h> | ||
18 | #include <linux/uaccess.h> | ||
19 | |||
20 | static LIST_HEAD(fc_devices); | ||
21 | static DEFINE_SPINLOCK(fc_lock); | ||
22 | |||
23 | struct fc_instance { | ||
24 | struct list_head list; | ||
25 | struct fmc_device *fmc; | ||
26 | struct miscdevice misc; | ||
27 | }; | ||
28 | |||
29 | /* at open time, we must identify our device */ | ||
30 | static int fc_open(struct inode *ino, struct file *f) | ||
31 | { | ||
32 | struct fmc_device *fmc; | ||
33 | struct fc_instance *fc; | ||
34 | int minor = iminor(ino); | ||
35 | |||
36 | list_for_each_entry(fc, &fc_devices, list) | ||
37 | if (fc->misc.minor == minor) | ||
38 | break; | ||
39 | if (fc->misc.minor != minor) | ||
40 | return -ENODEV; | ||
41 | fmc = fc->fmc; | ||
42 | if (try_module_get(fmc->owner) == 0) | ||
43 | return -ENODEV; | ||
44 | |||
45 | f->private_data = fmc; | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static int fc_release(struct inode *ino, struct file *f) | ||
50 | { | ||
51 | struct fmc_device *fmc = f->private_data; | ||
52 | module_put(fmc->owner); | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | /* read and write are simple after the default llseek has been used */ | ||
57 | static ssize_t fc_read(struct file *f, char __user *buf, size_t count, | ||
58 | loff_t *offp) | ||
59 | { | ||
60 | struct fmc_device *fmc = f->private_data; | ||
61 | unsigned long addr; | ||
62 | uint32_t val; | ||
63 | |||
64 | if (count < sizeof(val)) | ||
65 | return -EINVAL; | ||
66 | count = sizeof(val); | ||
67 | |||
68 | addr = *offp; | ||
69 | if (addr > fmc->memlen) | ||
70 | return -ESPIPE; /* Illegal seek */ | ||
71 | val = fmc_readl(fmc, addr); | ||
72 | if (copy_to_user(buf, &val, count)) | ||
73 | return -EFAULT; | ||
74 | *offp += count; | ||
75 | return count; | ||
76 | } | ||
77 | |||
78 | static ssize_t fc_write(struct file *f, const char __user *buf, size_t count, | ||
79 | loff_t *offp) | ||
80 | { | ||
81 | struct fmc_device *fmc = f->private_data; | ||
82 | unsigned long addr; | ||
83 | uint32_t val; | ||
84 | |||
85 | if (count < sizeof(val)) | ||
86 | return -EINVAL; | ||
87 | count = sizeof(val); | ||
88 | |||
89 | addr = *offp; | ||
90 | if (addr > fmc->memlen) | ||
91 | return -ESPIPE; /* Illegal seek */ | ||
92 | if (copy_from_user(&val, buf, count)) | ||
93 | return -EFAULT; | ||
94 | fmc_writel(fmc, val, addr); | ||
95 | *offp += count; | ||
96 | return count; | ||
97 | } | ||
98 | |||
99 | static const struct file_operations fc_fops = { | ||
100 | .owner = THIS_MODULE, | ||
101 | .open = fc_open, | ||
102 | .release = fc_release, | ||
103 | .llseek = generic_file_llseek, | ||
104 | .read = fc_read, | ||
105 | .write = fc_write, | ||
106 | }; | ||
107 | |||
108 | |||
109 | /* Device part .. */ | ||
110 | static int fc_probe(struct fmc_device *fmc); | ||
111 | static int fc_remove(struct fmc_device *fmc); | ||
112 | |||
113 | static struct fmc_driver fc_drv = { | ||
114 | .version = FMC_VERSION, | ||
115 | .driver.name = KBUILD_MODNAME, | ||
116 | .probe = fc_probe, | ||
117 | .remove = fc_remove, | ||
118 | /* no table: we want to match everything */ | ||
119 | }; | ||
120 | |||
121 | /* We accept the generic busid parameter */ | ||
122 | FMC_PARAM_BUSID(fc_drv); | ||
123 | |||
124 | /* probe and remove must allocate and release a misc device */ | ||
125 | static int fc_probe(struct fmc_device *fmc) | ||
126 | { | ||
127 | int ret; | ||
128 | int index = 0; | ||
129 | |||
130 | struct fc_instance *fc; | ||
131 | |||
132 | if (fmc->op->validate) | ||
133 | index = fmc->op->validate(fmc, &fc_drv); | ||
134 | if (index < 0) | ||
135 | return -EINVAL; /* not our device: invalid */ | ||
136 | |||
137 | /* Create a char device: we want to create it anew */ | ||
138 | fc = kzalloc(sizeof(*fc), GFP_KERNEL); | ||
139 | if (!fc) | ||
140 | return -ENOMEM; | ||
141 | fc->fmc = fmc; | ||
142 | fc->misc.minor = MISC_DYNAMIC_MINOR; | ||
143 | fc->misc.fops = &fc_fops; | ||
144 | fc->misc.name = kstrdup(dev_name(&fmc->dev), GFP_KERNEL); | ||
145 | |||
146 | spin_lock(&fc_lock); | ||
147 | ret = misc_register(&fc->misc); | ||
148 | if (ret < 0) | ||
149 | goto err_unlock; | ||
150 | list_add(&fc->list, &fc_devices); | ||
151 | spin_unlock(&fc_lock); | ||
152 | dev_info(&fc->fmc->dev, "Created misc device \"%s\"\n", | ||
153 | fc->misc.name); | ||
154 | return 0; | ||
155 | |||
156 | err_unlock: | ||
157 | spin_unlock(&fc_lock); | ||
158 | kfree(fc->misc.name); | ||
159 | kfree(fc); | ||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | static int fc_remove(struct fmc_device *fmc) | ||
164 | { | ||
165 | struct fc_instance *fc; | ||
166 | |||
167 | list_for_each_entry(fc, &fc_devices, list) | ||
168 | if (fc->fmc == fmc) | ||
169 | break; | ||
170 | if (fc->fmc != fmc) { | ||
171 | dev_err(&fmc->dev, "remove called but not found\n"); | ||
172 | return -ENODEV; | ||
173 | } | ||
174 | |||
175 | spin_lock(&fc_lock); | ||
176 | list_del(&fc->list); | ||
177 | misc_deregister(&fc->misc); | ||
178 | kfree(fc->misc.name); | ||
179 | kfree(fc); | ||
180 | spin_unlock(&fc_lock); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | |||
186 | static int fc_init(void) | ||
187 | { | ||
188 | int ret; | ||
189 | |||
190 | ret = fmc_driver_register(&fc_drv); | ||
191 | return ret; | ||
192 | } | ||
193 | |||
194 | static void fc_exit(void) | ||
195 | { | ||
196 | fmc_driver_unregister(&fc_drv); | ||
197 | } | ||
198 | |||
199 | module_init(fc_init); | ||
200 | module_exit(fc_exit); | ||
201 | |||
202 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/fmc/fmc-core.c b/drivers/fmc/fmc-core.c new file mode 100644 index 000000000000..24d52497524d --- /dev/null +++ b/drivers/fmc/fmc-core.c | |||
@@ -0,0 +1,296 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 CERN (www.cern.ch) | ||
3 | * Author: Alessandro Rubini <rubini@gnudd.com> | ||
4 | * | ||
5 | * Released according to the GNU GPL, version 2 or any later version. | ||
6 | * | ||
7 | * This work is part of the White Rabbit project, a research effort led | ||
8 | * by CERN, the European Institute for Nuclear Research. | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/fmc.h> | ||
16 | |||
17 | static int fmc_check_version(unsigned long version, const char *name) | ||
18 | { | ||
19 | if (__FMC_MAJOR(version) != FMC_MAJOR) { | ||
20 | pr_err("%s: \"%s\" has wrong major (has %li, expected %i)\n", | ||
21 | __func__, name, __FMC_MAJOR(version), FMC_MAJOR); | ||
22 | return -EINVAL; | ||
23 | } | ||
24 | |||
25 | if (__FMC_MINOR(version) != FMC_MINOR) | ||
26 | pr_info("%s: \"%s\" has wrong minor (has %li, expected %i)\n", | ||
27 | __func__, name, __FMC_MINOR(version), FMC_MINOR); | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | static int fmc_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
32 | { | ||
33 | /* struct fmc_device *fdev = to_fmc_device(dev); */ | ||
34 | |||
35 | /* FIXME: The MODALIAS */ | ||
36 | add_uevent_var(env, "MODALIAS=%s", "fmc"); | ||
37 | return 0; | ||
38 | } | ||
39 | |||
40 | static int fmc_probe(struct device *dev) | ||
41 | { | ||
42 | struct fmc_driver *fdrv = to_fmc_driver(dev->driver); | ||
43 | struct fmc_device *fdev = to_fmc_device(dev); | ||
44 | |||
45 | return fdrv->probe(fdev); | ||
46 | } | ||
47 | |||
48 | static int fmc_remove(struct device *dev) | ||
49 | { | ||
50 | struct fmc_driver *fdrv = to_fmc_driver(dev->driver); | ||
51 | struct fmc_device *fdev = to_fmc_device(dev); | ||
52 | |||
53 | return fdrv->remove(fdev); | ||
54 | } | ||
55 | |||
56 | static void fmc_shutdown(struct device *dev) | ||
57 | { | ||
58 | /* not implemented but mandatory */ | ||
59 | } | ||
60 | |||
61 | static struct bus_type fmc_bus_type = { | ||
62 | .name = "fmc", | ||
63 | .match = fmc_match, | ||
64 | .uevent = fmc_uevent, | ||
65 | .probe = fmc_probe, | ||
66 | .remove = fmc_remove, | ||
67 | .shutdown = fmc_shutdown, | ||
68 | }; | ||
69 | |||
70 | static void fmc_release(struct device *dev) | ||
71 | { | ||
72 | struct fmc_device *fmc = container_of(dev, struct fmc_device, dev); | ||
73 | |||
74 | kfree(fmc); | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * The eeprom is exported in sysfs, through a binary attribute | ||
79 | */ | ||
80 | |||
81 | static ssize_t fmc_read_eeprom(struct file *file, struct kobject *kobj, | ||
82 | struct bin_attribute *bin_attr, | ||
83 | char *buf, loff_t off, size_t count) | ||
84 | { | ||
85 | struct device *dev; | ||
86 | struct fmc_device *fmc; | ||
87 | int eelen; | ||
88 | |||
89 | dev = container_of(kobj, struct device, kobj); | ||
90 | fmc = container_of(dev, struct fmc_device, dev); | ||
91 | eelen = fmc->eeprom_len; | ||
92 | if (off > eelen) | ||
93 | return -ESPIPE; | ||
94 | if (off == eelen) | ||
95 | return 0; /* EOF */ | ||
96 | if (off + count > eelen) | ||
97 | count = eelen - off; | ||
98 | memcpy(buf, fmc->eeprom + off, count); | ||
99 | return count; | ||
100 | } | ||
101 | |||
102 | static struct bin_attribute fmc_eeprom_attr = { | ||
103 | .attr = { .name = "eeprom", .mode = S_IRUGO, }, | ||
104 | .size = 8192, /* more or less standard */ | ||
105 | .read = fmc_read_eeprom, | ||
106 | }; | ||
107 | |||
108 | /* | ||
109 | * Functions for client modules follow | ||
110 | */ | ||
111 | |||
112 | int fmc_driver_register(struct fmc_driver *drv) | ||
113 | { | ||
114 | if (fmc_check_version(drv->version, drv->driver.name)) | ||
115 | return -EINVAL; | ||
116 | drv->driver.bus = &fmc_bus_type; | ||
117 | return driver_register(&drv->driver); | ||
118 | } | ||
119 | EXPORT_SYMBOL(fmc_driver_register); | ||
120 | |||
121 | void fmc_driver_unregister(struct fmc_driver *drv) | ||
122 | { | ||
123 | driver_unregister(&drv->driver); | ||
124 | } | ||
125 | EXPORT_SYMBOL(fmc_driver_unregister); | ||
126 | |||
127 | /* | ||
128 | * When a device set is registered, all eeproms must be read | ||
129 | * and all FRUs must be parsed | ||
130 | */ | ||
131 | int fmc_device_register_n(struct fmc_device **devs, int n) | ||
132 | { | ||
133 | struct fmc_device *fmc, **devarray; | ||
134 | uint32_t device_id; | ||
135 | int i, ret = 0; | ||
136 | |||
137 | if (n < 1) | ||
138 | return 0; | ||
139 | |||
140 | /* Check the version of the first data structure (function prints) */ | ||
141 | if (fmc_check_version(devs[0]->version, devs[0]->carrier_name)) | ||
142 | return -EINVAL; | ||
143 | |||
144 | devarray = kmemdup(devs, n * sizeof(*devs), GFP_KERNEL); | ||
145 | if (!devarray) | ||
146 | return -ENOMEM; | ||
147 | |||
148 | /* Make all other checks before continuing, for all devices */ | ||
149 | for (i = 0; i < n; i++) { | ||
150 | fmc = devarray[i]; | ||
151 | if (!fmc->hwdev) { | ||
152 | pr_err("%s: device nr. %i has no hwdev pointer\n", | ||
153 | __func__, i); | ||
154 | ret = -EINVAL; | ||
155 | break; | ||
156 | } | ||
157 | if (fmc->flags == FMC_DEVICE_NO_MEZZANINE) { | ||
158 | dev_info(fmc->hwdev, "absent mezzanine in slot %d\n", | ||
159 | fmc->slot_id); | ||
160 | continue; | ||
161 | } | ||
162 | if (!fmc->eeprom) { | ||
163 | dev_err(fmc->hwdev, "no eeprom provided for slot %i\n", | ||
164 | fmc->slot_id); | ||
165 | ret = -EINVAL; | ||
166 | } | ||
167 | if (!fmc->eeprom_addr) { | ||
168 | dev_err(fmc->hwdev, "no eeprom_addr for slot %i\n", | ||
169 | fmc->slot_id); | ||
170 | ret = -EINVAL; | ||
171 | } | ||
172 | if (!fmc->carrier_name || !fmc->carrier_data || | ||
173 | !fmc->device_id) { | ||
174 | dev_err(fmc->hwdev, | ||
175 | "deivce nr %i: carrier name, " | ||
176 | "data or dev_id not set\n", i); | ||
177 | ret = -EINVAL; | ||
178 | } | ||
179 | if (ret) | ||
180 | break; | ||
181 | |||
182 | } | ||
183 | if (ret) { | ||
184 | kfree(devarray); | ||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | /* Validation is ok. Now init and register the devices */ | ||
189 | for (i = 0; i < n; i++) { | ||
190 | fmc = devarray[i]; | ||
191 | |||
192 | if (fmc->flags == FMC_DEVICE_NO_MEZZANINE) | ||
193 | continue; /* dev_info already done above */ | ||
194 | |||
195 | fmc->nr_slots = n; /* each slot must know how many are there */ | ||
196 | fmc->devarray = devarray; | ||
197 | |||
198 | device_initialize(&fmc->dev); | ||
199 | fmc->dev.release = fmc_release; | ||
200 | fmc->dev.parent = fmc->hwdev; | ||
201 | |||
202 | /* Fill the identification stuff (may fail) */ | ||
203 | fmc_fill_id_info(fmc); | ||
204 | |||
205 | fmc->dev.bus = &fmc_bus_type; | ||
206 | |||
207 | /* Name from mezzanine info or carrier info. Or 0,1,2.. */ | ||
208 | device_id = fmc->device_id; | ||
209 | if (!fmc->mezzanine_name) | ||
210 | dev_set_name(&fmc->dev, "fmc-%04x", device_id); | ||
211 | else | ||
212 | dev_set_name(&fmc->dev, "%s-%04x", fmc->mezzanine_name, | ||
213 | device_id); | ||
214 | ret = device_add(&fmc->dev); | ||
215 | if (ret < 0) { | ||
216 | dev_err(fmc->hwdev, "Slot %i: Failed in registering " | ||
217 | "\"%s\"\n", fmc->slot_id, fmc->dev.kobj.name); | ||
218 | goto out; | ||
219 | } | ||
220 | ret = sysfs_create_bin_file(&fmc->dev.kobj, &fmc_eeprom_attr); | ||
221 | if (ret < 0) { | ||
222 | dev_err(&fmc->dev, "Failed in registering eeprom\n"); | ||
223 | goto out1; | ||
224 | } | ||
225 | /* This device went well, give information to the user */ | ||
226 | fmc_dump_eeprom(fmc); | ||
227 | fmc_dump_sdb(fmc); | ||
228 | } | ||
229 | return 0; | ||
230 | |||
231 | out1: | ||
232 | device_del(&fmc->dev); | ||
233 | out: | ||
234 | fmc_free_id_info(fmc); | ||
235 | put_device(&fmc->dev); | ||
236 | |||
237 | kfree(devarray); | ||
238 | for (i--; i >= 0; i--) { | ||
239 | sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr); | ||
240 | device_del(&devs[i]->dev); | ||
241 | fmc_free_id_info(devs[i]); | ||
242 | put_device(&devs[i]->dev); | ||
243 | } | ||
244 | return ret; | ||
245 | |||
246 | } | ||
247 | EXPORT_SYMBOL(fmc_device_register_n); | ||
248 | |||
249 | int fmc_device_register(struct fmc_device *fmc) | ||
250 | { | ||
251 | return fmc_device_register_n(&fmc, 1); | ||
252 | } | ||
253 | EXPORT_SYMBOL(fmc_device_register); | ||
254 | |||
255 | void fmc_device_unregister_n(struct fmc_device **devs, int n) | ||
256 | { | ||
257 | int i; | ||
258 | |||
259 | if (n < 1) | ||
260 | return; | ||
261 | |||
262 | /* Free devarray first, not used by the later loop */ | ||
263 | kfree(devs[0]->devarray); | ||
264 | |||
265 | for (i = 0; i < n; i++) { | ||
266 | if (devs[i]->flags == FMC_DEVICE_NO_MEZZANINE) | ||
267 | continue; | ||
268 | sysfs_remove_bin_file(&devs[i]->dev.kobj, &fmc_eeprom_attr); | ||
269 | device_del(&devs[i]->dev); | ||
270 | fmc_free_id_info(devs[i]); | ||
271 | put_device(&devs[i]->dev); | ||
272 | } | ||
273 | } | ||
274 | EXPORT_SYMBOL(fmc_device_unregister_n); | ||
275 | |||
276 | void fmc_device_unregister(struct fmc_device *fmc) | ||
277 | { | ||
278 | fmc_device_unregister_n(&fmc, 1); | ||
279 | } | ||
280 | EXPORT_SYMBOL(fmc_device_unregister); | ||
281 | |||
282 | /* Init and exit are trivial */ | ||
283 | static int fmc_init(void) | ||
284 | { | ||
285 | return bus_register(&fmc_bus_type); | ||
286 | } | ||
287 | |||
288 | static void fmc_exit(void) | ||
289 | { | ||
290 | bus_unregister(&fmc_bus_type); | ||
291 | } | ||
292 | |||
293 | module_init(fmc_init); | ||
294 | module_exit(fmc_exit); | ||
295 | |||
296 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/fmc/fmc-dump.c b/drivers/fmc/fmc-dump.c new file mode 100644 index 000000000000..c91afd6388f6 --- /dev/null +++ b/drivers/fmc/fmc-dump.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 CERN (www.cern.ch) | ||
3 | * Author: Alessandro Rubini <rubini@gnudd.com> | ||
4 | * | ||
5 | * Released according to the GNU GPL, version 2 or any later version. | ||
6 | * | ||
7 | * This work is part of the White Rabbit project, a research effort led | ||
8 | * by CERN, the European Institute for Nuclear Research. | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/moduleparam.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/fmc.h> | ||
14 | #include <linux/fmc-sdb.h> | ||
15 | |||
16 | static int fmc_must_dump_eeprom; | ||
17 | module_param_named(dump_eeprom, fmc_must_dump_eeprom, int, 0644); | ||
18 | static int fmc_must_dump_sdb; | ||
19 | module_param_named(dump_sdb, fmc_must_dump_sdb, int, 0644); | ||
20 | |||
21 | #define LINELEN 16 | ||
22 | |||
23 | /* Dumping 8k takes oh so much: avoid duplicate lines */ | ||
24 | static const uint8_t *dump_line(int addr, const uint8_t *line, | ||
25 | const uint8_t *prev) | ||
26 | { | ||
27 | int i; | ||
28 | |||
29 | if (!prev || memcmp(line, prev, LINELEN)) { | ||
30 | pr_info("%04x: ", addr); | ||
31 | for (i = 0; i < LINELEN; ) { | ||
32 | printk(KERN_CONT "%02x", line[i]); | ||
33 | i++; | ||
34 | printk(i & 3 ? " " : i & (LINELEN - 1) ? " " : "\n"); | ||
35 | } | ||
36 | return line; | ||
37 | } | ||
38 | /* repeated line */ | ||
39 | if (line == prev + LINELEN) | ||
40 | pr_info("[...]\n"); | ||
41 | return prev; | ||
42 | } | ||
43 | |||
44 | void fmc_dump_eeprom(const struct fmc_device *fmc) | ||
45 | { | ||
46 | const uint8_t *line, *prev; | ||
47 | int i; | ||
48 | |||
49 | if (!fmc_must_dump_eeprom) | ||
50 | return; | ||
51 | |||
52 | pr_info("FMC: %s (%s), slot %i, device %s\n", dev_name(fmc->hwdev), | ||
53 | fmc->carrier_name, fmc->slot_id, dev_name(&fmc->dev)); | ||
54 | pr_info("FMC: dumping eeprom 0x%x (%i) bytes\n", fmc->eeprom_len, | ||
55 | fmc->eeprom_len); | ||
56 | |||
57 | line = fmc->eeprom; | ||
58 | prev = NULL; | ||
59 | for (i = 0; i < fmc->eeprom_len; i += LINELEN, line += LINELEN) | ||
60 | prev = dump_line(i, line, prev); | ||
61 | } | ||
62 | |||
63 | void fmc_dump_sdb(const struct fmc_device *fmc) | ||
64 | { | ||
65 | const uint8_t *line, *prev; | ||
66 | int i, len; | ||
67 | |||
68 | if (!fmc->sdb) | ||
69 | return; | ||
70 | if (!fmc_must_dump_sdb) | ||
71 | return; | ||
72 | |||
73 | /* If the argument is not-zero, do simple dump (== show) */ | ||
74 | if (fmc_must_dump_sdb > 0) | ||
75 | fmc_show_sdb_tree(fmc); | ||
76 | |||
77 | if (fmc_must_dump_sdb == 1) | ||
78 | return; | ||
79 | |||
80 | /* If bigger than 1, dump it seriously, to help debugging */ | ||
81 | |||
82 | /* | ||
83 | * Here we should really use libsdbfs (which is designed to | ||
84 | * work in kernel space as well) , but it doesn't support | ||
85 | * directories yet, and it requires better intergration (it | ||
86 | * should be used instead of fmc-specific code). | ||
87 | * | ||
88 | * So, lazily, just dump the top-level array | ||
89 | */ | ||
90 | pr_info("FMC: %s (%s), slot %i, device %s\n", dev_name(fmc->hwdev), | ||
91 | fmc->carrier_name, fmc->slot_id, dev_name(&fmc->dev)); | ||
92 | pr_info("FMC: poor dump of sdb first level:\n"); | ||
93 | |||
94 | len = fmc->sdb->len * sizeof(union sdb_record); | ||
95 | line = (void *)fmc->sdb->record; | ||
96 | prev = NULL; | ||
97 | for (i = 0; i < len; i += LINELEN, line += LINELEN) | ||
98 | prev = dump_line(i, line, prev); | ||
99 | return; | ||
100 | } | ||
diff --git a/drivers/fmc/fmc-fakedev.c b/drivers/fmc/fmc-fakedev.c new file mode 100644 index 000000000000..941d0930969a --- /dev/null +++ b/drivers/fmc/fmc-fakedev.c | |||
@@ -0,0 +1,355 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 CERN (www.cern.ch) | ||
3 | * Author: Alessandro Rubini <rubini@gnudd.com> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * The software is provided "as is"; the copyright holders disclaim | ||
10 | * all warranties and liabilities, to the extent permitted by | ||
11 | * applicable law. | ||
12 | */ | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/firmware.h> | ||
19 | #include <linux/workqueue.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/fmc.h> | ||
22 | |||
23 | #define FF_EEPROM_SIZE 8192 /* The standard eeprom size */ | ||
24 | #define FF_MAX_MEZZANINES 4 /* Fakes a multi-mezzanine carrier */ | ||
25 | |||
26 | /* The user can pass up to 4 names of eeprom images to load */ | ||
27 | static char *ff_eeprom[FF_MAX_MEZZANINES]; | ||
28 | static int ff_nr_eeprom; | ||
29 | module_param_array_named(eeprom, ff_eeprom, charp, &ff_nr_eeprom, 0444); | ||
30 | |||
31 | /* The user can ask for a multi-mezzanine carrier, with the default eeprom */ | ||
32 | static int ff_nr_dev = 1; | ||
33 | module_param_named(ndev, ff_nr_dev, int, 0444); | ||
34 | |||
35 | |||
36 | /* Lazily, don't support the "standard" module parameters */ | ||
37 | |||
38 | /* | ||
39 | * Eeprom built from these commands: | ||
40 | |||
41 | ../fru-generator -v fake-vendor -n fake-design-for-testing \ | ||
42 | -s 01234 -p none > IPMI-FRU | ||
43 | |||
44 | gensdbfs . ../fake-eeprom.bin | ||
45 | */ | ||
46 | static char ff_eeimg[FF_MAX_MEZZANINES][FF_EEPROM_SIZE] = { | ||
47 | { | ||
48 | 0x01, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x00, 0xf2, 0x01, 0x0b, 0x00, 0xb2, | ||
49 | 0x86, 0x87, 0xcb, 0x66, 0x61, 0x6b, 0x65, 0x2d, 0x76, 0x65, 0x6e, 0x64, | ||
50 | 0x6f, 0x72, 0xd7, 0x66, 0x61, 0x6b, 0x65, 0x2d, 0x64, 0x65, 0x73, 0x69, | ||
51 | 0x67, 0x6e, 0x2d, 0x66, 0x6f, 0x72, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x69, | ||
52 | 0x6e, 0x67, 0xc5, 0x30, 0x31, 0x32, 0x33, 0x34, 0xc4, 0x6e, 0x6f, 0x6e, | ||
53 | 0x65, 0xda, 0x32, 0x30, 0x31, 0x32, 0x2d, 0x31, 0x31, 0x2d, 0x31, 0x39, | ||
54 | 0x20, 0x32, 0x32, 0x3a, 0x34, 0x32, 0x3a, 0x33, 0x30, 0x2e, 0x30, 0x37, | ||
55 | 0x34, 0x30, 0x35, 0x35, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, | ||
56 | 0x02, 0x02, 0x0d, 0xf7, 0xf8, 0x02, 0xb0, 0x04, 0x74, 0x04, 0xec, 0x04, | ||
57 | 0x00, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x02, 0x02, 0x0d, 0x5c, 0x93, 0x01, | ||
58 | 0x4a, 0x01, 0x39, 0x01, 0x5a, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x0b, | ||
59 | 0x02, 0x02, 0x0d, 0x63, 0x8c, 0x00, 0xfa, 0x00, 0xed, 0x00, 0x06, 0x01, | ||
60 | 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x01, 0x02, 0x0d, 0xfb, 0xf5, 0x05, | ||
61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
62 | 0x01, 0x02, 0x0d, 0xfc, 0xf4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
63 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0d, 0xfd, 0xf3, 0x03, | ||
64 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
65 | 0xfa, 0x82, 0x0b, 0xea, 0x8f, 0xa2, 0x12, 0x00, 0x00, 0x1e, 0x44, 0x00, | ||
66 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
68 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
69 | 0x00, 0x00, 0x00, 0x00, 0x53, 0x44, 0x42, 0x2d, 0x00, 0x03, 0x01, 0x01, | ||
70 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
71 | 0x00, 0x00, 0x01, 0xc4, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, | ||
72 | 0x2e, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, | ||
73 | 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
74 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
75 | 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, | ||
76 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc4, 0x46, 0x69, 0x6c, 0x65, | ||
77 | 0x44, 0x61, 0x74, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x01, | ||
78 | 0x00, 0x00, 0x00, 0x00, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x20, | ||
79 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, | ||
80 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, | ||
81 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, | ||
82 | 0x46, 0x69, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x49, 0x50, 0x4d, 0x49, | ||
83 | 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x49, 0x50, 0x4d, 0x49, | ||
84 | 0x2d, 0x46, 0x52, 0x55, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
85 | 0x20, 0x20, 0x20, 0x01, 0x66, 0x61, 0x6b, 0x65, 0x0a, | ||
86 | }, | ||
87 | }; | ||
88 | |||
89 | struct ff_dev { | ||
90 | struct fmc_device *fmc[FF_MAX_MEZZANINES]; | ||
91 | struct device dev; | ||
92 | }; | ||
93 | |||
94 | static struct ff_dev *ff_current_dev; /* We have 1 carrier, 1 slot */ | ||
95 | |||
96 | static int ff_reprogram(struct fmc_device *fmc, struct fmc_driver *drv, | ||
97 | char *gw) | ||
98 | { | ||
99 | const struct firmware *fw; | ||
100 | int ret; | ||
101 | |||
102 | if (!gw) { | ||
103 | /* program golden: success */ | ||
104 | fmc->flags &= ~FMC_DEVICE_HAS_CUSTOM; | ||
105 | fmc->flags |= FMC_DEVICE_HAS_GOLDEN; | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | dev_info(&fmc->dev, "reprogramming with %s\n", gw); | ||
110 | ret = request_firmware(&fw, gw, &fmc->dev); | ||
111 | if (ret < 0) { | ||
112 | dev_warn(&fmc->dev, "request firmware \"%s\": error %i\n", | ||
113 | gw, ret); | ||
114 | goto out; | ||
115 | } | ||
116 | fmc->flags &= ~FMC_DEVICE_HAS_GOLDEN; | ||
117 | fmc->flags |= FMC_DEVICE_HAS_CUSTOM; | ||
118 | |||
119 | out: | ||
120 | release_firmware(fw); | ||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | static int ff_irq_request(struct fmc_device *fmc, irq_handler_t handler, | ||
125 | char *name, int flags) | ||
126 | { | ||
127 | return -EOPNOTSUPP; | ||
128 | } | ||
129 | |||
130 | /* FIXME: should also have some fake FMC GPIO mapping */ | ||
131 | |||
132 | |||
133 | /* | ||
134 | * This work function is called when we changed the eeprom. It removes the | ||
135 | * current fmc device and registers a new one, with different identifiers. | ||
136 | */ | ||
137 | static struct ff_dev *ff_dev_create(void); /* defined later */ | ||
138 | |||
139 | static void ff_work_fn(struct work_struct *work) | ||
140 | { | ||
141 | struct ff_dev *ff = ff_current_dev; | ||
142 | int ret; | ||
143 | |||
144 | fmc_device_unregister_n(ff->fmc, ff_nr_dev); | ||
145 | device_unregister(&ff->dev); | ||
146 | ff_current_dev = NULL; | ||
147 | |||
148 | ff = ff_dev_create(); | ||
149 | if (IS_ERR(ff)) { | ||
150 | pr_warning("%s: can't re-create FMC devices\n", __func__); | ||
151 | return; | ||
152 | } | ||
153 | ret = fmc_device_register_n(ff->fmc, ff_nr_dev); | ||
154 | if (ret < 0) { | ||
155 | dev_warn(&ff->dev, "can't re-register FMC devices\n"); | ||
156 | device_unregister(&ff->dev); | ||
157 | return; | ||
158 | } | ||
159 | |||
160 | ff_current_dev = ff; | ||
161 | } | ||
162 | |||
163 | static DECLARE_DELAYED_WORK(ff_work, ff_work_fn); | ||
164 | |||
165 | |||
166 | /* low-level i2c */ | ||
167 | static int ff_eeprom_read(struct fmc_device *fmc, uint32_t offset, | ||
168 | void *buf, size_t size) | ||
169 | { | ||
170 | if (offset > FF_EEPROM_SIZE) | ||
171 | return -EINVAL; | ||
172 | if (offset + size > FF_EEPROM_SIZE) | ||
173 | size = FF_EEPROM_SIZE - offset; | ||
174 | memcpy(buf, fmc->eeprom + offset, size); | ||
175 | return size; | ||
176 | } | ||
177 | |||
178 | static int ff_eeprom_write(struct fmc_device *fmc, uint32_t offset, | ||
179 | const void *buf, size_t size) | ||
180 | { | ||
181 | if (offset > FF_EEPROM_SIZE) | ||
182 | return -EINVAL; | ||
183 | if (offset + size > FF_EEPROM_SIZE) | ||
184 | size = FF_EEPROM_SIZE - offset; | ||
185 | dev_info(&fmc->dev, "write_eeprom: offset %i, size %zi\n", | ||
186 | (int)offset, size); | ||
187 | memcpy(fmc->eeprom + offset, buf, size); | ||
188 | schedule_delayed_work(&ff_work, HZ * 2); /* remove, replug, in 2s */ | ||
189 | return size; | ||
190 | } | ||
191 | |||
192 | /* i2c operations for fmc */ | ||
193 | static int ff_read_ee(struct fmc_device *fmc, int pos, void *data, int len) | ||
194 | { | ||
195 | if (!(fmc->flags & FMC_DEVICE_HAS_GOLDEN)) | ||
196 | return -EOPNOTSUPP; | ||
197 | return ff_eeprom_read(fmc, pos, data, len); | ||
198 | } | ||
199 | |||
200 | static int ff_write_ee(struct fmc_device *fmc, int pos, | ||
201 | const void *data, int len) | ||
202 | { | ||
203 | if (!(fmc->flags & FMC_DEVICE_HAS_GOLDEN)) | ||
204 | return -EOPNOTSUPP; | ||
205 | return ff_eeprom_write(fmc, pos, data, len); | ||
206 | } | ||
207 | |||
208 | /* readl and writel do not do anything. Don't waste RAM with "base" */ | ||
209 | static uint32_t ff_readl(struct fmc_device *fmc, int offset) | ||
210 | { | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static void ff_writel(struct fmc_device *fmc, uint32_t value, int offset) | ||
215 | { | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | /* validate is useful so fmc-write-eeprom will not reprogram every 2 seconds */ | ||
220 | static int ff_validate(struct fmc_device *fmc, struct fmc_driver *drv) | ||
221 | { | ||
222 | int i; | ||
223 | |||
224 | if (!drv->busid_n) | ||
225 | return 0; /* everyhing is valid */ | ||
226 | for (i = 0; i < drv->busid_n; i++) | ||
227 | if (drv->busid_val[i] == fmc->device_id) | ||
228 | return i; | ||
229 | return -ENOENT; | ||
230 | } | ||
231 | |||
232 | |||
233 | |||
234 | static struct fmc_operations ff_fmc_operations = { | ||
235 | .read32 = ff_readl, | ||
236 | .write32 = ff_writel, | ||
237 | .reprogram = ff_reprogram, | ||
238 | .irq_request = ff_irq_request, | ||
239 | .read_ee = ff_read_ee, | ||
240 | .write_ee = ff_write_ee, | ||
241 | .validate = ff_validate, | ||
242 | }; | ||
243 | |||
244 | /* This device is kmalloced: release it */ | ||
245 | static void ff_dev_release(struct device *dev) | ||
246 | { | ||
247 | struct ff_dev *ff = container_of(dev, struct ff_dev, dev); | ||
248 | kfree(ff); | ||
249 | } | ||
250 | |||
251 | static struct fmc_device ff_template_fmc = { | ||
252 | .version = FMC_VERSION, | ||
253 | .owner = THIS_MODULE, | ||
254 | .carrier_name = "fake-fmc-carrier", | ||
255 | .device_id = 0xf001, /* fool */ | ||
256 | .eeprom_len = sizeof(ff_eeimg[0]), | ||
257 | .memlen = 0x1000, /* 4k, to show something */ | ||
258 | .op = &ff_fmc_operations, | ||
259 | .hwdev = NULL, /* filled at creation time */ | ||
260 | .flags = FMC_DEVICE_HAS_GOLDEN, | ||
261 | }; | ||
262 | |||
263 | static struct ff_dev *ff_dev_create(void) | ||
264 | { | ||
265 | struct ff_dev *ff; | ||
266 | struct fmc_device *fmc; | ||
267 | int i, ret; | ||
268 | |||
269 | ff = kzalloc(sizeof(*ff), GFP_KERNEL); | ||
270 | if (!ff) | ||
271 | return ERR_PTR(-ENOMEM); | ||
272 | dev_set_name(&ff->dev, "fake-fmc-carrier"); | ||
273 | ff->dev.release = ff_dev_release; | ||
274 | |||
275 | ret = device_register(&ff->dev); | ||
276 | if (ret < 0) { | ||
277 | put_device(&ff->dev); | ||
278 | return ERR_PTR(ret); | ||
279 | } | ||
280 | |||
281 | /* Create fmc structures that refer to this new "hw" device */ | ||
282 | for (i = 0; i < ff_nr_dev; i++) { | ||
283 | fmc = kmemdup(&ff_template_fmc, sizeof(ff_template_fmc), | ||
284 | GFP_KERNEL); | ||
285 | fmc->hwdev = &ff->dev; | ||
286 | fmc->carrier_data = ff; | ||
287 | fmc->nr_slots = ff_nr_dev; | ||
288 | /* the following fields are different for each slot */ | ||
289 | fmc->eeprom = ff_eeimg[i]; | ||
290 | fmc->eeprom_addr = 0x50 + 2 * i; | ||
291 | fmc->slot_id = i; | ||
292 | ff->fmc[i] = fmc; | ||
293 | /* increment the identifier, each must be different */ | ||
294 | ff_template_fmc.device_id++; | ||
295 | } | ||
296 | return ff; | ||
297 | } | ||
298 | |||
299 | /* init and exit */ | ||
300 | static int ff_init(void) | ||
301 | { | ||
302 | struct ff_dev *ff; | ||
303 | const struct firmware *fw; | ||
304 | int i, len, ret = 0; | ||
305 | |||
306 | /* Replicate the default eeprom for the max number of mezzanines */ | ||
307 | for (i = 1; i < FF_MAX_MEZZANINES; i++) | ||
308 | memcpy(ff_eeimg[i], ff_eeimg[0], sizeof(ff_eeimg[0])); | ||
309 | |||
310 | if (ff_nr_eeprom > ff_nr_dev) | ||
311 | ff_nr_dev = ff_nr_eeprom; | ||
312 | |||
313 | ff = ff_dev_create(); | ||
314 | if (IS_ERR(ff)) | ||
315 | return PTR_ERR(ff); | ||
316 | |||
317 | /* If the user passed "eeprom=" as a parameter, fetch them */ | ||
318 | for (i = 0; i < ff_nr_eeprom; i++) { | ||
319 | if (!strlen(ff_eeprom[i])) | ||
320 | continue; | ||
321 | ret = request_firmware(&fw, ff_eeprom[i], &ff->dev); | ||
322 | if (ret < 0) { | ||
323 | dev_err(&ff->dev, "Mezzanine %i: can't load \"%s\" " | ||
324 | "(error %i)\n", i, ff_eeprom[i], -ret); | ||
325 | } else { | ||
326 | len = min_t(size_t, fw->size, (size_t)FF_EEPROM_SIZE); | ||
327 | memcpy(ff_eeimg[i], fw->data, len); | ||
328 | release_firmware(fw); | ||
329 | dev_info(&ff->dev, "Mezzanine %i: eeprom \"%s\"\n", i, | ||
330 | ff_eeprom[i]); | ||
331 | } | ||
332 | } | ||
333 | |||
334 | ret = fmc_device_register_n(ff->fmc, ff_nr_dev); | ||
335 | if (ret) { | ||
336 | device_unregister(&ff->dev); | ||
337 | return ret; | ||
338 | } | ||
339 | ff_current_dev = ff; | ||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | static void ff_exit(void) | ||
344 | { | ||
345 | if (ff_current_dev) { | ||
346 | fmc_device_unregister_n(ff_current_dev->fmc, ff_nr_dev); | ||
347 | device_unregister(&ff_current_dev->dev); | ||
348 | } | ||
349 | cancel_delayed_work_sync(&ff_work); | ||
350 | } | ||
351 | |||
352 | module_init(ff_init); | ||
353 | module_exit(ff_exit); | ||
354 | |||
355 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/drivers/fmc/fmc-match.c b/drivers/fmc/fmc-match.c new file mode 100644 index 000000000000..104a5efc2207 --- /dev/null +++ b/drivers/fmc/fmc-match.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 CERN (www.cern.ch) | ||
3 | * Author: Alessandro Rubini <rubini@gnudd.com> | ||
4 | * | ||
5 | * Released according to the GNU GPL, version 2 or any later version. | ||
6 | * | ||
7 | * This work is part of the White Rabbit project, a research effort led | ||
8 | * by CERN, the European Institute for Nuclear Research. | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/fmc.h> | ||
13 | #include <linux/ipmi-fru.h> | ||
14 | |||
15 | /* The fru parser is both user and kernel capable: it needs alloc */ | ||
16 | void *fru_alloc(size_t size) | ||
17 | { | ||
18 | return kzalloc(size, GFP_KERNEL); | ||
19 | } | ||
20 | |||
21 | /* The actual match function */ | ||
22 | int fmc_match(struct device *dev, struct device_driver *drv) | ||
23 | { | ||
24 | struct fmc_driver *fdrv = to_fmc_driver(drv); | ||
25 | struct fmc_device *fdev = to_fmc_device(dev); | ||
26 | struct fmc_fru_id *fid; | ||
27 | int i, matched = 0; | ||
28 | |||
29 | /* This currently only matches the EEPROM (FRU id) */ | ||
30 | fid = fdrv->id_table.fru_id; | ||
31 | if (!fid) { | ||
32 | dev_warn(&fdev->dev, "Driver has no ID: matches all\n"); | ||
33 | matched = 1; | ||
34 | } else { | ||
35 | if (!fdev->id.manufacturer || !fdev->id.product_name) | ||
36 | return 0; /* the device has no FRU information */ | ||
37 | for (i = 0; i < fdrv->id_table.fru_id_nr; i++, fid++) { | ||
38 | if (fid->manufacturer && | ||
39 | strcmp(fid->manufacturer, fdev->id.manufacturer)) | ||
40 | continue; | ||
41 | if (fid->product_name && | ||
42 | strcmp(fid->product_name, fdev->id.product_name)) | ||
43 | continue; | ||
44 | matched = 1; | ||
45 | break; | ||
46 | } | ||
47 | } | ||
48 | |||
49 | /* FIXME: match SDB contents */ | ||
50 | return matched; | ||
51 | } | ||
52 | |||
53 | /* This function creates ID info for a newly registered device */ | ||
54 | int fmc_fill_id_info(struct fmc_device *fmc) | ||
55 | { | ||
56 | struct fru_common_header *h; | ||
57 | struct fru_board_info_area *bia; | ||
58 | int ret, allocated = 0; | ||
59 | |||
60 | /* If we know the eeprom length, try to read it off the device */ | ||
61 | if (fmc->eeprom_len && !fmc->eeprom) { | ||
62 | fmc->eeprom = kzalloc(fmc->eeprom_len, GFP_KERNEL); | ||
63 | if (!fmc->eeprom) | ||
64 | return -ENOMEM; | ||
65 | allocated = 1; | ||
66 | ret = fmc->op->read_ee(fmc, 0, fmc->eeprom, fmc->eeprom_len); | ||
67 | if (ret < 0) | ||
68 | goto out; | ||
69 | } | ||
70 | |||
71 | /* If no eeprom, continue with other matches */ | ||
72 | if (!fmc->eeprom) | ||
73 | return 0; | ||
74 | |||
75 | dev_info(fmc->hwdev, "mezzanine %i\n", fmc->slot_id); /* header */ | ||
76 | |||
77 | /* So we have the eeprom: parse the FRU part (if any) */ | ||
78 | h = (void *)fmc->eeprom; | ||
79 | if (h->format != 1) { | ||
80 | pr_info(" EEPROM has no FRU information\n"); | ||
81 | goto out; | ||
82 | } | ||
83 | if (!fru_header_cksum_ok(h)) { | ||
84 | pr_info(" FRU: wrong header checksum\n"); | ||
85 | goto out; | ||
86 | } | ||
87 | bia = fru_get_board_area(h); | ||
88 | if (!fru_bia_cksum_ok(bia)) { | ||
89 | pr_info(" FRU: wrong board area checksum\n"); | ||
90 | goto out; | ||
91 | } | ||
92 | fmc->id.manufacturer = fru_get_board_manufacturer(h); | ||
93 | fmc->id.product_name = fru_get_product_name(h); | ||
94 | pr_info(" Manufacturer: %s\n", fmc->id.manufacturer); | ||
95 | pr_info(" Product name: %s\n", fmc->id.product_name); | ||
96 | |||
97 | /* Create the short name (FIXME: look in sdb as well) */ | ||
98 | fmc->mezzanine_name = kstrdup(fmc->id.product_name, GFP_KERNEL); | ||
99 | |||
100 | out: | ||
101 | if (allocated) { | ||
102 | kfree(fmc->eeprom); | ||
103 | fmc->eeprom = NULL; | ||
104 | } | ||
105 | return 0; /* no error: let other identification work */ | ||
106 | } | ||
107 | |||
108 | /* Some ID data is allocated using fru_alloc() above, so release it */ | ||
109 | void fmc_free_id_info(struct fmc_device *fmc) | ||
110 | { | ||
111 | kfree(fmc->mezzanine_name); | ||
112 | kfree(fmc->id.manufacturer); | ||
113 | kfree(fmc->id.product_name); | ||
114 | } | ||
diff --git a/drivers/fmc/fmc-sdb.c b/drivers/fmc/fmc-sdb.c new file mode 100644 index 000000000000..79adc39221ea --- /dev/null +++ b/drivers/fmc/fmc-sdb.c | |||
@@ -0,0 +1,266 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 CERN (www.cern.ch) | ||
3 | * Author: Alessandro Rubini <rubini@gnudd.com> | ||
4 | * | ||
5 | * Released according to the GNU GPL, version 2 or any later version. | ||
6 | * | ||
7 | * This work is part of the White Rabbit project, a research effort led | ||
8 | * by CERN, the European Institute for Nuclear Research. | ||
9 | */ | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/fmc.h> | ||
13 | #include <linux/sdb.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/fmc-sdb.h> | ||
16 | #include <asm/byteorder.h> | ||
17 | |||
18 | static uint32_t __sdb_rd(struct fmc_device *fmc, unsigned long address, | ||
19 | int convert) | ||
20 | { | ||
21 | uint32_t res = fmc_readl(fmc, address); | ||
22 | if (convert) | ||
23 | return __be32_to_cpu(res); | ||
24 | return res; | ||
25 | } | ||
26 | |||
27 | static struct sdb_array *__fmc_scan_sdb_tree(struct fmc_device *fmc, | ||
28 | unsigned long sdb_addr, | ||
29 | unsigned long reg_base, int level) | ||
30 | { | ||
31 | uint32_t onew; | ||
32 | int i, j, n, convert = 0; | ||
33 | struct sdb_array *arr, *sub; | ||
34 | |||
35 | onew = fmc_readl(fmc, sdb_addr); | ||
36 | if (onew == SDB_MAGIC) { | ||
37 | /* Uh! If we are little-endian, we must convert */ | ||
38 | if (SDB_MAGIC != __be32_to_cpu(SDB_MAGIC)) | ||
39 | convert = 1; | ||
40 | } else if (onew == __be32_to_cpu(SDB_MAGIC)) { | ||
41 | /* ok, don't convert */ | ||
42 | } else { | ||
43 | return ERR_PTR(-ENOENT); | ||
44 | } | ||
45 | /* So, the magic was there: get the count from offset 4*/ | ||
46 | onew = __sdb_rd(fmc, sdb_addr + 4, convert); | ||
47 | n = __be16_to_cpu(*(uint16_t *)&onew); | ||
48 | arr = kzalloc(sizeof(*arr), GFP_KERNEL); | ||
49 | if (!arr) | ||
50 | return ERR_PTR(-ENOMEM); | ||
51 | arr->record = kzalloc(sizeof(arr->record[0]) * n, GFP_KERNEL); | ||
52 | arr->subtree = kzalloc(sizeof(arr->subtree[0]) * n, GFP_KERNEL); | ||
53 | if (!arr->record || !arr->subtree) { | ||
54 | kfree(arr->record); | ||
55 | kfree(arr->subtree); | ||
56 | kfree(arr); | ||
57 | return ERR_PTR(-ENOMEM); | ||
58 | } | ||
59 | |||
60 | arr->len = n; | ||
61 | arr->level = level; | ||
62 | arr->fmc = fmc; | ||
63 | for (i = 0; i < n; i++) { | ||
64 | union sdb_record *r; | ||
65 | |||
66 | for (j = 0; j < sizeof(arr->record[0]); j += 4) { | ||
67 | *(uint32_t *)((void *)(arr->record + i) + j) = | ||
68 | __sdb_rd(fmc, sdb_addr + (i * 64) + j, convert); | ||
69 | } | ||
70 | r = &arr->record[i]; | ||
71 | arr->subtree[i] = ERR_PTR(-ENODEV); | ||
72 | if (r->empty.record_type == sdb_type_bridge) { | ||
73 | struct sdb_component *c = &r->bridge.sdb_component; | ||
74 | uint64_t subaddr = __be64_to_cpu(r->bridge.sdb_child); | ||
75 | uint64_t newbase = __be64_to_cpu(c->addr_first); | ||
76 | |||
77 | subaddr += reg_base; | ||
78 | newbase += reg_base; | ||
79 | sub = __fmc_scan_sdb_tree(fmc, subaddr, newbase, | ||
80 | level + 1); | ||
81 | arr->subtree[i] = sub; /* may be error */ | ||
82 | if (IS_ERR(sub)) | ||
83 | continue; | ||
84 | sub->parent = arr; | ||
85 | sub->baseaddr = newbase; | ||
86 | } | ||
87 | } | ||
88 | return arr; | ||
89 | } | ||
90 | |||
91 | int fmc_scan_sdb_tree(struct fmc_device *fmc, unsigned long address) | ||
92 | { | ||
93 | struct sdb_array *ret; | ||
94 | if (fmc->sdb) | ||
95 | return -EBUSY; | ||
96 | ret = __fmc_scan_sdb_tree(fmc, address, 0 /* regs */, 0); | ||
97 | if (IS_ERR(ret)) | ||
98 | return PTR_ERR(ret); | ||
99 | fmc->sdb = ret; | ||
100 | return 0; | ||
101 | } | ||
102 | EXPORT_SYMBOL(fmc_scan_sdb_tree); | ||
103 | |||
104 | static void __fmc_sdb_free(struct sdb_array *arr) | ||
105 | { | ||
106 | int i, n; | ||
107 | |||
108 | if (!arr) | ||
109 | return; | ||
110 | n = arr->len; | ||
111 | for (i = 0; i < n; i++) { | ||
112 | if (IS_ERR(arr->subtree[i])) | ||
113 | continue; | ||
114 | __fmc_sdb_free(arr->subtree[i]); | ||
115 | } | ||
116 | kfree(arr->record); | ||
117 | kfree(arr->subtree); | ||
118 | kfree(arr); | ||
119 | } | ||
120 | |||
121 | int fmc_free_sdb_tree(struct fmc_device *fmc) | ||
122 | { | ||
123 | __fmc_sdb_free(fmc->sdb); | ||
124 | fmc->sdb = NULL; | ||
125 | return 0; | ||
126 | } | ||
127 | EXPORT_SYMBOL(fmc_free_sdb_tree); | ||
128 | |||
129 | /* This helper calls reprogram and inizialized sdb as well */ | ||
130 | int fmc_reprogram(struct fmc_device *fmc, struct fmc_driver *d, char *gw, | ||
131 | int sdb_entry) | ||
132 | { | ||
133 | int ret; | ||
134 | |||
135 | ret = fmc->op->reprogram(fmc, d, gw); | ||
136 | if (ret < 0) | ||
137 | return ret; | ||
138 | if (sdb_entry < 0) | ||
139 | return ret; | ||
140 | |||
141 | /* We are required to find SDB at a given offset */ | ||
142 | ret = fmc_scan_sdb_tree(fmc, sdb_entry); | ||
143 | if (ret < 0) { | ||
144 | dev_err(&fmc->dev, "Can't find SDB at address 0x%x\n", | ||
145 | sdb_entry); | ||
146 | return -ENODEV; | ||
147 | } | ||
148 | fmc_dump_sdb(fmc); | ||
149 | return 0; | ||
150 | } | ||
151 | EXPORT_SYMBOL(fmc_reprogram); | ||
152 | |||
153 | static void __fmc_show_sdb_tree(const struct fmc_device *fmc, | ||
154 | const struct sdb_array *arr) | ||
155 | { | ||
156 | int i, j, n = arr->len, level = arr->level; | ||
157 | const struct sdb_array *ap; | ||
158 | |||
159 | for (i = 0; i < n; i++) { | ||
160 | unsigned long base; | ||
161 | union sdb_record *r; | ||
162 | struct sdb_product *p; | ||
163 | struct sdb_component *c; | ||
164 | r = &arr->record[i]; | ||
165 | c = &r->dev.sdb_component; | ||
166 | p = &c->product; | ||
167 | base = 0; | ||
168 | for (ap = arr; ap; ap = ap->parent) | ||
169 | base += ap->baseaddr; | ||
170 | dev_info(&fmc->dev, "SDB: "); | ||
171 | |||
172 | for (j = 0; j < level; j++) | ||
173 | printk(KERN_CONT " "); | ||
174 | switch (r->empty.record_type) { | ||
175 | case sdb_type_interconnect: | ||
176 | printk(KERN_CONT "%08llx:%08x %.19s\n", | ||
177 | __be64_to_cpu(p->vendor_id), | ||
178 | __be32_to_cpu(p->device_id), | ||
179 | p->name); | ||
180 | break; | ||
181 | case sdb_type_device: | ||
182 | printk(KERN_CONT "%08llx:%08x %.19s (%08llx-%08llx)\n", | ||
183 | __be64_to_cpu(p->vendor_id), | ||
184 | __be32_to_cpu(p->device_id), | ||
185 | p->name, | ||
186 | __be64_to_cpu(c->addr_first) + base, | ||
187 | __be64_to_cpu(c->addr_last) + base); | ||
188 | break; | ||
189 | case sdb_type_bridge: | ||
190 | printk(KERN_CONT "%08llx:%08x %.19s (bridge: %08llx)\n", | ||
191 | __be64_to_cpu(p->vendor_id), | ||
192 | __be32_to_cpu(p->device_id), | ||
193 | p->name, | ||
194 | __be64_to_cpu(c->addr_first) + base); | ||
195 | if (IS_ERR(arr->subtree[i])) { | ||
196 | printk(KERN_CONT "(bridge error %li)\n", | ||
197 | PTR_ERR(arr->subtree[i])); | ||
198 | break; | ||
199 | } | ||
200 | __fmc_show_sdb_tree(fmc, arr->subtree[i]); | ||
201 | break; | ||
202 | case sdb_type_integration: | ||
203 | printk(KERN_CONT "integration\n"); | ||
204 | break; | ||
205 | case sdb_type_repo_url: | ||
206 | printk(KERN_CONT "repo-url\n"); | ||
207 | break; | ||
208 | case sdb_type_synthesis: | ||
209 | printk(KERN_CONT "synthesis-info\n"); | ||
210 | break; | ||
211 | case sdb_type_empty: | ||
212 | printk(KERN_CONT "empty\n"); | ||
213 | break; | ||
214 | default: | ||
215 | printk(KERN_CONT "UNKNOWN TYPE 0x%02x\n", | ||
216 | r->empty.record_type); | ||
217 | break; | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | |||
222 | void fmc_show_sdb_tree(const struct fmc_device *fmc) | ||
223 | { | ||
224 | if (!fmc->sdb) | ||
225 | return; | ||
226 | __fmc_show_sdb_tree(fmc, fmc->sdb); | ||
227 | } | ||
228 | EXPORT_SYMBOL(fmc_show_sdb_tree); | ||
229 | |||
230 | signed long fmc_find_sdb_device(struct sdb_array *tree, | ||
231 | uint64_t vid, uint32_t did, unsigned long *sz) | ||
232 | { | ||
233 | signed long res = -ENODEV; | ||
234 | union sdb_record *r; | ||
235 | struct sdb_product *p; | ||
236 | struct sdb_component *c; | ||
237 | int i, n = tree->len; | ||
238 | uint64_t last, first; | ||
239 | |||
240 | /* FIXME: what if the first interconnect is not at zero? */ | ||
241 | for (i = 0; i < n; i++) { | ||
242 | r = &tree->record[i]; | ||
243 | c = &r->dev.sdb_component; | ||
244 | p = &c->product; | ||
245 | |||
246 | if (!IS_ERR(tree->subtree[i])) | ||
247 | res = fmc_find_sdb_device(tree->subtree[i], | ||
248 | vid, did, sz); | ||
249 | if (res >= 0) | ||
250 | return res + tree->baseaddr; | ||
251 | if (r->empty.record_type != sdb_type_device) | ||
252 | continue; | ||
253 | if (__be64_to_cpu(p->vendor_id) != vid) | ||
254 | continue; | ||
255 | if (__be32_to_cpu(p->device_id) != did) | ||
256 | continue; | ||
257 | /* found */ | ||
258 | last = __be64_to_cpu(c->addr_last); | ||
259 | first = __be64_to_cpu(c->addr_first); | ||
260 | if (sz) | ||
261 | *sz = (typeof(*sz))(last + 1 - first); | ||
262 | return first + tree->baseaddr; | ||
263 | } | ||
264 | return res; | ||
265 | } | ||
266 | EXPORT_SYMBOL(fmc_find_sdb_device); | ||
diff --git a/drivers/fmc/fmc-trivial.c b/drivers/fmc/fmc-trivial.c new file mode 100644 index 000000000000..6c590f54c79d --- /dev/null +++ b/drivers/fmc/fmc-trivial.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 CERN (www.cern.ch) | ||
3 | * Author: Alessandro Rubini <rubini@gnudd.com> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * The software is provided "as is"; the copyright holders disclaim | ||
10 | * all warranties and liabilities, to the extent permitted by | ||
11 | * applicable law. | ||
12 | */ | ||
13 | |||
14 | /* A trivial fmc driver that can load a gateware file and reports interrupts */ | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/fmc.h> | ||
20 | |||
21 | static struct fmc_driver t_drv; /* initialized later */ | ||
22 | |||
23 | static irqreturn_t t_handler(int irq, void *dev_id) | ||
24 | { | ||
25 | struct fmc_device *fmc = dev_id; | ||
26 | |||
27 | fmc->op->irq_ack(fmc); | ||
28 | dev_info(&fmc->dev, "received irq %i\n", irq); | ||
29 | return IRQ_HANDLED; | ||
30 | } | ||
31 | |||
32 | static struct fmc_gpio t_gpio[] = { | ||
33 | { | ||
34 | .gpio = FMC_GPIO_IRQ(0), | ||
35 | .mode = GPIOF_DIR_IN, | ||
36 | .irqmode = IRQF_TRIGGER_RISING, | ||
37 | }, { | ||
38 | .gpio = FMC_GPIO_IRQ(1), | ||
39 | .mode = GPIOF_DIR_IN, | ||
40 | .irqmode = IRQF_TRIGGER_RISING, | ||
41 | } | ||
42 | }; | ||
43 | |||
44 | static int t_probe(struct fmc_device *fmc) | ||
45 | { | ||
46 | int ret; | ||
47 | int index = 0; | ||
48 | |||
49 | if (fmc->op->validate) | ||
50 | index = fmc->op->validate(fmc, &t_drv); | ||
51 | if (index < 0) | ||
52 | return -EINVAL; /* not our device: invalid */ | ||
53 | |||
54 | ret = fmc->op->irq_request(fmc, t_handler, "fmc-trivial", IRQF_SHARED); | ||
55 | if (ret < 0) | ||
56 | return ret; | ||
57 | /* ignore error code of call below, we really don't care */ | ||
58 | fmc->op->gpio_config(fmc, t_gpio, ARRAY_SIZE(t_gpio)); | ||
59 | |||
60 | /* Reprogram, if asked to. ESRCH == no filename specified */ | ||
61 | ret = -ESRCH; | ||
62 | if (fmc->op->reprogram) | ||
63 | ret = fmc->op->reprogram(fmc, &t_drv, ""); | ||
64 | if (ret == -ESRCH) | ||
65 | ret = 0; | ||
66 | if (ret < 0) | ||
67 | fmc->op->irq_free(fmc); | ||
68 | |||
69 | /* FIXME: reprogram LM32 too */ | ||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | static int t_remove(struct fmc_device *fmc) | ||
74 | { | ||
75 | fmc->op->irq_free(fmc); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static struct fmc_driver t_drv = { | ||
80 | .version = FMC_VERSION, | ||
81 | .driver.name = KBUILD_MODNAME, | ||
82 | .probe = t_probe, | ||
83 | .remove = t_remove, | ||
84 | /* no table, as the current match just matches everything */ | ||
85 | }; | ||
86 | |||
87 | /* We accept the generic parameters */ | ||
88 | FMC_PARAM_BUSID(t_drv); | ||
89 | FMC_PARAM_GATEWARE(t_drv); | ||
90 | |||
91 | static int t_init(void) | ||
92 | { | ||
93 | int ret; | ||
94 | |||
95 | ret = fmc_driver_register(&t_drv); | ||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | static void t_exit(void) | ||
100 | { | ||
101 | fmc_driver_unregister(&t_drv); | ||
102 | } | ||
103 | |||
104 | module_init(t_init); | ||
105 | module_exit(t_exit); | ||
106 | |||
107 | MODULE_LICENSE("Dual BSD/GPL"); | ||
diff --git a/drivers/fmc/fmc-write-eeprom.c b/drivers/fmc/fmc-write-eeprom.c new file mode 100644 index 000000000000..2cc680dd604d --- /dev/null +++ b/drivers/fmc/fmc-write-eeprom.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 CERN (www.cern.ch) | ||
3 | * Author: Alessandro Rubini <rubini@gnudd.com> | ||
4 | * | ||
5 | * Released according to the GNU GPL, version 2 or any later version. | ||
6 | * | ||
7 | * This work is part of the White Rabbit project, a research effort led | ||
8 | * by CERN, the European Institute for Nuclear Research. | ||
9 | */ | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/string.h> | ||
12 | #include <linux/firmware.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/fmc.h> | ||
15 | #include <asm/unaligned.h> | ||
16 | |||
17 | /* | ||
18 | * This module uses the firmware loader to program the whole or part | ||
19 | * of the FMC eeprom. The meat is in the _run functions. However, no | ||
20 | * default file name is provided, to avoid accidental mishaps. Also, | ||
21 | * you must pass the busid argument | ||
22 | */ | ||
23 | static struct fmc_driver fwe_drv; | ||
24 | |||
25 | FMC_PARAM_BUSID(fwe_drv); | ||
26 | |||
27 | /* The "file=" is like the generic "gateware=" used elsewhere */ | ||
28 | static char *fwe_file[FMC_MAX_CARDS]; | ||
29 | static int fwe_file_n; | ||
30 | module_param_array_named(file, fwe_file, charp, &fwe_file_n, 444); | ||
31 | |||
32 | static int fwe_run_tlv(struct fmc_device *fmc, const struct firmware *fw, | ||
33 | int write) | ||
34 | { | ||
35 | const uint8_t *p = fw->data; | ||
36 | int len = fw->size; | ||
37 | uint16_t thislen, thisaddr; | ||
38 | int err; | ||
39 | |||
40 | /* format is: 'w' addr16 len16 data... */ | ||
41 | while (len > 5) { | ||
42 | thisaddr = get_unaligned_le16(p+1); | ||
43 | thislen = get_unaligned_le16(p+3); | ||
44 | if (p[0] != 'w' || thislen + 5 > len) { | ||
45 | dev_err(&fmc->dev, "invalid tlv at offset %ti\n", | ||
46 | p - fw->data); | ||
47 | return -EINVAL; | ||
48 | } | ||
49 | err = 0; | ||
50 | if (write) { | ||
51 | dev_info(&fmc->dev, "write %i bytes at 0x%04x\n", | ||
52 | thislen, thisaddr); | ||
53 | err = fmc->op->write_ee(fmc, thisaddr, p + 5, thislen); | ||
54 | } | ||
55 | if (err < 0) { | ||
56 | dev_err(&fmc->dev, "write failure @0x%04x\n", | ||
57 | thisaddr); | ||
58 | return err; | ||
59 | } | ||
60 | p += 5 + thislen; | ||
61 | len -= 5 + thislen; | ||
62 | } | ||
63 | if (write) | ||
64 | dev_info(&fmc->dev, "write_eeprom: success\n"); | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static int fwe_run_bin(struct fmc_device *fmc, const struct firmware *fw) | ||
69 | { | ||
70 | int ret; | ||
71 | |||
72 | dev_info(&fmc->dev, "programming %zi bytes\n", fw->size); | ||
73 | ret = fmc->op->write_ee(fmc, 0, (void *)fw->data, fw->size); | ||
74 | if (ret < 0) { | ||
75 | dev_info(&fmc->dev, "write_eeprom: error %i\n", ret); | ||
76 | return ret; | ||
77 | } | ||
78 | dev_info(&fmc->dev, "write_eeprom: success\n"); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int fwe_run(struct fmc_device *fmc, const struct firmware *fw, char *s) | ||
83 | { | ||
84 | char *last4 = s + strlen(s) - 4; | ||
85 | int err; | ||
86 | |||
87 | if (!strcmp(last4, ".bin")) | ||
88 | return fwe_run_bin(fmc, fw); | ||
89 | if (!strcmp(last4, ".tlv")) { | ||
90 | err = fwe_run_tlv(fmc, fw, 0); | ||
91 | if (!err) | ||
92 | err = fwe_run_tlv(fmc, fw, 1); | ||
93 | return err; | ||
94 | } | ||
95 | dev_err(&fmc->dev, "invalid file name \"%s\"\n", s); | ||
96 | return -EINVAL; | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * Programming is done at probe time. Morever, only those listed with | ||
101 | * busid= are programmed. | ||
102 | * card is probed for, only one is programmed. Unfortunately, it's | ||
103 | * difficult to know in advance when probing the first card if others | ||
104 | * are there. | ||
105 | */ | ||
106 | int fwe_probe(struct fmc_device *fmc) | ||
107 | { | ||
108 | int err, index = 0; | ||
109 | const struct firmware *fw; | ||
110 | struct device *dev = &fmc->dev; | ||
111 | char *s; | ||
112 | |||
113 | if (!fwe_drv.busid_n) { | ||
114 | dev_err(dev, "%s: no busid passed, refusing all cards\n", | ||
115 | KBUILD_MODNAME); | ||
116 | return -ENODEV; | ||
117 | } | ||
118 | if (fmc->op->validate) | ||
119 | index = fmc->op->validate(fmc, &fwe_drv); | ||
120 | if (index < 0) { | ||
121 | pr_err("%s: refusing device \"%s\"\n", KBUILD_MODNAME, | ||
122 | dev_name(dev)); | ||
123 | return -ENODEV; | ||
124 | } | ||
125 | if (index >= fwe_file_n) { | ||
126 | pr_err("%s: no filename for device index %i\n", | ||
127 | KBUILD_MODNAME, index); | ||
128 | return -ENODEV; | ||
129 | } | ||
130 | s = fwe_file[index]; | ||
131 | if (!s) { | ||
132 | pr_err("%s: no filename for \"%s\" not programming\n", | ||
133 | KBUILD_MODNAME, dev_name(dev)); | ||
134 | return -ENOENT; | ||
135 | } | ||
136 | err = request_firmware(&fw, s, dev); | ||
137 | if (err < 0) { | ||
138 | dev_err(&fmc->dev, "request firmware \"%s\": error %i\n", | ||
139 | s, err); | ||
140 | return err; | ||
141 | } | ||
142 | fwe_run(fmc, fw, s); | ||
143 | release_firmware(fw); | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | int fwe_remove(struct fmc_device *fmc) | ||
148 | { | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static struct fmc_driver fwe_drv = { | ||
153 | .version = FMC_VERSION, | ||
154 | .driver.name = KBUILD_MODNAME, | ||
155 | .probe = fwe_probe, | ||
156 | .remove = fwe_remove, | ||
157 | /* no table, as the current match just matches everything */ | ||
158 | }; | ||
159 | |||
160 | static int fwe_init(void) | ||
161 | { | ||
162 | int ret; | ||
163 | |||
164 | ret = fmc_driver_register(&fwe_drv); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | static void fwe_exit(void) | ||
169 | { | ||
170 | fmc_driver_unregister(&fwe_drv); | ||
171 | } | ||
172 | |||
173 | module_init(fwe_init); | ||
174 | module_exit(fwe_exit); | ||
175 | |||
176 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/fmc/fru-parse.c b/drivers/fmc/fru-parse.c new file mode 100644 index 000000000000..cb46263c5da2 --- /dev/null +++ b/drivers/fmc/fru-parse.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 CERN (www.cern.ch) | ||
3 | * Author: Alessandro Rubini <rubini@gnudd.com> | ||
4 | * | ||
5 | * Released according to the GNU GPL, version 2 or any later version. | ||
6 | * | ||
7 | * This work is part of the White Rabbit project, a research effort led | ||
8 | * by CERN, the European Institute for Nuclear Research. | ||
9 | */ | ||
10 | #include <linux/ipmi-fru.h> | ||
11 | |||
12 | /* Some internal helpers */ | ||
13 | static struct fru_type_length * | ||
14 | __fru_get_board_tl(struct fru_common_header *header, int nr) | ||
15 | { | ||
16 | struct fru_board_info_area *bia; | ||
17 | struct fru_type_length *tl; | ||
18 | |||
19 | bia = fru_get_board_area(header); | ||
20 | tl = bia->tl; | ||
21 | while (nr > 0 && !fru_is_eof(tl)) { | ||
22 | tl = fru_next_tl(tl); | ||
23 | nr--; | ||
24 | } | ||
25 | if (fru_is_eof(tl)) | ||
26 | return NULL; | ||
27 | return tl; | ||
28 | } | ||
29 | |||
30 | static char *__fru_alloc_get_tl(struct fru_common_header *header, int nr) | ||
31 | { | ||
32 | struct fru_type_length *tl; | ||
33 | char *res; | ||
34 | int len; | ||
35 | |||
36 | tl = __fru_get_board_tl(header, nr); | ||
37 | if (!tl) | ||
38 | return NULL; | ||
39 | len = fru_strlen(tl); | ||
40 | res = fru_alloc(fru_strlen(tl) + 1); | ||
41 | if (!res) | ||
42 | return NULL; | ||
43 | return fru_strcpy(res, tl); | ||
44 | } | ||
45 | |||
46 | /* Public checksum verifiers */ | ||
47 | int fru_header_cksum_ok(struct fru_common_header *header) | ||
48 | { | ||
49 | uint8_t *ptr = (void *)header; | ||
50 | int i, sum; | ||
51 | |||
52 | for (i = sum = 0; i < sizeof(*header); i++) | ||
53 | sum += ptr[i]; | ||
54 | return (sum & 0xff) == 0; | ||
55 | } | ||
56 | int fru_bia_cksum_ok(struct fru_board_info_area *bia) | ||
57 | { | ||
58 | uint8_t *ptr = (void *)bia; | ||
59 | int i, sum; | ||
60 | |||
61 | for (i = sum = 0; i < 8 * bia->area_len; i++) | ||
62 | sum += ptr[i]; | ||
63 | return (sum & 0xff) == 0; | ||
64 | } | ||
65 | |||
66 | /* Get various stuff, trivial */ | ||
67 | char *fru_get_board_manufacturer(struct fru_common_header *header) | ||
68 | { | ||
69 | return __fru_alloc_get_tl(header, 0); | ||
70 | } | ||
71 | char *fru_get_product_name(struct fru_common_header *header) | ||
72 | { | ||
73 | return __fru_alloc_get_tl(header, 1); | ||
74 | } | ||
75 | char *fru_get_serial_number(struct fru_common_header *header) | ||
76 | { | ||
77 | return __fru_alloc_get_tl(header, 2); | ||
78 | } | ||
79 | char *fru_get_part_number(struct fru_common_header *header) | ||
80 | { | ||
81 | return __fru_alloc_get_tl(header, 3); | ||
82 | } | ||
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 0b122f8c7005..6de6c98ce6eb 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c | |||
@@ -116,6 +116,15 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, | |||
116 | unsigned long flags; | 116 | unsigned long flags; |
117 | int ret, t, err = 0; | 117 | int ret, t, err = 0; |
118 | 118 | ||
119 | spin_lock_irqsave(&newchannel->sc_lock, flags); | ||
120 | if (newchannel->state == CHANNEL_OPEN_STATE) { | ||
121 | newchannel->state = CHANNEL_OPENING_STATE; | ||
122 | } else { | ||
123 | spin_unlock_irqrestore(&newchannel->sc_lock, flags); | ||
124 | return -EINVAL; | ||
125 | } | ||
126 | spin_unlock_irqrestore(&newchannel->sc_lock, flags); | ||
127 | |||
119 | newchannel->onchannel_callback = onchannelcallback; | 128 | newchannel->onchannel_callback = onchannelcallback; |
120 | newchannel->channel_callback_context = context; | 129 | newchannel->channel_callback_context = context; |
121 | 130 | ||
@@ -216,6 +225,9 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, | |||
216 | list_del(&open_info->msglistentry); | 225 | list_del(&open_info->msglistentry); |
217 | spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); | 226 | spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); |
218 | 227 | ||
228 | if (err == 0) | ||
229 | newchannel->state = CHANNEL_OPENED_STATE; | ||
230 | |||
219 | kfree(open_info); | 231 | kfree(open_info); |
220 | return err; | 232 | return err; |
221 | 233 | ||
@@ -500,15 +512,14 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) | |||
500 | } | 512 | } |
501 | EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl); | 513 | EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl); |
502 | 514 | ||
503 | /* | 515 | static void vmbus_close_internal(struct vmbus_channel *channel) |
504 | * vmbus_close - Close the specified channel | ||
505 | */ | ||
506 | void vmbus_close(struct vmbus_channel *channel) | ||
507 | { | 516 | { |
508 | struct vmbus_channel_close_channel *msg; | 517 | struct vmbus_channel_close_channel *msg; |
509 | int ret; | 518 | int ret; |
510 | unsigned long flags; | 519 | unsigned long flags; |
511 | 520 | ||
521 | channel->state = CHANNEL_OPEN_STATE; | ||
522 | channel->sc_creation_callback = NULL; | ||
512 | /* Stop callback and cancel the timer asap */ | 523 | /* Stop callback and cancel the timer asap */ |
513 | spin_lock_irqsave(&channel->inbound_lock, flags); | 524 | spin_lock_irqsave(&channel->inbound_lock, flags); |
514 | channel->onchannel_callback = NULL; | 525 | channel->onchannel_callback = NULL; |
@@ -538,6 +549,37 @@ void vmbus_close(struct vmbus_channel *channel) | |||
538 | 549 | ||
539 | 550 | ||
540 | } | 551 | } |
552 | |||
553 | /* | ||
554 | * vmbus_close - Close the specified channel | ||
555 | */ | ||
556 | void vmbus_close(struct vmbus_channel *channel) | ||
557 | { | ||
558 | struct list_head *cur, *tmp; | ||
559 | struct vmbus_channel *cur_channel; | ||
560 | |||
561 | if (channel->primary_channel != NULL) { | ||
562 | /* | ||
563 | * We will only close sub-channels when | ||
564 | * the primary is closed. | ||
565 | */ | ||
566 | return; | ||
567 | } | ||
568 | /* | ||
569 | * Close all the sub-channels first and then close the | ||
570 | * primary channel. | ||
571 | */ | ||
572 | list_for_each_safe(cur, tmp, &channel->sc_list) { | ||
573 | cur_channel = list_entry(cur, struct vmbus_channel, sc_list); | ||
574 | if (cur_channel->state != CHANNEL_OPENED_STATE) | ||
575 | continue; | ||
576 | vmbus_close_internal(cur_channel); | ||
577 | } | ||
578 | /* | ||
579 | * Now close the primary. | ||
580 | */ | ||
581 | vmbus_close_internal(channel); | ||
582 | } | ||
541 | EXPORT_SYMBOL_GPL(vmbus_close); | 583 | EXPORT_SYMBOL_GPL(vmbus_close); |
542 | 584 | ||
543 | /** | 585 | /** |
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 21ef68934a20..0df75908200e 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c | |||
@@ -115,6 +115,9 @@ static struct vmbus_channel *alloc_channel(void) | |||
115 | return NULL; | 115 | return NULL; |
116 | 116 | ||
117 | spin_lock_init(&channel->inbound_lock); | 117 | spin_lock_init(&channel->inbound_lock); |
118 | spin_lock_init(&channel->sc_lock); | ||
119 | |||
120 | INIT_LIST_HEAD(&channel->sc_list); | ||
118 | 121 | ||
119 | channel->controlwq = create_workqueue("hv_vmbus_ctl"); | 122 | channel->controlwq = create_workqueue("hv_vmbus_ctl"); |
120 | if (!channel->controlwq) { | 123 | if (!channel->controlwq) { |
@@ -166,6 +169,7 @@ static void vmbus_process_rescind_offer(struct work_struct *work) | |||
166 | struct vmbus_channel, | 169 | struct vmbus_channel, |
167 | work); | 170 | work); |
168 | unsigned long flags; | 171 | unsigned long flags; |
172 | struct vmbus_channel *primary_channel; | ||
169 | struct vmbus_channel_relid_released msg; | 173 | struct vmbus_channel_relid_released msg; |
170 | 174 | ||
171 | vmbus_device_unregister(channel->device_obj); | 175 | vmbus_device_unregister(channel->device_obj); |
@@ -174,9 +178,16 @@ static void vmbus_process_rescind_offer(struct work_struct *work) | |||
174 | msg.header.msgtype = CHANNELMSG_RELID_RELEASED; | 178 | msg.header.msgtype = CHANNELMSG_RELID_RELEASED; |
175 | vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released)); | 179 | vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released)); |
176 | 180 | ||
177 | spin_lock_irqsave(&vmbus_connection.channel_lock, flags); | 181 | if (channel->primary_channel == NULL) { |
178 | list_del(&channel->listentry); | 182 | spin_lock_irqsave(&vmbus_connection.channel_lock, flags); |
179 | spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); | 183 | list_del(&channel->listentry); |
184 | spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); | ||
185 | } else { | ||
186 | primary_channel = channel->primary_channel; | ||
187 | spin_lock_irqsave(&primary_channel->sc_lock, flags); | ||
188 | list_del(&channel->listentry); | ||
189 | spin_unlock_irqrestore(&primary_channel->sc_lock, flags); | ||
190 | } | ||
180 | free_channel(channel); | 191 | free_channel(channel); |
181 | } | 192 | } |
182 | 193 | ||
@@ -228,6 +239,24 @@ static void vmbus_process_offer(struct work_struct *work) | |||
228 | spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); | 239 | spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); |
229 | 240 | ||
230 | if (!fnew) { | 241 | if (!fnew) { |
242 | /* | ||
243 | * Check to see if this is a sub-channel. | ||
244 | */ | ||
245 | if (newchannel->offermsg.offer.sub_channel_index != 0) { | ||
246 | /* | ||
247 | * Process the sub-channel. | ||
248 | */ | ||
249 | newchannel->primary_channel = channel; | ||
250 | spin_lock_irqsave(&channel->sc_lock, flags); | ||
251 | list_add_tail(&newchannel->sc_list, &channel->sc_list); | ||
252 | spin_unlock_irqrestore(&channel->sc_lock, flags); | ||
253 | newchannel->state = CHANNEL_OPEN_STATE; | ||
254 | if (channel->sc_creation_callback != NULL) | ||
255 | channel->sc_creation_callback(newchannel); | ||
256 | |||
257 | return; | ||
258 | } | ||
259 | |||
231 | free_channel(newchannel); | 260 | free_channel(newchannel); |
232 | return; | 261 | return; |
233 | } | 262 | } |
@@ -685,4 +714,86 @@ cleanup: | |||
685 | return ret; | 714 | return ret; |
686 | } | 715 | } |
687 | 716 | ||
688 | /* eof */ | 717 | /* |
718 | * Retrieve the (sub) channel on which to send an outgoing request. | ||
719 | * When a primary channel has multiple sub-channels, we choose a | ||
720 | * channel whose VCPU binding is closest to the VCPU on which | ||
721 | * this call is being made. | ||
722 | */ | ||
723 | struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) | ||
724 | { | ||
725 | struct list_head *cur, *tmp; | ||
726 | int cur_cpu = hv_context.vp_index[smp_processor_id()]; | ||
727 | struct vmbus_channel *cur_channel; | ||
728 | struct vmbus_channel *outgoing_channel = primary; | ||
729 | int cpu_distance, new_cpu_distance; | ||
730 | |||
731 | if (list_empty(&primary->sc_list)) | ||
732 | return outgoing_channel; | ||
733 | |||
734 | list_for_each_safe(cur, tmp, &primary->sc_list) { | ||
735 | cur_channel = list_entry(cur, struct vmbus_channel, sc_list); | ||
736 | if (cur_channel->state != CHANNEL_OPENED_STATE) | ||
737 | continue; | ||
738 | |||
739 | if (cur_channel->target_vp == cur_cpu) | ||
740 | return cur_channel; | ||
741 | |||
742 | cpu_distance = ((outgoing_channel->target_vp > cur_cpu) ? | ||
743 | (outgoing_channel->target_vp - cur_cpu) : | ||
744 | (cur_cpu - outgoing_channel->target_vp)); | ||
745 | |||
746 | new_cpu_distance = ((cur_channel->target_vp > cur_cpu) ? | ||
747 | (cur_channel->target_vp - cur_cpu) : | ||
748 | (cur_cpu - cur_channel->target_vp)); | ||
749 | |||
750 | if (cpu_distance < new_cpu_distance) | ||
751 | continue; | ||
752 | |||
753 | outgoing_channel = cur_channel; | ||
754 | } | ||
755 | |||
756 | return outgoing_channel; | ||
757 | } | ||
758 | EXPORT_SYMBOL_GPL(vmbus_get_outgoing_channel); | ||
759 | |||
760 | static void invoke_sc_cb(struct vmbus_channel *primary_channel) | ||
761 | { | ||
762 | struct list_head *cur, *tmp; | ||
763 | struct vmbus_channel *cur_channel; | ||
764 | |||
765 | if (primary_channel->sc_creation_callback == NULL) | ||
766 | return; | ||
767 | |||
768 | list_for_each_safe(cur, tmp, &primary_channel->sc_list) { | ||
769 | cur_channel = list_entry(cur, struct vmbus_channel, sc_list); | ||
770 | |||
771 | primary_channel->sc_creation_callback(cur_channel); | ||
772 | } | ||
773 | } | ||
774 | |||
775 | void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel, | ||
776 | void (*sc_cr_cb)(struct vmbus_channel *new_sc)) | ||
777 | { | ||
778 | primary_channel->sc_creation_callback = sc_cr_cb; | ||
779 | } | ||
780 | EXPORT_SYMBOL_GPL(vmbus_set_sc_create_callback); | ||
781 | |||
782 | bool vmbus_are_subchannels_present(struct vmbus_channel *primary) | ||
783 | { | ||
784 | bool ret; | ||
785 | |||
786 | ret = !list_empty(&primary->sc_list); | ||
787 | |||
788 | if (ret) { | ||
789 | /* | ||
790 | * Invoke the callback on sub-channel creation. | ||
791 | * This will present a uniform interface to the | ||
792 | * clients. | ||
793 | */ | ||
794 | invoke_sc_cb(primary); | ||
795 | } | ||
796 | |||
797 | return ret; | ||
798 | } | ||
799 | EXPORT_SYMBOL_GPL(vmbus_are_subchannels_present); | ||
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 253a74ba245c..ec3b8cdf1e04 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c | |||
@@ -246,12 +246,26 @@ struct vmbus_channel *relid2channel(u32 relid) | |||
246 | struct vmbus_channel *channel; | 246 | struct vmbus_channel *channel; |
247 | struct vmbus_channel *found_channel = NULL; | 247 | struct vmbus_channel *found_channel = NULL; |
248 | unsigned long flags; | 248 | unsigned long flags; |
249 | struct list_head *cur, *tmp; | ||
250 | struct vmbus_channel *cur_sc; | ||
249 | 251 | ||
250 | spin_lock_irqsave(&vmbus_connection.channel_lock, flags); | 252 | spin_lock_irqsave(&vmbus_connection.channel_lock, flags); |
251 | list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { | 253 | list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { |
252 | if (channel->offermsg.child_relid == relid) { | 254 | if (channel->offermsg.child_relid == relid) { |
253 | found_channel = channel; | 255 | found_channel = channel; |
254 | break; | 256 | break; |
257 | } else if (!list_empty(&channel->sc_list)) { | ||
258 | /* | ||
259 | * Deal with sub-channels. | ||
260 | */ | ||
261 | list_for_each_safe(cur, tmp, &channel->sc_list) { | ||
262 | cur_sc = list_entry(cur, struct vmbus_channel, | ||
263 | sc_list); | ||
264 | if (cur_sc->offermsg.child_relid == relid) { | ||
265 | found_channel = cur_sc; | ||
266 | break; | ||
267 | } | ||
268 | } | ||
255 | } | 269 | } |
256 | } | 270 | } |
257 | spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); | 271 | spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); |
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index ae4923756d98..88f4096fa078 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c | |||
@@ -265,6 +265,59 @@ u16 hv_signal_event(void *con_id) | |||
265 | return status; | 265 | return status; |
266 | } | 266 | } |
267 | 267 | ||
268 | |||
269 | int hv_synic_alloc(void) | ||
270 | { | ||
271 | size_t size = sizeof(struct tasklet_struct); | ||
272 | int cpu; | ||
273 | |||
274 | for_each_online_cpu(cpu) { | ||
275 | hv_context.event_dpc[cpu] = kmalloc(size, GFP_ATOMIC); | ||
276 | if (hv_context.event_dpc[cpu] == NULL) { | ||
277 | pr_err("Unable to allocate event dpc\n"); | ||
278 | goto err; | ||
279 | } | ||
280 | tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu); | ||
281 | |||
282 | hv_context.synic_message_page[cpu] = | ||
283 | (void *)get_zeroed_page(GFP_ATOMIC); | ||
284 | |||
285 | if (hv_context.synic_message_page[cpu] == NULL) { | ||
286 | pr_err("Unable to allocate SYNIC message page\n"); | ||
287 | goto err; | ||
288 | } | ||
289 | |||
290 | hv_context.synic_event_page[cpu] = | ||
291 | (void *)get_zeroed_page(GFP_ATOMIC); | ||
292 | |||
293 | if (hv_context.synic_event_page[cpu] == NULL) { | ||
294 | pr_err("Unable to allocate SYNIC event page\n"); | ||
295 | goto err; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | return 0; | ||
300 | err: | ||
301 | return -ENOMEM; | ||
302 | } | ||
303 | |||
304 | void hv_synic_free_cpu(int cpu) | ||
305 | { | ||
306 | kfree(hv_context.event_dpc[cpu]); | ||
307 | if (hv_context.synic_message_page[cpu]) | ||
308 | free_page((unsigned long)hv_context.synic_event_page[cpu]); | ||
309 | if (hv_context.synic_message_page[cpu]) | ||
310 | free_page((unsigned long)hv_context.synic_message_page[cpu]); | ||
311 | } | ||
312 | |||
313 | void hv_synic_free(void) | ||
314 | { | ||
315 | int cpu; | ||
316 | |||
317 | for_each_online_cpu(cpu) | ||
318 | hv_synic_free_cpu(cpu); | ||
319 | } | ||
320 | |||
268 | /* | 321 | /* |
269 | * hv_synic_init - Initialize the Synthethic Interrupt Controller. | 322 | * hv_synic_init - Initialize the Synthethic Interrupt Controller. |
270 | * | 323 | * |
@@ -289,30 +342,6 @@ void hv_synic_init(void *arg) | |||
289 | /* Check the version */ | 342 | /* Check the version */ |
290 | rdmsrl(HV_X64_MSR_SVERSION, version); | 343 | rdmsrl(HV_X64_MSR_SVERSION, version); |
291 | 344 | ||
292 | hv_context.event_dpc[cpu] = kmalloc(sizeof(struct tasklet_struct), | ||
293 | GFP_ATOMIC); | ||
294 | if (hv_context.event_dpc[cpu] == NULL) { | ||
295 | pr_err("Unable to allocate event dpc\n"); | ||
296 | goto cleanup; | ||
297 | } | ||
298 | tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu); | ||
299 | |||
300 | hv_context.synic_message_page[cpu] = | ||
301 | (void *)get_zeroed_page(GFP_ATOMIC); | ||
302 | |||
303 | if (hv_context.synic_message_page[cpu] == NULL) { | ||
304 | pr_err("Unable to allocate SYNIC message page\n"); | ||
305 | goto cleanup; | ||
306 | } | ||
307 | |||
308 | hv_context.synic_event_page[cpu] = | ||
309 | (void *)get_zeroed_page(GFP_ATOMIC); | ||
310 | |||
311 | if (hv_context.synic_event_page[cpu] == NULL) { | ||
312 | pr_err("Unable to allocate SYNIC event page\n"); | ||
313 | goto cleanup; | ||
314 | } | ||
315 | |||
316 | /* Setup the Synic's message page */ | 345 | /* Setup the Synic's message page */ |
317 | rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64); | 346 | rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64); |
318 | simp.simp_enabled = 1; | 347 | simp.simp_enabled = 1; |
@@ -355,14 +384,6 @@ void hv_synic_init(void *arg) | |||
355 | rdmsrl(HV_X64_MSR_VP_INDEX, vp_index); | 384 | rdmsrl(HV_X64_MSR_VP_INDEX, vp_index); |
356 | hv_context.vp_index[cpu] = (u32)vp_index; | 385 | hv_context.vp_index[cpu] = (u32)vp_index; |
357 | return; | 386 | return; |
358 | |||
359 | cleanup: | ||
360 | if (hv_context.synic_event_page[cpu]) | ||
361 | free_page((unsigned long)hv_context.synic_event_page[cpu]); | ||
362 | |||
363 | if (hv_context.synic_message_page[cpu]) | ||
364 | free_page((unsigned long)hv_context.synic_message_page[cpu]); | ||
365 | return; | ||
366 | } | 387 | } |
367 | 388 | ||
368 | /* | 389 | /* |
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 12f2f9e989f7..d84918fe19ab 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h | |||
@@ -527,6 +527,10 @@ extern int hv_post_message(union hv_connection_id connection_id, | |||
527 | 527 | ||
528 | extern u16 hv_signal_event(void *con_id); | 528 | extern u16 hv_signal_event(void *con_id); |
529 | 529 | ||
530 | extern int hv_synic_alloc(void); | ||
531 | |||
532 | extern void hv_synic_free(void); | ||
533 | |||
530 | extern void hv_synic_init(void *irqarg); | 534 | extern void hv_synic_init(void *irqarg); |
531 | 535 | ||
532 | extern void hv_synic_cleanup(void *arg); | 536 | extern void hv_synic_cleanup(void *arg); |
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index d6fbb5772b8d..26c93cf9f6be 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c | |||
@@ -32,7 +32,7 @@ | |||
32 | void hv_begin_read(struct hv_ring_buffer_info *rbi) | 32 | void hv_begin_read(struct hv_ring_buffer_info *rbi) |
33 | { | 33 | { |
34 | rbi->ring_buffer->interrupt_mask = 1; | 34 | rbi->ring_buffer->interrupt_mask = 1; |
35 | smp_mb(); | 35 | mb(); |
36 | } | 36 | } |
37 | 37 | ||
38 | u32 hv_end_read(struct hv_ring_buffer_info *rbi) | 38 | u32 hv_end_read(struct hv_ring_buffer_info *rbi) |
@@ -41,7 +41,7 @@ u32 hv_end_read(struct hv_ring_buffer_info *rbi) | |||
41 | u32 write; | 41 | u32 write; |
42 | 42 | ||
43 | rbi->ring_buffer->interrupt_mask = 0; | 43 | rbi->ring_buffer->interrupt_mask = 0; |
44 | smp_mb(); | 44 | mb(); |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * Now check to see if the ring buffer is still empty. | 47 | * 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) | |||
71 | 71 | ||
72 | static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi) | 72 | static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi) |
73 | { | 73 | { |
74 | smp_mb(); | 74 | mb(); |
75 | if (rbi->ring_buffer->interrupt_mask) | 75 | if (rbi->ring_buffer->interrupt_mask) |
76 | return false; | 76 | return false; |
77 | 77 | ||
78 | /* check interrupt_mask before read_index */ | ||
79 | rmb(); | ||
78 | /* | 80 | /* |
79 | * This is the only case we need to signal when the | 81 | * This is the only case we need to signal when the |
80 | * ring transitions from being empty to non-empty. | 82 | * ring transitions from being empty to non-empty. |
@@ -442,7 +444,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info, | |||
442 | sizeof(u64)); | 444 | sizeof(u64)); |
443 | 445 | ||
444 | /* Issue a full memory barrier before updating the write index */ | 446 | /* Issue a full memory barrier before updating the write index */ |
445 | smp_mb(); | 447 | mb(); |
446 | 448 | ||
447 | /* Now, update the write location */ | 449 | /* Now, update the write location */ |
448 | hv_set_next_write_location(outring_info, next_write_location); | 450 | 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, | |||
549 | /* Make sure all reads are done before we update the read index since */ | 551 | /* Make sure all reads are done before we update the read index since */ |
550 | /* the writer may start writing to the read area once the read index */ | 552 | /* the writer may start writing to the read area once the read index */ |
551 | /*is updated */ | 553 | /*is updated */ |
552 | smp_mb(); | 554 | mb(); |
553 | 555 | ||
554 | /* Update the read index */ | 556 | /* Update the read index */ |
555 | hv_set_next_read_location(inring_info, next_read_location); | 557 | hv_set_next_read_location(inring_info, next_read_location); |
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index bf421e0efa1e..a2464bf07c49 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c | |||
@@ -434,7 +434,7 @@ static void vmbus_on_msg_dpc(unsigned long data) | |||
434 | * will not deliver any more messages since there is | 434 | * will not deliver any more messages since there is |
435 | * no empty slot | 435 | * no empty slot |
436 | */ | 436 | */ |
437 | smp_mb(); | 437 | mb(); |
438 | 438 | ||
439 | if (msg->header.message_flags.msg_pending) { | 439 | if (msg->header.message_flags.msg_pending) { |
440 | /* | 440 | /* |
@@ -563,6 +563,9 @@ static int vmbus_bus_init(int irq) | |||
563 | */ | 563 | */ |
564 | hv_register_vmbus_handler(irq, vmbus_isr); | 564 | hv_register_vmbus_handler(irq, vmbus_isr); |
565 | 565 | ||
566 | ret = hv_synic_alloc(); | ||
567 | if (ret) | ||
568 | goto err_alloc; | ||
566 | /* | 569 | /* |
567 | * Initialize the per-cpu interrupt state and | 570 | * Initialize the per-cpu interrupt state and |
568 | * connect to the host. | 571 | * connect to the host. |
@@ -570,13 +573,14 @@ static int vmbus_bus_init(int irq) | |||
570 | on_each_cpu(hv_synic_init, NULL, 1); | 573 | on_each_cpu(hv_synic_init, NULL, 1); |
571 | ret = vmbus_connect(); | 574 | ret = vmbus_connect(); |
572 | if (ret) | 575 | if (ret) |
573 | goto err_irq; | 576 | goto err_alloc; |
574 | 577 | ||
575 | vmbus_request_offers(); | 578 | vmbus_request_offers(); |
576 | 579 | ||
577 | return 0; | 580 | return 0; |
578 | 581 | ||
579 | err_irq: | 582 | err_alloc: |
583 | hv_synic_free(); | ||
580 | free_irq(irq, hv_acpi_dev); | 584 | free_irq(irq, hv_acpi_dev); |
581 | 585 | ||
582 | err_unregister: | 586 | err_unregister: |
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 067f31174a0e..29a11db365bc 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig | |||
@@ -20,6 +20,16 @@ config TI_EMIF | |||
20 | parameters and other settings during frequency, voltage and | 20 | parameters and other settings during frequency, voltage and |
21 | temperature changes | 21 | temperature changes |
22 | 22 | ||
23 | config MVEBU_DEVBUS | ||
24 | bool "Marvell EBU Device Bus Controller" | ||
25 | default y | ||
26 | depends on PLAT_ORION && OF | ||
27 | help | ||
28 | This driver is for the Device Bus controller available in some | ||
29 | Marvell EBU SoCs such as Discovery (mv78xx0), Orion (88f5xxx) and | ||
30 | Armada 370 and Armada XP. This controller allows to handle flash | ||
31 | devices such as NOR, NAND, SRAM, and FPGA. | ||
32 | |||
23 | config TEGRA20_MC | 33 | config TEGRA20_MC |
24 | bool "Tegra20 Memory Controller(MC) driver" | 34 | bool "Tegra20 Memory Controller(MC) driver" |
25 | default y | 35 | default y |
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index 9cce5d70ed52..969d923dad93 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile | |||
@@ -6,5 +6,6 @@ ifeq ($(CONFIG_DDR),y) | |||
6 | obj-$(CONFIG_OF) += of_memory.o | 6 | obj-$(CONFIG_OF) += of_memory.o |
7 | endif | 7 | endif |
8 | obj-$(CONFIG_TI_EMIF) += emif.o | 8 | obj-$(CONFIG_TI_EMIF) += emif.o |
9 | obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o | ||
9 | obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o | 10 | obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o |
10 | obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o | 11 | obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o |
diff --git a/drivers/memory/mvebu-devbus.c b/drivers/memory/mvebu-devbus.c new file mode 100644 index 000000000000..978e8e3abc5c --- /dev/null +++ b/drivers/memory/mvebu-devbus.c | |||
@@ -0,0 +1,340 @@ | |||
1 | /* | ||
2 | * Marvell EBU SoC Device Bus Controller | ||
3 | * (memory controller for NOR/NAND/SRAM/FPGA devices) | ||
4 | * | ||
5 | * Copyright (C) 2013 Marvell | ||
6 | * | ||
7 | * This program is free software: you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/clk.h> | ||
27 | #include <linux/mbus.h> | ||
28 | #include <linux/of_platform.h> | ||
29 | #include <linux/of_address.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | |||
32 | /* Register definitions */ | ||
33 | #define DEV_WIDTH_BIT 30 | ||
34 | #define BADR_SKEW_BIT 28 | ||
35 | #define RD_HOLD_BIT 23 | ||
36 | #define ACC_NEXT_BIT 17 | ||
37 | #define RD_SETUP_BIT 12 | ||
38 | #define ACC_FIRST_BIT 6 | ||
39 | |||
40 | #define SYNC_ENABLE_BIT 24 | ||
41 | #define WR_HIGH_BIT 16 | ||
42 | #define WR_LOW_BIT 8 | ||
43 | |||
44 | #define READ_PARAM_OFFSET 0x0 | ||
45 | #define WRITE_PARAM_OFFSET 0x4 | ||
46 | |||
47 | static const char * const devbus_wins[] = { | ||
48 | "devbus-boot", | ||
49 | "devbus-cs0", | ||
50 | "devbus-cs1", | ||
51 | "devbus-cs2", | ||
52 | "devbus-cs3", | ||
53 | }; | ||
54 | |||
55 | struct devbus_read_params { | ||
56 | u32 bus_width; | ||
57 | u32 badr_skew; | ||
58 | u32 turn_off; | ||
59 | u32 acc_first; | ||
60 | u32 acc_next; | ||
61 | u32 rd_setup; | ||
62 | u32 rd_hold; | ||
63 | }; | ||
64 | |||
65 | struct devbus_write_params { | ||
66 | u32 sync_enable; | ||
67 | u32 wr_high; | ||
68 | u32 wr_low; | ||
69 | u32 ale_wr; | ||
70 | }; | ||
71 | |||
72 | struct devbus { | ||
73 | struct device *dev; | ||
74 | void __iomem *base; | ||
75 | unsigned long tick_ps; | ||
76 | }; | ||
77 | |||
78 | static int get_timing_param_ps(struct devbus *devbus, | ||
79 | struct device_node *node, | ||
80 | const char *name, | ||
81 | u32 *ticks) | ||
82 | { | ||
83 | u32 time_ps; | ||
84 | int err; | ||
85 | |||
86 | err = of_property_read_u32(node, name, &time_ps); | ||
87 | if (err < 0) { | ||
88 | dev_err(devbus->dev, "%s has no '%s' property\n", | ||
89 | name, node->full_name); | ||
90 | return err; | ||
91 | } | ||
92 | |||
93 | *ticks = (time_ps + devbus->tick_ps - 1) / devbus->tick_ps; | ||
94 | |||
95 | dev_dbg(devbus->dev, "%s: %u ps -> 0x%x\n", | ||
96 | name, time_ps, *ticks); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static int devbus_set_timing_params(struct devbus *devbus, | ||
101 | struct device_node *node) | ||
102 | { | ||
103 | struct devbus_read_params r; | ||
104 | struct devbus_write_params w; | ||
105 | u32 value; | ||
106 | int err; | ||
107 | |||
108 | dev_dbg(devbus->dev, "Setting timing parameter, tick is %lu ps\n", | ||
109 | devbus->tick_ps); | ||
110 | |||
111 | /* Get read timings */ | ||
112 | err = of_property_read_u32(node, "devbus,bus-width", &r.bus_width); | ||
113 | if (err < 0) { | ||
114 | dev_err(devbus->dev, | ||
115 | "%s has no 'devbus,bus-width' property\n", | ||
116 | node->full_name); | ||
117 | return err; | ||
118 | } | ||
119 | /* Convert bit width to byte width */ | ||
120 | r.bus_width /= 8; | ||
121 | |||
122 | err = get_timing_param_ps(devbus, node, "devbus,badr-skew-ps", | ||
123 | &r.badr_skew); | ||
124 | if (err < 0) | ||
125 | return err; | ||
126 | |||
127 | err = get_timing_param_ps(devbus, node, "devbus,turn-off-ps", | ||
128 | &r.turn_off); | ||
129 | if (err < 0) | ||
130 | return err; | ||
131 | |||
132 | err = get_timing_param_ps(devbus, node, "devbus,acc-first-ps", | ||
133 | &r.acc_first); | ||
134 | if (err < 0) | ||
135 | return err; | ||
136 | |||
137 | err = get_timing_param_ps(devbus, node, "devbus,acc-next-ps", | ||
138 | &r.acc_next); | ||
139 | if (err < 0) | ||
140 | return err; | ||
141 | |||
142 | err = get_timing_param_ps(devbus, node, "devbus,rd-setup-ps", | ||
143 | &r.rd_setup); | ||
144 | if (err < 0) | ||
145 | return err; | ||
146 | |||
147 | err = get_timing_param_ps(devbus, node, "devbus,rd-hold-ps", | ||
148 | &r.rd_hold); | ||
149 | if (err < 0) | ||
150 | return err; | ||
151 | |||
152 | /* Get write timings */ | ||
153 | err = of_property_read_u32(node, "devbus,sync-enable", | ||
154 | &w.sync_enable); | ||
155 | if (err < 0) { | ||
156 | dev_err(devbus->dev, | ||
157 | "%s has no 'devbus,sync-enable' property\n", | ||
158 | node->full_name); | ||
159 | return err; | ||
160 | } | ||
161 | |||
162 | err = get_timing_param_ps(devbus, node, "devbus,ale-wr-ps", | ||
163 | &w.ale_wr); | ||
164 | if (err < 0) | ||
165 | return err; | ||
166 | |||
167 | err = get_timing_param_ps(devbus, node, "devbus,wr-low-ps", | ||
168 | &w.wr_low); | ||
169 | if (err < 0) | ||
170 | return err; | ||
171 | |||
172 | err = get_timing_param_ps(devbus, node, "devbus,wr-high-ps", | ||
173 | &w.wr_high); | ||
174 | if (err < 0) | ||
175 | return err; | ||
176 | |||
177 | /* Set read timings */ | ||
178 | value = r.bus_width << DEV_WIDTH_BIT | | ||
179 | r.badr_skew << BADR_SKEW_BIT | | ||
180 | r.rd_hold << RD_HOLD_BIT | | ||
181 | r.acc_next << ACC_NEXT_BIT | | ||
182 | r.rd_setup << RD_SETUP_BIT | | ||
183 | r.acc_first << ACC_FIRST_BIT | | ||
184 | r.turn_off; | ||
185 | |||
186 | dev_dbg(devbus->dev, "read parameters register 0x%p = 0x%x\n", | ||
187 | devbus->base + READ_PARAM_OFFSET, | ||
188 | value); | ||
189 | |||
190 | writel(value, devbus->base + READ_PARAM_OFFSET); | ||
191 | |||
192 | /* Set write timings */ | ||
193 | value = w.sync_enable << SYNC_ENABLE_BIT | | ||
194 | w.wr_low << WR_LOW_BIT | | ||
195 | w.wr_high << WR_HIGH_BIT | | ||
196 | w.ale_wr; | ||
197 | |||
198 | dev_dbg(devbus->dev, "write parameters register: 0x%p = 0x%x\n", | ||
199 | devbus->base + WRITE_PARAM_OFFSET, | ||
200 | value); | ||
201 | |||
202 | writel(value, devbus->base + WRITE_PARAM_OFFSET); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static int mvebu_devbus_probe(struct platform_device *pdev) | ||
208 | { | ||
209 | struct device *dev = &pdev->dev; | ||
210 | struct device_node *node = pdev->dev.of_node; | ||
211 | struct device_node *parent; | ||
212 | struct devbus *devbus; | ||
213 | struct resource *res; | ||
214 | struct clk *clk; | ||
215 | unsigned long rate; | ||
216 | const __be32 *ranges; | ||
217 | int err, cs; | ||
218 | int addr_cells, p_addr_cells, size_cells; | ||
219 | int ranges_len, tuple_len; | ||
220 | u32 base, size; | ||
221 | |||
222 | devbus = devm_kzalloc(&pdev->dev, sizeof(struct devbus), GFP_KERNEL); | ||
223 | if (!devbus) | ||
224 | return -ENOMEM; | ||
225 | |||
226 | devbus->dev = dev; | ||
227 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
228 | devbus->base = devm_ioremap_resource(&pdev->dev, res); | ||
229 | if (IS_ERR(devbus->base)) | ||
230 | return PTR_ERR(devbus->base); | ||
231 | |||
232 | clk = devm_clk_get(&pdev->dev, NULL); | ||
233 | if (IS_ERR(clk)) | ||
234 | return PTR_ERR(clk); | ||
235 | clk_prepare_enable(clk); | ||
236 | |||
237 | /* | ||
238 | * Obtain clock period in picoseconds, | ||
239 | * we need this in order to convert timing | ||
240 | * parameters from cycles to picoseconds. | ||
241 | */ | ||
242 | rate = clk_get_rate(clk) / 1000; | ||
243 | devbus->tick_ps = 1000000000 / rate; | ||
244 | |||
245 | /* Read the device tree node and set the new timing parameters */ | ||
246 | err = devbus_set_timing_params(devbus, node); | ||
247 | if (err < 0) | ||
248 | return err; | ||
249 | |||
250 | /* | ||
251 | * Allocate an address window for this device. | ||
252 | * If the device probing fails, then we won't be able to | ||
253 | * remove the allocated address decoding window. | ||
254 | * | ||
255 | * FIXME: This is only a temporary hack! We need to do this here | ||
256 | * because we still don't have device tree bindings for mbus. | ||
257 | * Once that support is added, we will declare these address windows | ||
258 | * statically in the device tree, and remove the window configuration | ||
259 | * from here. | ||
260 | */ | ||
261 | |||
262 | /* | ||
263 | * Get the CS to choose the window string. | ||
264 | * This is a bit hacky, but it will be removed once the | ||
265 | * address windows are declared in the device tree. | ||
266 | */ | ||
267 | cs = (((unsigned long)devbus->base) % 0x400) / 8; | ||
268 | |||
269 | /* | ||
270 | * Parse 'ranges' property to obtain a (base,size) window tuple. | ||
271 | * This will be removed once the address windows | ||
272 | * are declared in the device tree. | ||
273 | */ | ||
274 | parent = of_get_parent(node); | ||
275 | if (!parent) | ||
276 | return -EINVAL; | ||
277 | |||
278 | p_addr_cells = of_n_addr_cells(parent); | ||
279 | of_node_put(parent); | ||
280 | |||
281 | addr_cells = of_n_addr_cells(node); | ||
282 | size_cells = of_n_size_cells(node); | ||
283 | tuple_len = (p_addr_cells + addr_cells + size_cells) * sizeof(__be32); | ||
284 | |||
285 | ranges = of_get_property(node, "ranges", &ranges_len); | ||
286 | if (ranges == NULL || ranges_len != tuple_len) | ||
287 | return -EINVAL; | ||
288 | |||
289 | base = of_translate_address(node, ranges + addr_cells); | ||
290 | if (base == OF_BAD_ADDR) | ||
291 | return -EINVAL; | ||
292 | size = of_read_number(ranges + addr_cells + p_addr_cells, size_cells); | ||
293 | |||
294 | /* | ||
295 | * Create an mbus address windows. | ||
296 | * FIXME: Remove this, together with the above code, once the | ||
297 | * address windows are declared in the device tree. | ||
298 | */ | ||
299 | err = mvebu_mbus_add_window(devbus_wins[cs], base, size); | ||
300 | if (err < 0) | ||
301 | return err; | ||
302 | |||
303 | /* | ||
304 | * We need to create a child device explicitly from here to | ||
305 | * guarantee that the child will be probed after the timing | ||
306 | * parameters for the bus are written. | ||
307 | */ | ||
308 | err = of_platform_populate(node, NULL, NULL, dev); | ||
309 | if (err < 0) { | ||
310 | mvebu_mbus_del_window(base, size); | ||
311 | return err; | ||
312 | } | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static const struct of_device_id mvebu_devbus_of_match[] = { | ||
318 | { .compatible = "marvell,mvebu-devbus" }, | ||
319 | {}, | ||
320 | }; | ||
321 | MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match); | ||
322 | |||
323 | static struct platform_driver mvebu_devbus_driver = { | ||
324 | .probe = mvebu_devbus_probe, | ||
325 | .driver = { | ||
326 | .name = "mvebu-devbus", | ||
327 | .owner = THIS_MODULE, | ||
328 | .of_match_table = mvebu_devbus_of_match, | ||
329 | }, | ||
330 | }; | ||
331 | |||
332 | static int __init mvebu_devbus_init(void) | ||
333 | { | ||
334 | return platform_driver_register(&mvebu_devbus_driver); | ||
335 | } | ||
336 | module_init(mvebu_devbus_init); | ||
337 | |||
338 | MODULE_LICENSE("GPL v2"); | ||
339 | MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>"); | ||
340 | MODULE_DESCRIPTION("Marvell EBU SoC Device Bus controller"); | ||
diff --git a/drivers/memory/tegra20-mc.c b/drivers/memory/tegra20-mc.c index 2ca5f2814f4a..0548eeacd573 100644 --- a/drivers/memory/tegra20-mc.c +++ b/drivers/memory/tegra20-mc.c | |||
@@ -193,8 +193,11 @@ static irqreturn_t tegra20_mc_isr(int irq, void *data) | |||
193 | mask &= stat; | 193 | mask &= stat; |
194 | if (!mask) | 194 | if (!mask) |
195 | return IRQ_NONE; | 195 | return IRQ_NONE; |
196 | while ((bit = ffs(mask)) != 0) | 196 | while ((bit = ffs(mask)) != 0) { |
197 | tegra20_mc_decode(mc, bit - 1); | 197 | tegra20_mc_decode(mc, bit - 1); |
198 | mask &= ~BIT(bit - 1); | ||
199 | } | ||
200 | |||
198 | mc_writel(mc, stat, MC_INTSTATUS); | 201 | mc_writel(mc, stat, MC_INTSTATUS); |
199 | return IRQ_HANDLED; | 202 | return IRQ_HANDLED; |
200 | } | 203 | } |
diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c index f4ae074badc3..58d2979b4035 100644 --- a/drivers/memory/tegra30-mc.c +++ b/drivers/memory/tegra30-mc.c | |||
@@ -218,7 +218,7 @@ static void tegra30_mc_decode(struct tegra30_mc *mc, int n) | |||
218 | return; | 218 | return; |
219 | } | 219 | } |
220 | 220 | ||
221 | err = readl(mc + MC_ERR_STATUS); | 221 | err = mc_readl(mc, MC_ERR_STATUS); |
222 | 222 | ||
223 | type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT; | 223 | type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT; |
224 | perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >> | 224 | perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >> |
@@ -235,7 +235,7 @@ static void tegra30_mc_decode(struct tegra30_mc *mc, int n) | |||
235 | if (cid < ARRAY_SIZE(tegra30_mc_client)) | 235 | if (cid < ARRAY_SIZE(tegra30_mc_client)) |
236 | client = tegra30_mc_client[cid]; | 236 | client = tegra30_mc_client[cid]; |
237 | 237 | ||
238 | addr = readl(mc + MC_ERR_ADR); | 238 | addr = mc_readl(mc, MC_ERR_ADR); |
239 | 239 | ||
240 | dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n", | 240 | dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n", |
241 | mc_int_err[idx], err, addr, client, | 241 | mc_int_err[idx], err, addr, client, |
@@ -313,8 +313,11 @@ static irqreturn_t tegra30_mc_isr(int irq, void *data) | |||
313 | mask &= stat; | 313 | mask &= stat; |
314 | if (!mask) | 314 | if (!mask) |
315 | return IRQ_NONE; | 315 | return IRQ_NONE; |
316 | while ((bit = ffs(mask)) != 0) | 316 | while ((bit = ffs(mask)) != 0) { |
317 | tegra30_mc_decode(mc, bit - 1); | 317 | tegra30_mc_decode(mc, bit - 1); |
318 | mask &= ~BIT(bit - 1); | ||
319 | } | ||
320 | |||
318 | mc_writel(mc, stat, MC_INTSTATUS); | 321 | mc_writel(mc, stat, MC_INTSTATUS); |
319 | return IRQ_HANDLED; | 322 | return IRQ_HANDLED; |
320 | } | 323 | } |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index c002d8660e30..80889d5f95f5 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -480,6 +480,7 @@ config BMP085_SPI | |||
480 | 480 | ||
481 | config PCH_PHUB | 481 | config PCH_PHUB |
482 | tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB" | 482 | tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB" |
483 | select GENERIC_NET_UTILS | ||
483 | depends on PCI | 484 | depends on PCI |
484 | help | 485 | help |
485 | This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of | 486 | This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of |
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c index 8f99e8e3f0ac..0daadcf1ed7a 100644 --- a/drivers/misc/ad525x_dpot.c +++ b/drivers/misc/ad525x_dpot.c | |||
@@ -470,7 +470,7 @@ static ssize_t sysfs_set_reg(struct device *dev, | |||
470 | !test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask)) | 470 | !test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask)) |
471 | return -EPERM; | 471 | return -EPERM; |
472 | 472 | ||
473 | err = strict_strtoul(buf, 10, &value); | 473 | err = kstrtoul(buf, 10, &value); |
474 | if (err) | 474 | if (err) |
475 | return err; | 475 | return err; |
476 | 476 | ||
diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c index 5b5fd8416b3e..0c6e037153d2 100644 --- a/drivers/misc/apds9802als.c +++ b/drivers/misc/apds9802als.c | |||
@@ -126,8 +126,9 @@ static ssize_t als_sensing_range_store(struct device *dev, | |||
126 | int ret_val; | 126 | int ret_val; |
127 | unsigned long val; | 127 | unsigned long val; |
128 | 128 | ||
129 | if (strict_strtoul(buf, 10, &val)) | 129 | ret_val = kstrtoul(buf, 10, &val); |
130 | return -EINVAL; | 130 | if (ret_val) |
131 | return ret_val; | ||
131 | 132 | ||
132 | if (val < 4096) | 133 | if (val < 4096) |
133 | val = 1; | 134 | val = 1; |
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c index 98f9bb26492a..868a30a1b417 100644 --- a/drivers/misc/apds990x.c +++ b/drivers/misc/apds990x.c | |||
@@ -696,9 +696,11 @@ static ssize_t apds990x_lux_calib_store(struct device *dev, | |||
696 | { | 696 | { |
697 | struct apds990x_chip *chip = dev_get_drvdata(dev); | 697 | struct apds990x_chip *chip = dev_get_drvdata(dev); |
698 | unsigned long value; | 698 | unsigned long value; |
699 | int ret; | ||
699 | 700 | ||
700 | if (strict_strtoul(buf, 0, &value)) | 701 | ret = kstrtoul(buf, 0, &value); |
701 | return -EINVAL; | 702 | if (ret) |
703 | return ret; | ||
702 | 704 | ||
703 | chip->lux_calib = value; | 705 | chip->lux_calib = value; |
704 | 706 | ||
@@ -759,8 +761,9 @@ static ssize_t apds990x_rate_store(struct device *dev, | |||
759 | unsigned long value; | 761 | unsigned long value; |
760 | int ret; | 762 | int ret; |
761 | 763 | ||
762 | if (strict_strtoul(buf, 0, &value)) | 764 | ret = kstrtoul(buf, 0, &value); |
763 | return -EINVAL; | 765 | if (ret) |
766 | return ret; | ||
764 | 767 | ||
765 | mutex_lock(&chip->mutex); | 768 | mutex_lock(&chip->mutex); |
766 | ret = apds990x_set_arate(chip, value); | 769 | ret = apds990x_set_arate(chip, value); |
@@ -813,9 +816,11 @@ static ssize_t apds990x_prox_enable_store(struct device *dev, | |||
813 | { | 816 | { |
814 | struct apds990x_chip *chip = dev_get_drvdata(dev); | 817 | struct apds990x_chip *chip = dev_get_drvdata(dev); |
815 | unsigned long value; | 818 | unsigned long value; |
819 | int ret; | ||
816 | 820 | ||
817 | if (strict_strtoul(buf, 0, &value)) | 821 | ret = kstrtoul(buf, 0, &value); |
818 | return -EINVAL; | 822 | if (ret) |
823 | return ret; | ||
819 | 824 | ||
820 | mutex_lock(&chip->mutex); | 825 | mutex_lock(&chip->mutex); |
821 | 826 | ||
@@ -892,11 +897,12 @@ static ssize_t apds990x_lux_thresh_below_show(struct device *dev, | |||
892 | static ssize_t apds990x_set_lux_thresh(struct apds990x_chip *chip, u32 *target, | 897 | static ssize_t apds990x_set_lux_thresh(struct apds990x_chip *chip, u32 *target, |
893 | const char *buf) | 898 | const char *buf) |
894 | { | 899 | { |
895 | int ret = 0; | ||
896 | unsigned long thresh; | 900 | unsigned long thresh; |
901 | int ret; | ||
897 | 902 | ||
898 | if (strict_strtoul(buf, 0, &thresh)) | 903 | ret = kstrtoul(buf, 0, &thresh); |
899 | return -EINVAL; | 904 | if (ret) |
905 | return ret; | ||
900 | 906 | ||
901 | if (thresh > APDS_RANGE) | 907 | if (thresh > APDS_RANGE) |
902 | return -EINVAL; | 908 | return -EINVAL; |
@@ -957,9 +963,11 @@ static ssize_t apds990x_prox_threshold_store(struct device *dev, | |||
957 | { | 963 | { |
958 | struct apds990x_chip *chip = dev_get_drvdata(dev); | 964 | struct apds990x_chip *chip = dev_get_drvdata(dev); |
959 | unsigned long value; | 965 | unsigned long value; |
966 | int ret; | ||
960 | 967 | ||
961 | if (strict_strtoul(buf, 0, &value)) | 968 | ret = kstrtoul(buf, 0, &value); |
962 | return -EINVAL; | 969 | if (ret) |
970 | return ret; | ||
963 | 971 | ||
964 | if ((value > APDS_RANGE) || (value == 0) || | 972 | if ((value > APDS_RANGE) || (value == 0) || |
965 | (value < APDS_PROX_HYSTERESIS)) | 973 | (value < APDS_PROX_HYSTERESIS)) |
@@ -990,9 +998,12 @@ static ssize_t apds990x_power_state_store(struct device *dev, | |||
990 | { | 998 | { |
991 | struct apds990x_chip *chip = dev_get_drvdata(dev); | 999 | struct apds990x_chip *chip = dev_get_drvdata(dev); |
992 | unsigned long value; | 1000 | unsigned long value; |
1001 | int ret; | ||
1002 | |||
1003 | ret = kstrtoul(buf, 0, &value); | ||
1004 | if (ret) | ||
1005 | return ret; | ||
993 | 1006 | ||
994 | if (strict_strtoul(buf, 0, &value)) | ||
995 | return -EINVAL; | ||
996 | if (value) { | 1007 | if (value) { |
997 | pm_runtime_get_sync(dev); | 1008 | pm_runtime_get_sync(dev); |
998 | mutex_lock(&chip->mutex); | 1009 | mutex_lock(&chip->mutex); |
diff --git a/drivers/misc/arm-charlcd.c b/drivers/misc/arm-charlcd.c index 48651ef0028c..1256a4bf1c04 100644 --- a/drivers/misc/arm-charlcd.c +++ b/drivers/misc/arm-charlcd.c | |||
@@ -291,7 +291,7 @@ static int __init charlcd_probe(struct platform_device *pdev) | |||
291 | lcd->virtbase = ioremap(lcd->phybase, lcd->physize); | 291 | lcd->virtbase = ioremap(lcd->phybase, lcd->physize); |
292 | if (!lcd->virtbase) { | 292 | if (!lcd->virtbase) { |
293 | ret = -ENOMEM; | 293 | ret = -ENOMEM; |
294 | goto out_no_remap; | 294 | goto out_no_memregion; |
295 | } | 295 | } |
296 | 296 | ||
297 | lcd->irq = platform_get_irq(pdev, 0); | 297 | lcd->irq = platform_get_irq(pdev, 0); |
@@ -320,8 +320,6 @@ static int __init charlcd_probe(struct platform_device *pdev) | |||
320 | 320 | ||
321 | out_no_irq: | 321 | out_no_irq: |
322 | iounmap(lcd->virtbase); | 322 | iounmap(lcd->virtbase); |
323 | out_no_remap: | ||
324 | platform_set_drvdata(pdev, NULL); | ||
325 | out_no_memregion: | 323 | out_no_memregion: |
326 | release_mem_region(lcd->phybase, SZ_4K); | 324 | release_mem_region(lcd->phybase, SZ_4K); |
327 | out_no_resource: | 325 | out_no_resource: |
@@ -337,7 +335,6 @@ static int __exit charlcd_remove(struct platform_device *pdev) | |||
337 | free_irq(lcd->irq, lcd); | 335 | free_irq(lcd->irq, lcd); |
338 | iounmap(lcd->virtbase); | 336 | iounmap(lcd->virtbase); |
339 | release_mem_region(lcd->phybase, lcd->physize); | 337 | release_mem_region(lcd->phybase, lcd->physize); |
340 | platform_set_drvdata(pdev, NULL); | ||
341 | kfree(lcd); | 338 | kfree(lcd); |
342 | } | 339 | } |
343 | 340 | ||
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c index f4975f7d0d5b..99a04686e45f 100644 --- a/drivers/misc/bh1770glc.c +++ b/drivers/misc/bh1770glc.c | |||
@@ -651,8 +651,9 @@ static ssize_t bh1770_power_state_store(struct device *dev, | |||
651 | unsigned long value; | 651 | unsigned long value; |
652 | ssize_t ret; | 652 | ssize_t ret; |
653 | 653 | ||
654 | if (strict_strtoul(buf, 0, &value)) | 654 | ret = kstrtoul(buf, 0, &value); |
655 | return -EINVAL; | 655 | if (ret) |
656 | return ret; | ||
656 | 657 | ||
657 | mutex_lock(&chip->mutex); | 658 | mutex_lock(&chip->mutex); |
658 | if (value) { | 659 | if (value) { |
@@ -726,9 +727,11 @@ static ssize_t bh1770_prox_enable_store(struct device *dev, | |||
726 | { | 727 | { |
727 | struct bh1770_chip *chip = dev_get_drvdata(dev); | 728 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
728 | unsigned long value; | 729 | unsigned long value; |
730 | int ret; | ||
729 | 731 | ||
730 | if (strict_strtoul(buf, 0, &value)) | 732 | ret = kstrtoul(buf, 0, &value); |
731 | return -EINVAL; | 733 | if (ret) |
734 | return ret; | ||
732 | 735 | ||
733 | mutex_lock(&chip->mutex); | 736 | mutex_lock(&chip->mutex); |
734 | /* Assume no proximity. Sensor will tell real state soon */ | 737 | /* Assume no proximity. Sensor will tell real state soon */ |
@@ -824,9 +827,11 @@ static ssize_t bh1770_set_prox_rate_above(struct device *dev, | |||
824 | { | 827 | { |
825 | struct bh1770_chip *chip = dev_get_drvdata(dev); | 828 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
826 | unsigned long value; | 829 | unsigned long value; |
830 | int ret; | ||
827 | 831 | ||
828 | if (strict_strtoul(buf, 0, &value)) | 832 | ret = kstrtoul(buf, 0, &value); |
829 | return -EINVAL; | 833 | if (ret) |
834 | return ret; | ||
830 | 835 | ||
831 | mutex_lock(&chip->mutex); | 836 | mutex_lock(&chip->mutex); |
832 | chip->prox_rate_threshold = bh1770_prox_rate_validate(value); | 837 | chip->prox_rate_threshold = bh1770_prox_rate_validate(value); |
@@ -840,9 +845,11 @@ static ssize_t bh1770_set_prox_rate_below(struct device *dev, | |||
840 | { | 845 | { |
841 | struct bh1770_chip *chip = dev_get_drvdata(dev); | 846 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
842 | unsigned long value; | 847 | unsigned long value; |
848 | int ret; | ||
843 | 849 | ||
844 | if (strict_strtoul(buf, 0, &value)) | 850 | ret = kstrtoul(buf, 0, &value); |
845 | return -EINVAL; | 851 | if (ret) |
852 | return ret; | ||
846 | 853 | ||
847 | mutex_lock(&chip->mutex); | 854 | mutex_lock(&chip->mutex); |
848 | chip->prox_rate = bh1770_prox_rate_validate(value); | 855 | chip->prox_rate = bh1770_prox_rate_validate(value); |
@@ -865,8 +872,10 @@ static ssize_t bh1770_set_prox_thres(struct device *dev, | |||
865 | unsigned long value; | 872 | unsigned long value; |
866 | int ret; | 873 | int ret; |
867 | 874 | ||
868 | if (strict_strtoul(buf, 0, &value)) | 875 | ret = kstrtoul(buf, 0, &value); |
869 | return -EINVAL; | 876 | if (ret) |
877 | return ret; | ||
878 | |||
870 | if (value > BH1770_PROX_RANGE) | 879 | if (value > BH1770_PROX_RANGE) |
871 | return -EINVAL; | 880 | return -EINVAL; |
872 | 881 | ||
@@ -893,9 +902,11 @@ static ssize_t bh1770_prox_persistence_store(struct device *dev, | |||
893 | { | 902 | { |
894 | struct bh1770_chip *chip = dev_get_drvdata(dev); | 903 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
895 | unsigned long value; | 904 | unsigned long value; |
905 | int ret; | ||
896 | 906 | ||
897 | if (strict_strtoul(buf, 0, &value)) | 907 | ret = kstrtoul(buf, 0, &value); |
898 | return -EINVAL; | 908 | if (ret) |
909 | return ret; | ||
899 | 910 | ||
900 | if (value > BH1770_PROX_MAX_PERSISTENCE) | 911 | if (value > BH1770_PROX_MAX_PERSISTENCE) |
901 | return -EINVAL; | 912 | return -EINVAL; |
@@ -918,9 +929,11 @@ static ssize_t bh1770_prox_abs_thres_store(struct device *dev, | |||
918 | { | 929 | { |
919 | struct bh1770_chip *chip = dev_get_drvdata(dev); | 930 | struct bh1770_chip *chip = dev_get_drvdata(dev); |
920 | unsigned long value; | 931 | unsigned long value; |
932 | int ret; | ||
921 | 933 | ||
922 | if (strict_strtoul(buf, 0, &value)) | 934 | ret = kstrtoul(buf, 0, &value); |
923 | return -EINVAL; | 935 | if (ret) |
936 | return ret; | ||
924 | 937 | ||
925 | if (value > BH1770_PROX_RANGE) | 938 | if (value > BH1770_PROX_RANGE) |
926 | return -EINVAL; | 939 | return -EINVAL; |
@@ -963,9 +976,11 @@ static ssize_t bh1770_lux_calib_store(struct device *dev, | |||
963 | unsigned long value; | 976 | unsigned long value; |
964 | u32 old_calib; | 977 | u32 old_calib; |
965 | u32 new_corr; | 978 | u32 new_corr; |
979 | int ret; | ||
966 | 980 | ||
967 | if (strict_strtoul(buf, 0, &value)) | 981 | ret = kstrtoul(buf, 0, &value); |
968 | return -EINVAL; | 982 | if (ret) |
983 | return ret; | ||
969 | 984 | ||
970 | mutex_lock(&chip->mutex); | 985 | mutex_lock(&chip->mutex); |
971 | old_calib = chip->lux_calib; | 986 | old_calib = chip->lux_calib; |
@@ -1012,8 +1027,9 @@ static ssize_t bh1770_set_lux_rate(struct device *dev, | |||
1012 | unsigned long rate_hz; | 1027 | unsigned long rate_hz; |
1013 | int ret, i; | 1028 | int ret, i; |
1014 | 1029 | ||
1015 | if (strict_strtoul(buf, 0, &rate_hz)) | 1030 | ret = kstrtoul(buf, 0, &rate_hz); |
1016 | return -EINVAL; | 1031 | if (ret) |
1032 | return ret; | ||
1017 | 1033 | ||
1018 | for (i = 0; i < ARRAY_SIZE(lux_rates_hz) - 1; i++) | 1034 | for (i = 0; i < ARRAY_SIZE(lux_rates_hz) - 1; i++) |
1019 | if (rate_hz >= lux_rates_hz[i]) | 1035 | if (rate_hz >= lux_rates_hz[i]) |
@@ -1047,11 +1063,12 @@ static ssize_t bh1770_get_lux_thresh_below(struct device *dev, | |||
1047 | static ssize_t bh1770_set_lux_thresh(struct bh1770_chip *chip, u16 *target, | 1063 | static ssize_t bh1770_set_lux_thresh(struct bh1770_chip *chip, u16 *target, |
1048 | const char *buf) | 1064 | const char *buf) |
1049 | { | 1065 | { |
1050 | int ret = 0; | ||
1051 | unsigned long thresh; | 1066 | unsigned long thresh; |
1067 | int ret; | ||
1052 | 1068 | ||
1053 | if (strict_strtoul(buf, 0, &thresh)) | 1069 | ret = kstrtoul(buf, 0, &thresh); |
1054 | return -EINVAL; | 1070 | if (ret) |
1071 | return ret; | ||
1055 | 1072 | ||
1056 | if (thresh > BH1770_LUX_RANGE) | 1073 | if (thresh > BH1770_LUX_RANGE) |
1057 | return -EINVAL; | 1074 | return -EINVAL; |
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c index 818f3a0e62bf..057580e026c0 100644 --- a/drivers/misc/bh1780gli.c +++ b/drivers/misc/bh1780gli.c | |||
@@ -107,7 +107,7 @@ static ssize_t bh1780_store_power_state(struct device *dev, | |||
107 | unsigned long val; | 107 | unsigned long val; |
108 | int error; | 108 | int error; |
109 | 109 | ||
110 | error = strict_strtoul(buf, 0, &val); | 110 | error = kstrtoul(buf, 0, &val); |
111 | if (error) | 111 | if (error) |
112 | return error; | 112 | return error; |
113 | 113 | ||
diff --git a/drivers/misc/carma/carma-fpga-program.c b/drivers/misc/carma/carma-fpga-program.c index 736c7714f565..c6bd7e84de24 100644 --- a/drivers/misc/carma/carma-fpga-program.c +++ b/drivers/misc/carma/carma-fpga-program.c | |||
@@ -830,8 +830,9 @@ static ssize_t penable_store(struct device *dev, struct device_attribute *attr, | |||
830 | unsigned long val; | 830 | unsigned long val; |
831 | int ret; | 831 | int ret; |
832 | 832 | ||
833 | if (strict_strtoul(buf, 0, &val)) | 833 | ret = kstrtoul(buf, 0, &val); |
834 | return -EINVAL; | 834 | if (ret) |
835 | return ret; | ||
835 | 836 | ||
836 | if (val) { | 837 | if (val) { |
837 | ret = fpga_enable_power_supplies(priv); | 838 | ret = fpga_enable_power_supplies(priv); |
@@ -859,8 +860,9 @@ static ssize_t program_store(struct device *dev, struct device_attribute *attr, | |||
859 | unsigned long val; | 860 | unsigned long val; |
860 | int ret; | 861 | int ret; |
861 | 862 | ||
862 | if (strict_strtoul(buf, 0, &val)) | 863 | ret = kstrtoul(buf, 0, &val); |
863 | return -EINVAL; | 864 | if (ret) |
865 | return ret; | ||
864 | 866 | ||
865 | /* We can't have an image writer and be programming simultaneously */ | 867 | /* We can't have an image writer and be programming simultaneously */ |
866 | if (mutex_lock_interruptible(&priv->lock)) | 868 | if (mutex_lock_interruptible(&priv->lock)) |
@@ -919,7 +921,7 @@ static bool dma_filter(struct dma_chan *chan, void *data) | |||
919 | 921 | ||
920 | static int fpga_of_remove(struct platform_device *op) | 922 | static int fpga_of_remove(struct platform_device *op) |
921 | { | 923 | { |
922 | struct fpga_dev *priv = dev_get_drvdata(&op->dev); | 924 | struct fpga_dev *priv = platform_get_drvdata(op); |
923 | struct device *this_device = priv->miscdev.this_device; | 925 | struct device *this_device = priv->miscdev.this_device; |
924 | 926 | ||
925 | sysfs_remove_group(&this_device->kobj, &fpga_attr_group); | 927 | sysfs_remove_group(&this_device->kobj, &fpga_attr_group); |
@@ -969,7 +971,7 @@ static int fpga_of_probe(struct platform_device *op) | |||
969 | 971 | ||
970 | kref_init(&priv->ref); | 972 | kref_init(&priv->ref); |
971 | 973 | ||
972 | dev_set_drvdata(&op->dev, priv); | 974 | platform_set_drvdata(op, priv); |
973 | priv->dev = &op->dev; | 975 | priv->dev = &op->dev; |
974 | mutex_init(&priv->lock); | 976 | mutex_init(&priv->lock); |
975 | init_completion(&priv->completion); | 977 | init_completion(&priv->completion); |
diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c index 7508cafff103..7b56563f8b74 100644 --- a/drivers/misc/carma/carma-fpga.c +++ b/drivers/misc/carma/carma-fpga.c | |||
@@ -1002,10 +1002,10 @@ static ssize_t data_en_set(struct device *dev, struct device_attribute *attr, | |||
1002 | unsigned long enable; | 1002 | unsigned long enable; |
1003 | int ret; | 1003 | int ret; |
1004 | 1004 | ||
1005 | ret = strict_strtoul(buf, 0, &enable); | 1005 | ret = kstrtoul(buf, 0, &enable); |
1006 | if (ret) { | 1006 | if (ret) { |
1007 | dev_err(priv->dev, "unable to parse enable input\n"); | 1007 | dev_err(priv->dev, "unable to parse enable input\n"); |
1008 | return -EINVAL; | 1008 | return ret; |
1009 | } | 1009 | } |
1010 | 1010 | ||
1011 | /* protect against concurrent enable/disable */ | 1011 | /* protect against concurrent enable/disable */ |
@@ -1296,7 +1296,7 @@ static int data_of_probe(struct platform_device *op) | |||
1296 | goto out_return; | 1296 | goto out_return; |
1297 | } | 1297 | } |
1298 | 1298 | ||
1299 | dev_set_drvdata(&op->dev, priv); | 1299 | platform_set_drvdata(op, priv); |
1300 | priv->dev = &op->dev; | 1300 | priv->dev = &op->dev; |
1301 | kref_init(&priv->ref); | 1301 | kref_init(&priv->ref); |
1302 | mutex_init(&priv->mutex); | 1302 | mutex_init(&priv->mutex); |
@@ -1400,7 +1400,7 @@ out_return: | |||
1400 | 1400 | ||
1401 | static int data_of_remove(struct platform_device *op) | 1401 | static int data_of_remove(struct platform_device *op) |
1402 | { | 1402 | { |
1403 | struct fpga_device *priv = dev_get_drvdata(&op->dev); | 1403 | struct fpga_device *priv = platform_get_drvdata(op); |
1404 | struct device *this_device = priv->miscdev.this_device; | 1404 | struct device *this_device = priv->miscdev.this_device; |
1405 | 1405 | ||
1406 | /* remove all sysfs files, now the device cannot be re-enabled */ | 1406 | /* remove all sysfs files, now the device cannot be re-enabled */ |
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 2baeec56edfe..5d4fd69d04ca 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c | |||
@@ -492,10 +492,9 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
492 | if (client->dev.platform_data) { | 492 | if (client->dev.platform_data) { |
493 | chip = *(struct at24_platform_data *)client->dev.platform_data; | 493 | chip = *(struct at24_platform_data *)client->dev.platform_data; |
494 | } else { | 494 | } else { |
495 | if (!id->driver_data) { | 495 | if (!id->driver_data) |
496 | err = -ENODEV; | 496 | return -ENODEV; |
497 | goto err_out; | 497 | |
498 | } | ||
499 | magic = id->driver_data; | 498 | magic = id->driver_data; |
500 | chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); | 499 | chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); |
501 | magic >>= AT24_SIZE_BYTELEN; | 500 | magic >>= AT24_SIZE_BYTELEN; |
@@ -519,8 +518,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
519 | "byte_len looks suspicious (no power of 2)!\n"); | 518 | "byte_len looks suspicious (no power of 2)!\n"); |
520 | if (!chip.page_size) { | 519 | if (!chip.page_size) { |
521 | dev_err(&client->dev, "page_size must not be 0!\n"); | 520 | dev_err(&client->dev, "page_size must not be 0!\n"); |
522 | err = -EINVAL; | 521 | return -EINVAL; |
523 | goto err_out; | ||
524 | } | 522 | } |
525 | if (!is_power_of_2(chip.page_size)) | 523 | if (!is_power_of_2(chip.page_size)) |
526 | dev_warn(&client->dev, | 524 | dev_warn(&client->dev, |
@@ -528,10 +526,9 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
528 | 526 | ||
529 | /* Use I2C operations unless we're stuck with SMBus extensions. */ | 527 | /* Use I2C operations unless we're stuck with SMBus extensions. */ |
530 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | 528 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { |
531 | if (chip.flags & AT24_FLAG_ADDR16) { | 529 | if (chip.flags & AT24_FLAG_ADDR16) |
532 | err = -EPFNOSUPPORT; | 530 | return -EPFNOSUPPORT; |
533 | goto err_out; | 531 | |
534 | } | ||
535 | if (i2c_check_functionality(client->adapter, | 532 | if (i2c_check_functionality(client->adapter, |
536 | I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { | 533 | I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { |
537 | use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; | 534 | 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) | |||
542 | I2C_FUNC_SMBUS_READ_BYTE_DATA)) { | 539 | I2C_FUNC_SMBUS_READ_BYTE_DATA)) { |
543 | use_smbus = I2C_SMBUS_BYTE_DATA; | 540 | use_smbus = I2C_SMBUS_BYTE_DATA; |
544 | } else { | 541 | } else { |
545 | err = -EPFNOSUPPORT; | 542 | return -EPFNOSUPPORT; |
546 | goto err_out; | ||
547 | } | 543 | } |
548 | } | 544 | } |
549 | 545 | ||
@@ -553,12 +549,10 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
553 | num_addresses = DIV_ROUND_UP(chip.byte_len, | 549 | num_addresses = DIV_ROUND_UP(chip.byte_len, |
554 | (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); | 550 | (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); |
555 | 551 | ||
556 | at24 = kzalloc(sizeof(struct at24_data) + | 552 | at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) + |
557 | num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); | 553 | num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); |
558 | if (!at24) { | 554 | if (!at24) |
559 | err = -ENOMEM; | 555 | return -ENOMEM; |
560 | goto err_out; | ||
561 | } | ||
562 | 556 | ||
563 | mutex_init(&at24->lock); | 557 | mutex_init(&at24->lock); |
564 | at24->use_smbus = use_smbus; | 558 | at24->use_smbus = use_smbus; |
@@ -596,11 +590,10 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
596 | at24->write_max = write_max; | 590 | at24->write_max = write_max; |
597 | 591 | ||
598 | /* buffer (data + address at the beginning) */ | 592 | /* buffer (data + address at the beginning) */ |
599 | at24->writebuf = kmalloc(write_max + 2, GFP_KERNEL); | 593 | at24->writebuf = devm_kzalloc(&client->dev, |
600 | if (!at24->writebuf) { | 594 | write_max + 2, GFP_KERNEL); |
601 | err = -ENOMEM; | 595 | if (!at24->writebuf) |
602 | goto err_struct; | 596 | return -ENOMEM; |
603 | } | ||
604 | } else { | 597 | } else { |
605 | dev_warn(&client->dev, | 598 | dev_warn(&client->dev, |
606 | "cannot write due to controller restrictions."); | 599 | "cannot write due to controller restrictions."); |
@@ -648,11 +641,6 @@ err_clients: | |||
648 | if (at24->client[i]) | 641 | if (at24->client[i]) |
649 | i2c_unregister_device(at24->client[i]); | 642 | i2c_unregister_device(at24->client[i]); |
650 | 643 | ||
651 | kfree(at24->writebuf); | ||
652 | err_struct: | ||
653 | kfree(at24); | ||
654 | err_out: | ||
655 | dev_dbg(&client->dev, "probe error %d\n", err); | ||
656 | return err; | 644 | return err; |
657 | } | 645 | } |
658 | 646 | ||
@@ -667,8 +655,6 @@ static int at24_remove(struct i2c_client *client) | |||
667 | for (i = 1; i < at24->num_addresses; i++) | 655 | for (i = 1; i < at24->num_addresses; i++) |
668 | i2c_unregister_device(at24->client[i]); | 656 | i2c_unregister_device(at24->client[i]); |
669 | 657 | ||
670 | kfree(at24->writebuf); | ||
671 | kfree(at24); | ||
672 | return 0; | 658 | return 0; |
673 | } | 659 | } |
674 | 660 | ||
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index ad8fd8e64937..840b3594a5ae 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c | |||
@@ -371,11 +371,10 @@ static int at25_probe(struct spi_device *spi) | |||
371 | if (np) { | 371 | if (np) { |
372 | err = at25_np_to_chip(&spi->dev, np, &chip); | 372 | err = at25_np_to_chip(&spi->dev, np, &chip); |
373 | if (err) | 373 | if (err) |
374 | goto fail; | 374 | return err; |
375 | } else { | 375 | } else { |
376 | dev_err(&spi->dev, "Error: no chip description\n"); | 376 | dev_err(&spi->dev, "Error: no chip description\n"); |
377 | err = -ENODEV; | 377 | return -ENODEV; |
378 | goto fail; | ||
379 | } | 378 | } |
380 | } else | 379 | } else |
381 | chip = *(struct spi_eeprom *)spi->dev.platform_data; | 380 | chip = *(struct spi_eeprom *)spi->dev.platform_data; |
@@ -389,8 +388,7 @@ static int at25_probe(struct spi_device *spi) | |||
389 | addrlen = 3; | 388 | addrlen = 3; |
390 | else { | 389 | else { |
391 | dev_dbg(&spi->dev, "unsupported address type\n"); | 390 | dev_dbg(&spi->dev, "unsupported address type\n"); |
392 | err = -EINVAL; | 391 | return -EINVAL; |
393 | goto fail; | ||
394 | } | 392 | } |
395 | 393 | ||
396 | /* Ping the chip ... the status register is pretty portable, | 394 | /* Ping the chip ... the status register is pretty portable, |
@@ -400,14 +398,12 @@ static int at25_probe(struct spi_device *spi) | |||
400 | sr = spi_w8r8(spi, AT25_RDSR); | 398 | sr = spi_w8r8(spi, AT25_RDSR); |
401 | if (sr < 0 || sr & AT25_SR_nRDY) { | 399 | if (sr < 0 || sr & AT25_SR_nRDY) { |
402 | dev_dbg(&spi->dev, "rdsr --> %d (%02x)\n", sr, sr); | 400 | dev_dbg(&spi->dev, "rdsr --> %d (%02x)\n", sr, sr); |
403 | err = -ENXIO; | 401 | return -ENXIO; |
404 | goto fail; | ||
405 | } | 402 | } |
406 | 403 | ||
407 | if (!(at25 = kzalloc(sizeof *at25, GFP_KERNEL))) { | 404 | at25 = devm_kzalloc(&spi->dev, sizeof(struct at25_data), GFP_KERNEL); |
408 | err = -ENOMEM; | 405 | if (!at25) |
409 | goto fail; | 406 | return -ENOMEM; |
410 | } | ||
411 | 407 | ||
412 | mutex_init(&at25->lock); | 408 | mutex_init(&at25->lock); |
413 | at25->chip = chip; | 409 | at25->chip = chip; |
@@ -439,7 +435,7 @@ static int at25_probe(struct spi_device *spi) | |||
439 | 435 | ||
440 | err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin); | 436 | err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin); |
441 | if (err) | 437 | if (err) |
442 | goto fail; | 438 | return err; |
443 | 439 | ||
444 | if (chip.setup) | 440 | if (chip.setup) |
445 | chip.setup(&at25->mem, chip.context); | 441 | chip.setup(&at25->mem, chip.context); |
@@ -453,10 +449,6 @@ static int at25_probe(struct spi_device *spi) | |||
453 | (chip.flags & EE_READONLY) ? " (readonly)" : "", | 449 | (chip.flags & EE_READONLY) ? " (readonly)" : "", |
454 | at25->chip.page_size); | 450 | at25->chip.page_size); |
455 | return 0; | 451 | return 0; |
456 | fail: | ||
457 | dev_dbg(&spi->dev, "probe err %d\n", err); | ||
458 | kfree(at25); | ||
459 | return err; | ||
460 | } | 452 | } |
461 | 453 | ||
462 | static int at25_remove(struct spi_device *spi) | 454 | static int at25_remove(struct spi_device *spi) |
@@ -465,7 +457,6 @@ static int at25_remove(struct spi_device *spi) | |||
465 | 457 | ||
466 | at25 = spi_get_drvdata(spi); | 458 | at25 = spi_get_drvdata(spi); |
467 | sysfs_remove_bin_file(&spi->dev.kobj, &at25->bin); | 459 | sysfs_remove_bin_file(&spi->dev.kobj, &at25->bin); |
468 | kfree(at25); | ||
469 | return 0; | 460 | return 0; |
470 | } | 461 | } |
471 | 462 | ||
diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c index 96787ec15cad..cdb67a9c1959 100644 --- a/drivers/misc/ep93xx_pwm.c +++ b/drivers/misc/ep93xx_pwm.c | |||
@@ -39,63 +39,6 @@ struct ep93xx_pwm { | |||
39 | u32 duty_percent; | 39 | u32 duty_percent; |
40 | }; | 40 | }; |
41 | 41 | ||
42 | static inline void ep93xx_pwm_writel(struct ep93xx_pwm *pwm, | ||
43 | unsigned int val, unsigned int off) | ||
44 | { | ||
45 | __raw_writel(val, pwm->mmio_base + off); | ||
46 | } | ||
47 | |||
48 | static inline unsigned int ep93xx_pwm_readl(struct ep93xx_pwm *pwm, | ||
49 | unsigned int off) | ||
50 | { | ||
51 | return __raw_readl(pwm->mmio_base + off); | ||
52 | } | ||
53 | |||
54 | static inline void ep93xx_pwm_write_tc(struct ep93xx_pwm *pwm, u16 value) | ||
55 | { | ||
56 | ep93xx_pwm_writel(pwm, value, EP93XX_PWMx_TERM_COUNT); | ||
57 | } | ||
58 | |||
59 | static inline u16 ep93xx_pwm_read_tc(struct ep93xx_pwm *pwm) | ||
60 | { | ||
61 | return ep93xx_pwm_readl(pwm, EP93XX_PWMx_TERM_COUNT); | ||
62 | } | ||
63 | |||
64 | static inline void ep93xx_pwm_write_dc(struct ep93xx_pwm *pwm, u16 value) | ||
65 | { | ||
66 | ep93xx_pwm_writel(pwm, value, EP93XX_PWMx_DUTY_CYCLE); | ||
67 | } | ||
68 | |||
69 | static inline void ep93xx_pwm_enable(struct ep93xx_pwm *pwm) | ||
70 | { | ||
71 | ep93xx_pwm_writel(pwm, 0x1, EP93XX_PWMx_ENABLE); | ||
72 | } | ||
73 | |||
74 | static inline void ep93xx_pwm_disable(struct ep93xx_pwm *pwm) | ||
75 | { | ||
76 | ep93xx_pwm_writel(pwm, 0x0, EP93XX_PWMx_ENABLE); | ||
77 | } | ||
78 | |||
79 | static inline int ep93xx_pwm_is_enabled(struct ep93xx_pwm *pwm) | ||
80 | { | ||
81 | return ep93xx_pwm_readl(pwm, EP93XX_PWMx_ENABLE) & 0x1; | ||
82 | } | ||
83 | |||
84 | static inline void ep93xx_pwm_invert(struct ep93xx_pwm *pwm) | ||
85 | { | ||
86 | ep93xx_pwm_writel(pwm, 0x1, EP93XX_PWMx_INVERT); | ||
87 | } | ||
88 | |||
89 | static inline void ep93xx_pwm_normal(struct ep93xx_pwm *pwm) | ||
90 | { | ||
91 | ep93xx_pwm_writel(pwm, 0x0, EP93XX_PWMx_INVERT); | ||
92 | } | ||
93 | |||
94 | static inline int ep93xx_pwm_is_inverted(struct ep93xx_pwm *pwm) | ||
95 | { | ||
96 | return ep93xx_pwm_readl(pwm, EP93XX_PWMx_INVERT) & 0x1; | ||
97 | } | ||
98 | |||
99 | /* | 42 | /* |
100 | * /sys/devices/platform/ep93xx-pwm.N | 43 | * /sys/devices/platform/ep93xx-pwm.N |
101 | * /min_freq read-only minimum pwm output frequency | 44 | * /min_freq read-only minimum pwm output frequency |
@@ -131,9 +74,9 @@ static ssize_t ep93xx_pwm_get_freq(struct device *dev, | |||
131 | struct platform_device *pdev = to_platform_device(dev); | 74 | struct platform_device *pdev = to_platform_device(dev); |
132 | struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); | 75 | struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); |
133 | 76 | ||
134 | if (ep93xx_pwm_is_enabled(pwm)) { | 77 | if (readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1) { |
135 | unsigned long rate = clk_get_rate(pwm->clk); | 78 | unsigned long rate = clk_get_rate(pwm->clk); |
136 | u16 term = ep93xx_pwm_read_tc(pwm); | 79 | u16 term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); |
137 | 80 | ||
138 | return sprintf(buf, "%ld\n", rate / (term + 1)); | 81 | return sprintf(buf, "%ld\n", rate / (term + 1)); |
139 | } else { | 82 | } else { |
@@ -149,12 +92,12 @@ static ssize_t ep93xx_pwm_set_freq(struct device *dev, | |||
149 | long val; | 92 | long val; |
150 | int err; | 93 | int err; |
151 | 94 | ||
152 | err = strict_strtol(buf, 10, &val); | 95 | err = kstrtol(buf, 10, &val); |
153 | if (err) | 96 | if (err) |
154 | return -EINVAL; | 97 | return -EINVAL; |
155 | 98 | ||
156 | if (val == 0) { | 99 | if (val == 0) { |
157 | ep93xx_pwm_disable(pwm); | 100 | writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE); |
158 | } else if (val <= (clk_get_rate(pwm->clk) / 2)) { | 101 | } else if (val <= (clk_get_rate(pwm->clk) / 2)) { |
159 | u32 term, duty; | 102 | u32 term, duty; |
160 | 103 | ||
@@ -164,20 +107,20 @@ static ssize_t ep93xx_pwm_set_freq(struct device *dev, | |||
164 | if (val < 1) | 107 | if (val < 1) |
165 | val = 1; | 108 | val = 1; |
166 | 109 | ||
167 | term = ep93xx_pwm_read_tc(pwm); | 110 | term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); |
168 | duty = ((val + 1) * pwm->duty_percent / 100) - 1; | 111 | duty = ((val + 1) * pwm->duty_percent / 100) - 1; |
169 | 112 | ||
170 | /* If pwm is running, order is important */ | 113 | /* If pwm is running, order is important */ |
171 | if (val > term) { | 114 | if (val > term) { |
172 | ep93xx_pwm_write_tc(pwm, val); | 115 | writel(val, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); |
173 | ep93xx_pwm_write_dc(pwm, duty); | 116 | writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE); |
174 | } else { | 117 | } else { |
175 | ep93xx_pwm_write_dc(pwm, duty); | 118 | writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE); |
176 | ep93xx_pwm_write_tc(pwm, val); | 119 | writel(val, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); |
177 | } | 120 | } |
178 | 121 | ||
179 | if (!ep93xx_pwm_is_enabled(pwm)) | 122 | if (!readl(pwm->mmio_base + EP93XX_PWMx_ENABLE) & 0x1) |
180 | ep93xx_pwm_enable(pwm); | 123 | writel(0x1, pwm->mmio_base + EP93XX_PWMx_ENABLE); |
181 | } else { | 124 | } else { |
182 | return -EINVAL; | 125 | return -EINVAL; |
183 | } | 126 | } |
@@ -202,13 +145,15 @@ static ssize_t ep93xx_pwm_set_duty_percent(struct device *dev, | |||
202 | long val; | 145 | long val; |
203 | int err; | 146 | int err; |
204 | 147 | ||
205 | err = strict_strtol(buf, 10, &val); | 148 | err = kstrtol(buf, 10, &val); |
206 | if (err) | 149 | if (err) |
207 | return -EINVAL; | 150 | return -EINVAL; |
208 | 151 | ||
209 | if (val > 0 && val < 100) { | 152 | if (val > 0 && val < 100) { |
210 | u32 term = ep93xx_pwm_read_tc(pwm); | 153 | u32 term = readl(pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); |
211 | ep93xx_pwm_write_dc(pwm, ((term + 1) * val / 100) - 1); | 154 | u32 duty = ((term + 1) * val / 100) - 1; |
155 | |||
156 | writel(duty, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE); | ||
212 | pwm->duty_percent = val; | 157 | pwm->duty_percent = val; |
213 | return count; | 158 | return count; |
214 | } | 159 | } |
@@ -221,8 +166,9 @@ static ssize_t ep93xx_pwm_get_invert(struct device *dev, | |||
221 | { | 166 | { |
222 | struct platform_device *pdev = to_platform_device(dev); | 167 | struct platform_device *pdev = to_platform_device(dev); |
223 | struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); | 168 | struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); |
169 | int inverted = readl(pwm->mmio_base + EP93XX_PWMx_INVERT) & 0x1; | ||
224 | 170 | ||
225 | return sprintf(buf, "%d\n", ep93xx_pwm_is_inverted(pwm)); | 171 | return sprintf(buf, "%d\n", inverted); |
226 | } | 172 | } |
227 | 173 | ||
228 | static ssize_t ep93xx_pwm_set_invert(struct device *dev, | 174 | static ssize_t ep93xx_pwm_set_invert(struct device *dev, |
@@ -233,14 +179,14 @@ static ssize_t ep93xx_pwm_set_invert(struct device *dev, | |||
233 | long val; | 179 | long val; |
234 | int err; | 180 | int err; |
235 | 181 | ||
236 | err = strict_strtol(buf, 10, &val); | 182 | err = kstrtol(buf, 10, &val); |
237 | if (err) | 183 | if (err) |
238 | return -EINVAL; | 184 | return -EINVAL; |
239 | 185 | ||
240 | if (val == 0) | 186 | if (val == 0) |
241 | ep93xx_pwm_normal(pwm); | 187 | writel(0x0, pwm->mmio_base + EP93XX_PWMx_INVERT); |
242 | else if (val == 1) | 188 | else if (val == 1) |
243 | ep93xx_pwm_invert(pwm); | 189 | writel(0x1, pwm->mmio_base + EP93XX_PWMx_INVERT); |
244 | else | 190 | else |
245 | return -EINVAL; | 191 | return -EINVAL; |
246 | 192 | ||
@@ -269,89 +215,55 @@ static const struct attribute_group ep93xx_pwm_sysfs_files = { | |||
269 | .attrs = ep93xx_pwm_attrs, | 215 | .attrs = ep93xx_pwm_attrs, |
270 | }; | 216 | }; |
271 | 217 | ||
272 | static int __init ep93xx_pwm_probe(struct platform_device *pdev) | 218 | static int ep93xx_pwm_probe(struct platform_device *pdev) |
273 | { | 219 | { |
274 | struct ep93xx_pwm *pwm; | 220 | struct ep93xx_pwm *pwm; |
275 | struct resource *res; | 221 | struct resource *res; |
276 | int err; | 222 | int ret; |
277 | 223 | ||
278 | err = ep93xx_pwm_acquire_gpio(pdev); | 224 | pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); |
279 | if (err) | 225 | if (!pwm) |
280 | return err; | 226 | return -ENOMEM; |
281 | 227 | ||
282 | pwm = kzalloc(sizeof(struct ep93xx_pwm), GFP_KERNEL); | 228 | pwm->clk = devm_clk_get(&pdev->dev, "pwm_clk"); |
283 | if (!pwm) { | 229 | if (IS_ERR(pwm->clk)) |
284 | err = -ENOMEM; | 230 | return PTR_ERR(pwm->clk); |
285 | goto fail_no_mem; | ||
286 | } | ||
287 | 231 | ||
288 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 232 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
289 | if (res == NULL) { | 233 | pwm->mmio_base = devm_ioremap_resource(&pdev->dev, res); |
290 | err = -ENXIO; | 234 | if (IS_ERR(pwm->mmio_base)) |
291 | goto fail_no_mem_resource; | 235 | return PTR_ERR(pwm->mmio_base); |
292 | } | 236 | |
293 | 237 | ret = ep93xx_pwm_acquire_gpio(pdev); | |
294 | res = request_mem_region(res->start, resource_size(res), pdev->name); | 238 | if (ret) |
295 | if (res == NULL) { | 239 | return ret; |
296 | err = -EBUSY; | 240 | |
297 | goto fail_no_mem_resource; | 241 | ret = sysfs_create_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files); |
298 | } | 242 | if (ret) { |
299 | 243 | ep93xx_pwm_release_gpio(pdev); | |
300 | pwm->mmio_base = ioremap(res->start, resource_size(res)); | 244 | return ret; |
301 | if (pwm->mmio_base == NULL) { | ||
302 | err = -ENXIO; | ||
303 | goto fail_no_ioremap; | ||
304 | } | ||
305 | |||
306 | err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files); | ||
307 | if (err) | ||
308 | goto fail_no_sysfs; | ||
309 | |||
310 | pwm->clk = clk_get(&pdev->dev, "pwm_clk"); | ||
311 | if (IS_ERR(pwm->clk)) { | ||
312 | err = PTR_ERR(pwm->clk); | ||
313 | goto fail_no_clk; | ||
314 | } | 245 | } |
315 | 246 | ||
316 | pwm->duty_percent = 50; | 247 | pwm->duty_percent = 50; |
317 | 248 | ||
318 | platform_set_drvdata(pdev, pwm); | ||
319 | |||
320 | /* disable pwm at startup. Avoids zero value. */ | 249 | /* disable pwm at startup. Avoids zero value. */ |
321 | ep93xx_pwm_disable(pwm); | 250 | writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE); |
322 | ep93xx_pwm_write_tc(pwm, EP93XX_PWM_MAX_COUNT); | 251 | writel(EP93XX_PWM_MAX_COUNT, pwm->mmio_base + EP93XX_PWMx_TERM_COUNT); |
323 | ep93xx_pwm_write_dc(pwm, EP93XX_PWM_MAX_COUNT / 2); | 252 | writel(EP93XX_PWM_MAX_COUNT/2, pwm->mmio_base + EP93XX_PWMx_DUTY_CYCLE); |
324 | 253 | ||
325 | clk_enable(pwm->clk); | 254 | clk_enable(pwm->clk); |
326 | 255 | ||
256 | platform_set_drvdata(pdev, pwm); | ||
327 | return 0; | 257 | return 0; |
328 | |||
329 | fail_no_clk: | ||
330 | sysfs_remove_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files); | ||
331 | fail_no_sysfs: | ||
332 | iounmap(pwm->mmio_base); | ||
333 | fail_no_ioremap: | ||
334 | release_mem_region(res->start, resource_size(res)); | ||
335 | fail_no_mem_resource: | ||
336 | kfree(pwm); | ||
337 | fail_no_mem: | ||
338 | ep93xx_pwm_release_gpio(pdev); | ||
339 | return err; | ||
340 | } | 258 | } |
341 | 259 | ||
342 | static int __exit ep93xx_pwm_remove(struct platform_device *pdev) | 260 | static int ep93xx_pwm_remove(struct platform_device *pdev) |
343 | { | 261 | { |
344 | struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); | 262 | struct ep93xx_pwm *pwm = platform_get_drvdata(pdev); |
345 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
346 | 263 | ||
347 | ep93xx_pwm_disable(pwm); | 264 | writel(0x0, pwm->mmio_base + EP93XX_PWMx_ENABLE); |
348 | clk_disable(pwm->clk); | 265 | clk_disable(pwm->clk); |
349 | clk_put(pwm->clk); | ||
350 | platform_set_drvdata(pdev, NULL); | ||
351 | sysfs_remove_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files); | 266 | sysfs_remove_group(&pdev->dev.kobj, &ep93xx_pwm_sysfs_files); |
352 | iounmap(pwm->mmio_base); | ||
353 | release_mem_region(res->start, resource_size(res)); | ||
354 | kfree(pwm); | ||
355 | ep93xx_pwm_release_gpio(pdev); | 267 | ep93xx_pwm_release_gpio(pdev); |
356 | 268 | ||
357 | return 0; | 269 | return 0; |
@@ -362,10 +274,10 @@ static struct platform_driver ep93xx_pwm_driver = { | |||
362 | .name = "ep93xx-pwm", | 274 | .name = "ep93xx-pwm", |
363 | .owner = THIS_MODULE, | 275 | .owner = THIS_MODULE, |
364 | }, | 276 | }, |
365 | .remove = __exit_p(ep93xx_pwm_remove), | 277 | .probe = ep93xx_pwm_probe, |
278 | .remove = ep93xx_pwm_remove, | ||
366 | }; | 279 | }; |
367 | 280 | module_platform_driver(ep93xx_pwm_driver); | |
368 | module_platform_driver_probe(ep93xx_pwm_driver, ep93xx_pwm_probe); | ||
369 | 281 | ||
370 | MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>, " | 282 | MODULE_AUTHOR("Matthieu Crapet <mcrapet@gmail.com>, " |
371 | "H Hartley Sweeten <hsweeten@visionengravers.com>"); | 283 | "H Hartley Sweeten <hsweeten@visionengravers.com>"); |
diff --git a/drivers/misc/hmc6352.c b/drivers/misc/hmc6352.c index 423cd40f1c0f..170bd3daf336 100644 --- a/drivers/misc/hmc6352.c +++ b/drivers/misc/hmc6352.c | |||
@@ -46,8 +46,9 @@ static int compass_store(struct device *dev, const char *buf, size_t count, | |||
46 | int ret; | 46 | int ret; |
47 | unsigned long val; | 47 | unsigned long val; |
48 | 48 | ||
49 | if (strict_strtoul(buf, 10, &val)) | 49 | ret = kstrtoul(buf, 10, &val); |
50 | return -EINVAL; | 50 | if (ret) |
51 | return ret; | ||
51 | if (val >= strlen(map)) | 52 | if (val >= strlen(map)) |
52 | return -EINVAL; | 53 | return -EINVAL; |
53 | mutex_lock(&compass_mutex); | 54 | mutex_lock(&compass_mutex); |
diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c index c5145b3fcce8..e3183f26216b 100644 --- a/drivers/misc/isl29003.c +++ b/drivers/misc/isl29003.c | |||
@@ -208,7 +208,11 @@ static ssize_t isl29003_store_range(struct device *dev, | |||
208 | unsigned long val; | 208 | unsigned long val; |
209 | int ret; | 209 | int ret; |
210 | 210 | ||
211 | if ((strict_strtoul(buf, 10, &val) < 0) || (val > 3)) | 211 | ret = kstrtoul(buf, 10, &val); |
212 | if (ret) | ||
213 | return ret; | ||
214 | |||
215 | if (val > 3) | ||
212 | return -EINVAL; | 216 | return -EINVAL; |
213 | 217 | ||
214 | ret = isl29003_set_range(client, val); | 218 | ret = isl29003_set_range(client, val); |
@@ -239,7 +243,11 @@ static ssize_t isl29003_store_resolution(struct device *dev, | |||
239 | unsigned long val; | 243 | unsigned long val; |
240 | int ret; | 244 | int ret; |
241 | 245 | ||
242 | if ((strict_strtoul(buf, 10, &val) < 0) || (val > 3)) | 246 | ret = kstrtoul(buf, 10, &val); |
247 | if (ret) | ||
248 | return ret; | ||
249 | |||
250 | if (val > 3) | ||
243 | return -EINVAL; | 251 | return -EINVAL; |
244 | 252 | ||
245 | ret = isl29003_set_resolution(client, val); | 253 | ret = isl29003_set_resolution(client, val); |
@@ -267,7 +275,11 @@ static ssize_t isl29003_store_mode(struct device *dev, | |||
267 | unsigned long val; | 275 | unsigned long val; |
268 | int ret; | 276 | int ret; |
269 | 277 | ||
270 | if ((strict_strtoul(buf, 10, &val) < 0) || (val > 2)) | 278 | ret = kstrtoul(buf, 10, &val); |
279 | if (ret) | ||
280 | return ret; | ||
281 | |||
282 | if (val > 2) | ||
271 | return -EINVAL; | 283 | return -EINVAL; |
272 | 284 | ||
273 | ret = isl29003_set_mode(client, val); | 285 | ret = isl29003_set_mode(client, val); |
@@ -298,7 +310,11 @@ static ssize_t isl29003_store_power_state(struct device *dev, | |||
298 | unsigned long val; | 310 | unsigned long val; |
299 | int ret; | 311 | int ret; |
300 | 312 | ||
301 | if ((strict_strtoul(buf, 10, &val) < 0) || (val > 1)) | 313 | ret = kstrtoul(buf, 10, &val); |
314 | if (ret) | ||
315 | return ret; | ||
316 | |||
317 | if (val > 1) | ||
302 | return -EINVAL; | 318 | return -EINVAL; |
303 | 319 | ||
304 | ret = isl29003_set_power_state(client, val); | 320 | ret = isl29003_set_power_state(client, val); |
diff --git a/drivers/misc/isl29020.c b/drivers/misc/isl29020.c index 0aa08c746463..b7f84dacf822 100644 --- a/drivers/misc/isl29020.c +++ b/drivers/misc/isl29020.c | |||
@@ -90,8 +90,10 @@ static ssize_t als_sensing_range_store(struct device *dev, | |||
90 | int ret_val; | 90 | int ret_val; |
91 | unsigned long val; | 91 | unsigned long val; |
92 | 92 | ||
93 | if (strict_strtoul(buf, 10, &val)) | 93 | ret_val = kstrtoul(buf, 10, &val); |
94 | return -EINVAL; | 94 | if (ret_val) |
95 | return ret_val; | ||
96 | |||
95 | if (val < 1 || val > 64000) | 97 | if (val < 1 || val > 64000) |
96 | return -EINVAL; | 98 | return -EINVAL; |
97 | 99 | ||
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c index 4cd4a3d2a76a..036effe9a795 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d.c +++ b/drivers/misc/lis3lv02d/lis3lv02d.c | |||
@@ -831,9 +831,11 @@ static ssize_t lis3lv02d_rate_set(struct device *dev, | |||
831 | { | 831 | { |
832 | struct lis3lv02d *lis3 = dev_get_drvdata(dev); | 832 | struct lis3lv02d *lis3 = dev_get_drvdata(dev); |
833 | unsigned long rate; | 833 | unsigned long rate; |
834 | int ret; | ||
834 | 835 | ||
835 | if (strict_strtoul(buf, 0, &rate)) | 836 | ret = kstrtoul(buf, 0, &rate); |
836 | return -EINVAL; | 837 | if (ret) |
838 | return ret; | ||
837 | 839 | ||
838 | lis3lv02d_sysfs_poweron(lis3); | 840 | lis3lv02d_sysfs_poweron(lis3); |
839 | if (lis3lv02d_set_odr(lis3, rate)) | 841 | if (lis3lv02d_set_odr(lis3, rate)) |
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index b3e50984d2c8..749452f8e2f6 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c | |||
@@ -443,11 +443,11 @@ unsigned int mei_amthif_poll(struct mei_device *dev, | |||
443 | * | 443 | * |
444 | * returns 0, OK; otherwise, error. | 444 | * returns 0, OK; otherwise, error. |
445 | */ | 445 | */ |
446 | int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots, | 446 | int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb, |
447 | struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list) | 447 | s32 *slots, struct mei_cl_cb *cmpl_list) |
448 | { | 448 | { |
449 | struct mei_device *dev = cl->dev; | ||
449 | struct mei_msg_hdr mei_hdr; | 450 | struct mei_msg_hdr mei_hdr; |
450 | struct mei_cl *cl = cb->cl; | ||
451 | size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index; | 451 | size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index; |
452 | u32 msg_slots = mei_data2slots(len); | 452 | u32 msg_slots = mei_data2slots(len); |
453 | 453 | ||
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index e310ca6ed1a3..21d3f5aa8353 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c | |||
@@ -485,7 +485,6 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file) | |||
485 | { | 485 | { |
486 | struct mei_device *dev; | 486 | struct mei_device *dev; |
487 | struct mei_cl_cb *cb; | 487 | struct mei_cl_cb *cb; |
488 | long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT); | ||
489 | int rets; | 488 | int rets; |
490 | 489 | ||
491 | if (WARN_ON(!cl || !cl->dev)) | 490 | if (WARN_ON(!cl || !cl->dev)) |
@@ -518,7 +517,7 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file) | |||
518 | rets = wait_event_timeout(dev->wait_recvd_msg, | 517 | rets = wait_event_timeout(dev->wait_recvd_msg, |
519 | (cl->state == MEI_FILE_CONNECTED || | 518 | (cl->state == MEI_FILE_CONNECTED || |
520 | cl->state == MEI_FILE_DISCONNECTED), | 519 | cl->state == MEI_FILE_DISCONNECTED), |
521 | timeout * HZ); | 520 | mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT)); |
522 | mutex_lock(&dev->device_lock); | 521 | mutex_lock(&dev->device_lock); |
523 | 522 | ||
524 | if (cl->state != MEI_FILE_CONNECTED) { | 523 | if (cl->state != MEI_FILE_CONNECTED) { |
@@ -682,6 +681,68 @@ err: | |||
682 | } | 681 | } |
683 | 682 | ||
684 | /** | 683 | /** |
684 | * mei_cl_irq_write_complete - write a message to device | ||
685 | * from the interrupt thread context | ||
686 | * | ||
687 | * @cl: client | ||
688 | * @cb: callback block. | ||
689 | * @slots: free slots. | ||
690 | * @cmpl_list: complete list. | ||
691 | * | ||
692 | * returns 0, OK; otherwise error. | ||
693 | */ | ||
694 | int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb, | ||
695 | s32 *slots, struct mei_cl_cb *cmpl_list) | ||
696 | { | ||
697 | struct mei_device *dev = cl->dev; | ||
698 | struct mei_msg_hdr mei_hdr; | ||
699 | size_t len = cb->request_buffer.size - cb->buf_idx; | ||
700 | u32 msg_slots = mei_data2slots(len); | ||
701 | |||
702 | mei_hdr.host_addr = cl->host_client_id; | ||
703 | mei_hdr.me_addr = cl->me_client_id; | ||
704 | mei_hdr.reserved = 0; | ||
705 | |||
706 | if (*slots >= msg_slots) { | ||
707 | mei_hdr.length = len; | ||
708 | mei_hdr.msg_complete = 1; | ||
709 | /* Split the message only if we can write the whole host buffer */ | ||
710 | } else if (*slots == dev->hbuf_depth) { | ||
711 | msg_slots = *slots; | ||
712 | len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); | ||
713 | mei_hdr.length = len; | ||
714 | mei_hdr.msg_complete = 0; | ||
715 | } else { | ||
716 | /* wait for next time the host buffer is empty */ | ||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n", | ||
721 | cb->request_buffer.size, cb->buf_idx); | ||
722 | dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr)); | ||
723 | |||
724 | *slots -= msg_slots; | ||
725 | if (mei_write_message(dev, &mei_hdr, | ||
726 | cb->request_buffer.data + cb->buf_idx)) { | ||
727 | cl->status = -ENODEV; | ||
728 | list_move_tail(&cb->list, &cmpl_list->list); | ||
729 | return -ENODEV; | ||
730 | } | ||
731 | |||
732 | cl->status = 0; | ||
733 | cl->writing_state = MEI_WRITING; | ||
734 | cb->buf_idx += mei_hdr.length; | ||
735 | |||
736 | if (mei_hdr.msg_complete) { | ||
737 | if (mei_cl_flow_ctrl_reduce(cl)) | ||
738 | return -ENODEV; | ||
739 | list_move_tail(&cb->list, &dev->write_waiting_list.list); | ||
740 | } | ||
741 | |||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | /** | ||
685 | * mei_cl_write - submit a write cb to mei device | 746 | * mei_cl_write - submit a write cb to mei device |
686 | assumes device_lock is locked | 747 | assumes device_lock is locked |
687 | * | 748 | * |
@@ -723,7 +784,6 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking) | |||
723 | cb->buf_idx = 0; | 784 | cb->buf_idx = 0; |
724 | /* unseting complete will enqueue the cb for write */ | 785 | /* unseting complete will enqueue the cb for write */ |
725 | mei_hdr.msg_complete = 0; | 786 | mei_hdr.msg_complete = 0; |
726 | cl->writing_state = MEI_WRITING; | ||
727 | rets = buf->size; | 787 | rets = buf->size; |
728 | goto out; | 788 | goto out; |
729 | } | 789 | } |
@@ -785,6 +845,32 @@ err: | |||
785 | } | 845 | } |
786 | 846 | ||
787 | 847 | ||
848 | /** | ||
849 | * mei_cl_complete - processes completed operation for a client | ||
850 | * | ||
851 | * @cl: private data of the file object. | ||
852 | * @cb: callback block. | ||
853 | */ | ||
854 | void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb) | ||
855 | { | ||
856 | if (cb->fop_type == MEI_FOP_WRITE) { | ||
857 | mei_io_cb_free(cb); | ||
858 | cb = NULL; | ||
859 | cl->writing_state = MEI_WRITE_COMPLETE; | ||
860 | if (waitqueue_active(&cl->tx_wait)) | ||
861 | wake_up_interruptible(&cl->tx_wait); | ||
862 | |||
863 | } else if (cb->fop_type == MEI_FOP_READ && | ||
864 | MEI_READING == cl->reading_state) { | ||
865 | cl->reading_state = MEI_READ_COMPLETE; | ||
866 | if (waitqueue_active(&cl->rx_wait)) | ||
867 | wake_up_interruptible(&cl->rx_wait); | ||
868 | else | ||
869 | mei_cl_bus_rx_event(cl); | ||
870 | |||
871 | } | ||
872 | } | ||
873 | |||
788 | 874 | ||
789 | /** | 875 | /** |
790 | * mei_cl_all_disconnect - disconnect forcefully all connected clients | 876 | * mei_cl_all_disconnect - disconnect forcefully all connected clients |
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index cfdb144526aa..26b157d8bad5 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h | |||
@@ -89,6 +89,10 @@ int mei_cl_disconnect(struct mei_cl *cl); | |||
89 | int mei_cl_connect(struct mei_cl *cl, struct file *file); | 89 | int mei_cl_connect(struct mei_cl *cl, struct file *file); |
90 | int mei_cl_read_start(struct mei_cl *cl, size_t length); | 90 | int mei_cl_read_start(struct mei_cl *cl, size_t length); |
91 | int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking); | 91 | int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking); |
92 | int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb, | ||
93 | s32 *slots, struct mei_cl_cb *cmpl_list); | ||
94 | |||
95 | void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb); | ||
92 | 96 | ||
93 | void mei_host_client_init(struct work_struct *work); | 97 | void mei_host_client_init(struct work_struct *work); |
94 | 98 | ||
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 6916045166eb..565027b1bc73 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c | |||
@@ -536,6 +536,20 @@ static void mei_hbm_fw_disconnect_req(struct mei_device *dev, | |||
536 | 536 | ||
537 | 537 | ||
538 | /** | 538 | /** |
539 | * mei_hbm_version_is_supported - checks whether the driver can | ||
540 | * support the hbm version of the device | ||
541 | * | ||
542 | * @dev: the device structure | ||
543 | * returns true if driver can support hbm version of the device | ||
544 | */ | ||
545 | bool mei_hbm_version_is_supported(struct mei_device *dev) | ||
546 | { | ||
547 | return (dev->version.major_version < HBM_MAJOR_VERSION) || | ||
548 | (dev->version.major_version == HBM_MAJOR_VERSION && | ||
549 | dev->version.minor_version <= HBM_MINOR_VERSION); | ||
550 | } | ||
551 | |||
552 | /** | ||
539 | * mei_hbm_dispatch - bottom half read routine after ISR to | 553 | * mei_hbm_dispatch - bottom half read routine after ISR to |
540 | * handle the read bus message cmd processing. | 554 | * handle the read bus message cmd processing. |
541 | * | 555 | * |
@@ -562,9 +576,24 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) | |||
562 | switch (mei_msg->hbm_cmd) { | 576 | switch (mei_msg->hbm_cmd) { |
563 | case HOST_START_RES_CMD: | 577 | case HOST_START_RES_CMD: |
564 | version_res = (struct hbm_host_version_response *)mei_msg; | 578 | version_res = (struct hbm_host_version_response *)mei_msg; |
565 | if (!version_res->host_version_supported) { | 579 | |
566 | dev->version = version_res->me_max_version; | 580 | dev_dbg(&dev->pdev->dev, "HBM VERSION: DRIVER=%02d:%02d DEVICE=%02d:%02d\n", |
567 | dev_dbg(&dev->pdev->dev, "version mismatch.\n"); | 581 | HBM_MAJOR_VERSION, HBM_MINOR_VERSION, |
582 | version_res->me_max_version.major_version, | ||
583 | version_res->me_max_version.minor_version); | ||
584 | |||
585 | if (version_res->host_version_supported) { | ||
586 | dev->version.major_version = HBM_MAJOR_VERSION; | ||
587 | dev->version.minor_version = HBM_MINOR_VERSION; | ||
588 | } else { | ||
589 | dev->version.major_version = | ||
590 | version_res->me_max_version.major_version; | ||
591 | dev->version.minor_version = | ||
592 | version_res->me_max_version.minor_version; | ||
593 | } | ||
594 | |||
595 | if (!mei_hbm_version_is_supported(dev)) { | ||
596 | dev_warn(&dev->pdev->dev, "hbm version mismatch: stopping the driver.\n"); | ||
568 | 597 | ||
569 | dev->hbm_state = MEI_HBM_STOP; | 598 | dev->hbm_state = MEI_HBM_STOP; |
570 | mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr, | 599 | 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) | |||
575 | return; | 604 | return; |
576 | } | 605 | } |
577 | 606 | ||
578 | dev->version.major_version = HBM_MAJOR_VERSION; | ||
579 | dev->version.minor_version = HBM_MINOR_VERSION; | ||
580 | if (dev->dev_state == MEI_DEV_INIT_CLIENTS && | 607 | if (dev->dev_state == MEI_DEV_INIT_CLIENTS && |
581 | dev->hbm_state == MEI_HBM_START) { | 608 | dev->hbm_state == MEI_HBM_START) { |
582 | dev->init_clients_timer = 0; | 609 | dev->init_clients_timer = 0; |
diff --git a/drivers/misc/mei/hbm.h b/drivers/misc/mei/hbm.h index e80dc24ef3e2..4ae2e56e404f 100644 --- a/drivers/misc/mei/hbm.h +++ b/drivers/misc/mei/hbm.h | |||
@@ -54,7 +54,7 @@ int mei_hbm_start_wait(struct mei_device *dev); | |||
54 | int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl); | 54 | int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl); |
55 | int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl); | 55 | int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl); |
56 | int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl); | 56 | int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl); |
57 | 57 | bool mei_hbm_version_is_supported(struct mei_device *dev); | |
58 | 58 | ||
59 | #endif /* _MEI_HBM_H_ */ | 59 | #endif /* _MEI_HBM_H_ */ |
60 | 60 | ||
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 822170f00348..e4f8dec4dc3c 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c | |||
@@ -171,7 +171,7 @@ static void mei_me_hw_reset_release(struct mei_device *dev) | |||
171 | * @dev: the device structure | 171 | * @dev: the device structure |
172 | * @intr_enable: if interrupt should be enabled after reset. | 172 | * @intr_enable: if interrupt should be enabled after reset. |
173 | */ | 173 | */ |
174 | static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable) | 174 | static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable) |
175 | { | 175 | { |
176 | struct mei_me_hw *hw = to_me_hw(dev); | 176 | struct mei_me_hw *hw = to_me_hw(dev); |
177 | u32 hcsr = mei_hcsr_read(hw); | 177 | u32 hcsr = mei_hcsr_read(hw); |
@@ -191,6 +191,7 @@ static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable) | |||
191 | mei_me_hw_reset_release(dev); | 191 | mei_me_hw_reset_release(dev); |
192 | 192 | ||
193 | dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", mei_hcsr_read(hw)); | 193 | dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", mei_hcsr_read(hw)); |
194 | return 0; | ||
194 | } | 195 | } |
195 | 196 | ||
196 | /** | 197 | /** |
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index f580d30bb784..6fc573cef178 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
@@ -106,8 +106,7 @@ int mei_start(struct mei_device *dev) | |||
106 | goto err; | 106 | goto err; |
107 | } | 107 | } |
108 | 108 | ||
109 | if (dev->version.major_version != HBM_MAJOR_VERSION || | 109 | if (!mei_hbm_version_is_supported(dev)) { |
110 | dev->version.minor_version != HBM_MINOR_VERSION) { | ||
111 | dev_dbg(&dev->pdev->dev, "MEI start failed.\n"); | 110 | dev_dbg(&dev->pdev->dev, "MEI start failed.\n"); |
112 | goto err; | 111 | goto err; |
113 | } | 112 | } |
@@ -133,13 +132,19 @@ EXPORT_SYMBOL_GPL(mei_start); | |||
133 | void mei_reset(struct mei_device *dev, int interrupts_enabled) | 132 | void mei_reset(struct mei_device *dev, int interrupts_enabled) |
134 | { | 133 | { |
135 | bool unexpected; | 134 | bool unexpected; |
135 | int ret; | ||
136 | 136 | ||
137 | unexpected = (dev->dev_state != MEI_DEV_INITIALIZING && | 137 | unexpected = (dev->dev_state != MEI_DEV_INITIALIZING && |
138 | dev->dev_state != MEI_DEV_DISABLED && | 138 | dev->dev_state != MEI_DEV_DISABLED && |
139 | dev->dev_state != MEI_DEV_POWER_DOWN && | 139 | dev->dev_state != MEI_DEV_POWER_DOWN && |
140 | dev->dev_state != MEI_DEV_POWER_UP); | 140 | dev->dev_state != MEI_DEV_POWER_UP); |
141 | 141 | ||
142 | mei_hw_reset(dev, interrupts_enabled); | 142 | ret = mei_hw_reset(dev, interrupts_enabled); |
143 | if (ret) { | ||
144 | dev_err(&dev->pdev->dev, "hw reset failed disabling the device\n"); | ||
145 | interrupts_enabled = false; | ||
146 | dev->dev_state = MEI_DEV_DISABLED; | ||
147 | } | ||
143 | 148 | ||
144 | dev->hbm_state = MEI_HBM_IDLE; | 149 | dev->hbm_state = MEI_HBM_IDLE; |
145 | 150 | ||
@@ -176,7 +181,12 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
176 | return; | 181 | return; |
177 | } | 182 | } |
178 | 183 | ||
179 | mei_hw_start(dev); | 184 | ret = mei_hw_start(dev); |
185 | if (ret) { | ||
186 | dev_err(&dev->pdev->dev, "hw_start failed disabling the device\n"); | ||
187 | dev->dev_state = MEI_DEV_DISABLED; | ||
188 | return; | ||
189 | } | ||
180 | 190 | ||
181 | dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); | 191 | dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); |
182 | /* link is established * start sending messages. */ | 192 | /* link is established * start sending messages. */ |
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 2ad736989410..4b59cb742dee 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c | |||
@@ -31,32 +31,6 @@ | |||
31 | 31 | ||
32 | 32 | ||
33 | /** | 33 | /** |
34 | * mei_cl_complete_handler - processes completed operation for a client | ||
35 | * | ||
36 | * @cl: private data of the file object. | ||
37 | * @cb: callback block. | ||
38 | */ | ||
39 | static void mei_cl_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb) | ||
40 | { | ||
41 | if (cb->fop_type == MEI_FOP_WRITE) { | ||
42 | mei_io_cb_free(cb); | ||
43 | cb = NULL; | ||
44 | cl->writing_state = MEI_WRITE_COMPLETE; | ||
45 | if (waitqueue_active(&cl->tx_wait)) | ||
46 | wake_up_interruptible(&cl->tx_wait); | ||
47 | |||
48 | } else if (cb->fop_type == MEI_FOP_READ && | ||
49 | MEI_READING == cl->reading_state) { | ||
50 | cl->reading_state = MEI_READ_COMPLETE; | ||
51 | if (waitqueue_active(&cl->rx_wait)) | ||
52 | wake_up_interruptible(&cl->rx_wait); | ||
53 | else | ||
54 | mei_cl_bus_rx_event(cl); | ||
55 | |||
56 | } | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * mei_irq_compl_handler - dispatch complete handelers | 34 | * mei_irq_compl_handler - dispatch complete handelers |
61 | * for the completed callbacks | 35 | * for the completed callbacks |
62 | * | 36 | * |
@@ -78,7 +52,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list) | |||
78 | if (cl == &dev->iamthif_cl) | 52 | if (cl == &dev->iamthif_cl) |
79 | mei_amthif_complete(dev, cb); | 53 | mei_amthif_complete(dev, cb); |
80 | else | 54 | else |
81 | mei_cl_complete_handler(cl, cb); | 55 | mei_cl_complete(cl, cb); |
82 | } | 56 | } |
83 | } | 57 | } |
84 | EXPORT_SYMBOL_GPL(mei_irq_compl_handler); | 58 | EXPORT_SYMBOL_GPL(mei_irq_compl_handler); |
@@ -189,21 +163,21 @@ static int mei_cl_irq_read_msg(struct mei_device *dev, | |||
189 | } | 163 | } |
190 | 164 | ||
191 | /** | 165 | /** |
192 | * _mei_irq_thread_close - processes close related operation. | 166 | * mei_cl_irq_close - processes close related operation from |
167 | * interrupt thread context - send disconnect request | ||
193 | * | 168 | * |
194 | * @dev: the device structure. | 169 | * @cl: client |
170 | * @cb: callback block. | ||
195 | * @slots: free slots. | 171 | * @slots: free slots. |
196 | * @cb_pos: callback block. | ||
197 | * @cl: private data of the file object. | ||
198 | * @cmpl_list: complete list. | 172 | * @cmpl_list: complete list. |
199 | * | 173 | * |
200 | * returns 0, OK; otherwise, error. | 174 | * returns 0, OK; otherwise, error. |
201 | */ | 175 | */ |
202 | static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots, | 176 | static int mei_cl_irq_close(struct mei_cl *cl, struct mei_cl_cb *cb, |
203 | struct mei_cl_cb *cb_pos, | 177 | s32 *slots, struct mei_cl_cb *cmpl_list) |
204 | struct mei_cl *cl, | ||
205 | struct mei_cl_cb *cmpl_list) | ||
206 | { | 178 | { |
179 | struct mei_device *dev = cl->dev; | ||
180 | |||
207 | u32 msg_slots = | 181 | u32 msg_slots = |
208 | mei_data2slots(sizeof(struct hbm_client_connect_request)); | 182 | mei_data2slots(sizeof(struct hbm_client_connect_request)); |
209 | 183 | ||
@@ -214,15 +188,15 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots, | |||
214 | 188 | ||
215 | if (mei_hbm_cl_disconnect_req(dev, cl)) { | 189 | if (mei_hbm_cl_disconnect_req(dev, cl)) { |
216 | cl->status = 0; | 190 | cl->status = 0; |
217 | cb_pos->buf_idx = 0; | 191 | cb->buf_idx = 0; |
218 | list_move_tail(&cb_pos->list, &cmpl_list->list); | 192 | list_move_tail(&cb->list, &cmpl_list->list); |
219 | return -EIO; | 193 | return -EIO; |
220 | } | 194 | } |
221 | 195 | ||
222 | cl->state = MEI_FILE_DISCONNECTING; | 196 | cl->state = MEI_FILE_DISCONNECTING; |
223 | cl->status = 0; | 197 | cl->status = 0; |
224 | cb_pos->buf_idx = 0; | 198 | cb->buf_idx = 0; |
225 | list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list); | 199 | list_move_tail(&cb->list, &dev->ctrl_rd_list.list); |
226 | cl->timer_count = MEI_CONNECT_TIMEOUT; | 200 | cl->timer_count = MEI_CONNECT_TIMEOUT; |
227 | 201 | ||
228 | return 0; | 202 | return 0; |
@@ -230,26 +204,26 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots, | |||
230 | 204 | ||
231 | 205 | ||
232 | /** | 206 | /** |
233 | * _mei_irq_thread_read - processes read related operation. | 207 | * mei_cl_irq_close - processes client read related operation from the |
208 | * interrupt thread context - request for flow control credits | ||
234 | * | 209 | * |
235 | * @dev: the device structure. | 210 | * @cl: client |
211 | * @cb: callback block. | ||
236 | * @slots: free slots. | 212 | * @slots: free slots. |
237 | * @cb_pos: callback block. | ||
238 | * @cl: private data of the file object. | ||
239 | * @cmpl_list: complete list. | 213 | * @cmpl_list: complete list. |
240 | * | 214 | * |
241 | * returns 0, OK; otherwise, error. | 215 | * returns 0, OK; otherwise, error. |
242 | */ | 216 | */ |
243 | static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots, | 217 | static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb, |
244 | struct mei_cl_cb *cb_pos, | 218 | s32 *slots, struct mei_cl_cb *cmpl_list) |
245 | struct mei_cl *cl, | ||
246 | struct mei_cl_cb *cmpl_list) | ||
247 | { | 219 | { |
220 | struct mei_device *dev = cl->dev; | ||
221 | |||
248 | u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control)); | 222 | u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control)); |
249 | 223 | ||
250 | if (*slots < msg_slots) { | 224 | if (*slots < msg_slots) { |
251 | /* return the cancel routine */ | 225 | /* return the cancel routine */ |
252 | list_del(&cb_pos->list); | 226 | list_del(&cb->list); |
253 | return -EMSGSIZE; | 227 | return -EMSGSIZE; |
254 | } | 228 | } |
255 | 229 | ||
@@ -257,38 +231,38 @@ static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots, | |||
257 | 231 | ||
258 | if (mei_hbm_cl_flow_control_req(dev, cl)) { | 232 | if (mei_hbm_cl_flow_control_req(dev, cl)) { |
259 | cl->status = -ENODEV; | 233 | cl->status = -ENODEV; |
260 | cb_pos->buf_idx = 0; | 234 | cb->buf_idx = 0; |
261 | list_move_tail(&cb_pos->list, &cmpl_list->list); | 235 | list_move_tail(&cb->list, &cmpl_list->list); |
262 | return -ENODEV; | 236 | return -ENODEV; |
263 | } | 237 | } |
264 | list_move_tail(&cb_pos->list, &dev->read_list.list); | 238 | list_move_tail(&cb->list, &dev->read_list.list); |
265 | 239 | ||
266 | return 0; | 240 | return 0; |
267 | } | 241 | } |
268 | 242 | ||
269 | 243 | ||
270 | /** | 244 | /** |
271 | * _mei_irq_thread_ioctl - processes ioctl related operation. | 245 | * mei_cl_irq_ioctl - processes client ioctl related operation from the |
246 | * interrupt thread context - send connection request | ||
272 | * | 247 | * |
273 | * @dev: the device structure. | 248 | * @cl: client |
249 | * @cb: callback block. | ||
274 | * @slots: free slots. | 250 | * @slots: free slots. |
275 | * @cb_pos: callback block. | ||
276 | * @cl: private data of the file object. | ||
277 | * @cmpl_list: complete list. | 251 | * @cmpl_list: complete list. |
278 | * | 252 | * |
279 | * returns 0, OK; otherwise, error. | 253 | * returns 0, OK; otherwise, error. |
280 | */ | 254 | */ |
281 | static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots, | 255 | static int mei_cl_irq_ioctl(struct mei_cl *cl, struct mei_cl_cb *cb, |
282 | struct mei_cl_cb *cb_pos, | 256 | s32 *slots, struct mei_cl_cb *cmpl_list) |
283 | struct mei_cl *cl, | ||
284 | struct mei_cl_cb *cmpl_list) | ||
285 | { | 257 | { |
258 | struct mei_device *dev = cl->dev; | ||
259 | |||
286 | u32 msg_slots = | 260 | u32 msg_slots = |
287 | mei_data2slots(sizeof(struct hbm_client_connect_request)); | 261 | mei_data2slots(sizeof(struct hbm_client_connect_request)); |
288 | 262 | ||
289 | if (*slots < msg_slots) { | 263 | if (*slots < msg_slots) { |
290 | /* return the cancel routine */ | 264 | /* return the cancel routine */ |
291 | list_del(&cb_pos->list); | 265 | list_del(&cb->list); |
292 | return -EMSGSIZE; | 266 | return -EMSGSIZE; |
293 | } | 267 | } |
294 | 268 | ||
@@ -298,76 +272,17 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots, | |||
298 | 272 | ||
299 | if (mei_hbm_cl_connect_req(dev, cl)) { | 273 | if (mei_hbm_cl_connect_req(dev, cl)) { |
300 | cl->status = -ENODEV; | 274 | cl->status = -ENODEV; |
301 | cb_pos->buf_idx = 0; | 275 | cb->buf_idx = 0; |
302 | list_del(&cb_pos->list); | 276 | list_del(&cb->list); |
303 | return -ENODEV; | ||
304 | } else { | ||
305 | list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list); | ||
306 | cl->timer_count = MEI_CONNECT_TIMEOUT; | ||
307 | } | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * mei_irq_thread_write_complete - write messages to device. | ||
313 | * | ||
314 | * @dev: the device structure. | ||
315 | * @slots: free slots. | ||
316 | * @cb: callback block. | ||
317 | * @cmpl_list: complete list. | ||
318 | * | ||
319 | * returns 0, OK; otherwise, error. | ||
320 | */ | ||
321 | static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots, | ||
322 | struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list) | ||
323 | { | ||
324 | struct mei_msg_hdr mei_hdr; | ||
325 | struct mei_cl *cl = cb->cl; | ||
326 | size_t len = cb->request_buffer.size - cb->buf_idx; | ||
327 | u32 msg_slots = mei_data2slots(len); | ||
328 | |||
329 | mei_hdr.host_addr = cl->host_client_id; | ||
330 | mei_hdr.me_addr = cl->me_client_id; | ||
331 | mei_hdr.reserved = 0; | ||
332 | |||
333 | if (*slots >= msg_slots) { | ||
334 | mei_hdr.length = len; | ||
335 | mei_hdr.msg_complete = 1; | ||
336 | /* Split the message only if we can write the whole host buffer */ | ||
337 | } else if (*slots == dev->hbuf_depth) { | ||
338 | msg_slots = *slots; | ||
339 | len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); | ||
340 | mei_hdr.length = len; | ||
341 | mei_hdr.msg_complete = 0; | ||
342 | } else { | ||
343 | /* wait for next time the host buffer is empty */ | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n", | ||
348 | cb->request_buffer.size, cb->buf_idx); | ||
349 | dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr)); | ||
350 | |||
351 | *slots -= msg_slots; | ||
352 | if (mei_write_message(dev, &mei_hdr, | ||
353 | cb->request_buffer.data + cb->buf_idx)) { | ||
354 | cl->status = -ENODEV; | ||
355 | list_move_tail(&cb->list, &cmpl_list->list); | ||
356 | return -ENODEV; | 277 | return -ENODEV; |
357 | } | 278 | } |
358 | 279 | ||
359 | 280 | list_move_tail(&cb->list, &dev->ctrl_rd_list.list); | |
360 | cl->status = 0; | 281 | cl->timer_count = MEI_CONNECT_TIMEOUT; |
361 | cb->buf_idx += mei_hdr.length; | ||
362 | if (mei_hdr.msg_complete) { | ||
363 | if (mei_cl_flow_ctrl_reduce(cl)) | ||
364 | return -ENODEV; | ||
365 | list_move_tail(&cb->list, &dev->write_waiting_list.list); | ||
366 | } | ||
367 | |||
368 | return 0; | 282 | return 0; |
369 | } | 283 | } |
370 | 284 | ||
285 | |||
371 | /** | 286 | /** |
372 | * mei_irq_read_handler - bottom half read routine after ISR to | 287 | * mei_irq_read_handler - bottom half read routine after ISR to |
373 | * handle the read processing. | 288 | * handle the read processing. |
@@ -481,7 +396,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) | |||
481 | { | 396 | { |
482 | 397 | ||
483 | struct mei_cl *cl; | 398 | struct mei_cl *cl; |
484 | struct mei_cl_cb *pos = NULL, *next = NULL; | 399 | struct mei_cl_cb *cb, *next; |
485 | struct mei_cl_cb *list; | 400 | struct mei_cl_cb *list; |
486 | s32 slots; | 401 | s32 slots; |
487 | int ret; | 402 | int ret; |
@@ -498,19 +413,19 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) | |||
498 | dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n"); | 413 | dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n"); |
499 | 414 | ||
500 | list = &dev->write_waiting_list; | 415 | list = &dev->write_waiting_list; |
501 | list_for_each_entry_safe(pos, next, &list->list, list) { | 416 | list_for_each_entry_safe(cb, next, &list->list, list) { |
502 | cl = pos->cl; | 417 | cl = cb->cl; |
503 | if (cl == NULL) | 418 | if (cl == NULL) |
504 | continue; | 419 | continue; |
505 | 420 | ||
506 | cl->status = 0; | 421 | cl->status = 0; |
507 | list_del(&pos->list); | 422 | list_del(&cb->list); |
508 | if (MEI_WRITING == cl->writing_state && | 423 | if (MEI_WRITING == cl->writing_state && |
509 | pos->fop_type == MEI_FOP_WRITE && | 424 | cb->fop_type == MEI_FOP_WRITE && |
510 | cl != &dev->iamthif_cl) { | 425 | cl != &dev->iamthif_cl) { |
511 | dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n"); | 426 | dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n"); |
512 | cl->writing_state = MEI_WRITE_COMPLETE; | 427 | cl->writing_state = MEI_WRITE_COMPLETE; |
513 | list_add_tail(&pos->list, &cmpl_list->list); | 428 | list_add_tail(&cb->list, &cmpl_list->list); |
514 | } | 429 | } |
515 | if (cl == &dev->iamthif_cl) { | 430 | if (cl == &dev->iamthif_cl) { |
516 | dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n"); | 431 | 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) | |||
552 | 467 | ||
553 | /* complete control write list CB */ | 468 | /* complete control write list CB */ |
554 | dev_dbg(&dev->pdev->dev, "complete control write list cb.\n"); | 469 | dev_dbg(&dev->pdev->dev, "complete control write list cb.\n"); |
555 | list_for_each_entry_safe(pos, next, &dev->ctrl_wr_list.list, list) { | 470 | list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) { |
556 | cl = pos->cl; | 471 | cl = cb->cl; |
557 | if (!cl) { | 472 | if (!cl) { |
558 | list_del(&pos->list); | 473 | list_del(&cb->list); |
559 | return -ENODEV; | 474 | return -ENODEV; |
560 | } | 475 | } |
561 | switch (pos->fop_type) { | 476 | switch (cb->fop_type) { |
562 | case MEI_FOP_CLOSE: | 477 | case MEI_FOP_CLOSE: |
563 | /* send disconnect message */ | 478 | /* send disconnect message */ |
564 | ret = _mei_irq_thread_close(dev, &slots, pos, | 479 | ret = mei_cl_irq_close(cl, cb, &slots, cmpl_list); |
565 | cl, cmpl_list); | ||
566 | if (ret) | 480 | if (ret) |
567 | return ret; | 481 | return ret; |
568 | 482 | ||
569 | break; | 483 | break; |
570 | case MEI_FOP_READ: | 484 | case MEI_FOP_READ: |
571 | /* send flow control message */ | 485 | /* send flow control message */ |
572 | ret = _mei_irq_thread_read(dev, &slots, pos, | 486 | ret = mei_cl_irq_read(cl, cb, &slots, cmpl_list); |
573 | cl, cmpl_list); | ||
574 | if (ret) | 487 | if (ret) |
575 | return ret; | 488 | return ret; |
576 | 489 | ||
@@ -579,8 +492,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) | |||
579 | /* connect message */ | 492 | /* connect message */ |
580 | if (mei_cl_is_other_connecting(cl)) | 493 | if (mei_cl_is_other_connecting(cl)) |
581 | continue; | 494 | continue; |
582 | ret = _mei_irq_thread_ioctl(dev, &slots, pos, | 495 | ret = mei_cl_irq_ioctl(cl, cb, &slots, cmpl_list); |
583 | cl, cmpl_list); | ||
584 | if (ret) | 496 | if (ret) |
585 | return ret; | 497 | return ret; |
586 | 498 | ||
@@ -593,8 +505,8 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) | |||
593 | } | 505 | } |
594 | /* complete write list CB */ | 506 | /* complete write list CB */ |
595 | dev_dbg(&dev->pdev->dev, "complete write list cb.\n"); | 507 | dev_dbg(&dev->pdev->dev, "complete write list cb.\n"); |
596 | list_for_each_entry_safe(pos, next, &dev->write_list.list, list) { | 508 | list_for_each_entry_safe(cb, next, &dev->write_list.list, list) { |
597 | cl = pos->cl; | 509 | cl = cb->cl; |
598 | if (cl == NULL) | 510 | if (cl == NULL) |
599 | continue; | 511 | continue; |
600 | if (mei_cl_flow_ctrl_creds(cl) <= 0) { | 512 | 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) | |||
605 | } | 517 | } |
606 | 518 | ||
607 | if (cl == &dev->iamthif_cl) | 519 | if (cl == &dev->iamthif_cl) |
608 | ret = mei_amthif_irq_write_complete(dev, &slots, | 520 | ret = mei_amthif_irq_write_complete(cl, cb, |
609 | pos, cmpl_list); | 521 | &slots, cmpl_list); |
610 | else | 522 | else |
611 | ret = mei_irq_thread_write_complete(dev, &slots, pos, | 523 | ret = mei_cl_irq_write_complete(cl, cb, |
612 | cmpl_list); | 524 | &slots, cmpl_list); |
613 | if (ret) | 525 | if (ret) |
614 | return ret; | 526 | return ret; |
615 | |||
616 | } | 527 | } |
617 | return 0; | 528 | return 0; |
618 | } | 529 | } |
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 053139f61086..5e11b5b9b65d 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c | |||
@@ -194,7 +194,6 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, | |||
194 | struct mei_cl_cb *cb_pos = NULL; | 194 | struct mei_cl_cb *cb_pos = NULL; |
195 | struct mei_cl_cb *cb = NULL; | 195 | struct mei_cl_cb *cb = NULL; |
196 | struct mei_device *dev; | 196 | struct mei_device *dev; |
197 | int i; | ||
198 | int rets; | 197 | int rets; |
199 | int err; | 198 | int err; |
200 | 199 | ||
@@ -210,38 +209,26 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, | |||
210 | goto out; | 209 | goto out; |
211 | } | 210 | } |
212 | 211 | ||
213 | if ((cl->sm_state & MEI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) { | ||
214 | /* Do not allow to read watchdog client */ | ||
215 | i = mei_me_cl_by_uuid(dev, &mei_wd_guid); | ||
216 | if (i >= 0) { | ||
217 | struct mei_me_client *me_client = &dev->me_clients[i]; | ||
218 | if (cl->me_client_id == me_client->client_id) { | ||
219 | rets = -EBADF; | ||
220 | goto out; | ||
221 | } | ||
222 | } | ||
223 | } else { | ||
224 | cl->sm_state &= ~MEI_WD_STATE_INDEPENDENCE_MSG_SENT; | ||
225 | } | ||
226 | |||
227 | if (cl == &dev->iamthif_cl) { | 212 | if (cl == &dev->iamthif_cl) { |
228 | rets = mei_amthif_read(dev, file, ubuf, length, offset); | 213 | rets = mei_amthif_read(dev, file, ubuf, length, offset); |
229 | goto out; | 214 | goto out; |
230 | } | 215 | } |
231 | 216 | ||
232 | if (cl->read_cb && cl->read_cb->buf_idx > *offset) { | 217 | if (cl->read_cb) { |
233 | cb = cl->read_cb; | ||
234 | goto copy_buffer; | ||
235 | } else if (cl->read_cb && cl->read_cb->buf_idx > 0 && | ||
236 | cl->read_cb->buf_idx <= *offset) { | ||
237 | cb = cl->read_cb; | 218 | cb = cl->read_cb; |
238 | rets = 0; | 219 | /* read what left */ |
239 | goto free; | 220 | if (cb->buf_idx > *offset) |
240 | } else if ((!cl->read_cb || !cl->read_cb->buf_idx) && *offset > 0) { | 221 | goto copy_buffer; |
241 | /*Offset needs to be cleaned for contiguous reads*/ | 222 | /* offset is beyond buf_idx we have no more data return 0 */ |
223 | if (cb->buf_idx > 0 && cb->buf_idx <= *offset) { | ||
224 | rets = 0; | ||
225 | goto free; | ||
226 | } | ||
227 | /* Offset needs to be cleaned for contiguous reads*/ | ||
228 | if (cb->buf_idx == 0 && *offset > 0) | ||
229 | *offset = 0; | ||
230 | } else if (*offset > 0) { | ||
242 | *offset = 0; | 231 | *offset = 0; |
243 | rets = 0; | ||
244 | goto out; | ||
245 | } | 232 | } |
246 | 233 | ||
247 | err = mei_cl_read_start(cl, length); | 234 | err = mei_cl_read_start(cl, length); |
@@ -420,16 +407,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, | |||
420 | if (rets) | 407 | if (rets) |
421 | goto out; | 408 | goto out; |
422 | 409 | ||
423 | cl->sm_state = 0; | ||
424 | if (length == 4 && | ||
425 | ((memcmp(mei_wd_state_independence_msg[0], | ||
426 | write_cb->request_buffer.data, 4) == 0) || | ||
427 | (memcmp(mei_wd_state_independence_msg[1], | ||
428 | write_cb->request_buffer.data, 4) == 0) || | ||
429 | (memcmp(mei_wd_state_independence_msg[2], | ||
430 | write_cb->request_buffer.data, 4) == 0))) | ||
431 | cl->sm_state |= MEI_WD_STATE_INDEPENDENCE_MSG_SENT; | ||
432 | |||
433 | if (cl == &dev->iamthif_cl) { | 410 | if (cl == &dev->iamthif_cl) { |
434 | rets = mei_amthif_write(dev, write_cb); | 411 | rets = mei_amthif_write(dev, write_cb); |
435 | 412 | ||
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 4de5140e7379..7b918b2fb894 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h | |||
@@ -56,11 +56,6 @@ extern const uuid_le mei_amthif_guid; | |||
56 | extern const uuid_le mei_wd_guid; | 56 | extern const uuid_le mei_wd_guid; |
57 | 57 | ||
58 | /* | 58 | /* |
59 | * Watchdog independence state message | ||
60 | */ | ||
61 | extern const u8 mei_wd_state_independence_msg[3][4]; | ||
62 | |||
63 | /* | ||
64 | * Number of Maximum MEI Clients | 59 | * Number of Maximum MEI Clients |
65 | */ | 60 | */ |
66 | #define MEI_CLIENTS_MAX 256 | 61 | #define MEI_CLIENTS_MAX 256 |
@@ -201,7 +196,6 @@ struct mei_cl { | |||
201 | u8 timer_count; | 196 | u8 timer_count; |
202 | enum mei_file_transaction_states reading_state; | 197 | enum mei_file_transaction_states reading_state; |
203 | enum mei_file_transaction_states writing_state; | 198 | enum mei_file_transaction_states writing_state; |
204 | int sm_state; | ||
205 | struct mei_cl_cb *read_cb; | 199 | struct mei_cl_cb *read_cb; |
206 | 200 | ||
207 | /* MEI CL bus data */ | 201 | /* MEI CL bus data */ |
@@ -239,7 +233,7 @@ struct mei_hw_ops { | |||
239 | bool (*host_is_ready) (struct mei_device *dev); | 233 | bool (*host_is_ready) (struct mei_device *dev); |
240 | 234 | ||
241 | bool (*hw_is_ready) (struct mei_device *dev); | 235 | bool (*hw_is_ready) (struct mei_device *dev); |
242 | void (*hw_reset) (struct mei_device *dev, bool enable); | 236 | int (*hw_reset) (struct mei_device *dev, bool enable); |
243 | int (*hw_start) (struct mei_device *dev); | 237 | int (*hw_start) (struct mei_device *dev); |
244 | void (*hw_config) (struct mei_device *dev); | 238 | void (*hw_config) (struct mei_device *dev); |
245 | 239 | ||
@@ -502,8 +496,8 @@ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, | |||
502 | 496 | ||
503 | void mei_amthif_run_next_cmd(struct mei_device *dev); | 497 | void mei_amthif_run_next_cmd(struct mei_device *dev); |
504 | 498 | ||
505 | int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots, | 499 | int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb, |
506 | struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list); | 500 | s32 *slots, struct mei_cl_cb *cmpl_list); |
507 | 501 | ||
508 | void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb); | 502 | void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb); |
509 | int mei_amthif_irq_read_msg(struct mei_device *dev, | 503 | int mei_amthif_irq_read_msg(struct mei_device *dev, |
@@ -522,15 +516,6 @@ void mei_nfc_host_exit(void); | |||
522 | */ | 516 | */ |
523 | extern const uuid_le mei_nfc_guid; | 517 | extern const uuid_le mei_nfc_guid; |
524 | 518 | ||
525 | int mei_amthif_irq_write_complete(struct mei_device *dev, s32 *slots, | ||
526 | struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list); | ||
527 | |||
528 | void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb); | ||
529 | int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list, | ||
530 | struct mei_device *dev, struct mei_msg_hdr *mei_hdr); | ||
531 | int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); | ||
532 | |||
533 | |||
534 | int mei_wd_send(struct mei_device *dev); | 519 | int mei_wd_send(struct mei_device *dev); |
535 | int mei_wd_stop(struct mei_device *dev); | 520 | int mei_wd_stop(struct mei_device *dev); |
536 | int mei_wd_host_init(struct mei_device *dev); | 521 | int mei_wd_host_init(struct mei_device *dev); |
@@ -554,14 +539,14 @@ static inline void mei_hw_config(struct mei_device *dev) | |||
554 | { | 539 | { |
555 | dev->ops->hw_config(dev); | 540 | dev->ops->hw_config(dev); |
556 | } | 541 | } |
557 | static inline void mei_hw_reset(struct mei_device *dev, bool enable) | 542 | static inline int mei_hw_reset(struct mei_device *dev, bool enable) |
558 | { | 543 | { |
559 | dev->ops->hw_reset(dev, enable); | 544 | return dev->ops->hw_reset(dev, enable); |
560 | } | 545 | } |
561 | 546 | ||
562 | static inline void mei_hw_start(struct mei_device *dev) | 547 | static inline int mei_hw_start(struct mei_device *dev) |
563 | { | 548 | { |
564 | dev->ops->hw_start(dev); | 549 | return dev->ops->hw_start(dev); |
565 | } | 550 | } |
566 | 551 | ||
567 | static inline void mei_clear_interrupts(struct mei_device *dev) | 552 | static inline void mei_clear_interrupts(struct mei_device *dev) |
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 0f268329bd3a..1b3844e82379 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c | |||
@@ -43,9 +43,6 @@ | |||
43 | #include "hw-me.h" | 43 | #include "hw-me.h" |
44 | #include "client.h" | 44 | #include "client.h" |
45 | 45 | ||
46 | /* AMT device is a singleton on the platform */ | ||
47 | static struct pci_dev *mei_pdev; | ||
48 | |||
49 | /* mei_pci_tbl - PCI Device ID Table */ | 46 | /* mei_pci_tbl - PCI Device ID Table */ |
50 | static DEFINE_PCI_DEVICE_TABLE(mei_me_pci_tbl) = { | 47 | static DEFINE_PCI_DEVICE_TABLE(mei_me_pci_tbl) = { |
51 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82946GZ)}, | 48 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82946GZ)}, |
@@ -88,8 +85,6 @@ static DEFINE_PCI_DEVICE_TABLE(mei_me_pci_tbl) = { | |||
88 | 85 | ||
89 | MODULE_DEVICE_TABLE(pci, mei_me_pci_tbl); | 86 | MODULE_DEVICE_TABLE(pci, mei_me_pci_tbl); |
90 | 87 | ||
91 | static DEFINE_MUTEX(mei_mutex); | ||
92 | |||
93 | /** | 88 | /** |
94 | * mei_quirk_probe - probe for devices that doesn't valid ME interface | 89 | * mei_quirk_probe - probe for devices that doesn't valid ME interface |
95 | * | 90 | * |
@@ -126,17 +121,12 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
126 | struct mei_me_hw *hw; | 121 | struct mei_me_hw *hw; |
127 | int err; | 122 | int err; |
128 | 123 | ||
129 | mutex_lock(&mei_mutex); | ||
130 | 124 | ||
131 | if (!mei_me_quirk_probe(pdev, ent)) { | 125 | if (!mei_me_quirk_probe(pdev, ent)) { |
132 | err = -ENODEV; | 126 | err = -ENODEV; |
133 | goto end; | 127 | goto end; |
134 | } | 128 | } |
135 | 129 | ||
136 | if (mei_pdev) { | ||
137 | err = -EEXIST; | ||
138 | goto end; | ||
139 | } | ||
140 | /* enable pci dev */ | 130 | /* enable pci dev */ |
141 | err = pci_enable_device(pdev); | 131 | err = pci_enable_device(pdev); |
142 | if (err) { | 132 | if (err) { |
@@ -195,13 +185,10 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
195 | if (err) | 185 | if (err) |
196 | goto release_irq; | 186 | goto release_irq; |
197 | 187 | ||
198 | mei_pdev = pdev; | ||
199 | pci_set_drvdata(pdev, dev); | 188 | pci_set_drvdata(pdev, dev); |
200 | 189 | ||
201 | schedule_delayed_work(&dev->timer_work, HZ); | 190 | schedule_delayed_work(&dev->timer_work, HZ); |
202 | 191 | ||
203 | mutex_unlock(&mei_mutex); | ||
204 | |||
205 | pr_debug("initialization successful.\n"); | 192 | pr_debug("initialization successful.\n"); |
206 | 193 | ||
207 | return 0; | 194 | return 0; |
@@ -220,7 +207,6 @@ release_regions: | |||
220 | disable_device: | 207 | disable_device: |
221 | pci_disable_device(pdev); | 208 | pci_disable_device(pdev); |
222 | end: | 209 | end: |
223 | mutex_unlock(&mei_mutex); | ||
224 | dev_err(&pdev->dev, "initialization failed.\n"); | 210 | dev_err(&pdev->dev, "initialization failed.\n"); |
225 | return err; | 211 | return err; |
226 | } | 212 | } |
@@ -238,9 +224,6 @@ static void mei_me_remove(struct pci_dev *pdev) | |||
238 | struct mei_device *dev; | 224 | struct mei_device *dev; |
239 | struct mei_me_hw *hw; | 225 | struct mei_me_hw *hw; |
240 | 226 | ||
241 | if (mei_pdev != pdev) | ||
242 | return; | ||
243 | |||
244 | dev = pci_get_drvdata(pdev); | 227 | dev = pci_get_drvdata(pdev); |
245 | if (!dev) | 228 | if (!dev) |
246 | return; | 229 | return; |
@@ -251,8 +234,6 @@ static void mei_me_remove(struct pci_dev *pdev) | |||
251 | dev_err(&pdev->dev, "stop\n"); | 234 | dev_err(&pdev->dev, "stop\n"); |
252 | mei_stop(dev); | 235 | mei_stop(dev); |
253 | 236 | ||
254 | mei_pdev = NULL; | ||
255 | |||
256 | /* disable interrupts */ | 237 | /* disable interrupts */ |
257 | mei_disable_interrupts(dev); | 238 | mei_disable_interrupts(dev); |
258 | 239 | ||
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index 6251a4ee7067..b8921432e89d 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c | |||
@@ -31,12 +31,6 @@ | |||
31 | static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; | 31 | static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; |
32 | static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; | 32 | static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; |
33 | 33 | ||
34 | const u8 mei_wd_state_independence_msg[3][4] = { | ||
35 | {0x05, 0x02, 0x51, 0x10}, | ||
36 | {0x05, 0x02, 0x52, 0x10}, | ||
37 | {0x07, 0x02, 0x01, 0x10} | ||
38 | }; | ||
39 | |||
40 | /* | 34 | /* |
41 | * AMT Watchdog Device | 35 | * AMT Watchdog Device |
42 | */ | 36 | */ |
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index 931e635aa491..a5925f7f17f6 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c | |||
@@ -633,17 +633,13 @@ static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr, | |||
633 | static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr, | 633 | static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr, |
634 | const char *buf, size_t count) | 634 | const char *buf, size_t count) |
635 | { | 635 | { |
636 | u8 mac[6]; | 636 | u8 mac[ETH_ALEN]; |
637 | ssize_t rom_size; | 637 | ssize_t rom_size; |
638 | struct pch_phub_reg *chip = dev_get_drvdata(dev); | 638 | struct pch_phub_reg *chip = dev_get_drvdata(dev); |
639 | 639 | ||
640 | if (count != 18) | 640 | if (!mac_pton(buf, mac)) |
641 | return -EINVAL; | 641 | return -EINVAL; |
642 | 642 | ||
643 | sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", | ||
644 | (u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3], | ||
645 | (u32 *)&mac[4], (u32 *)&mac[5]); | ||
646 | |||
647 | chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); | 643 | chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); |
648 | if (!chip->pch_phub_extrom_base_address) | 644 | if (!chip->pch_phub_extrom_base_address) |
649 | return -ENOMEM; | 645 | return -ENOMEM; |
@@ -669,8 +665,6 @@ static struct bin_attribute pch_bin_attr = { | |||
669 | static int pch_phub_probe(struct pci_dev *pdev, | 665 | static int pch_phub_probe(struct pci_dev *pdev, |
670 | const struct pci_device_id *id) | 666 | const struct pci_device_id *id) |
671 | { | 667 | { |
672 | int retval; | ||
673 | |||
674 | int ret; | 668 | int ret; |
675 | struct pch_phub_reg *chip; | 669 | struct pch_phub_reg *chip; |
676 | 670 | ||
@@ -713,13 +707,13 @@ static int pch_phub_probe(struct pci_dev *pdev, | |||
713 | if (id->driver_data == 1) { /* EG20T PCH */ | 707 | if (id->driver_data == 1) { /* EG20T PCH */ |
714 | const char *board_name; | 708 | const char *board_name; |
715 | 709 | ||
716 | retval = sysfs_create_file(&pdev->dev.kobj, | 710 | ret = sysfs_create_file(&pdev->dev.kobj, |
717 | &dev_attr_pch_mac.attr); | 711 | &dev_attr_pch_mac.attr); |
718 | if (retval) | 712 | if (ret) |
719 | goto err_sysfs_create; | 713 | goto err_sysfs_create; |
720 | 714 | ||
721 | retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); | 715 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); |
722 | if (retval) | 716 | if (ret) |
723 | goto exit_bin_attr; | 717 | goto exit_bin_attr; |
724 | 718 | ||
725 | pch_phub_read_modify_write_reg(chip, | 719 | pch_phub_read_modify_write_reg(chip, |
@@ -743,8 +737,8 @@ static int pch_phub_probe(struct pci_dev *pdev, | |||
743 | chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T; | 737 | chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T; |
744 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T; | 738 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T; |
745 | } else if (id->driver_data == 2) { /* ML7213 IOH */ | 739 | } else if (id->driver_data == 2) { /* ML7213 IOH */ |
746 | retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); | 740 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); |
747 | if (retval) | 741 | if (ret) |
748 | goto err_sysfs_create; | 742 | goto err_sysfs_create; |
749 | /* set the prefech value | 743 | /* set the prefech value |
750 | * Device2(USB OHCI #1/ USB EHCI #1/ USB Device):a | 744 | * Device2(USB OHCI #1/ USB EHCI #1/ USB Device):a |
@@ -766,12 +760,12 @@ static int pch_phub_probe(struct pci_dev *pdev, | |||
766 | PCH_PHUB_ROM_START_ADDR_ML7223; | 760 | PCH_PHUB_ROM_START_ADDR_ML7223; |
767 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; | 761 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; |
768 | } else if (id->driver_data == 4) { /* ML7223 IOH Bus-n*/ | 762 | } else if (id->driver_data == 4) { /* ML7223 IOH Bus-n*/ |
769 | retval = sysfs_create_file(&pdev->dev.kobj, | 763 | ret = sysfs_create_file(&pdev->dev.kobj, |
770 | &dev_attr_pch_mac.attr); | 764 | &dev_attr_pch_mac.attr); |
771 | if (retval) | 765 | if (ret) |
772 | goto err_sysfs_create; | 766 | goto err_sysfs_create; |
773 | retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); | 767 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); |
774 | if (retval) | 768 | if (ret) |
775 | goto exit_bin_attr; | 769 | goto exit_bin_attr; |
776 | /* set the prefech value | 770 | /* set the prefech value |
777 | * Device2(USB OHCI #0,1,2,3/ USB EHCI #0):a | 771 | * Device2(USB OHCI #0,1,2,3/ USB EHCI #0):a |
@@ -783,13 +777,13 @@ static int pch_phub_probe(struct pci_dev *pdev, | |||
783 | PCH_PHUB_ROM_START_ADDR_ML7223; | 777 | PCH_PHUB_ROM_START_ADDR_ML7223; |
784 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; | 778 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; |
785 | } else if (id->driver_data == 5) { /* ML7831 */ | 779 | } else if (id->driver_data == 5) { /* ML7831 */ |
786 | retval = sysfs_create_file(&pdev->dev.kobj, | 780 | ret = sysfs_create_file(&pdev->dev.kobj, |
787 | &dev_attr_pch_mac.attr); | 781 | &dev_attr_pch_mac.attr); |
788 | if (retval) | 782 | if (ret) |
789 | goto err_sysfs_create; | 783 | goto err_sysfs_create; |
790 | 784 | ||
791 | retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); | 785 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); |
792 | if (retval) | 786 | if (ret) |
793 | goto exit_bin_attr; | 787 | goto exit_bin_attr; |
794 | 788 | ||
795 | /* set the prefech value */ | 789 | /* set the prefech value */ |
diff --git a/drivers/misc/sgi-gru/gruprocfs.c b/drivers/misc/sgi-gru/gruprocfs.c index 797d7962cc88..4f7635922394 100644 --- a/drivers/misc/sgi-gru/gruprocfs.c +++ b/drivers/misc/sgi-gru/gruprocfs.c | |||
@@ -160,15 +160,11 @@ static int options_show(struct seq_file *s, void *p) | |||
160 | static ssize_t options_write(struct file *file, const char __user *userbuf, | 160 | static ssize_t options_write(struct file *file, const char __user *userbuf, |
161 | size_t count, loff_t *data) | 161 | size_t count, loff_t *data) |
162 | { | 162 | { |
163 | char buf[20]; | 163 | int ret; |
164 | 164 | ||
165 | if (count >= sizeof(buf)) | 165 | ret = kstrtoul_from_user(userbuf, count, 0, &gru_options); |
166 | return -EINVAL; | 166 | if (ret) |
167 | if (copy_from_user(buf, userbuf, count)) | 167 | return ret; |
168 | return -EFAULT; | ||
169 | buf[count] = '\0'; | ||
170 | if (strict_strtoul(buf, 0, &gru_options)) | ||
171 | return -EINVAL; | ||
172 | 168 | ||
173 | return count; | 169 | return count; |
174 | } | 170 | } |
diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c index 7deb25dc86a7..2e13614d41e8 100644 --- a/drivers/misc/spear13xx_pcie_gadget.c +++ b/drivers/misc/spear13xx_pcie_gadget.c | |||
@@ -316,8 +316,12 @@ static ssize_t pcie_gadget_store_no_of_msi( | |||
316 | struct spear_pcie_gadget_config *config, | 316 | struct spear_pcie_gadget_config *config, |
317 | const char *buf, size_t count) | 317 | const char *buf, size_t count) |
318 | { | 318 | { |
319 | if (strict_strtoul(buf, 0, &config->requested_msi)) | 319 | int ret; |
320 | return -EINVAL; | 320 | |
321 | ret = kstrtoul(buf, 0, &config->requested_msi); | ||
322 | if (ret) | ||
323 | return ret; | ||
324 | |||
321 | if (config->requested_msi > 32) | 325 | if (config->requested_msi > 32) |
322 | config->requested_msi = 32; | 326 | config->requested_msi = 32; |
323 | 327 | ||
@@ -330,9 +334,11 @@ static ssize_t pcie_gadget_store_inta( | |||
330 | { | 334 | { |
331 | struct pcie_app_reg __iomem *app_reg = config->va_app_base; | 335 | struct pcie_app_reg __iomem *app_reg = config->va_app_base; |
332 | ulong en; | 336 | ulong en; |
337 | int ret; | ||
333 | 338 | ||
334 | if (strict_strtoul(buf, 0, &en)) | 339 | ret = kstrtoul(buf, 0, &en); |
335 | return -EINVAL; | 340 | if (ret) |
341 | return ret; | ||
336 | 342 | ||
337 | if (en) | 343 | if (en) |
338 | writel(readl(&app_reg->app_ctrl_0) | (1 << SYS_INT_ID), | 344 | writel(readl(&app_reg->app_ctrl_0) | (1 << SYS_INT_ID), |
@@ -351,9 +357,11 @@ static ssize_t pcie_gadget_store_send_msi( | |||
351 | struct pcie_app_reg __iomem *app_reg = config->va_app_base; | 357 | struct pcie_app_reg __iomem *app_reg = config->va_app_base; |
352 | ulong vector; | 358 | ulong vector; |
353 | u32 ven_msi; | 359 | u32 ven_msi; |
360 | int ret; | ||
354 | 361 | ||
355 | if (strict_strtoul(buf, 0, &vector)) | 362 | ret = kstrtoul(buf, 0, &vector); |
356 | return -EINVAL; | 363 | if (ret) |
364 | return ret; | ||
357 | 365 | ||
358 | if (!config->configured_msi) | 366 | if (!config->configured_msi) |
359 | return -EINVAL; | 367 | return -EINVAL; |
@@ -395,9 +403,11 @@ static ssize_t pcie_gadget_store_vendor_id( | |||
395 | const char *buf, size_t count) | 403 | const char *buf, size_t count) |
396 | { | 404 | { |
397 | ulong id; | 405 | ulong id; |
406 | int ret; | ||
398 | 407 | ||
399 | if (strict_strtoul(buf, 0, &id)) | 408 | ret = kstrtoul(buf, 0, &id); |
400 | return -EINVAL; | 409 | if (ret) |
410 | return ret; | ||
401 | 411 | ||
402 | spear_dbi_write_reg(config, PCI_VENDOR_ID, 2, id); | 412 | spear_dbi_write_reg(config, PCI_VENDOR_ID, 2, id); |
403 | 413 | ||
@@ -420,9 +430,11 @@ static ssize_t pcie_gadget_store_device_id( | |||
420 | const char *buf, size_t count) | 430 | const char *buf, size_t count) |
421 | { | 431 | { |
422 | ulong id; | 432 | ulong id; |
433 | int ret; | ||
423 | 434 | ||
424 | if (strict_strtoul(buf, 0, &id)) | 435 | ret = kstrtoul(buf, 0, &id); |
425 | return -EINVAL; | 436 | if (ret) |
437 | return ret; | ||
426 | 438 | ||
427 | spear_dbi_write_reg(config, PCI_DEVICE_ID, 2, id); | 439 | spear_dbi_write_reg(config, PCI_DEVICE_ID, 2, id); |
428 | 440 | ||
@@ -443,9 +455,12 @@ static ssize_t pcie_gadget_store_bar0_size( | |||
443 | ulong size; | 455 | ulong size; |
444 | u32 pos, pos1; | 456 | u32 pos, pos1; |
445 | u32 no_of_bit = 0; | 457 | u32 no_of_bit = 0; |
458 | int ret; | ||
459 | |||
460 | ret = kstrtoul(buf, 0, &size); | ||
461 | if (ret) | ||
462 | return ret; | ||
446 | 463 | ||
447 | if (strict_strtoul(buf, 0, &size)) | ||
448 | return -EINVAL; | ||
449 | /* min bar size is 256 */ | 464 | /* min bar size is 256 */ |
450 | if (size <= 0x100) | 465 | if (size <= 0x100) |
451 | size = 0x100; | 466 | size = 0x100; |
@@ -490,9 +505,11 @@ static ssize_t pcie_gadget_store_bar0_address( | |||
490 | { | 505 | { |
491 | struct pcie_app_reg __iomem *app_reg = config->va_app_base; | 506 | struct pcie_app_reg __iomem *app_reg = config->va_app_base; |
492 | ulong address; | 507 | ulong address; |
508 | int ret; | ||
493 | 509 | ||
494 | if (strict_strtoul(buf, 0, &address)) | 510 | ret = kstrtoul(buf, 0, &address); |
495 | return -EINVAL; | 511 | if (ret) |
512 | return ret; | ||
496 | 513 | ||
497 | address &= ~(config->bar0_size - 1); | 514 | address &= ~(config->bar0_size - 1); |
498 | if (config->va_bar0_address) | 515 | if (config->va_bar0_address) |
@@ -518,9 +535,11 @@ static ssize_t pcie_gadget_store_bar0_rw_offset( | |||
518 | const char *buf, size_t count) | 535 | const char *buf, size_t count) |
519 | { | 536 | { |
520 | ulong offset; | 537 | ulong offset; |
538 | int ret; | ||
521 | 539 | ||
522 | if (strict_strtoul(buf, 0, &offset)) | 540 | ret = kstrtoul(buf, 0, &offset); |
523 | return -EINVAL; | 541 | if (ret) |
542 | return ret; | ||
524 | 543 | ||
525 | if (offset % 4) | 544 | if (offset % 4) |
526 | return -EINVAL; | 545 | return -EINVAL; |
@@ -549,9 +568,11 @@ static ssize_t pcie_gadget_store_bar0_data( | |||
549 | const char *buf, size_t count) | 568 | const char *buf, size_t count) |
550 | { | 569 | { |
551 | ulong data; | 570 | ulong data; |
571 | int ret; | ||
552 | 572 | ||
553 | if (strict_strtoul(buf, 0, &data)) | 573 | ret = kstrtoul(buf, 0, &data); |
554 | return -EINVAL; | 574 | if (ret) |
575 | return ret; | ||
555 | 576 | ||
556 | if (!config->va_bar0_address) | 577 | if (!config->va_bar0_address) |
557 | return -ENOMEM; | 578 | return -ENOMEM; |
@@ -776,7 +797,7 @@ static int spear_pcie_gadget_probe(struct platform_device *pdev) | |||
776 | goto err_iounmap_app; | 797 | goto err_iounmap_app; |
777 | } | 798 | } |
778 | 799 | ||
779 | dev_set_drvdata(&pdev->dev, target); | 800 | platform_set_drvdata(pdev, target); |
780 | 801 | ||
781 | irq = platform_get_irq(pdev, 0); | 802 | irq = platform_get_irq(pdev, 0); |
782 | if (irq < 0) { | 803 | if (irq < 0) { |
@@ -814,9 +835,11 @@ static int spear_pcie_gadget_probe(struct platform_device *pdev) | |||
814 | clk = clk_get_sys("pcie1", NULL); | 835 | clk = clk_get_sys("pcie1", NULL); |
815 | if (IS_ERR(clk)) { | 836 | if (IS_ERR(clk)) { |
816 | pr_err("%s:couldn't get clk for pcie1\n", __func__); | 837 | pr_err("%s:couldn't get clk for pcie1\n", __func__); |
838 | status = PTR_ERR(clk); | ||
817 | goto err_irq; | 839 | goto err_irq; |
818 | } | 840 | } |
819 | if (clk_enable(clk)) { | 841 | status = clk_enable(clk); |
842 | if (status) { | ||
820 | pr_err("%s:couldn't enable clk for pcie1\n", __func__); | 843 | pr_err("%s:couldn't enable clk for pcie1\n", __func__); |
821 | goto err_irq; | 844 | goto err_irq; |
822 | } | 845 | } |
@@ -828,9 +851,11 @@ static int spear_pcie_gadget_probe(struct platform_device *pdev) | |||
828 | clk = clk_get_sys("pcie2", NULL); | 851 | clk = clk_get_sys("pcie2", NULL); |
829 | if (IS_ERR(clk)) { | 852 | if (IS_ERR(clk)) { |
830 | pr_err("%s:couldn't get clk for pcie2\n", __func__); | 853 | pr_err("%s:couldn't get clk for pcie2\n", __func__); |
854 | status = PTR_ERR(clk); | ||
831 | goto err_irq; | 855 | goto err_irq; |
832 | } | 856 | } |
833 | if (clk_enable(clk)) { | 857 | status = clk_enable(clk); |
858 | if (status) { | ||
834 | pr_err("%s:couldn't enable clk for pcie2\n", __func__); | 859 | pr_err("%s:couldn't enable clk for pcie2\n", __func__); |
835 | goto err_irq; | 860 | goto err_irq; |
836 | } | 861 | } |
@@ -863,7 +888,7 @@ static int spear_pcie_gadget_remove(struct platform_device *pdev) | |||
863 | res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 888 | res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
864 | res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 889 | res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
865 | irq = platform_get_irq(pdev, 0); | 890 | irq = platform_get_irq(pdev, 0); |
866 | target = dev_get_drvdata(&pdev->dev); | 891 | target = platform_get_drvdata(pdev); |
867 | config = &target->config; | 892 | config = &target->config; |
868 | 893 | ||
869 | free_irq(irq, NULL); | 894 | free_irq(irq, NULL); |
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c index 437192e43006..d87cc91bc016 100644 --- a/drivers/misc/sram.c +++ b/drivers/misc/sram.c | |||
@@ -45,15 +45,12 @@ static int sram_probe(struct platform_device *pdev) | |||
45 | int ret; | 45 | int ret; |
46 | 46 | ||
47 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 47 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
48 | if (!res) | 48 | virt_base = devm_ioremap_resource(&pdev->dev, res); |
49 | return -EINVAL; | 49 | if (IS_ERR(virt_base)) |
50 | return PTR_ERR(virt_base); | ||
50 | 51 | ||
51 | size = resource_size(res); | 52 | size = resource_size(res); |
52 | 53 | ||
53 | virt_base = devm_request_and_ioremap(&pdev->dev, res); | ||
54 | if (!virt_base) | ||
55 | return -EADDRNOTAVAIL; | ||
56 | |||
57 | sram = devm_kzalloc(&pdev->dev, sizeof(*sram), GFP_KERNEL); | 54 | sram = devm_kzalloc(&pdev->dev, sizeof(*sram), GFP_KERNEL); |
58 | if (!sram) | 55 | if (!sram) |
59 | return -ENOMEM; | 56 | return -ENOMEM; |
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 83269f1d16e3..83907c720594 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c | |||
@@ -680,7 +680,7 @@ void st_kim_ref(struct st_data_s **core_data, int id) | |||
680 | *core_data = NULL; | 680 | *core_data = NULL; |
681 | return; | 681 | return; |
682 | } | 682 | } |
683 | kim_gdata = dev_get_drvdata(&pdev->dev); | 683 | kim_gdata = platform_get_drvdata(pdev); |
684 | *core_data = kim_gdata->core_data; | 684 | *core_data = kim_gdata->core_data; |
685 | } | 685 | } |
686 | 686 | ||
@@ -735,7 +735,7 @@ static int kim_probe(struct platform_device *pdev) | |||
735 | pr_err("no mem to allocate"); | 735 | pr_err("no mem to allocate"); |
736 | return -ENOMEM; | 736 | return -ENOMEM; |
737 | } | 737 | } |
738 | dev_set_drvdata(&pdev->dev, kim_gdata); | 738 | platform_set_drvdata(pdev, kim_gdata); |
739 | 739 | ||
740 | err = st_core_init(&kim_gdata->core_data); | 740 | err = st_core_init(&kim_gdata->core_data); |
741 | if (err != 0) { | 741 | if (err != 0) { |
@@ -810,7 +810,7 @@ static int kim_remove(struct platform_device *pdev) | |||
810 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | 810 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; |
811 | struct kim_data_s *kim_gdata; | 811 | struct kim_data_s *kim_gdata; |
812 | 812 | ||
813 | kim_gdata = dev_get_drvdata(&pdev->dev); | 813 | kim_gdata = platform_get_drvdata(pdev); |
814 | 814 | ||
815 | /* Free the Bluetooth/FM/GPIO | 815 | /* Free the Bluetooth/FM/GPIO |
816 | * nShutdown gpio from the system | 816 | * nShutdown gpio from the system |
diff --git a/drivers/misc/ti_dac7512.c b/drivers/misc/ti_dac7512.c index 1d86407189eb..9b237221bc4e 100644 --- a/drivers/misc/ti_dac7512.c +++ b/drivers/misc/ti_dac7512.c | |||
@@ -33,9 +33,11 @@ static ssize_t dac7512_store_val(struct device *dev, | |||
33 | struct spi_device *spi = to_spi_device(dev); | 33 | struct spi_device *spi = to_spi_device(dev); |
34 | unsigned char tmp[2]; | 34 | unsigned char tmp[2]; |
35 | unsigned long val; | 35 | unsigned long val; |
36 | int ret; | ||
36 | 37 | ||
37 | if (strict_strtoul(buf, 10, &val) < 0) | 38 | ret = kstrtoul(buf, 10, &val); |
38 | return -EINVAL; | 39 | if (ret) |
40 | return ret; | ||
39 | 41 | ||
40 | tmp[0] = val >> 8; | 42 | tmp[0] = val >> 8; |
41 | tmp[1] = val & 0xff; | 43 | tmp[1] = val & 0xff; |
diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c index 1dfde4d543db..5bc10fa193de 100644 --- a/drivers/misc/tsl2550.c +++ b/drivers/misc/tsl2550.c | |||
@@ -204,7 +204,7 @@ static ssize_t tsl2550_store_power_state(struct device *dev, | |||
204 | unsigned long val = simple_strtoul(buf, NULL, 10); | 204 | unsigned long val = simple_strtoul(buf, NULL, 10); |
205 | int ret; | 205 | int ret; |
206 | 206 | ||
207 | if (val < 0 || val > 1) | 207 | if (val > 1) |
208 | return -EINVAL; | 208 | return -EINVAL; |
209 | 209 | ||
210 | mutex_lock(&data->update_lock); | 210 | mutex_lock(&data->update_lock); |
@@ -236,7 +236,7 @@ static ssize_t tsl2550_store_operating_mode(struct device *dev, | |||
236 | unsigned long val = simple_strtoul(buf, NULL, 10); | 236 | unsigned long val = simple_strtoul(buf, NULL, 10); |
237 | int ret; | 237 | int ret; |
238 | 238 | ||
239 | if (val < 0 || val > 1) | 239 | if (val > 1) |
240 | return -EINVAL; | 240 | return -EINVAL; |
241 | 241 | ||
242 | if (data->power_state == 0) | 242 | if (data->power_state == 0) |
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 59ac143dec25..4f777ed9b089 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | #include <linux/console.h> | 41 | #include <linux/console.h> |
42 | #include <linux/moduleparam.h> | 42 | #include <linux/moduleparam.h> |
43 | #include <linux/kernel.h> | ||
43 | #include <linux/string.h> | 44 | #include <linux/string.h> |
44 | #include <linux/netpoll.h> | 45 | #include <linux/netpoll.h> |
45 | #include <linux/inet.h> | 46 | #include <linux/inet.h> |
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index b90f85bf5f81..6f6193168281 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
@@ -243,7 +243,7 @@ config PCMCIA_DEBUG | |||
243 | 243 | ||
244 | config PCMCIA_PROBE | 244 | config PCMCIA_PROBE |
245 | bool | 245 | bool |
246 | default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X && !PARISC | 246 | default y if ISA && !ARCH_SA1100 && !PARISC |
247 | 247 | ||
248 | config M32R_PCC | 248 | config M32R_PCC |
249 | bool "M32R PCMCIA I/F" | 249 | bool "M32R PCMCIA I/F" |
@@ -288,7 +288,7 @@ config BFIN_CFPCMCIA | |||
288 | 288 | ||
289 | config AT91_CF | 289 | config AT91_CF |
290 | tristate "AT91 CompactFlash Controller" | 290 | tristate "AT91 CompactFlash Controller" |
291 | depends on PCMCIA && ARCH_AT91RM9200 | 291 | depends on PCMCIA && ARCH_AT91 |
292 | help | 292 | help |
293 | Say Y here to support the CompactFlash controller on AT91 chips. | 293 | Say Y here to support the CompactFlash controller on AT91 chips. |
294 | Or choose M to compile the driver as a module named "at91_cf". | 294 | Or choose M to compile the driver as a module named "at91_cf". |
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index 01463c781847..b8f5acf02261 100644 --- a/drivers/pcmcia/at91_cf.c +++ b/drivers/pcmcia/at91_cf.c | |||
@@ -18,13 +18,14 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/gpio.h> | 19 | #include <linux/gpio.h> |
20 | #include <linux/platform_data/atmel.h> | 20 | #include <linux/platform_data/atmel.h> |
21 | #include <linux/io.h> | ||
22 | #include <linux/sizes.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/of_device.h> | ||
25 | #include <linux/of_gpio.h> | ||
21 | 26 | ||
22 | #include <pcmcia/ss.h> | 27 | #include <pcmcia/ss.h> |
23 | 28 | ||
24 | #include <mach/hardware.h> | ||
25 | #include <asm/io.h> | ||
26 | #include <asm/sizes.h> | ||
27 | |||
28 | #include <mach/at91rm9200_mc.h> | 29 | #include <mach/at91rm9200_mc.h> |
29 | #include <mach/at91_ramc.h> | 30 | #include <mach/at91_ramc.h> |
30 | 31 | ||
@@ -41,8 +42,6 @@ | |||
41 | 42 | ||
42 | /*--------------------------------------------------------------------------*/ | 43 | /*--------------------------------------------------------------------------*/ |
43 | 44 | ||
44 | static const char driver_name[] = "at91_cf"; | ||
45 | |||
46 | struct at91_cf_socket { | 45 | struct at91_cf_socket { |
47 | struct pcmcia_socket socket; | 46 | struct pcmcia_socket socket; |
48 | 47 | ||
@@ -76,7 +75,7 @@ static irqreturn_t at91_cf_irq(int irq, void *_cf) | |||
76 | /* kick pccard as needed */ | 75 | /* kick pccard as needed */ |
77 | if (present != cf->present) { | 76 | if (present != cf->present) { |
78 | cf->present = present; | 77 | cf->present = present; |
79 | pr_debug("%s: card %s\n", driver_name, | 78 | dev_dbg(&cf->pdev->dev, "card %s\n", |
80 | present ? "present" : "gone"); | 79 | present ? "present" : "gone"); |
81 | pcmcia_parse_events(&cf->socket, SS_DETECT); | 80 | pcmcia_parse_events(&cf->socket, SS_DETECT); |
82 | } | 81 | } |
@@ -100,9 +99,9 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp) | |||
100 | int vcc = gpio_is_valid(cf->board->vcc_pin); | 99 | int vcc = gpio_is_valid(cf->board->vcc_pin); |
101 | 100 | ||
102 | *sp = SS_DETECT | SS_3VCARD; | 101 | *sp = SS_DETECT | SS_3VCARD; |
103 | if (!rdy || gpio_get_value(rdy)) | 102 | if (!rdy || gpio_get_value(cf->board->irq_pin)) |
104 | *sp |= SS_READY; | 103 | *sp |= SS_READY; |
105 | if (!vcc || gpio_get_value(vcc)) | 104 | if (!vcc || gpio_get_value(cf->board->vcc_pin)) |
106 | *sp |= SS_POWERON; | 105 | *sp |= SS_POWERON; |
107 | } else | 106 | } else |
108 | *sp = 0; | 107 | *sp = 0; |
@@ -120,22 +119,22 @@ at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s) | |||
120 | /* switch Vcc if needed and possible */ | 119 | /* switch Vcc if needed and possible */ |
121 | if (gpio_is_valid(cf->board->vcc_pin)) { | 120 | if (gpio_is_valid(cf->board->vcc_pin)) { |
122 | switch (s->Vcc) { | 121 | switch (s->Vcc) { |
123 | case 0: | 122 | case 0: |
124 | gpio_set_value(cf->board->vcc_pin, 0); | 123 | gpio_set_value(cf->board->vcc_pin, 0); |
125 | break; | 124 | break; |
126 | case 33: | 125 | case 33: |
127 | gpio_set_value(cf->board->vcc_pin, 1); | 126 | gpio_set_value(cf->board->vcc_pin, 1); |
128 | break; | 127 | break; |
129 | default: | 128 | default: |
130 | return -EINVAL; | 129 | return -EINVAL; |
131 | } | 130 | } |
132 | } | 131 | } |
133 | 132 | ||
134 | /* toggle reset if needed */ | 133 | /* toggle reset if needed */ |
135 | gpio_set_value(cf->board->rst_pin, s->flags & SS_RESET); | 134 | gpio_set_value(cf->board->rst_pin, s->flags & SS_RESET); |
136 | 135 | ||
137 | pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n", | 136 | dev_dbg(&cf->pdev->dev, "Vcc %d, io_irq %d, flags %04x csc %04x\n", |
138 | driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask); | 137 | s->Vcc, s->io_irq, s->flags, s->csc_mask); |
139 | 138 | ||
140 | return 0; | 139 | return 0; |
141 | } | 140 | } |
@@ -171,10 +170,10 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) | |||
171 | */ | 170 | */ |
172 | if (!(io->flags & (MAP_16BIT | MAP_AUTOSZ))) { | 171 | if (!(io->flags & (MAP_16BIT | MAP_AUTOSZ))) { |
173 | csr |= AT91_SMC_DBW_8; | 172 | csr |= AT91_SMC_DBW_8; |
174 | pr_debug("%s: 8bit i/o bus\n", driver_name); | 173 | dev_dbg(&cf->pdev->dev, "8bit i/o bus\n"); |
175 | } else { | 174 | } else { |
176 | csr |= AT91_SMC_DBW_16; | 175 | csr |= AT91_SMC_DBW_16; |
177 | pr_debug("%s: 16bit i/o bus\n", driver_name); | 176 | dev_dbg(&cf->pdev->dev, "16bit i/o bus\n"); |
178 | } | 177 | } |
179 | at91_ramc_write(0, AT91_SMC_CSR(cf->board->chipselect), csr); | 178 | at91_ramc_write(0, AT91_SMC_CSR(cf->board->chipselect), csr); |
180 | 179 | ||
@@ -215,6 +214,37 @@ static struct pccard_operations at91_cf_ops = { | |||
215 | 214 | ||
216 | /*--------------------------------------------------------------------------*/ | 215 | /*--------------------------------------------------------------------------*/ |
217 | 216 | ||
217 | #if defined(CONFIG_OF) | ||
218 | static const struct of_device_id at91_cf_dt_ids[] = { | ||
219 | { .compatible = "atmel,at91rm9200-cf" }, | ||
220 | { /* sentinel */ } | ||
221 | }; | ||
222 | MODULE_DEVICE_TABLE(of, at91_cf_dt_ids); | ||
223 | |||
224 | static int at91_cf_dt_init(struct platform_device *pdev) | ||
225 | { | ||
226 | struct at91_cf_data *board; | ||
227 | |||
228 | board = devm_kzalloc(&pdev->dev, sizeof(*board), GFP_KERNEL); | ||
229 | if (!board) | ||
230 | return -ENOMEM; | ||
231 | |||
232 | board->irq_pin = of_get_gpio(pdev->dev.of_node, 0); | ||
233 | board->det_pin = of_get_gpio(pdev->dev.of_node, 1); | ||
234 | board->vcc_pin = of_get_gpio(pdev->dev.of_node, 2); | ||
235 | board->rst_pin = of_get_gpio(pdev->dev.of_node, 3); | ||
236 | |||
237 | pdev->dev.platform_data = board; | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | #else | ||
242 | static int at91_cf_dt_init(struct platform_device *pdev) | ||
243 | { | ||
244 | return -ENODEV; | ||
245 | } | ||
246 | #endif | ||
247 | |||
218 | static int __init at91_cf_probe(struct platform_device *pdev) | 248 | static int __init at91_cf_probe(struct platform_device *pdev) |
219 | { | 249 | { |
220 | struct at91_cf_socket *cf; | 250 | struct at91_cf_socket *cf; |
@@ -222,14 +252,22 @@ static int __init at91_cf_probe(struct platform_device *pdev) | |||
222 | struct resource *io; | 252 | struct resource *io; |
223 | int status; | 253 | int status; |
224 | 254 | ||
225 | if (!board || !gpio_is_valid(board->det_pin) || !gpio_is_valid(board->rst_pin)) | 255 | if (!board) { |
256 | status = at91_cf_dt_init(pdev); | ||
257 | if (status) | ||
258 | return status; | ||
259 | |||
260 | board = pdev->dev.platform_data; | ||
261 | } | ||
262 | |||
263 | if (!gpio_is_valid(board->det_pin) || !gpio_is_valid(board->rst_pin)) | ||
226 | return -ENODEV; | 264 | return -ENODEV; |
227 | 265 | ||
228 | io = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 266 | io = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
229 | if (!io) | 267 | if (!io) |
230 | return -ENODEV; | 268 | return -ENODEV; |
231 | 269 | ||
232 | cf = kzalloc(sizeof *cf, GFP_KERNEL); | 270 | cf = devm_kzalloc(&pdev->dev, sizeof(*cf), GFP_KERNEL); |
233 | if (!cf) | 271 | if (!cf) |
234 | return -ENOMEM; | 272 | return -ENOMEM; |
235 | 273 | ||
@@ -239,22 +277,25 @@ static int __init at91_cf_probe(struct platform_device *pdev) | |||
239 | platform_set_drvdata(pdev, cf); | 277 | platform_set_drvdata(pdev, cf); |
240 | 278 | ||
241 | /* must be a GPIO; ergo must trigger on both edges */ | 279 | /* must be a GPIO; ergo must trigger on both edges */ |
242 | status = gpio_request(board->det_pin, "cf_det"); | 280 | status = devm_gpio_request(&pdev->dev, board->det_pin, "cf_det"); |
243 | if (status < 0) | 281 | if (status < 0) |
244 | goto fail0; | 282 | return status; |
245 | status = request_irq(gpio_to_irq(board->det_pin), at91_cf_irq, 0, driver_name, cf); | 283 | |
284 | status = devm_request_irq(&pdev->dev, gpio_to_irq(board->det_pin), | ||
285 | at91_cf_irq, 0, "at91_cf detect", cf); | ||
246 | if (status < 0) | 286 | if (status < 0) |
247 | goto fail00; | 287 | return status; |
288 | |||
248 | device_init_wakeup(&pdev->dev, 1); | 289 | device_init_wakeup(&pdev->dev, 1); |
249 | 290 | ||
250 | status = gpio_request(board->rst_pin, "cf_rst"); | 291 | status = devm_gpio_request(&pdev->dev, board->rst_pin, "cf_rst"); |
251 | if (status < 0) | 292 | if (status < 0) |
252 | goto fail0a; | 293 | goto fail0a; |
253 | 294 | ||
254 | if (gpio_is_valid(board->vcc_pin)) { | 295 | if (gpio_is_valid(board->vcc_pin)) { |
255 | status = gpio_request(board->vcc_pin, "cf_vcc"); | 296 | status = devm_gpio_request(&pdev->dev, board->vcc_pin, "cf_vcc"); |
256 | if (status < 0) | 297 | if (status < 0) |
257 | goto fail0b; | 298 | goto fail0a; |
258 | } | 299 | } |
259 | 300 | ||
260 | /* | 301 | /* |
@@ -264,32 +305,33 @@ static int __init at91_cf_probe(struct platform_device *pdev) | |||
264 | * (Note: DK board doesn't wire the IRQ pin...) | 305 | * (Note: DK board doesn't wire the IRQ pin...) |
265 | */ | 306 | */ |
266 | if (gpio_is_valid(board->irq_pin)) { | 307 | if (gpio_is_valid(board->irq_pin)) { |
267 | status = gpio_request(board->irq_pin, "cf_irq"); | 308 | status = devm_gpio_request(&pdev->dev, board->irq_pin, "cf_irq"); |
268 | if (status < 0) | 309 | if (status < 0) |
269 | goto fail0c; | 310 | goto fail0a; |
270 | status = request_irq(gpio_to_irq(board->irq_pin), at91_cf_irq, | 311 | |
271 | IRQF_SHARED, driver_name, cf); | 312 | status = devm_request_irq(&pdev->dev, gpio_to_irq(board->irq_pin), |
313 | at91_cf_irq, IRQF_SHARED, "at91_cf", cf); | ||
272 | if (status < 0) | 314 | if (status < 0) |
273 | goto fail0d; | 315 | goto fail0a; |
274 | cf->socket.pci_irq = gpio_to_irq(board->irq_pin); | 316 | cf->socket.pci_irq = gpio_to_irq(board->irq_pin); |
275 | } else | 317 | } else |
276 | cf->socket.pci_irq = nr_irqs + 1; | 318 | cf->socket.pci_irq = nr_irqs + 1; |
277 | 319 | ||
278 | /* pcmcia layer only remaps "real" memory not iospace */ | 320 | /* pcmcia layer only remaps "real" memory not iospace */ |
279 | cf->socket.io_offset = (unsigned long) | 321 | cf->socket.io_offset = (unsigned long) devm_ioremap(&pdev->dev, |
280 | ioremap(cf->phys_baseaddr + CF_IO_PHYS, SZ_2K); | 322 | cf->phys_baseaddr + CF_IO_PHYS, SZ_2K); |
281 | if (!cf->socket.io_offset) { | 323 | if (!cf->socket.io_offset) { |
282 | status = -ENXIO; | 324 | status = -ENXIO; |
283 | goto fail1; | 325 | goto fail0a; |
284 | } | 326 | } |
285 | 327 | ||
286 | /* reserve chip-select regions */ | 328 | /* reserve chip-select regions */ |
287 | if (!request_mem_region(io->start, resource_size(io), driver_name)) { | 329 | if (!devm_request_mem_region(&pdev->dev, io->start, resource_size(io), "at91_cf")) { |
288 | status = -ENXIO; | 330 | status = -ENXIO; |
289 | goto fail1; | 331 | goto fail0a; |
290 | } | 332 | } |
291 | 333 | ||
292 | pr_info("%s: irqs det #%d, io #%d\n", driver_name, | 334 | dev_info(&pdev->dev, "irqs det #%d, io #%d\n", |
293 | gpio_to_irq(board->det_pin), gpio_to_irq(board->irq_pin)); | 335 | gpio_to_irq(board->det_pin), gpio_to_irq(board->irq_pin)); |
294 | 336 | ||
295 | cf->socket.owner = THIS_MODULE; | 337 | cf->socket.owner = THIS_MODULE; |
@@ -303,55 +345,22 @@ static int __init at91_cf_probe(struct platform_device *pdev) | |||
303 | 345 | ||
304 | status = pcmcia_register_socket(&cf->socket); | 346 | status = pcmcia_register_socket(&cf->socket); |
305 | if (status < 0) | 347 | if (status < 0) |
306 | goto fail2; | 348 | goto fail0a; |
307 | 349 | ||
308 | return 0; | 350 | return 0; |
309 | 351 | ||
310 | fail2: | ||
311 | release_mem_region(io->start, resource_size(io)); | ||
312 | fail1: | ||
313 | if (cf->socket.io_offset) | ||
314 | iounmap((void __iomem *) cf->socket.io_offset); | ||
315 | if (gpio_is_valid(board->irq_pin)) { | ||
316 | free_irq(gpio_to_irq(board->irq_pin), cf); | ||
317 | fail0d: | ||
318 | gpio_free(board->irq_pin); | ||
319 | } | ||
320 | fail0c: | ||
321 | if (gpio_is_valid(board->vcc_pin)) | ||
322 | gpio_free(board->vcc_pin); | ||
323 | fail0b: | ||
324 | gpio_free(board->rst_pin); | ||
325 | fail0a: | 352 | fail0a: |
326 | device_init_wakeup(&pdev->dev, 0); | 353 | device_init_wakeup(&pdev->dev, 0); |
327 | free_irq(gpio_to_irq(board->det_pin), cf); | ||
328 | fail00: | ||
329 | gpio_free(board->det_pin); | ||
330 | fail0: | ||
331 | kfree(cf); | ||
332 | return status; | 354 | return status; |
333 | } | 355 | } |
334 | 356 | ||
335 | static int __exit at91_cf_remove(struct platform_device *pdev) | 357 | static int __exit at91_cf_remove(struct platform_device *pdev) |
336 | { | 358 | { |
337 | struct at91_cf_socket *cf = platform_get_drvdata(pdev); | 359 | struct at91_cf_socket *cf = platform_get_drvdata(pdev); |
338 | struct at91_cf_data *board = cf->board; | ||
339 | struct resource *io = cf->socket.io[0].res; | ||
340 | 360 | ||
341 | pcmcia_unregister_socket(&cf->socket); | 361 | pcmcia_unregister_socket(&cf->socket); |
342 | release_mem_region(io->start, resource_size(io)); | ||
343 | iounmap((void __iomem *) cf->socket.io_offset); | ||
344 | if (gpio_is_valid(board->irq_pin)) { | ||
345 | free_irq(gpio_to_irq(board->irq_pin), cf); | ||
346 | gpio_free(board->irq_pin); | ||
347 | } | ||
348 | if (gpio_is_valid(board->vcc_pin)) | ||
349 | gpio_free(board->vcc_pin); | ||
350 | gpio_free(board->rst_pin); | ||
351 | device_init_wakeup(&pdev->dev, 0); | 362 | device_init_wakeup(&pdev->dev, 0); |
352 | free_irq(gpio_to_irq(board->det_pin), cf); | 363 | |
353 | gpio_free(board->det_pin); | ||
354 | kfree(cf); | ||
355 | return 0; | 364 | return 0; |
356 | } | 365 | } |
357 | 366 | ||
@@ -391,8 +400,9 @@ static int at91_cf_resume(struct platform_device *pdev) | |||
391 | 400 | ||
392 | static struct platform_driver at91_cf_driver = { | 401 | static struct platform_driver at91_cf_driver = { |
393 | .driver = { | 402 | .driver = { |
394 | .name = (char *) driver_name, | 403 | .name = "at91_cf", |
395 | .owner = THIS_MODULE, | 404 | .owner = THIS_MODULE, |
405 | .of_match_table = of_match_ptr(at91_cf_dt_ids), | ||
396 | }, | 406 | }, |
397 | .remove = __exit_p(at91_cf_remove), | 407 | .remove = __exit_p(at91_cf_remove), |
398 | .suspend = at91_cf_suspend, | 408 | .suspend = at91_cf_suspend, |
@@ -401,17 +411,7 @@ static struct platform_driver at91_cf_driver = { | |||
401 | 411 | ||
402 | /*--------------------------------------------------------------------------*/ | 412 | /*--------------------------------------------------------------------------*/ |
403 | 413 | ||
404 | static int __init at91_cf_init(void) | 414 | module_platform_driver_probe(at91_cf_driver, at91_cf_probe); |
405 | { | ||
406 | return platform_driver_probe(&at91_cf_driver, at91_cf_probe); | ||
407 | } | ||
408 | module_init(at91_cf_init); | ||
409 | |||
410 | static void __exit at91_cf_exit(void) | ||
411 | { | ||
412 | platform_driver_unregister(&at91_cf_driver); | ||
413 | } | ||
414 | module_exit(at91_cf_exit); | ||
415 | 415 | ||
416 | MODULE_DESCRIPTION("AT91 Compact Flash Driver"); | 416 | MODULE_DESCRIPTION("AT91 Compact Flash Driver"); |
417 | MODULE_AUTHOR("David Brownell"); | 417 | MODULE_AUTHOR("David Brownell"); |
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index b29d97e170ae..a4c16ee5c718 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c | |||
@@ -644,6 +644,7 @@ static int pd6729_pci_probe(struct pci_dev *dev, | |||
644 | if (!pci_resource_start(dev, 0)) { | 644 | if (!pci_resource_start(dev, 0)) { |
645 | dev_warn(&dev->dev, "refusing to load the driver as the " | 645 | dev_warn(&dev->dev, "refusing to load the driver as the " |
646 | "io_base is NULL.\n"); | 646 | "io_base is NULL.\n"); |
647 | ret = -ENOMEM; | ||
647 | goto err_out_disable; | 648 | goto err_out_disable; |
648 | } | 649 | } |
649 | 650 | ||
@@ -673,6 +674,7 @@ static int pd6729_pci_probe(struct pci_dev *dev, | |||
673 | mask = pd6729_isa_scan(); | 674 | mask = pd6729_isa_scan(); |
674 | if (irq_mode == 0 && mask == 0) { | 675 | if (irq_mode == 0 && mask == 0) { |
675 | dev_warn(&dev->dev, "no ISA interrupt is available.\n"); | 676 | dev_warn(&dev->dev, "no ISA interrupt is available.\n"); |
677 | ret = -ENODEV; | ||
676 | goto err_out_free_res; | 678 | goto err_out_free_res; |
677 | } | 679 | } |
678 | 680 | ||
diff --git a/drivers/uio/uio_aec.c b/drivers/uio/uio_aec.c index 1548982db58b..f3611c2d83b6 100644 --- a/drivers/uio/uio_aec.c +++ b/drivers/uio/uio_aec.c | |||
@@ -160,17 +160,5 @@ static struct pci_driver pci_driver = { | |||
160 | .remove = remove, | 160 | .remove = remove, |
161 | }; | 161 | }; |
162 | 162 | ||
163 | static int __init aectc_init(void) | 163 | module_pci_driver(pci_driver); |
164 | { | ||
165 | return pci_register_driver(&pci_driver); | ||
166 | } | ||
167 | |||
168 | static void __exit aectc_exit(void) | ||
169 | { | ||
170 | pci_unregister_driver(&pci_driver); | ||
171 | } | ||
172 | |||
173 | MODULE_LICENSE("GPL"); | 164 | MODULE_LICENSE("GPL"); |
174 | |||
175 | module_init(aectc_init); | ||
176 | module_exit(aectc_exit); | ||
diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c index 7dd6fc60539d..22cdf385ab33 100644 --- a/drivers/uio/uio_cif.c +++ b/drivers/uio/uio_cif.c | |||
@@ -135,19 +135,7 @@ static struct pci_driver hilscher_pci_driver = { | |||
135 | .remove = hilscher_pci_remove, | 135 | .remove = hilscher_pci_remove, |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static int __init hilscher_init_module(void) | 138 | module_pci_driver(hilscher_pci_driver); |
139 | { | ||
140 | return pci_register_driver(&hilscher_pci_driver); | ||
141 | } | ||
142 | |||
143 | static void __exit hilscher_exit_module(void) | ||
144 | { | ||
145 | pci_unregister_driver(&hilscher_pci_driver); | ||
146 | } | ||
147 | |||
148 | module_init(hilscher_init_module); | ||
149 | module_exit(hilscher_exit_module); | ||
150 | |||
151 | MODULE_DEVICE_TABLE(pci, hilscher_pci_ids); | 139 | MODULE_DEVICE_TABLE(pci, hilscher_pci_ids); |
152 | MODULE_LICENSE("GPL v2"); | 140 | MODULE_LICENSE("GPL v2"); |
153 | MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger"); | 141 | MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger"); |
diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c index 252434c9ea9d..125d0e5a6887 100644 --- a/drivers/uio/uio_dmem_genirq.c +++ b/drivers/uio/uio_dmem_genirq.c | |||
@@ -336,8 +336,6 @@ static const struct of_device_id uio_of_genirq_match[] = { | |||
336 | { /* empty for now */ }, | 336 | { /* empty for now */ }, |
337 | }; | 337 | }; |
338 | MODULE_DEVICE_TABLE(of, uio_of_genirq_match); | 338 | MODULE_DEVICE_TABLE(of, uio_of_genirq_match); |
339 | #else | ||
340 | # define uio_of_genirq_match NULL | ||
341 | #endif | 339 | #endif |
342 | 340 | ||
343 | static struct platform_driver uio_dmem_genirq = { | 341 | static struct platform_driver uio_dmem_genirq = { |
@@ -347,7 +345,7 @@ static struct platform_driver uio_dmem_genirq = { | |||
347 | .name = DRIVER_NAME, | 345 | .name = DRIVER_NAME, |
348 | .owner = THIS_MODULE, | 346 | .owner = THIS_MODULE, |
349 | .pm = &uio_dmem_genirq_dev_pm_ops, | 347 | .pm = &uio_dmem_genirq_dev_pm_ops, |
350 | .of_match_table = uio_of_genirq_match, | 348 | .of_match_table = of_match_ptr(uio_of_genirq_match), |
351 | }, | 349 | }, |
352 | }; | 350 | }; |
353 | 351 | ||
diff --git a/drivers/uio/uio_netx.c b/drivers/uio/uio_netx.c index 6a4ba5e83e37..28a766b9e198 100644 --- a/drivers/uio/uio_netx.c +++ b/drivers/uio/uio_netx.c | |||
@@ -174,19 +174,7 @@ static struct pci_driver netx_pci_driver = { | |||
174 | .remove = netx_pci_remove, | 174 | .remove = netx_pci_remove, |
175 | }; | 175 | }; |
176 | 176 | ||
177 | static int __init netx_init_module(void) | 177 | module_pci_driver(netx_pci_driver); |
178 | { | ||
179 | return pci_register_driver(&netx_pci_driver); | ||
180 | } | ||
181 | |||
182 | static void __exit netx_exit_module(void) | ||
183 | { | ||
184 | pci_unregister_driver(&netx_pci_driver); | ||
185 | } | ||
186 | |||
187 | module_init(netx_init_module); | ||
188 | module_exit(netx_exit_module); | ||
189 | |||
190 | MODULE_DEVICE_TABLE(pci, netx_pci_ids); | 178 | MODULE_DEVICE_TABLE(pci, netx_pci_ids); |
191 | MODULE_LICENSE("GPL v2"); | 179 | MODULE_LICENSE("GPL v2"); |
192 | MODULE_AUTHOR("Hans J. Koch, Manuel Traut"); | 180 | MODULE_AUTHOR("Hans J. Koch, Manuel Traut"); |
diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c index 14aa10c1f6de..077ae12269ce 100644 --- a/drivers/uio/uio_pci_generic.c +++ b/drivers/uio/uio_pci_generic.c | |||
@@ -113,27 +113,14 @@ static void remove(struct pci_dev *pdev) | |||
113 | kfree(gdev); | 113 | kfree(gdev); |
114 | } | 114 | } |
115 | 115 | ||
116 | static struct pci_driver driver = { | 116 | static struct pci_driver uio_pci_driver = { |
117 | .name = "uio_pci_generic", | 117 | .name = "uio_pci_generic", |
118 | .id_table = NULL, /* only dynamic id's */ | 118 | .id_table = NULL, /* only dynamic id's */ |
119 | .probe = probe, | 119 | .probe = probe, |
120 | .remove = remove, | 120 | .remove = remove, |
121 | }; | 121 | }; |
122 | 122 | ||
123 | static int __init init(void) | 123 | module_pci_driver(uio_pci_driver); |
124 | { | ||
125 | pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | ||
126 | return pci_register_driver(&driver); | ||
127 | } | ||
128 | |||
129 | static void __exit cleanup(void) | ||
130 | { | ||
131 | pci_unregister_driver(&driver); | ||
132 | } | ||
133 | |||
134 | module_init(init); | ||
135 | module_exit(cleanup); | ||
136 | |||
137 | MODULE_VERSION(DRIVER_VERSION); | 124 | MODULE_VERSION(DRIVER_VERSION); |
138 | MODULE_LICENSE("GPL v2"); | 125 | MODULE_LICENSE("GPL v2"); |
139 | MODULE_AUTHOR(DRIVER_AUTHOR); | 126 | MODULE_AUTHOR(DRIVER_AUTHOR); |
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c index c122bca669b6..4eb8eaf71be8 100644 --- a/drivers/uio/uio_pdrv_genirq.c +++ b/drivers/uio/uio_pdrv_genirq.c | |||
@@ -37,6 +37,11 @@ struct uio_pdrv_genirq_platdata { | |||
37 | struct platform_device *pdev; | 37 | struct platform_device *pdev; |
38 | }; | 38 | }; |
39 | 39 | ||
40 | /* Bits in uio_pdrv_genirq_platdata.flags */ | ||
41 | enum { | ||
42 | UIO_IRQ_DISABLED = 0, | ||
43 | }; | ||
44 | |||
40 | static int uio_pdrv_genirq_open(struct uio_info *info, struct inode *inode) | 45 | static int uio_pdrv_genirq_open(struct uio_info *info, struct inode *inode) |
41 | { | 46 | { |
42 | struct uio_pdrv_genirq_platdata *priv = info->priv; | 47 | 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) | |||
63 | * remember the state so we can allow user space to enable it later. | 68 | * remember the state so we can allow user space to enable it later. |
64 | */ | 69 | */ |
65 | 70 | ||
66 | if (!test_and_set_bit(0, &priv->flags)) | 71 | spin_lock(&priv->lock); |
72 | if (!__test_and_set_bit(UIO_IRQ_DISABLED, &priv->flags)) | ||
67 | disable_irq_nosync(irq); | 73 | disable_irq_nosync(irq); |
74 | spin_unlock(&priv->lock); | ||
68 | 75 | ||
69 | return IRQ_HANDLED; | 76 | return IRQ_HANDLED; |
70 | } | 77 | } |
@@ -78,16 +85,17 @@ static int uio_pdrv_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) | |||
78 | * in the interrupt controller, but keep track of the | 85 | * in the interrupt controller, but keep track of the |
79 | * state to prevent per-irq depth damage. | 86 | * state to prevent per-irq depth damage. |
80 | * | 87 | * |
81 | * Serialize this operation to support multiple tasks. | 88 | * Serialize this operation to support multiple tasks and concurrency |
89 | * with irq handler on SMP systems. | ||
82 | */ | 90 | */ |
83 | 91 | ||
84 | spin_lock_irqsave(&priv->lock, flags); | 92 | spin_lock_irqsave(&priv->lock, flags); |
85 | if (irq_on) { | 93 | if (irq_on) { |
86 | if (test_and_clear_bit(0, &priv->flags)) | 94 | if (__test_and_clear_bit(UIO_IRQ_DISABLED, &priv->flags)) |
87 | enable_irq(dev_info->irq); | 95 | enable_irq(dev_info->irq); |
88 | } else { | 96 | } else { |
89 | if (!test_and_set_bit(0, &priv->flags)) | 97 | if (!__test_and_set_bit(UIO_IRQ_DISABLED, &priv->flags)) |
90 | disable_irq(dev_info->irq); | 98 | disable_irq_nosync(dev_info->irq); |
91 | } | 99 | } |
92 | spin_unlock_irqrestore(&priv->lock, flags); | 100 | spin_unlock_irqrestore(&priv->lock, flags); |
93 | 101 | ||
@@ -103,24 +111,16 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev) | |||
103 | int i; | 111 | int i; |
104 | 112 | ||
105 | if (pdev->dev.of_node) { | 113 | if (pdev->dev.of_node) { |
106 | int irq; | ||
107 | |||
108 | /* alloc uioinfo for one device */ | 114 | /* alloc uioinfo for one device */ |
109 | uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL); | 115 | uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL); |
110 | if (!uioinfo) { | 116 | if (!uioinfo) { |
111 | ret = -ENOMEM; | 117 | ret = -ENOMEM; |
112 | dev_err(&pdev->dev, "unable to kmalloc\n"); | 118 | dev_err(&pdev->dev, "unable to kmalloc\n"); |
113 | goto bad2; | 119 | return ret; |
114 | } | 120 | } |
115 | uioinfo->name = pdev->dev.of_node->name; | 121 | uioinfo->name = pdev->dev.of_node->name; |
116 | uioinfo->version = "devicetree"; | 122 | uioinfo->version = "devicetree"; |
117 | |||
118 | /* Multiple IRQs are not supported */ | 123 | /* Multiple IRQs are not supported */ |
119 | irq = platform_get_irq(pdev, 0); | ||
120 | if (irq == -ENXIO) | ||
121 | uioinfo->irq = UIO_IRQ_NONE; | ||
122 | else | ||
123 | uioinfo->irq = irq; | ||
124 | } | 124 | } |
125 | 125 | ||
126 | if (!uioinfo || !uioinfo->name || !uioinfo->version) { | 126 | if (!uioinfo || !uioinfo->name || !uioinfo->version) { |
@@ -148,12 +148,15 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev) | |||
148 | 148 | ||
149 | if (!uioinfo->irq) { | 149 | if (!uioinfo->irq) { |
150 | ret = platform_get_irq(pdev, 0); | 150 | ret = platform_get_irq(pdev, 0); |
151 | if (ret < 0) { | 151 | uioinfo->irq = ret; |
152 | if (ret == -ENXIO && pdev->dev.of_node) | ||
153 | uioinfo->irq = UIO_IRQ_NONE; | ||
154 | else if (ret < 0) { | ||
152 | dev_err(&pdev->dev, "failed to get IRQ\n"); | 155 | dev_err(&pdev->dev, "failed to get IRQ\n"); |
153 | goto bad0; | 156 | goto bad1; |
154 | } | 157 | } |
155 | uioinfo->irq = ret; | ||
156 | } | 158 | } |
159 | |||
157 | uiomem = &uioinfo->mem[0]; | 160 | uiomem = &uioinfo->mem[0]; |
158 | 161 | ||
159 | for (i = 0; i < pdev->num_resources; ++i) { | 162 | for (i = 0; i < pdev->num_resources; ++i) { |
@@ -206,19 +209,19 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev) | |||
206 | ret = uio_register_device(&pdev->dev, priv->uioinfo); | 209 | ret = uio_register_device(&pdev->dev, priv->uioinfo); |
207 | if (ret) { | 210 | if (ret) { |
208 | dev_err(&pdev->dev, "unable to register uio device\n"); | 211 | dev_err(&pdev->dev, "unable to register uio device\n"); |
209 | goto bad1; | 212 | goto bad2; |
210 | } | 213 | } |
211 | 214 | ||
212 | platform_set_drvdata(pdev, priv); | 215 | platform_set_drvdata(pdev, priv); |
213 | return 0; | 216 | return 0; |
217 | bad2: | ||
218 | pm_runtime_disable(&pdev->dev); | ||
214 | bad1: | 219 | bad1: |
215 | kfree(priv); | 220 | kfree(priv); |
216 | pm_runtime_disable(&pdev->dev); | ||
217 | bad0: | 221 | bad0: |
218 | /* kfree uioinfo for OF */ | 222 | /* kfree uioinfo for OF */ |
219 | if (pdev->dev.of_node) | 223 | if (pdev->dev.of_node) |
220 | kfree(uioinfo); | 224 | kfree(uioinfo); |
221 | bad2: | ||
222 | return ret; | 225 | return ret; |
223 | } | 226 | } |
224 | 227 | ||
@@ -263,12 +266,13 @@ static const struct dev_pm_ops uio_pdrv_genirq_dev_pm_ops = { | |||
263 | }; | 266 | }; |
264 | 267 | ||
265 | #ifdef CONFIG_OF | 268 | #ifdef CONFIG_OF |
266 | static const struct of_device_id uio_of_genirq_match[] = { | 269 | static struct of_device_id uio_of_genirq_match[] = { |
267 | { /* empty for now */ }, | 270 | { /* This is filled with module_parm */ }, |
271 | { /* Sentinel */ }, | ||
268 | }; | 272 | }; |
269 | MODULE_DEVICE_TABLE(of, uio_of_genirq_match); | 273 | MODULE_DEVICE_TABLE(of, uio_of_genirq_match); |
270 | #else | 274 | module_param_string(of_id, uio_of_genirq_match[0].compatible, 128, 0); |
271 | # define uio_of_genirq_match NULL | 275 | MODULE_PARM_DESC(of_id, "Openfirmware id of the device to be handled by uio"); |
272 | #endif | 276 | #endif |
273 | 277 | ||
274 | static struct platform_driver uio_pdrv_genirq = { | 278 | static struct platform_driver uio_pdrv_genirq = { |
@@ -278,7 +282,7 @@ static struct platform_driver uio_pdrv_genirq = { | |||
278 | .name = DRIVER_NAME, | 282 | .name = DRIVER_NAME, |
279 | .owner = THIS_MODULE, | 283 | .owner = THIS_MODULE, |
280 | .pm = &uio_pdrv_genirq_dev_pm_ops, | 284 | .pm = &uio_pdrv_genirq_dev_pm_ops, |
281 | .of_match_table = uio_of_genirq_match, | 285 | .of_match_table = of_match_ptr(uio_of_genirq_match), |
282 | }, | 286 | }, |
283 | }; | 287 | }; |
284 | 288 | ||
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c index 6e2ab007fe9c..21f7a72301e4 100644 --- a/drivers/uio/uio_pruss.c +++ b/drivers/uio/uio_pruss.c | |||
@@ -136,9 +136,9 @@ static int pruss_probe(struct platform_device *dev) | |||
136 | gdev->pruss_clk = clk_get(&dev->dev, "pruss"); | 136 | gdev->pruss_clk = clk_get(&dev->dev, "pruss"); |
137 | if (IS_ERR(gdev->pruss_clk)) { | 137 | if (IS_ERR(gdev->pruss_clk)) { |
138 | dev_err(&dev->dev, "Failed to get clock\n"); | 138 | dev_err(&dev->dev, "Failed to get clock\n"); |
139 | ret = PTR_ERR(gdev->pruss_clk); | ||
139 | kfree(gdev->info); | 140 | kfree(gdev->info); |
140 | kfree(gdev); | 141 | kfree(gdev); |
141 | ret = PTR_ERR(gdev->pruss_clk); | ||
142 | return ret; | 142 | return ret; |
143 | } else { | 143 | } else { |
144 | clk_enable(gdev->pruss_clk); | 144 | clk_enable(gdev->pruss_clk); |
diff --git a/drivers/uio/uio_sercos3.c b/drivers/uio/uio_sercos3.c index 81a10a563120..541983217085 100644 --- a/drivers/uio/uio_sercos3.c +++ b/drivers/uio/uio_sercos3.c | |||
@@ -226,19 +226,7 @@ static struct pci_driver sercos3_pci_driver = { | |||
226 | .remove = sercos3_pci_remove, | 226 | .remove = sercos3_pci_remove, |
227 | }; | 227 | }; |
228 | 228 | ||
229 | static int __init sercos3_init_module(void) | 229 | module_pci_driver(sercos3_pci_driver); |
230 | { | ||
231 | return pci_register_driver(&sercos3_pci_driver); | ||
232 | } | ||
233 | |||
234 | static void __exit sercos3_exit_module(void) | ||
235 | { | ||
236 | pci_unregister_driver(&sercos3_pci_driver); | ||
237 | } | ||
238 | |||
239 | module_init(sercos3_init_module); | ||
240 | module_exit(sercos3_exit_module); | ||
241 | |||
242 | MODULE_DESCRIPTION("UIO driver for the Automata Sercos III PCI card"); | 230 | MODULE_DESCRIPTION("UIO driver for the Automata Sercos III PCI card"); |
243 | MODULE_AUTHOR("John Ogness <john.ogness@linutronix.de>"); | 231 | MODULE_AUTHOR("John Ogness <john.ogness@linutronix.de>"); |
244 | MODULE_LICENSE("GPL v2"); | 232 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 9c1aa4dc39c9..94c892f27be4 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c | |||
@@ -169,7 +169,7 @@ static u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge) | |||
169 | unsigned int error_addr_high, error_addr_low; | 169 | unsigned int error_addr_high, error_addr_low; |
170 | unsigned long long error_addr; | 170 | unsigned long long error_addr; |
171 | u32 error_attrib; | 171 | u32 error_attrib; |
172 | struct vme_bus_error *error; | 172 | struct vme_bus_error *error = NULL; |
173 | struct tsi148_driver *bridge; | 173 | struct tsi148_driver *bridge; |
174 | 174 | ||
175 | bridge = tsi148_bridge->driver_priv; | 175 | bridge = tsi148_bridge->driver_priv; |
@@ -186,16 +186,22 @@ static u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge) | |||
186 | "Occurred\n"); | 186 | "Occurred\n"); |
187 | } | 187 | } |
188 | 188 | ||
189 | error = kmalloc(sizeof(struct vme_bus_error), GFP_ATOMIC); | 189 | if (err_chk) { |
190 | if (error) { | 190 | error = kmalloc(sizeof(struct vme_bus_error), GFP_ATOMIC); |
191 | error->address = error_addr; | 191 | if (error) { |
192 | error->attributes = error_attrib; | 192 | error->address = error_addr; |
193 | list_add_tail(&error->list, &tsi148_bridge->vme_errors); | 193 | error->attributes = error_attrib; |
194 | } else { | 194 | list_add_tail(&error->list, &tsi148_bridge->vme_errors); |
195 | dev_err(tsi148_bridge->parent, "Unable to alloc memory for " | 195 | } else { |
196 | "VMEbus Error reporting\n"); | 196 | dev_err(tsi148_bridge->parent, |
197 | dev_err(tsi148_bridge->parent, "VME Bus Error at address: " | 197 | "Unable to alloc memory for VMEbus Error reporting\n"); |
198 | "0x%llx, attributes: %08x\n", error_addr, error_attrib); | 198 | } |
199 | } | ||
200 | |||
201 | if (!error) { | ||
202 | dev_err(tsi148_bridge->parent, | ||
203 | "VME Bus Error at address: 0x%llx, attributes: %08x\n", | ||
204 | error_addr, error_attrib); | ||
199 | } | 205 | } |
200 | 206 | ||
201 | /* Clear Status */ | 207 | /* Clear Status */ |
@@ -2294,12 +2300,13 @@ static int tsi148_crcsr_init(struct vme_bridge *tsi148_bridge, | |||
2294 | dev_info(tsi148_bridge->parent, "CR/CSR Offset: %d\n", cbar); | 2300 | dev_info(tsi148_bridge->parent, "CR/CSR Offset: %d\n", cbar); |
2295 | 2301 | ||
2296 | crat = ioread32be(bridge->base + TSI148_LCSR_CRAT); | 2302 | crat = ioread32be(bridge->base + TSI148_LCSR_CRAT); |
2297 | if (crat & TSI148_LCSR_CRAT_EN) { | 2303 | if (crat & TSI148_LCSR_CRAT_EN) |
2304 | dev_info(tsi148_bridge->parent, "CR/CSR already enabled\n"); | ||
2305 | else { | ||
2298 | dev_info(tsi148_bridge->parent, "Enabling CR/CSR space\n"); | 2306 | dev_info(tsi148_bridge->parent, "Enabling CR/CSR space\n"); |
2299 | iowrite32be(crat | TSI148_LCSR_CRAT_EN, | 2307 | iowrite32be(crat | TSI148_LCSR_CRAT_EN, |
2300 | bridge->base + TSI148_LCSR_CRAT); | 2308 | bridge->base + TSI148_LCSR_CRAT); |
2301 | } else | 2309 | } |
2302 | dev_info(tsi148_bridge->parent, "CR/CSR already enabled\n"); | ||
2303 | 2310 | ||
2304 | /* If we want flushed, error-checked writes, set up a window | 2311 | /* If we want flushed, error-checked writes, set up a window |
2305 | * over the CR/CSR registers. We read from here to safely flush | 2312 | * over the CR/CSR registers. We read from here to safely flush |
@@ -2441,13 +2448,6 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2441 | spin_lock_init(&tsi148_device->flush_image->lock); | 2448 | spin_lock_init(&tsi148_device->flush_image->lock); |
2442 | tsi148_device->flush_image->locked = 1; | 2449 | tsi148_device->flush_image->locked = 1; |
2443 | tsi148_device->flush_image->number = master_num; | 2450 | tsi148_device->flush_image->number = master_num; |
2444 | tsi148_device->flush_image->address_attr = VME_A16 | VME_A24 | | ||
2445 | VME_A32 | VME_A64; | ||
2446 | tsi148_device->flush_image->cycle_attr = VME_SCT | VME_BLT | | ||
2447 | VME_MBLT | VME_2eVME | VME_2eSST | VME_2eSSTB | | ||
2448 | VME_2eSST160 | VME_2eSST267 | VME_2eSST320 | VME_SUPER | | ||
2449 | VME_USER | VME_PROG | VME_DATA; | ||
2450 | tsi148_device->flush_image->width_attr = VME_D16 | VME_D32; | ||
2451 | memset(&tsi148_device->flush_image->bus_resource, 0, | 2451 | memset(&tsi148_device->flush_image->bus_resource, 0, |
2452 | sizeof(struct resource)); | 2452 | sizeof(struct resource)); |
2453 | tsi148_device->flush_image->kern_base = NULL; | 2453 | tsi148_device->flush_image->kern_base = NULL; |
@@ -2582,7 +2582,8 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2582 | dev_info(&pdev->dev, "VME Write and flush and error check is %s\n", | 2582 | dev_info(&pdev->dev, "VME Write and flush and error check is %s\n", |
2583 | err_chk ? "enabled" : "disabled"); | 2583 | err_chk ? "enabled" : "disabled"); |
2584 | 2584 | ||
2585 | if (tsi148_crcsr_init(tsi148_bridge, pdev)) { | 2585 | retval = tsi148_crcsr_init(tsi148_bridge, pdev); |
2586 | if (retval) { | ||
2586 | dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); | 2587 | dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); |
2587 | goto err_crcsr; | 2588 | goto err_crcsr; |
2588 | } | 2589 | } |
diff --git a/drivers/vme/vme.c b/drivers/vme/vme.c index 5e6c7d74e19f..f6856b427496 100644 --- a/drivers/vme/vme.c +++ b/drivers/vme/vme.c | |||
@@ -959,6 +959,8 @@ int vme_dma_free(struct vme_resource *resource) | |||
959 | 959 | ||
960 | mutex_unlock(&ctrlr->mtx); | 960 | mutex_unlock(&ctrlr->mtx); |
961 | 961 | ||
962 | kfree(resource); | ||
963 | |||
962 | return 0; | 964 | return 0; |
963 | } | 965 | } |
964 | EXPORT_SYMBOL(vme_dma_free); | 966 | EXPORT_SYMBOL(vme_dma_free); |
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c index 46d97014342e..f54ece268c98 100644 --- a/drivers/w1/masters/w1-gpio.c +++ b/drivers/w1/masters/w1-gpio.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
17 | #include <linux/of_platform.h> | 17 | #include <linux/of_platform.h> |
18 | #include <linux/of_gpio.h> | 18 | #include <linux/of_gpio.h> |
19 | #include <linux/pinctrl/consumer.h> | ||
20 | #include <linux/err.h> | 19 | #include <linux/err.h> |
21 | #include <linux/of.h> | 20 | #include <linux/of.h> |
22 | 21 | ||
@@ -78,13 +77,8 @@ static int w1_gpio_probe(struct platform_device *pdev) | |||
78 | { | 77 | { |
79 | struct w1_bus_master *master; | 78 | struct w1_bus_master *master; |
80 | struct w1_gpio_platform_data *pdata; | 79 | struct w1_gpio_platform_data *pdata; |
81 | struct pinctrl *pinctrl; | ||
82 | int err; | 80 | int err; |
83 | 81 | ||
84 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
85 | if (IS_ERR(pinctrl)) | ||
86 | dev_warn(&pdev->dev, "unable to select pin group\n"); | ||
87 | |||
88 | if (of_have_populated_dt()) { | 82 | if (of_have_populated_dt()) { |
89 | err = w1_gpio_probe_dt(pdev); | 83 | err = w1_gpio_probe_dt(pdev); |
90 | if (err < 0) { | 84 | if (err < 0) { |
diff --git a/drivers/w1/slaves/w1_ds2408.c b/drivers/w1/slaves/w1_ds2408.c index e45eca1044bd..91cc2cdf02c0 100644 --- a/drivers/w1/slaves/w1_ds2408.c +++ b/drivers/w1/slaves/w1_ds2408.c | |||
@@ -22,6 +22,7 @@ | |||
22 | MODULE_LICENSE("GPL"); | 22 | MODULE_LICENSE("GPL"); |
23 | MODULE_AUTHOR("Jean-Francois Dagenais <dagenaisj@sonatest.com>"); | 23 | MODULE_AUTHOR("Jean-Francois Dagenais <dagenaisj@sonatest.com>"); |
24 | MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO"); | 24 | MODULE_DESCRIPTION("w1 family 29 driver for DS2408 8 Pin IO"); |
25 | MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2408)); | ||
25 | 26 | ||
26 | 27 | ||
27 | #define W1_F29_RETRIES 3 | 28 | #define W1_F29_RETRIES 3 |
diff --git a/drivers/w1/slaves/w1_ds2413.c b/drivers/w1/slaves/w1_ds2413.c index 829786252c6b..85937773a96a 100644 --- a/drivers/w1/slaves/w1_ds2413.c +++ b/drivers/w1/slaves/w1_ds2413.c | |||
@@ -23,6 +23,7 @@ | |||
23 | MODULE_LICENSE("GPL"); | 23 | MODULE_LICENSE("GPL"); |
24 | MODULE_AUTHOR("Mariusz Bialonczyk <manio@skyboo.net>"); | 24 | MODULE_AUTHOR("Mariusz Bialonczyk <manio@skyboo.net>"); |
25 | MODULE_DESCRIPTION("w1 family 3a driver for DS2413 2 Pin IO"); | 25 | MODULE_DESCRIPTION("w1 family 3a driver for DS2413 2 Pin IO"); |
26 | MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2413)); | ||
26 | 27 | ||
27 | #define W1_F3A_RETRIES 3 | 28 | #define W1_F3A_RETRIES 3 |
28 | #define W1_F3A_FUNC_PIO_ACCESS_READ 0xF5 | 29 | #define W1_F3A_FUNC_PIO_ACCESS_READ 0xF5 |
diff --git a/drivers/w1/slaves/w1_ds2423.c b/drivers/w1/slaves/w1_ds2423.c index 40a10b5ed120..7f86aec74088 100644 --- a/drivers/w1/slaves/w1_ds2423.c +++ b/drivers/w1/slaves/w1_ds2423.c | |||
@@ -164,3 +164,4 @@ module_exit(w1_f1d_exit); | |||
164 | MODULE_LICENSE("GPL"); | 164 | MODULE_LICENSE("GPL"); |
165 | MODULE_AUTHOR("Mika Laitio <lamikr@pilppa.org>"); | 165 | MODULE_AUTHOR("Mika Laitio <lamikr@pilppa.org>"); |
166 | MODULE_DESCRIPTION("w1 family 1d driver for DS2423, 4 counters and 4kb ram"); | 166 | MODULE_DESCRIPTION("w1 family 1d driver for DS2423, 4 counters and 4kb ram"); |
167 | MODULE_ALIAS("w1-family-" __stringify(W1_COUNTER_DS2423)); | ||
diff --git a/drivers/w1/slaves/w1_ds2431.c b/drivers/w1/slaves/w1_ds2431.c index 984b30331a45..cef8605e43ec 100644 --- a/drivers/w1/slaves/w1_ds2431.c +++ b/drivers/w1/slaves/w1_ds2431.c | |||
@@ -310,3 +310,4 @@ module_exit(w1_f2d_fini); | |||
310 | MODULE_LICENSE("GPL"); | 310 | MODULE_LICENSE("GPL"); |
311 | MODULE_AUTHOR("Bernhard Weirich <bernhard.weirich@riedel.net>"); | 311 | MODULE_AUTHOR("Bernhard Weirich <bernhard.weirich@riedel.net>"); |
312 | MODULE_DESCRIPTION("w1 family 2d driver for DS2431, 1kb EEPROM"); | 312 | MODULE_DESCRIPTION("w1 family 2d driver for DS2431, 1kb EEPROM"); |
313 | MODULE_ALIAS("w1-family-" __stringify(W1_EEPROM_DS2431)); | ||
diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c index 85f2cdb27fa2..10cc1b6176e6 100644 --- a/drivers/w1/slaves/w1_ds2433.c +++ b/drivers/w1/slaves/w1_ds2433.c | |||
@@ -29,6 +29,7 @@ | |||
29 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
30 | MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>"); | 30 | MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>"); |
31 | MODULE_DESCRIPTION("w1 family 23 driver for DS2433, 4kb EEPROM"); | 31 | MODULE_DESCRIPTION("w1 family 23 driver for DS2433, 4kb EEPROM"); |
32 | MODULE_ALIAS("w1-family-" __stringify(W1_EEPROM_DS2433)); | ||
32 | 33 | ||
33 | #define W1_EEPROM_SIZE 512 | 34 | #define W1_EEPROM_SIZE 512 |
34 | #define W1_PAGE_COUNT 16 | 35 | #define W1_PAGE_COUNT 16 |
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c index e86a69dc411e..93719d25d849 100644 --- a/drivers/w1/slaves/w1_ds2760.c +++ b/drivers/w1/slaves/w1_ds2760.c | |||
@@ -203,3 +203,4 @@ module_exit(w1_ds2760_exit); | |||
203 | MODULE_LICENSE("GPL"); | 203 | MODULE_LICENSE("GPL"); |
204 | MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>"); | 204 | MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>"); |
205 | MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip"); | 205 | MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip"); |
206 | MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2760)); | ||
diff --git a/drivers/w1/slaves/w1_ds2780.c b/drivers/w1/slaves/w1_ds2780.c index 98ed9c49cf50..0cd7a27b5d6b 100644 --- a/drivers/w1/slaves/w1_ds2780.c +++ b/drivers/w1/slaves/w1_ds2780.c | |||
@@ -188,3 +188,4 @@ module_exit(w1_ds2780_exit); | |||
188 | MODULE_LICENSE("GPL"); | 188 | MODULE_LICENSE("GPL"); |
189 | MODULE_AUTHOR("Clifton Barnes <cabarnes@indesign-llc.com>"); | 189 | MODULE_AUTHOR("Clifton Barnes <cabarnes@indesign-llc.com>"); |
190 | MODULE_DESCRIPTION("1-wire Driver for Maxim/Dallas DS2780 Stand-Alone Fuel Gauge IC"); | 190 | MODULE_DESCRIPTION("1-wire Driver for Maxim/Dallas DS2780 Stand-Alone Fuel Gauge IC"); |
191 | MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2780)); | ||
diff --git a/drivers/w1/slaves/w1_ds2781.c b/drivers/w1/slaves/w1_ds2781.c index 5140d7be67ab..1aba8e41ad46 100644 --- a/drivers/w1/slaves/w1_ds2781.c +++ b/drivers/w1/slaves/w1_ds2781.c | |||
@@ -186,3 +186,4 @@ module_exit(w1_ds2781_exit); | |||
186 | MODULE_LICENSE("GPL"); | 186 | MODULE_LICENSE("GPL"); |
187 | MODULE_AUTHOR("Renata Sayakhova <renata@oktetlabs.ru>"); | 187 | MODULE_AUTHOR("Renata Sayakhova <renata@oktetlabs.ru>"); |
188 | MODULE_DESCRIPTION("1-wire Driver for Maxim/Dallas DS2781 Stand-Alone Fuel Gauge IC"); | 188 | MODULE_DESCRIPTION("1-wire Driver for Maxim/Dallas DS2781 Stand-Alone Fuel Gauge IC"); |
189 | MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2781)); | ||
diff --git a/drivers/w1/slaves/w1_ds28e04.c b/drivers/w1/slaves/w1_ds28e04.c index 98117db595bb..cd30a6d95ea5 100644 --- a/drivers/w1/slaves/w1_ds28e04.c +++ b/drivers/w1/slaves/w1_ds28e04.c | |||
@@ -27,6 +27,7 @@ | |||
27 | MODULE_LICENSE("GPL"); | 27 | MODULE_LICENSE("GPL"); |
28 | MODULE_AUTHOR("Markus Franke <franke.m@sebakmt.com>, <franm@hrz.tu-chemnitz.de>"); | 28 | MODULE_AUTHOR("Markus Franke <franke.m@sebakmt.com>, <franm@hrz.tu-chemnitz.de>"); |
29 | MODULE_DESCRIPTION("w1 family 1C driver for DS28E04, 4kb EEPROM and PIO"); | 29 | MODULE_DESCRIPTION("w1 family 1C driver for DS28E04, 4kb EEPROM and PIO"); |
30 | MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS28E04)); | ||
30 | 31 | ||
31 | /* Allow the strong pullup to be disabled, but default to enabled. | 32 | /* Allow the strong pullup to be disabled, but default to enabled. |
32 | * If it was disabled a parasite powered device might not get the required | 33 | * If it was disabled a parasite powered device might not get the required |
diff --git a/drivers/w1/slaves/w1_smem.c b/drivers/w1/slaves/w1_smem.c index 84655625c870..ed4c87506def 100644 --- a/drivers/w1/slaves/w1_smem.c +++ b/drivers/w1/slaves/w1_smem.c | |||
@@ -34,6 +34,8 @@ | |||
34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
35 | MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); | 35 | MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); |
36 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family."); | 36 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family."); |
37 | MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_SMEM_01)); | ||
38 | MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_SMEM_81)); | ||
37 | 39 | ||
38 | static struct w1_family w1_smem_family_01 = { | 40 | static struct w1_family w1_smem_family_01 = { |
39 | .fid = W1_FAMILY_SMEM_01, | 41 | .fid = W1_FAMILY_SMEM_01, |
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index c1a702f8c803..8978360bd387 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c | |||
@@ -36,6 +36,11 @@ | |||
36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
37 | MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); | 37 | MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); |
38 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family."); | 38 | MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family."); |
39 | MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS18S20)); | ||
40 | MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS1822)); | ||
41 | MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS18B20)); | ||
42 | MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS1825)); | ||
43 | MODULE_ALIAS("w1-family-" __stringify(W1_THERM_DS28EA00)); | ||
39 | 44 | ||
40 | /* Allow the strong pullup to be disabled, but default to enabled. | 45 | /* Allow the strong pullup to be disabled, but default to enabled. |
41 | * If it was disabled a parasite powered device might not get the require | 46 | * If it was disabled a parasite powered device might not get the require |
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 7ce277d2bb67..0459df843c58 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
@@ -680,6 +680,8 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) | |||
680 | atomic_set(&sl->refcnt, 0); | 680 | atomic_set(&sl->refcnt, 0); |
681 | init_completion(&sl->released); | 681 | init_completion(&sl->released); |
682 | 682 | ||
683 | request_module("w1-family-0x%0x", rn->family); | ||
684 | |||
683 | spin_lock(&w1_flock); | 685 | spin_lock(&w1_flock); |
684 | f = w1_family_registered(rn->family); | 686 | f = w1_family_registered(rn->family); |
685 | if (!f) { | 687 | if (!f) { |
diff --git a/include/linux/fmc-sdb.h b/include/linux/fmc-sdb.h new file mode 100644 index 000000000000..1974317a9b3d --- /dev/null +++ b/include/linux/fmc-sdb.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * This file is separate from sdb.h, because I want that one to remain | ||
3 | * unchanged (as far as possible) from the official sdb distribution | ||
4 | * | ||
5 | * This file and associated functionality are a playground for me to | ||
6 | * understand stuff which will later be implemented in more generic places. | ||
7 | */ | ||
8 | #include <linux/sdb.h> | ||
9 | |||
10 | /* This is the union of all currently defined types */ | ||
11 | union sdb_record { | ||
12 | struct sdb_interconnect ic; | ||
13 | struct sdb_device dev; | ||
14 | struct sdb_bridge bridge; | ||
15 | struct sdb_integration integr; | ||
16 | struct sdb_empty empty; | ||
17 | }; | ||
18 | |||
19 | struct fmc_device; | ||
20 | |||
21 | /* Every sdb table is turned into this structure */ | ||
22 | struct sdb_array { | ||
23 | int len; | ||
24 | int level; | ||
25 | unsigned long baseaddr; | ||
26 | struct fmc_device *fmc; /* the device that hosts it */ | ||
27 | struct sdb_array *parent; /* NULL at root */ | ||
28 | union sdb_record *record; /* copies of the struct */ | ||
29 | struct sdb_array **subtree; /* only valid for bridge items */ | ||
30 | }; | ||
31 | |||
32 | extern int fmc_scan_sdb_tree(struct fmc_device *fmc, unsigned long address); | ||
33 | extern void fmc_show_sdb_tree(const struct fmc_device *fmc); | ||
34 | extern signed long fmc_find_sdb_device(struct sdb_array *tree, uint64_t vendor, | ||
35 | uint32_t device, unsigned long *sz); | ||
36 | extern int fmc_free_sdb_tree(struct fmc_device *fmc); | ||
diff --git a/include/linux/fmc.h b/include/linux/fmc.h new file mode 100644 index 000000000000..a5f0aa5c2a8d --- /dev/null +++ b/include/linux/fmc.h | |||
@@ -0,0 +1,237 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 CERN (www.cern.ch) | ||
3 | * Author: Alessandro Rubini <rubini@gnudd.com> | ||
4 | * | ||
5 | * Released according to the GNU GPL, version 2 or any later version. | ||
6 | * | ||
7 | * This work is part of the White Rabbit project, a research effort led | ||
8 | * by CERN, the European Institute for Nuclear Research. | ||
9 | */ | ||
10 | #ifndef __LINUX_FMC_H__ | ||
11 | #define __LINUX_FMC_H__ | ||
12 | #include <linux/types.h> | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/list.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/io.h> | ||
18 | |||
19 | struct fmc_device; | ||
20 | struct fmc_driver; | ||
21 | |||
22 | /* | ||
23 | * This bus abstraction is developed separately from drivers, so we need | ||
24 | * to check the version of the data structures we receive. | ||
25 | */ | ||
26 | |||
27 | #define FMC_MAJOR 3 | ||
28 | #define FMC_MINOR 0 | ||
29 | #define FMC_VERSION ((FMC_MAJOR << 16) | FMC_MINOR) | ||
30 | #define __FMC_MAJOR(x) ((x) >> 16) | ||
31 | #define __FMC_MINOR(x) ((x) & 0xffff) | ||
32 | |||
33 | /* | ||
34 | * The device identification, as defined by the IPMI FRU (Field Replaceable | ||
35 | * Unit) includes four different strings to describe the device. Here we | ||
36 | * only match the "Board Manufacturer" and the "Board Product Name", | ||
37 | * ignoring the "Board Serial Number" and "Board Part Number". All 4 are | ||
38 | * expected to be strings, so they are treated as zero-terminated C strings. | ||
39 | * Unspecified string (NULL) means "any", so if both are unspecified this | ||
40 | * is a catch-all driver. So null entries are allowed and we use array | ||
41 | * and length. This is unlike pci and usb that use null-terminated arrays | ||
42 | */ | ||
43 | struct fmc_fru_id { | ||
44 | char *manufacturer; | ||
45 | char *product_name; | ||
46 | }; | ||
47 | |||
48 | /* | ||
49 | * If the FPGA is already programmed (think Etherbone or the second | ||
50 | * SVEC slot), we can match on SDB devices in the memory image. This | ||
51 | * match uses an array of devices that must all be present, and the | ||
52 | * match is based on vendor and device only. Further checks are expected | ||
53 | * to happen in the probe function. Zero means "any" and catch-all is allowed. | ||
54 | */ | ||
55 | struct fmc_sdb_one_id { | ||
56 | uint64_t vendor; | ||
57 | uint32_t device; | ||
58 | }; | ||
59 | struct fmc_sdb_id { | ||
60 | struct fmc_sdb_one_id *cores; | ||
61 | int cores_nr; | ||
62 | }; | ||
63 | |||
64 | struct fmc_device_id { | ||
65 | struct fmc_fru_id *fru_id; | ||
66 | int fru_id_nr; | ||
67 | struct fmc_sdb_id *sdb_id; | ||
68 | int sdb_id_nr; | ||
69 | }; | ||
70 | |||
71 | /* This sizes the module_param_array used by generic module parameters */ | ||
72 | #define FMC_MAX_CARDS 32 | ||
73 | |||
74 | /* The driver is a pretty simple thing */ | ||
75 | struct fmc_driver { | ||
76 | unsigned long version; | ||
77 | struct device_driver driver; | ||
78 | int (*probe)(struct fmc_device *); | ||
79 | int (*remove)(struct fmc_device *); | ||
80 | const struct fmc_device_id id_table; | ||
81 | /* What follows is for generic module parameters */ | ||
82 | int busid_n; | ||
83 | int busid_val[FMC_MAX_CARDS]; | ||
84 | int gw_n; | ||
85 | char *gw_val[FMC_MAX_CARDS]; | ||
86 | }; | ||
87 | #define to_fmc_driver(x) container_of((x), struct fmc_driver, driver) | ||
88 | |||
89 | /* These are the generic parameters, that drivers may instantiate */ | ||
90 | #define FMC_PARAM_BUSID(_d) \ | ||
91 | module_param_array_named(busid, _d.busid_val, int, &_d.busid_n, 0444) | ||
92 | #define FMC_PARAM_GATEWARE(_d) \ | ||
93 | module_param_array_named(gateware, _d.gw_val, charp, &_d.gw_n, 0444) | ||
94 | |||
95 | /* | ||
96 | * Drivers may need to configure gpio pins in the carrier. To read input | ||
97 | * (a very uncommon operation, and definitely not in the hot paths), just | ||
98 | * configure one gpio only and get 0 or 1 as retval of the config method | ||
99 | */ | ||
100 | struct fmc_gpio { | ||
101 | char *carrier_name; /* name or NULL for virtual pins */ | ||
102 | int gpio; | ||
103 | int _gpio; /* internal use by the carrier */ | ||
104 | int mode; /* GPIOF_DIR_OUT etc, from <linux/gpio.h> */ | ||
105 | int irqmode; /* IRQF_TRIGGER_LOW and so on */ | ||
106 | }; | ||
107 | |||
108 | /* The numbering of gpio pins allows access to raw pins or virtual roles */ | ||
109 | #define FMC_GPIO_RAW(x) (x) /* 4096 of them */ | ||
110 | #define __FMC_GPIO_IS_RAW(x) ((x) < 0x1000) | ||
111 | #define FMC_GPIO_IRQ(x) ((x) + 0x1000) /* 256 of them */ | ||
112 | #define FMC_GPIO_LED(x) ((x) + 0x1100) /* 256 of them */ | ||
113 | #define FMC_GPIO_KEY(x) ((x) + 0x1200) /* 256 of them */ | ||
114 | #define FMC_GPIO_TP(x) ((x) + 0x1300) /* 256 of them */ | ||
115 | #define FMC_GPIO_USER(x) ((x) + 0x1400) /* 256 of them */ | ||
116 | /* We may add SCL and SDA, or other roles if the need arises */ | ||
117 | |||
118 | /* GPIOF_DIR_IN etc are missing before 3.0. copy from <linux/gpio.h> */ | ||
119 | #ifndef GPIOF_DIR_IN | ||
120 | # define GPIOF_DIR_OUT (0 << 0) | ||
121 | # define GPIOF_DIR_IN (1 << 0) | ||
122 | # define GPIOF_INIT_LOW (0 << 1) | ||
123 | # define GPIOF_INIT_HIGH (1 << 1) | ||
124 | #endif | ||
125 | |||
126 | /* | ||
127 | * The operations are offered by each carrier and should make driver | ||
128 | * design completely independent of the carrier. Named GPIO pins may be | ||
129 | * the exception. | ||
130 | */ | ||
131 | struct fmc_operations { | ||
132 | uint32_t (*read32)(struct fmc_device *fmc, int offset); | ||
133 | void (*write32)(struct fmc_device *fmc, uint32_t value, int offset); | ||
134 | int (*validate)(struct fmc_device *fmc, struct fmc_driver *drv); | ||
135 | int (*reprogram)(struct fmc_device *f, struct fmc_driver *d, char *gw); | ||
136 | int (*irq_request)(struct fmc_device *fmc, irq_handler_t h, | ||
137 | char *name, int flags); | ||
138 | void (*irq_ack)(struct fmc_device *fmc); | ||
139 | int (*irq_free)(struct fmc_device *fmc); | ||
140 | int (*gpio_config)(struct fmc_device *fmc, struct fmc_gpio *gpio, | ||
141 | int ngpio); | ||
142 | int (*read_ee)(struct fmc_device *fmc, int pos, void *d, int l); | ||
143 | int (*write_ee)(struct fmc_device *fmc, int pos, const void *d, int l); | ||
144 | }; | ||
145 | |||
146 | /* Prefer this helper rather than calling of fmc->reprogram directly */ | ||
147 | extern int fmc_reprogram(struct fmc_device *f, struct fmc_driver *d, char *gw, | ||
148 | int sdb_entry); | ||
149 | |||
150 | /* | ||
151 | * The device reports all information needed to access hw. | ||
152 | * | ||
153 | * If we have eeprom_len and not contents, the core reads it. | ||
154 | * Then, parsing of identifiers is done by the core which fills fmc_fru_id.. | ||
155 | * Similarly a device that must be matched based on SDB cores must | ||
156 | * fill the entry point and the core will scan the bus (FIXME: sdb match) | ||
157 | */ | ||
158 | struct fmc_device { | ||
159 | unsigned long version; | ||
160 | unsigned long flags; | ||
161 | struct module *owner; /* char device must pin it */ | ||
162 | struct fmc_fru_id id; /* for EEPROM-based match */ | ||
163 | struct fmc_operations *op; /* carrier-provided */ | ||
164 | int irq; /* according to host bus. 0 == none */ | ||
165 | int eeprom_len; /* Usually 8kB, may be less */ | ||
166 | int eeprom_addr; /* 0x50, 0x52 etc */ | ||
167 | uint8_t *eeprom; /* Full contents or leading part */ | ||
168 | char *carrier_name; /* "SPEC" or similar, for special use */ | ||
169 | void *carrier_data; /* "struct spec *" or equivalent */ | ||
170 | __iomem void *fpga_base; /* May be NULL (Etherbone) */ | ||
171 | __iomem void *slot_base; /* Set by the driver */ | ||
172 | struct fmc_device **devarray; /* Allocated by the bus */ | ||
173 | int slot_id; /* Index in the slot array */ | ||
174 | int nr_slots; /* Number of slots in this carrier */ | ||
175 | unsigned long memlen; /* Used for the char device */ | ||
176 | struct device dev; /* For Linux use */ | ||
177 | struct device *hwdev; /* The underlying hardware device */ | ||
178 | unsigned long sdbfs_entry; | ||
179 | struct sdb_array *sdb; | ||
180 | uint32_t device_id; /* Filled by the device */ | ||
181 | char *mezzanine_name; /* Defaults to ``fmc'' */ | ||
182 | void *mezzanine_data; | ||
183 | }; | ||
184 | #define to_fmc_device(x) container_of((x), struct fmc_device, dev) | ||
185 | |||
186 | #define FMC_DEVICE_HAS_GOLDEN 1 | ||
187 | #define FMC_DEVICE_HAS_CUSTOM 2 | ||
188 | #define FMC_DEVICE_NO_MEZZANINE 4 | ||
189 | #define FMC_DEVICE_MATCH_SDB 8 /* fmc-core must scan sdb in fpga */ | ||
190 | |||
191 | /* | ||
192 | * If fpga_base can be used, the carrier offers no readl/writel methods, and | ||
193 | * this expands to a single, fast, I/O access. | ||
194 | */ | ||
195 | static inline uint32_t fmc_readl(struct fmc_device *fmc, int offset) | ||
196 | { | ||
197 | if (unlikely(fmc->op->read32)) | ||
198 | return fmc->op->read32(fmc, offset); | ||
199 | return readl(fmc->fpga_base + offset); | ||
200 | } | ||
201 | static inline void fmc_writel(struct fmc_device *fmc, uint32_t val, int off) | ||
202 | { | ||
203 | if (unlikely(fmc->op->write32)) | ||
204 | fmc->op->write32(fmc, val, off); | ||
205 | else | ||
206 | writel(val, fmc->fpga_base + off); | ||
207 | } | ||
208 | |||
209 | /* pci-like naming */ | ||
210 | static inline void *fmc_get_drvdata(const struct fmc_device *fmc) | ||
211 | { | ||
212 | return dev_get_drvdata(&fmc->dev); | ||
213 | } | ||
214 | |||
215 | static inline void fmc_set_drvdata(struct fmc_device *fmc, void *data) | ||
216 | { | ||
217 | dev_set_drvdata(&fmc->dev, data); | ||
218 | } | ||
219 | |||
220 | /* The 4 access points */ | ||
221 | extern int fmc_driver_register(struct fmc_driver *drv); | ||
222 | extern void fmc_driver_unregister(struct fmc_driver *drv); | ||
223 | extern int fmc_device_register(struct fmc_device *tdev); | ||
224 | extern void fmc_device_unregister(struct fmc_device *tdev); | ||
225 | |||
226 | /* Two more for device sets, all driven by the same FPGA */ | ||
227 | extern int fmc_device_register_n(struct fmc_device **devs, int n); | ||
228 | extern void fmc_device_unregister_n(struct fmc_device **devs, int n); | ||
229 | |||
230 | /* Internal cross-calls between files; not exported to other modules */ | ||
231 | extern int fmc_match(struct device *dev, struct device_driver *drv); | ||
232 | extern int fmc_fill_id_info(struct fmc_device *fmc); | ||
233 | extern void fmc_free_id_info(struct fmc_device *fmc); | ||
234 | extern void fmc_dump_eeprom(const struct fmc_device *fmc); | ||
235 | extern void fmc_dump_sdb(const struct fmc_device *fmc); | ||
236 | |||
237 | #endif /* __LINUX_FMC_H__ */ | ||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index c2559847d7ee..fae8bac907ef 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h | |||
@@ -909,6 +909,7 @@ enum vmbus_channel_state { | |||
909 | CHANNEL_OFFER_STATE, | 909 | CHANNEL_OFFER_STATE, |
910 | CHANNEL_OPENING_STATE, | 910 | CHANNEL_OPENING_STATE, |
911 | CHANNEL_OPEN_STATE, | 911 | CHANNEL_OPEN_STATE, |
912 | CHANNEL_OPENED_STATE, | ||
912 | }; | 913 | }; |
913 | 914 | ||
914 | struct vmbus_channel_debug_info { | 915 | struct vmbus_channel_debug_info { |
@@ -1046,6 +1047,38 @@ struct vmbus_channel { | |||
1046 | * preserve the earlier behavior. | 1047 | * preserve the earlier behavior. |
1047 | */ | 1048 | */ |
1048 | u32 target_vp; | 1049 | u32 target_vp; |
1050 | /* | ||
1051 | * Support for sub-channels. For high performance devices, | ||
1052 | * it will be useful to have multiple sub-channels to support | ||
1053 | * a scalable communication infrastructure with the host. | ||
1054 | * The support for sub-channels is implemented as an extention | ||
1055 | * to the current infrastructure. | ||
1056 | * The initial offer is considered the primary channel and this | ||
1057 | * offer message will indicate if the host supports sub-channels. | ||
1058 | * The guest is free to ask for sub-channels to be offerred and can | ||
1059 | * open these sub-channels as a normal "primary" channel. However, | ||
1060 | * all sub-channels will have the same type and instance guids as the | ||
1061 | * primary channel. Requests sent on a given channel will result in a | ||
1062 | * response on the same channel. | ||
1063 | */ | ||
1064 | |||
1065 | /* | ||
1066 | * Sub-channel creation callback. This callback will be called in | ||
1067 | * process context when a sub-channel offer is received from the host. | ||
1068 | * The guest can open the sub-channel in the context of this callback. | ||
1069 | */ | ||
1070 | void (*sc_creation_callback)(struct vmbus_channel *new_sc); | ||
1071 | |||
1072 | spinlock_t sc_lock; | ||
1073 | /* | ||
1074 | * All Sub-channels of a primary channel are linked here. | ||
1075 | */ | ||
1076 | struct list_head sc_list; | ||
1077 | /* | ||
1078 | * The primary channel this sub-channel belongs to. | ||
1079 | * This will be NULL for the primary channel. | ||
1080 | */ | ||
1081 | struct vmbus_channel *primary_channel; | ||
1049 | }; | 1082 | }; |
1050 | 1083 | ||
1051 | static inline void set_channel_read_state(struct vmbus_channel *c, bool state) | 1084 | static inline void set_channel_read_state(struct vmbus_channel *c, bool state) |
@@ -1057,6 +1090,34 @@ void vmbus_onmessage(void *context); | |||
1057 | 1090 | ||
1058 | int vmbus_request_offers(void); | 1091 | int vmbus_request_offers(void); |
1059 | 1092 | ||
1093 | /* | ||
1094 | * APIs for managing sub-channels. | ||
1095 | */ | ||
1096 | |||
1097 | void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel, | ||
1098 | void (*sc_cr_cb)(struct vmbus_channel *new_sc)); | ||
1099 | |||
1100 | /* | ||
1101 | * Retrieve the (sub) channel on which to send an outgoing request. | ||
1102 | * When a primary channel has multiple sub-channels, we choose a | ||
1103 | * channel whose VCPU binding is closest to the VCPU on which | ||
1104 | * this call is being made. | ||
1105 | */ | ||
1106 | struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary); | ||
1107 | |||
1108 | /* | ||
1109 | * Check if sub-channels have already been offerred. This API will be useful | ||
1110 | * when the driver is unloaded after establishing sub-channels. In this case, | ||
1111 | * when the driver is re-loaded, the driver would have to check if the | ||
1112 | * subchannels have already been established before attempting to request | ||
1113 | * the creation of sub-channels. | ||
1114 | * This function returns TRUE to indicate that subchannels have already been | ||
1115 | * created. | ||
1116 | * This function should be invoked after setting the callback function for | ||
1117 | * sub-channel creation. | ||
1118 | */ | ||
1119 | bool vmbus_are_subchannels_present(struct vmbus_channel *primary); | ||
1120 | |||
1060 | /* The format must be the same as struct vmdata_gpa_direct */ | 1121 | /* The format must be the same as struct vmdata_gpa_direct */ |
1061 | struct vmbus_channel_packet_page_buffer { | 1122 | struct vmbus_channel_packet_page_buffer { |
1062 | u16 type; | 1123 | u16 type; |
@@ -1327,6 +1388,15 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver); | |||
1327 | 0x8e, 0x77, 0x05, 0x58, 0xeb, 0x10, 0x73, 0xf8 \ | 1388 | 0x8e, 0x77, 0x05, 0x58, 0xeb, 0x10, 0x73, 0xf8 \ |
1328 | } | 1389 | } |
1329 | 1390 | ||
1391 | /* | ||
1392 | * Synthetic FC GUID | ||
1393 | * {2f9bcc4a-0069-4af3-b76b-6fd0be528cda} | ||
1394 | */ | ||
1395 | #define HV_SYNTHFC_GUID \ | ||
1396 | .guid = { \ | ||
1397 | 0x4A, 0xCC, 0x9B, 0x2F, 0x69, 0x00, 0xF3, 0x4A, \ | ||
1398 | 0xB7, 0x6B, 0x6F, 0xD0, 0xBE, 0x52, 0x8C, 0xDA \ | ||
1399 | } | ||
1330 | 1400 | ||
1331 | /* | 1401 | /* |
1332 | * Common header for Hyper-V ICs | 1402 | * Common header for Hyper-V ICs |
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 12b4d55a02af..d5569734f672 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h | |||
@@ -30,7 +30,6 @@ static inline struct ethhdr *eth_hdr(const struct sk_buff *skb) | |||
30 | 30 | ||
31 | int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr); | 31 | int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr); |
32 | 32 | ||
33 | int mac_pton(const char *s, u8 *mac); | ||
34 | extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); | 33 | extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); |
35 | 34 | ||
36 | #endif /* _LINUX_IF_ETHER_H */ | 35 | #endif /* _LINUX_IF_ETHER_H */ |
diff --git a/include/linux/ipmi-fru.h b/include/linux/ipmi-fru.h new file mode 100644 index 000000000000..4d3a76380e32 --- /dev/null +++ b/include/linux/ipmi-fru.h | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 CERN (www.cern.ch) | ||
3 | * Author: Alessandro Rubini <rubini@gnudd.com> | ||
4 | * | ||
5 | * Released according to the GNU GPL, version 2 or any later version. | ||
6 | * | ||
7 | * This work is part of the White Rabbit project, a research effort led | ||
8 | * by CERN, the European Institute for Nuclear Research. | ||
9 | */ | ||
10 | #ifndef __LINUX_IPMI_FRU_H__ | ||
11 | #define __LINUX_IPMI_FRU_H__ | ||
12 | #ifdef __KERNEL__ | ||
13 | # include <linux/types.h> | ||
14 | # include <linux/string.h> | ||
15 | #else | ||
16 | # include <stdint.h> | ||
17 | # include <string.h> | ||
18 | #endif | ||
19 | |||
20 | /* | ||
21 | * These structures match the unaligned crap we have in FRU1011.pdf | ||
22 | * (http://download.intel.com/design/servers/ipmi/FRU1011.pdf) | ||
23 | */ | ||
24 | |||
25 | /* chapter 8, page 5 */ | ||
26 | struct fru_common_header { | ||
27 | uint8_t format; /* 0x01 */ | ||
28 | uint8_t internal_use_off; /* multiple of 8 bytes */ | ||
29 | uint8_t chassis_info_off; /* multiple of 8 bytes */ | ||
30 | uint8_t board_area_off; /* multiple of 8 bytes */ | ||
31 | uint8_t product_area_off; /* multiple of 8 bytes */ | ||
32 | uint8_t multirecord_off; /* multiple of 8 bytes */ | ||
33 | uint8_t pad; /* must be 0 */ | ||
34 | uint8_t checksum; /* sum modulo 256 must be 0 */ | ||
35 | }; | ||
36 | |||
37 | /* chapter 9, page 5 -- internal_use: not used by us */ | ||
38 | |||
39 | /* chapter 10, page 6 -- chassis info: not used by us */ | ||
40 | |||
41 | /* chapter 13, page 9 -- used by board_info_area below */ | ||
42 | struct fru_type_length { | ||
43 | uint8_t type_length; | ||
44 | uint8_t data[0]; | ||
45 | }; | ||
46 | |||
47 | /* chapter 11, page 7 */ | ||
48 | struct fru_board_info_area { | ||
49 | uint8_t format; /* 0x01 */ | ||
50 | uint8_t area_len; /* multiple of 8 bytes */ | ||
51 | uint8_t language; /* I hope it's 0 */ | ||
52 | uint8_t mfg_date[3]; /* LSB, minutes since 1996-01-01 */ | ||
53 | struct fru_type_length tl[0]; /* type-length stuff follows */ | ||
54 | |||
55 | /* | ||
56 | * the TL there are in order: | ||
57 | * Board Manufacturer | ||
58 | * Board Product Name | ||
59 | * Board Serial Number | ||
60 | * Board Part Number | ||
61 | * FRU File ID (may be null) | ||
62 | * more manufacturer-specific stuff | ||
63 | * 0xc1 as a terminator | ||
64 | * 0x00 pad to a multiple of 8 bytes - 1 | ||
65 | * checksum (sum of all stuff module 256 must be zero) | ||
66 | */ | ||
67 | }; | ||
68 | |||
69 | enum fru_type { | ||
70 | FRU_TYPE_BINARY = 0x00, | ||
71 | FRU_TYPE_BCDPLUS = 0x40, | ||
72 | FRU_TYPE_ASCII6 = 0x80, | ||
73 | FRU_TYPE_ASCII = 0xc0, /* not ascii: depends on language */ | ||
74 | }; | ||
75 | |||
76 | /* | ||
77 | * some helpers | ||
78 | */ | ||
79 | static inline struct fru_board_info_area *fru_get_board_area( | ||
80 | const struct fru_common_header *header) | ||
81 | { | ||
82 | /* we know for sure that the header is 8 bytes in size */ | ||
83 | return (struct fru_board_info_area *)(header + header->board_area_off); | ||
84 | } | ||
85 | |||
86 | static inline int fru_type(struct fru_type_length *tl) | ||
87 | { | ||
88 | return tl->type_length & 0xc0; | ||
89 | } | ||
90 | |||
91 | static inline int fru_length(struct fru_type_length *tl) | ||
92 | { | ||
93 | return (tl->type_length & 0x3f) + 1; /* len of whole record */ | ||
94 | } | ||
95 | |||
96 | /* assume ascii-latin1 encoding */ | ||
97 | static inline int fru_strlen(struct fru_type_length *tl) | ||
98 | { | ||
99 | return fru_length(tl) - 1; | ||
100 | } | ||
101 | |||
102 | static inline char *fru_strcpy(char *dest, struct fru_type_length *tl) | ||
103 | { | ||
104 | int len = fru_strlen(tl); | ||
105 | memcpy(dest, tl->data, len); | ||
106 | dest[len] = '\0'; | ||
107 | return dest; | ||
108 | } | ||
109 | |||
110 | static inline struct fru_type_length *fru_next_tl(struct fru_type_length *tl) | ||
111 | { | ||
112 | return tl + fru_length(tl); | ||
113 | } | ||
114 | |||
115 | static inline int fru_is_eof(struct fru_type_length *tl) | ||
116 | { | ||
117 | return tl->type_length == 0xc1; | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * External functions defined in fru-parse.c. | ||
122 | */ | ||
123 | extern int fru_header_cksum_ok(struct fru_common_header *header); | ||
124 | extern int fru_bia_cksum_ok(struct fru_board_info_area *bia); | ||
125 | |||
126 | /* All these 4 return allocated strings by calling fru_alloc() */ | ||
127 | extern char *fru_get_board_manufacturer(struct fru_common_header *header); | ||
128 | extern char *fru_get_product_name(struct fru_common_header *header); | ||
129 | extern char *fru_get_serial_number(struct fru_common_header *header); | ||
130 | extern char *fru_get_part_number(struct fru_common_header *header); | ||
131 | |||
132 | /* This must be defined by the caller of the above functions */ | ||
133 | extern void *fru_alloc(size_t size); | ||
134 | |||
135 | #endif /* __LINUX_IMPI_FRU_H__ */ | ||
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index e9ef6d6b51d5..3afb969441d1 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -450,6 +450,8 @@ static inline char * __deprecated pack_hex_byte(char *buf, u8 byte) | |||
450 | extern int hex_to_bin(char ch); | 450 | extern int hex_to_bin(char ch); |
451 | extern int __must_check hex2bin(u8 *dst, const char *src, size_t count); | 451 | extern int __must_check hex2bin(u8 *dst, const char *src, size_t count); |
452 | 452 | ||
453 | int mac_pton(const char *s, u8 *mac); | ||
454 | |||
453 | /* | 455 | /* |
454 | * General tracing related utility functions - trace_printk(), | 456 | * General tracing related utility functions - trace_printk(), |
455 | * tracing_on/tracing_off and tracing_start()/tracing_stop | 457 | * tracing_on/tracing_off and tracing_start()/tracing_stop |
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h index 8f21daf62fb5..9b81b2bdc46b 100644 --- a/include/linux/mfd/palmas.h +++ b/include/linux/mfd/palmas.h | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/leds.h> | 20 | #include <linux/leds.h> |
21 | #include <linux/regmap.h> | 21 | #include <linux/regmap.h> |
22 | #include <linux/regulator/driver.h> | 22 | #include <linux/regulator/driver.h> |
23 | #include <linux/extcon.h> | ||
24 | #include <linux/usb/phy_companion.h> | ||
23 | 25 | ||
24 | #define PALMAS_NUM_CLIENTS 3 | 26 | #define PALMAS_NUM_CLIENTS 3 |
25 | 27 | ||
@@ -37,6 +39,12 @@ struct palmas_gpadc; | |||
37 | struct palmas_resource; | 39 | struct palmas_resource; |
38 | struct palmas_usb; | 40 | struct palmas_usb; |
39 | 41 | ||
42 | enum palmas_usb_state { | ||
43 | PALMAS_USB_STATE_DISCONNECT, | ||
44 | PALMAS_USB_STATE_VBUS, | ||
45 | PALMAS_USB_STATE_ID, | ||
46 | }; | ||
47 | |||
40 | struct palmas { | 48 | struct palmas { |
41 | struct device *dev; | 49 | struct device *dev; |
42 | 50 | ||
@@ -180,9 +188,6 @@ struct palmas_pmic_platform_data { | |||
180 | }; | 188 | }; |
181 | 189 | ||
182 | struct palmas_usb_platform_data { | 190 | struct palmas_usb_platform_data { |
183 | /* Set this if platform wishes its own vbus control */ | ||
184 | int no_control_vbus; | ||
185 | |||
186 | /* Do we enable the wakeup comparator on probe */ | 191 | /* Do we enable the wakeup comparator on probe */ |
187 | int wakeup; | 192 | int wakeup; |
188 | }; | 193 | }; |
@@ -350,22 +355,19 @@ struct palmas_usb { | |||
350 | struct palmas *palmas; | 355 | struct palmas *palmas; |
351 | struct device *dev; | 356 | struct device *dev; |
352 | 357 | ||
353 | /* for vbus reporting with irqs disabled */ | 358 | struct extcon_dev edev; |
354 | spinlock_t lock; | ||
355 | |||
356 | struct regulator *vbus_reg; | ||
357 | 359 | ||
358 | /* used to set vbus, in atomic path */ | 360 | /* used to set vbus, in atomic path */ |
359 | struct work_struct set_vbus_work; | 361 | struct work_struct set_vbus_work; |
360 | 362 | ||
361 | int irq1; | 363 | int id_otg_irq; |
362 | int irq2; | 364 | int id_irq; |
363 | int irq3; | 365 | int vbus_otg_irq; |
364 | int irq4; | 366 | int vbus_irq; |
365 | 367 | ||
366 | int vbus_enable; | 368 | int vbus_enable; |
367 | 369 | ||
368 | u8 linkstat; | 370 | enum palmas_usb_state linkstat; |
369 | }; | 371 | }; |
370 | 372 | ||
371 | #define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator) | 373 | #define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator) |
diff --git a/include/linux/sdb.h b/include/linux/sdb.h new file mode 100644 index 000000000000..fbb76a46c8a5 --- /dev/null +++ b/include/linux/sdb.h | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * This is the official version 1.1 of sdb.h | ||
3 | */ | ||
4 | #ifndef __SDB_H__ | ||
5 | #define __SDB_H__ | ||
6 | #ifdef __KERNEL__ | ||
7 | #include <linux/types.h> | ||
8 | #else | ||
9 | #include <stdint.h> | ||
10 | #endif | ||
11 | |||
12 | /* | ||
13 | * All structures are 64 bytes long and are expected | ||
14 | * to live in an array, one for each interconnect. | ||
15 | * Most fields of the structures are shared among the | ||
16 | * various types, and most-specific fields are at the | ||
17 | * beginning (for alignment reasons, and to keep the | ||
18 | * magic number at the head of the interconnect record | ||
19 | */ | ||
20 | |||
21 | /* Product, 40 bytes at offset 24, 8-byte aligned | ||
22 | * | ||
23 | * device_id is vendor-assigned; version is device-specific, | ||
24 | * date is hex (e.g 0x20120501), name is UTF-8, blank-filled | ||
25 | * and not terminated with a 0 byte. | ||
26 | */ | ||
27 | struct sdb_product { | ||
28 | uint64_t vendor_id; /* 0x18..0x1f */ | ||
29 | uint32_t device_id; /* 0x20..0x23 */ | ||
30 | uint32_t version; /* 0x24..0x27 */ | ||
31 | uint32_t date; /* 0x28..0x2b */ | ||
32 | uint8_t name[19]; /* 0x2c..0x3e */ | ||
33 | uint8_t record_type; /* 0x3f */ | ||
34 | }; | ||
35 | |||
36 | /* | ||
37 | * Component, 56 bytes at offset 8, 8-byte aligned | ||
38 | * | ||
39 | * The address range is first to last, inclusive | ||
40 | * (for example 0x100000 - 0x10ffff) | ||
41 | */ | ||
42 | struct sdb_component { | ||
43 | uint64_t addr_first; /* 0x08..0x0f */ | ||
44 | uint64_t addr_last; /* 0x10..0x17 */ | ||
45 | struct sdb_product product; /* 0x18..0x3f */ | ||
46 | }; | ||
47 | |||
48 | /* Type of the SDB record */ | ||
49 | enum sdb_record_type { | ||
50 | sdb_type_interconnect = 0x00, | ||
51 | sdb_type_device = 0x01, | ||
52 | sdb_type_bridge = 0x02, | ||
53 | sdb_type_integration = 0x80, | ||
54 | sdb_type_repo_url = 0x81, | ||
55 | sdb_type_synthesis = 0x82, | ||
56 | sdb_type_empty = 0xFF, | ||
57 | }; | ||
58 | |||
59 | /* Type 0: interconnect (first of the array) | ||
60 | * | ||
61 | * sdb_records is the length of the table including this first | ||
62 | * record, version is 1. The bus type is enumerated later. | ||
63 | */ | ||
64 | #define SDB_MAGIC 0x5344422d /* "SDB-" */ | ||
65 | struct sdb_interconnect { | ||
66 | uint32_t sdb_magic; /* 0x00-0x03 */ | ||
67 | uint16_t sdb_records; /* 0x04-0x05 */ | ||
68 | uint8_t sdb_version; /* 0x06 */ | ||
69 | uint8_t sdb_bus_type; /* 0x07 */ | ||
70 | struct sdb_component sdb_component; /* 0x08-0x3f */ | ||
71 | }; | ||
72 | |||
73 | /* Type 1: device | ||
74 | * | ||
75 | * class is 0 for "custom device", other values are | ||
76 | * to be standardized; ABI version is for the driver, | ||
77 | * bus-specific bits are defined by each bus (see below) | ||
78 | */ | ||
79 | struct sdb_device { | ||
80 | uint16_t abi_class; /* 0x00-0x01 */ | ||
81 | uint8_t abi_ver_major; /* 0x02 */ | ||
82 | uint8_t abi_ver_minor; /* 0x03 */ | ||
83 | uint32_t bus_specific; /* 0x04-0x07 */ | ||
84 | struct sdb_component sdb_component; /* 0x08-0x3f */ | ||
85 | }; | ||
86 | |||
87 | /* Type 2: bridge | ||
88 | * | ||
89 | * child is the address of the nested SDB table | ||
90 | */ | ||
91 | struct sdb_bridge { | ||
92 | uint64_t sdb_child; /* 0x00-0x07 */ | ||
93 | struct sdb_component sdb_component; /* 0x08-0x3f */ | ||
94 | }; | ||
95 | |||
96 | /* Type 0x80: integration | ||
97 | * | ||
98 | * all types with bit 7 set are meta-information, so | ||
99 | * software can ignore the types it doesn't know. Here we | ||
100 | * just provide product information for an aggregate device | ||
101 | */ | ||
102 | struct sdb_integration { | ||
103 | uint8_t reserved[24]; /* 0x00-0x17 */ | ||
104 | struct sdb_product product; /* 0x08-0x3f */ | ||
105 | }; | ||
106 | |||
107 | /* Type 0x81: Top module repository url | ||
108 | * | ||
109 | * again, an informative field that software can ignore | ||
110 | */ | ||
111 | struct sdb_repo_url { | ||
112 | uint8_t repo_url[63]; /* 0x00-0x3e */ | ||
113 | uint8_t record_type; /* 0x3f */ | ||
114 | }; | ||
115 | |||
116 | /* Type 0x82: Synthesis tool information | ||
117 | * | ||
118 | * this informative record | ||
119 | */ | ||
120 | struct sdb_synthesis { | ||
121 | uint8_t syn_name[16]; /* 0x00-0x0f */ | ||
122 | uint8_t commit_id[16]; /* 0x10-0x1f */ | ||
123 | uint8_t tool_name[8]; /* 0x20-0x27 */ | ||
124 | uint32_t tool_version; /* 0x28-0x2b */ | ||
125 | uint32_t date; /* 0x2c-0x2f */ | ||
126 | uint8_t user_name[15]; /* 0x30-0x3e */ | ||
127 | uint8_t record_type; /* 0x3f */ | ||
128 | }; | ||
129 | |||
130 | /* Type 0xff: empty | ||
131 | * | ||
132 | * this allows keeping empty slots during development, | ||
133 | * so they can be filled later with minimal efforts and | ||
134 | * no misleading description is ever shipped -- hopefully. | ||
135 | * It can also be used to pad a table to a desired length. | ||
136 | */ | ||
137 | struct sdb_empty { | ||
138 | uint8_t reserved[63]; /* 0x00-0x3e */ | ||
139 | uint8_t record_type; /* 0x3f */ | ||
140 | }; | ||
141 | |||
142 | /* The type of bus, for bus-specific flags */ | ||
143 | enum sdb_bus_type { | ||
144 | sdb_wishbone = 0x00, | ||
145 | sdb_data = 0x01, | ||
146 | }; | ||
147 | |||
148 | #define SDB_WB_WIDTH_MASK 0x0f | ||
149 | #define SDB_WB_ACCESS8 0x01 | ||
150 | #define SDB_WB_ACCESS16 0x02 | ||
151 | #define SDB_WB_ACCESS32 0x04 | ||
152 | #define SDB_WB_ACCESS64 0x08 | ||
153 | #define SDB_WB_LITTLE_ENDIAN 0x80 | ||
154 | |||
155 | #define SDB_DATA_READ 0x04 | ||
156 | #define SDB_DATA_WRITE 0x02 | ||
157 | #define SDB_DATA_EXEC 0x01 | ||
158 | |||
159 | #endif /* __SDB_H__ */ | ||
diff --git a/lib/Kconfig b/lib/Kconfig index fe01d418b09a..d246a3bbd6ef 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
@@ -22,6 +22,9 @@ config GENERIC_STRNCPY_FROM_USER | |||
22 | config GENERIC_STRNLEN_USER | 22 | config GENERIC_STRNLEN_USER |
23 | bool | 23 | bool |
24 | 24 | ||
25 | config GENERIC_NET_UTILS | ||
26 | bool | ||
27 | |||
25 | config GENERIC_FIND_FIRST_BIT | 28 | config GENERIC_FIND_FIRST_BIT |
26 | bool | 29 | bool |
27 | 30 | ||
diff --git a/lib/Makefile b/lib/Makefile index c55a037a354e..22f0f4e8a9e1 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
@@ -137,6 +137,8 @@ obj-$(CONFIG_DDR) += jedec_ddr_data.o | |||
137 | obj-$(CONFIG_GENERIC_STRNCPY_FROM_USER) += strncpy_from_user.o | 137 | obj-$(CONFIG_GENERIC_STRNCPY_FROM_USER) += strncpy_from_user.o |
138 | obj-$(CONFIG_GENERIC_STRNLEN_USER) += strnlen_user.o | 138 | obj-$(CONFIG_GENERIC_STRNLEN_USER) += strnlen_user.o |
139 | 139 | ||
140 | obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o | ||
141 | |||
140 | obj-$(CONFIG_STMP_DEVICE) += stmp_device.o | 142 | obj-$(CONFIG_STMP_DEVICE) += stmp_device.o |
141 | 143 | ||
142 | libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o | 144 | libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o |
diff --git a/lib/net_utils.c b/lib/net_utils.c new file mode 100644 index 000000000000..2e3c52c8d050 --- /dev/null +++ b/lib/net_utils.c | |||
@@ -0,0 +1,26 @@ | |||
1 | #include <linux/string.h> | ||
2 | #include <linux/if_ether.h> | ||
3 | #include <linux/ctype.h> | ||
4 | #include <linux/kernel.h> | ||
5 | |||
6 | int mac_pton(const char *s, u8 *mac) | ||
7 | { | ||
8 | int i; | ||
9 | |||
10 | /* XX:XX:XX:XX:XX:XX */ | ||
11 | if (strlen(s) < 3 * ETH_ALEN - 1) | ||
12 | return 0; | ||
13 | |||
14 | /* Don't dirty result unless string is valid MAC. */ | ||
15 | for (i = 0; i < ETH_ALEN; i++) { | ||
16 | if (!isxdigit(s[i * 3]) || !isxdigit(s[i * 3 + 1])) | ||
17 | return 0; | ||
18 | if (i != ETH_ALEN - 1 && s[i * 3 + 2] != ':') | ||
19 | return 0; | ||
20 | } | ||
21 | for (i = 0; i < ETH_ALEN; i++) { | ||
22 | mac[i] = (hex_to_bin(s[i * 3]) << 4) | hex_to_bin(s[i * 3 + 1]); | ||
23 | } | ||
24 | return 1; | ||
25 | } | ||
26 | EXPORT_SYMBOL(mac_pton); | ||
diff --git a/net/Kconfig b/net/Kconfig index 2ddc9046868e..6dfe1c636a80 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -5,6 +5,7 @@ | |||
5 | menuconfig NET | 5 | menuconfig NET |
6 | bool "Networking support" | 6 | bool "Networking support" |
7 | select NLATTR | 7 | select NLATTR |
8 | select GENERIC_NET_UTILS | ||
8 | ---help--- | 9 | ---help--- |
9 | Unless you really know what you are doing, you should say Y here. | 10 | Unless you really know what you are doing, you should say Y here. |
10 | The reason is that some programs need kernel networking support even | 11 | The reason is that some programs need kernel networking support even |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index cec074be8c43..35a9f0804b6f 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
13 | 13 | ||
14 | #include <linux/moduleparam.h> | 14 | #include <linux/moduleparam.h> |
15 | #include <linux/kernel.h> | ||
15 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
16 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
17 | #include <linux/string.h> | 18 | #include <linux/string.h> |
diff --git a/net/core/utils.c b/net/core/utils.c index 3c7f5b51b979..aa88e23fc87a 100644 --- a/net/core/utils.c +++ b/net/core/utils.c | |||
@@ -338,25 +338,3 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, | |||
338 | csum_unfold(*sum))); | 338 | csum_unfold(*sum))); |
339 | } | 339 | } |
340 | EXPORT_SYMBOL(inet_proto_csum_replace16); | 340 | EXPORT_SYMBOL(inet_proto_csum_replace16); |
341 | |||
342 | int mac_pton(const char *s, u8 *mac) | ||
343 | { | ||
344 | int i; | ||
345 | |||
346 | /* XX:XX:XX:XX:XX:XX */ | ||
347 | if (strlen(s) < 3 * ETH_ALEN - 1) | ||
348 | return 0; | ||
349 | |||
350 | /* Don't dirty result unless string is valid MAC. */ | ||
351 | for (i = 0; i < ETH_ALEN; i++) { | ||
352 | if (!isxdigit(s[i * 3]) || !isxdigit(s[i * 3 + 1])) | ||
353 | return 0; | ||
354 | if (i != ETH_ALEN - 1 && s[i * 3 + 2] != ':') | ||
355 | return 0; | ||
356 | } | ||
357 | for (i = 0; i < ETH_ALEN; i++) { | ||
358 | mac[i] = (hex_to_bin(s[i * 3]) << 4) | hex_to_bin(s[i * 3 + 1]); | ||
359 | } | ||
360 | return 1; | ||
361 | } | ||
362 | EXPORT_SYMBOL(mac_pton); | ||
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 5a1f6489d185..ca9fa4d32e07 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c | |||
@@ -127,7 +127,8 @@ static void kvp_acquire_lock(int pool) | |||
127 | fl.l_pid = getpid(); | 127 | fl.l_pid = getpid(); |
128 | 128 | ||
129 | if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) { | 129 | if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) { |
130 | syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool); | 130 | syslog(LOG_ERR, "Failed to acquire the lock pool: %d; error: %d %s", pool, |
131 | errno, strerror(errno)); | ||
131 | exit(EXIT_FAILURE); | 132 | exit(EXIT_FAILURE); |
132 | } | 133 | } |
133 | } | 134 | } |
@@ -138,8 +139,8 @@ static void kvp_release_lock(int pool) | |||
138 | fl.l_pid = getpid(); | 139 | fl.l_pid = getpid(); |
139 | 140 | ||
140 | if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) { | 141 | if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) { |
141 | perror("fcntl"); | 142 | syslog(LOG_ERR, "Failed to release the lock pool: %d; error: %d %s", pool, |
142 | syslog(LOG_ERR, "Failed to release the lock pool: %d", pool); | 143 | errno, strerror(errno)); |
143 | exit(EXIT_FAILURE); | 144 | exit(EXIT_FAILURE); |
144 | } | 145 | } |
145 | } | 146 | } |
@@ -157,8 +158,9 @@ static void kvp_update_file(int pool) | |||
157 | 158 | ||
158 | filep = fopen(kvp_file_info[pool].fname, "we"); | 159 | filep = fopen(kvp_file_info[pool].fname, "we"); |
159 | if (!filep) { | 160 | if (!filep) { |
161 | syslog(LOG_ERR, "Failed to open file, pool: %d; error: %d %s", pool, | ||
162 | errno, strerror(errno)); | ||
160 | kvp_release_lock(pool); | 163 | kvp_release_lock(pool); |
161 | syslog(LOG_ERR, "Failed to open file, pool: %d", pool); | ||
162 | exit(EXIT_FAILURE); | 164 | exit(EXIT_FAILURE); |
163 | } | 165 | } |
164 | 166 | ||
@@ -188,8 +190,9 @@ static void kvp_update_mem_state(int pool) | |||
188 | 190 | ||
189 | filep = fopen(kvp_file_info[pool].fname, "re"); | 191 | filep = fopen(kvp_file_info[pool].fname, "re"); |
190 | if (!filep) { | 192 | if (!filep) { |
193 | syslog(LOG_ERR, "Failed to open file, pool: %d; error: %d %s", pool, | ||
194 | errno, strerror(errno)); | ||
191 | kvp_release_lock(pool); | 195 | kvp_release_lock(pool); |
192 | syslog(LOG_ERR, "Failed to open file, pool: %d", pool); | ||
193 | exit(EXIT_FAILURE); | 196 | exit(EXIT_FAILURE); |
194 | } | 197 | } |
195 | for (;;) { | 198 | for (;;) { |
@@ -240,7 +243,8 @@ static int kvp_file_init(void) | |||
240 | 243 | ||
241 | if (access(KVP_CONFIG_LOC, F_OK)) { | 244 | if (access(KVP_CONFIG_LOC, F_OK)) { |
242 | if (mkdir(KVP_CONFIG_LOC, 0755 /* rwxr-xr-x */)) { | 245 | if (mkdir(KVP_CONFIG_LOC, 0755 /* rwxr-xr-x */)) { |
243 | syslog(LOG_ERR, " Failed to create %s", KVP_CONFIG_LOC); | 246 | syslog(LOG_ERR, "Failed to create '%s'; error: %d %s", KVP_CONFIG_LOC, |
247 | errno, strerror(errno)); | ||
244 | exit(EXIT_FAILURE); | 248 | exit(EXIT_FAILURE); |
245 | } | 249 | } |
246 | } | 250 | } |
@@ -257,12 +261,15 @@ static int kvp_file_init(void) | |||
257 | 261 | ||
258 | 262 | ||
259 | filep = fopen(fname, "re"); | 263 | filep = fopen(fname, "re"); |
260 | if (!filep) | 264 | if (!filep) { |
265 | close(fd); | ||
261 | return 1; | 266 | return 1; |
267 | } | ||
262 | 268 | ||
263 | record = malloc(alloc_unit * num_blocks); | 269 | record = malloc(alloc_unit * num_blocks); |
264 | if (record == NULL) { | 270 | if (record == NULL) { |
265 | fclose(filep); | 271 | fclose(filep); |
272 | close(fd); | ||
266 | return 1; | 273 | return 1; |
267 | } | 274 | } |
268 | for (;;) { | 275 | for (;;) { |
@@ -286,6 +293,7 @@ static int kvp_file_init(void) | |||
286 | num_blocks); | 293 | num_blocks); |
287 | if (record == NULL) { | 294 | if (record == NULL) { |
288 | fclose(filep); | 295 | fclose(filep); |
296 | close(fd); | ||
289 | return 1; | 297 | return 1; |
290 | } | 298 | } |
291 | continue; | 299 | continue; |
@@ -765,7 +773,9 @@ static void kvp_process_ipconfig_file(char *cmd, | |||
765 | break; | 773 | break; |
766 | 774 | ||
767 | x = strchr(p, '\n'); | 775 | x = strchr(p, '\n'); |
768 | *x = '\0'; | 776 | if (x) |
777 | *x = '\0'; | ||
778 | |||
769 | strcat(config_buf, p); | 779 | strcat(config_buf, p); |
770 | strcat(config_buf, ";"); | 780 | strcat(config_buf, ";"); |
771 | } | 781 | } |
@@ -1274,7 +1284,8 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) | |||
1274 | file = fopen(if_file, "w"); | 1284 | file = fopen(if_file, "w"); |
1275 | 1285 | ||
1276 | if (file == NULL) { | 1286 | if (file == NULL) { |
1277 | syslog(LOG_ERR, "Failed to open config file"); | 1287 | syslog(LOG_ERR, "Failed to open config file; error: %d %s", |
1288 | errno, strerror(errno)); | ||
1278 | return HV_E_FAIL; | 1289 | return HV_E_FAIL; |
1279 | } | 1290 | } |
1280 | 1291 | ||
@@ -1441,7 +1452,8 @@ int main(void) | |||
1441 | 1452 | ||
1442 | fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); | 1453 | fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); |
1443 | if (fd < 0) { | 1454 | if (fd < 0) { |
1444 | syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); | 1455 | syslog(LOG_ERR, "netlink socket creation failed; error: %d %s", errno, |
1456 | strerror(errno)); | ||
1445 | exit(EXIT_FAILURE); | 1457 | exit(EXIT_FAILURE); |
1446 | } | 1458 | } |
1447 | addr.nl_family = AF_NETLINK; | 1459 | addr.nl_family = AF_NETLINK; |
@@ -1452,12 +1464,18 @@ int main(void) | |||
1452 | 1464 | ||
1453 | error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); | 1465 | error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); |
1454 | if (error < 0) { | 1466 | if (error < 0) { |
1455 | syslog(LOG_ERR, "bind failed; error:%d", error); | 1467 | syslog(LOG_ERR, "bind failed; error: %d %s", errno, strerror(errno)); |
1456 | close(fd); | 1468 | close(fd); |
1457 | exit(EXIT_FAILURE); | 1469 | exit(EXIT_FAILURE); |
1458 | } | 1470 | } |
1459 | nl_group = CN_KVP_IDX; | 1471 | nl_group = CN_KVP_IDX; |
1460 | setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)); | 1472 | |
1473 | if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)) < 0) { | ||
1474 | syslog(LOG_ERR, "setsockopt failed; error: %d %s", errno, strerror(errno)); | ||
1475 | close(fd); | ||
1476 | exit(EXIT_FAILURE); | ||
1477 | } | ||
1478 | |||
1461 | /* | 1479 | /* |
1462 | * Register ourselves with the kernel. | 1480 | * Register ourselves with the kernel. |
1463 | */ | 1481 | */ |
@@ -1472,7 +1490,7 @@ int main(void) | |||
1472 | 1490 | ||
1473 | len = netlink_send(fd, message); | 1491 | len = netlink_send(fd, message); |
1474 | if (len < 0) { | 1492 | if (len < 0) { |
1475 | syslog(LOG_ERR, "netlink_send failed; error:%d", len); | 1493 | syslog(LOG_ERR, "netlink_send failed; error: %d %s", errno, strerror(errno)); |
1476 | close(fd); | 1494 | close(fd); |
1477 | exit(EXIT_FAILURE); | 1495 | exit(EXIT_FAILURE); |
1478 | } | 1496 | } |
@@ -1484,7 +1502,16 @@ int main(void) | |||
1484 | socklen_t addr_l = sizeof(addr); | 1502 | socklen_t addr_l = sizeof(addr); |
1485 | pfd.events = POLLIN; | 1503 | pfd.events = POLLIN; |
1486 | pfd.revents = 0; | 1504 | pfd.revents = 0; |
1487 | poll(&pfd, 1, -1); | 1505 | |
1506 | if (poll(&pfd, 1, -1) < 0) { | ||
1507 | syslog(LOG_ERR, "poll failed; error: %d %s", errno, strerror(errno)); | ||
1508 | if (errno == EINVAL) { | ||
1509 | close(fd); | ||
1510 | exit(EXIT_FAILURE); | ||
1511 | } | ||
1512 | else | ||
1513 | continue; | ||
1514 | } | ||
1488 | 1515 | ||
1489 | len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0, | 1516 | len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0, |
1490 | addr_p, &addr_l); | 1517 | addr_p, &addr_l); |
@@ -1695,7 +1722,8 @@ kvp_done: | |||
1695 | 1722 | ||
1696 | len = netlink_send(fd, incoming_cn_msg); | 1723 | len = netlink_send(fd, incoming_cn_msg); |
1697 | if (len < 0) { | 1724 | if (len < 0) { |
1698 | syslog(LOG_ERR, "net_link send failed; error:%d", len); | 1725 | syslog(LOG_ERR, "net_link send failed; error: %d %s", errno, |
1726 | strerror(errno)); | ||
1699 | exit(EXIT_FAILURE); | 1727 | exit(EXIT_FAILURE); |
1700 | } | 1728 | } |
1701 | } | 1729 | } |