Skip to content

Commit 63f4f7e

Browse files
committed
Merge tag 'chrome-platform-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/olof/chrome-platform
Pull chrome platform updates from Olof Johansson: "Here's the branch of chrome platform changes for v4.4. Some have been queued up for the full 4.3 release cycle since I forgot to send them in for that round (rebased early on to deal with fixes conflicts). Most of these enable EC communication stuff -- Pixel 2015 support, enabling building for ARM64 platforms, and a few fixes for memory leaks. There's also a patch in here to allow reading/writing the verified boot context, which depends on a sysfs patch acked by Greg" * tag 'chrome-platform-4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/olof/chrome-platform: platform/chrome: Fix i2c-designware adapter name platform/chrome: Support reading/writing the vboot context sysfs: Support is_visible() on binary attributes platform/chrome: cros_ec: Fix possible leak in led_rgb_store() platform/chrome: cros_ec: Fix leak in sequence_store() platform/chrome: Enable Chrome platforms on 64-bit ARM platform/chrome: cros_ec_dev - Add a platform device ID table platform/chrome: cros_ec_lpc - Add support for Google Pixel 2 platform/chrome: cros_ec_lpc - Use existing function to check EC result platform/chrome: Make depends on MFD_CROS_EC instead CROS_EC_PROTO Revert "platform/chrome: Don't make CHROME_PLATFORMS depends on X86 || ARM"
2 parents 4bfc89d + ebaf31c commit 63f4f7e

File tree

10 files changed

+207
-37
lines changed

10 files changed

+207
-37
lines changed

drivers/platform/chrome/Kconfig

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
menuconfig CHROME_PLATFORMS
66
bool "Platform support for Chrome hardware"
7+
depends on X86 || ARM || ARM64 || COMPILE_TEST
78
---help---
89
Say Y here to get to see options for platform support for
910
various Chromebooks and Chromeboxes. This option alone does
@@ -39,7 +40,7 @@ config CHROMEOS_PSTORE
3940

4041
config CROS_EC_CHARDEV
4142
tristate "Chrome OS Embedded Controller userspace device interface"
42-
depends on CROS_EC_PROTO
43+
depends on MFD_CROS_EC
4344
---help---
4445
This driver adds support to talk with the ChromeOS EC from userspace.
4546

@@ -48,7 +49,7 @@ config CROS_EC_CHARDEV
4849

4950
config CROS_EC_LPC
5051
tristate "ChromeOS Embedded Controller (LPC)"
51-
depends on MFD_CROS_EC && CROS_EC_PROTO && (X86 || COMPILE_TEST)
52+
depends on MFD_CROS_EC && (X86 || COMPILE_TEST)
5253
help
5354
If you say Y here, you get support for talking to the ChromeOS EC
5455
over an LPC bus. This uses a simple byte-level protocol with a

drivers/platform/chrome/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11

22
obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o
33
obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
4-
cros_ec_devs-objs := cros_ec_dev.o cros_ec_sysfs.o cros_ec_lightbar.o
4+
cros_ec_devs-objs := cros_ec_dev.o cros_ec_sysfs.o \
5+
cros_ec_lightbar.o cros_ec_vbc.o
56
obj-$(CONFIG_CROS_EC_CHARDEV) += cros_ec_devs.o
67
obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o
78
obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o

drivers/platform/chrome/chromeos_laptop.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ static const char *i2c_adapter_names[] = {
4747
"SMBus I801 adapter",
4848
"i915 gmbus vga",
4949
"i915 gmbus panel",
50-
"i2c-designware-pci",
51-
"i2c-designware-pci",
50+
"Synopsys DesignWare I2C adapter",
51+
"Synopsys DesignWare I2C adapter",
5252
};
5353

5454
/* Keep this enum consistent with i2c_adapter_names */

drivers/platform/chrome/cros_ec_dev.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ static int ec_major;
3232
static const struct attribute_group *cros_ec_groups[] = {
3333
&cros_ec_attr_group,
3434
&cros_ec_lightbar_attr_group,
35+
&cros_ec_vbc_attr_group,
3536
NULL,
3637
};
3738

@@ -287,6 +288,12 @@ static int ec_device_remove(struct platform_device *pdev)
287288
return 0;
288289
}
289290

291+
static const struct platform_device_id cros_ec_id[] = {
292+
{ "cros-ec-ctl", 0 },
293+
{ /* sentinel */ },
294+
};
295+
MODULE_DEVICE_TABLE(platform, cros_ec_id);
296+
290297
static struct platform_driver cros_ec_dev_driver = {
291298
.driver = {
292299
.name = "cros-ec-ctl",

drivers/platform/chrome/cros_ec_lightbar.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
252252

253253
ret = sscanf(buf, "%i", &val[i++]);
254254
if (ret == 0)
255-
return -EINVAL;
255+
goto exit;
256256

257257
if (i == 4) {
258258
param = (struct ec_params_lightbar *)msg->data;
@@ -268,17 +268,15 @@ static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
268268
if ((j++ % 4) == 0) {
269269
ret = lb_throttle();
270270
if (ret)
271-
return ret;
271+
goto exit;
272272
}
273273

274274
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
275275
if (ret < 0)
276276
goto exit;
277277

278-
if (msg->result != EC_RES_SUCCESS) {
279-
ret = -EINVAL;
278+
if (msg->result != EC_RES_SUCCESS)
280279
goto exit;
281-
}
282280

283281
i = 0;
284282
ok = 1;
@@ -352,10 +350,6 @@ static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
352350
struct cros_ec_dev *ec = container_of(dev,
353351
struct cros_ec_dev, class_dev);
354352

355-
msg = alloc_lightbar_cmd_msg(ec);
356-
if (!msg)
357-
return -ENOMEM;
358-
359353
for (len = 0; len < count; len++)
360354
if (!isalnum(buf[len]))
361355
break;
@@ -370,21 +364,30 @@ static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
370364
return ret;
371365
}
372366

367+
msg = alloc_lightbar_cmd_msg(ec);
368+
if (!msg)
369+
return -ENOMEM;
370+
373371
param = (struct ec_params_lightbar *)msg->data;
374372
param->cmd = LIGHTBAR_CMD_SEQ;
375373
param->seq.num = num;
376374
ret = lb_throttle();
377375
if (ret)
378-
return ret;
376+
goto exit;
379377

380378
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
381379
if (ret < 0)
382-
return ret;
380+
goto exit;
383381

384-
if (msg->result != EC_RES_SUCCESS)
385-
return -EINVAL;
382+
if (msg->result != EC_RES_SUCCESS) {
383+
ret = -EINVAL;
384+
goto exit;
385+
}
386386

387-
return count;
387+
ret = count;
388+
exit:
389+
kfree(msg);
390+
return ret;
388391
}
389392

390393
/* Module initialization */

drivers/platform/chrome/cros_ec_lpc.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -166,19 +166,9 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
166166

167167
/* Check result */
168168
msg->result = inb(EC_LPC_ADDR_HOST_DATA);
169-
170-
switch (msg->result) {
171-
case EC_RES_SUCCESS:
172-
break;
173-
case EC_RES_IN_PROGRESS:
174-
ret = -EAGAIN;
175-
dev_dbg(ec->dev, "command 0x%02x in progress\n",
176-
msg->command);
169+
ret = cros_ec_check_result(ec, msg);
170+
if (ret)
177171
goto done;
178-
default:
179-
dev_dbg(ec->dev, "command 0x%02x returned %d\n",
180-
msg->command, msg->result);
181-
}
182172

183173
/* Read back args */
184174
args.flags = inb(EC_LPC_ADDR_HOST_ARGS);
@@ -329,6 +319,13 @@ static struct dmi_system_id cros_ec_lpc_dmi_table[] __initdata = {
329319
DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
330320
},
331321
},
322+
{
323+
/* x86-samus, the Chromebook Pixel 2. */
324+
.matches = {
325+
DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
326+
DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
327+
},
328+
},
332329
{
333330
/* x86-peppy, the Acer C720 Chromebook. */
334331
.matches = {

drivers/platform/chrome/cros_ec_vbc.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* cros_ec_vbc - Expose the vboot context nvram to userspace
3+
*
4+
* Copyright (C) 2015 Collabora Ltd.
5+
*
6+
* based on vendor driver,
7+
*
8+
* Copyright (C) 2012 The Chromium OS Authors
9+
*
10+
* This program is free software; you can redistribute it and/or modify
11+
* it under the terms of the GNU General Public License as published by
12+
* the Free Software Foundation; either version 2 of the License, or
13+
* (at your option) any later version.
14+
*
15+
* This program is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
* GNU General Public License for more details.
19+
*/
20+
21+
#include <linux/of.h>
22+
#include <linux/platform_device.h>
23+
#include <linux/mfd/cros_ec.h>
24+
#include <linux/mfd/cros_ec_commands.h>
25+
#include <linux/slab.h>
26+
27+
static ssize_t vboot_context_read(struct file *filp, struct kobject *kobj,
28+
struct bin_attribute *att, char *buf,
29+
loff_t pos, size_t count)
30+
{
31+
struct device *dev = container_of(kobj, struct device, kobj);
32+
struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
33+
class_dev);
34+
struct cros_ec_device *ecdev = ec->ec_dev;
35+
struct ec_params_vbnvcontext *params;
36+
struct cros_ec_command *msg;
37+
int err;
38+
const size_t para_sz = sizeof(params->op);
39+
const size_t resp_sz = sizeof(struct ec_response_vbnvcontext);
40+
const size_t payload = max(para_sz, resp_sz);
41+
42+
msg = kmalloc(sizeof(*msg) + payload, GFP_KERNEL);
43+
if (!msg)
44+
return -ENOMEM;
45+
46+
/* NB: we only kmalloc()ated enough space for the op field */
47+
params = (struct ec_params_vbnvcontext *)msg->data;
48+
params->op = EC_VBNV_CONTEXT_OP_READ;
49+
50+
msg->version = EC_VER_VBNV_CONTEXT;
51+
msg->command = EC_CMD_VBNV_CONTEXT;
52+
msg->outsize = para_sz;
53+
msg->insize = resp_sz;
54+
55+
err = cros_ec_cmd_xfer(ecdev, msg);
56+
if (err < 0) {
57+
dev_err(dev, "Error sending read request: %d\n", err);
58+
kfree(msg);
59+
return err;
60+
}
61+
62+
memcpy(buf, msg->data, resp_sz);
63+
64+
kfree(msg);
65+
return resp_sz;
66+
}
67+
68+
static ssize_t vboot_context_write(struct file *filp, struct kobject *kobj,
69+
struct bin_attribute *attr, char *buf,
70+
loff_t pos, size_t count)
71+
{
72+
struct device *dev = container_of(kobj, struct device, kobj);
73+
struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
74+
class_dev);
75+
struct cros_ec_device *ecdev = ec->ec_dev;
76+
struct ec_params_vbnvcontext *params;
77+
struct cros_ec_command *msg;
78+
int err;
79+
const size_t para_sz = sizeof(*params);
80+
const size_t data_sz = sizeof(params->block);
81+
82+
/* Only write full values */
83+
if (count != data_sz)
84+
return -EINVAL;
85+
86+
msg = kmalloc(sizeof(*msg) + para_sz, GFP_KERNEL);
87+
if (!msg)
88+
return -ENOMEM;
89+
90+
params = (struct ec_params_vbnvcontext *)msg->data;
91+
params->op = EC_VBNV_CONTEXT_OP_WRITE;
92+
memcpy(params->block, buf, data_sz);
93+
94+
msg->version = EC_VER_VBNV_CONTEXT;
95+
msg->command = EC_CMD_VBNV_CONTEXT;
96+
msg->outsize = para_sz;
97+
msg->insize = 0;
98+
99+
err = cros_ec_cmd_xfer(ecdev, msg);
100+
if (err < 0) {
101+
dev_err(dev, "Error sending write request: %d\n", err);
102+
kfree(msg);
103+
return err;
104+
}
105+
106+
kfree(msg);
107+
return data_sz;
108+
}
109+
110+
static umode_t cros_ec_vbc_is_visible(struct kobject *kobj,
111+
struct bin_attribute *a, int n)
112+
{
113+
struct device *dev = container_of(kobj, struct device, kobj);
114+
struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
115+
class_dev);
116+
struct device_node *np = ec->ec_dev->dev->of_node;
117+
118+
if (IS_ENABLED(CONFIG_OF) && np) {
119+
if (of_property_read_bool(np, "google,has-vbc-nvram"))
120+
return a->attr.mode;
121+
}
122+
123+
return 0;
124+
}
125+
126+
static BIN_ATTR_RW(vboot_context, 16);
127+
128+
static struct bin_attribute *cros_ec_vbc_bin_attrs[] = {
129+
&bin_attr_vboot_context,
130+
NULL
131+
};
132+
133+
struct attribute_group cros_ec_vbc_attr_group = {
134+
.name = "vbc",
135+
.bin_attrs = cros_ec_vbc_bin_attrs,
136+
.is_bin_visible = cros_ec_vbc_is_visible,
137+
};

fs/sysfs/group.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,26 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
7373
}
7474

7575
if (grp->bin_attrs) {
76-
for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) {
76+
for (i = 0, bin_attr = grp->bin_attrs; *bin_attr; i++, bin_attr++) {
77+
umode_t mode = (*bin_attr)->attr.mode;
78+
7779
if (update)
7880
kernfs_remove_by_name(parent,
7981
(*bin_attr)->attr.name);
82+
if (grp->is_bin_visible) {
83+
mode = grp->is_bin_visible(kobj, *bin_attr, i);
84+
if (!mode)
85+
continue;
86+
}
87+
88+
WARN(mode & ~(SYSFS_PREALLOC | 0664),
89+
"Attribute %s: Invalid permissions 0%o\n",
90+
(*bin_attr)->attr.name, mode);
91+
92+
mode &= SYSFS_PREALLOC | 0664;
8093
error = sysfs_add_file_mode_ns(parent,
8194
&(*bin_attr)->attr, true,
82-
(*bin_attr)->attr.mode, NULL);
95+
mode, NULL);
8396
if (error)
8497
break;
8598
}

include/linux/mfd/cros_ec.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,5 +255,6 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev);
255255
/* sysfs stuff */
256256
extern struct attribute_group cros_ec_attr_group;
257257
extern struct attribute_group cros_ec_lightbar_attr_group;
258+
extern struct attribute_group cros_ec_vbc_attr_group;
258259

259260
#endif /* __LINUX_MFD_CROS_EC_H */

include/linux/sysfs.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,18 @@ do { \
6464
* a new subdirectory with this name.
6565
* @is_visible: Optional: Function to return permissions associated with an
6666
* attribute of the group. Will be called repeatedly for each
67-
* attribute in the group. Only read/write permissions as well as
68-
* SYSFS_PREALLOC are accepted. Must return 0 if an attribute is
69-
* not visible. The returned value will replace static permissions
70-
* defined in struct attribute or struct bin_attribute.
67+
* non-binary attribute in the group. Only read/write
68+
* permissions as well as SYSFS_PREALLOC are accepted. Must
69+
* return 0 if an attribute is not visible. The returned value
70+
* will replace static permissions defined in struct attribute.
71+
* @is_bin_visible:
72+
* Optional: Function to return permissions associated with a
73+
* binary attribute of the group. Will be called repeatedly
74+
* for each binary attribute in the group. Only read/write
75+
* permissions as well as SYSFS_PREALLOC are accepted. Must
76+
* return 0 if a binary attribute is not visible. The returned
77+
* value will replace static permissions defined in
78+
* struct bin_attribute.
7179
* @attrs: Pointer to NULL terminated list of attributes.
7280
* @bin_attrs: Pointer to NULL terminated list of binary attributes.
7381
* Either attrs or bin_attrs or both must be provided.
@@ -76,6 +84,8 @@ struct attribute_group {
7684
const char *name;
7785
umode_t (*is_visible)(struct kobject *,
7886
struct attribute *, int);
87+
umode_t (*is_bin_visible)(struct kobject *,
88+
struct bin_attribute *, int);
7989
struct attribute **attrs;
8090
struct bin_attribute **bin_attrs;
8191
};

0 commit comments

Comments
 (0)