Skip to content

Commit 57cf7a6

Browse files
committed
Merge tag 'chrome-platform-v6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux
Pull chrome platform updates from Tzung-Bi Shih: "New: - Add a new API cros_ec_device_registered() for checking if the cros_ec_deivce is ready Improvements: - Use TRAILING_OVERLAP() to fix -Wflex-array-member-not-at-end warning - Defer probe until parent EC device is ready in cros_ec_keyb Cleanups: - Remove redundant and simplify code in cros_ec_chardev - Centralize cros_ec_device allocation and initialization to remove duplicate code" * tag 'chrome-platform-v6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux: Input: cros_ec_keyb - Defer probe until parent EC device is registered platform/chrome: cros_ec: Add a flag to track registration state platform/chrome: cros_ec: Separate initialization from cros_ec_register() platform/chrome: Centralize common cros_ec_device initialization platform/chrome: Centralize cros_ec_device allocation platform/chrome: wilco_ec: Remove redundant semicolons platform/chrome: cros_ec: Avoid -Wflex-array-member-not-at-end warning platform/chrome: cros_ec_chardev: Decouple fops from struct cros_ec_dev platform/chrome: cros_ec_chardev: Remove redundant struct field
2 parents eb3289f + 48633ac commit 57cf7a6

13 files changed

Lines changed: 139 additions & 107 deletions

File tree

drivers/input/keyboard/cros_ec_keyb.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,12 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
705705
ec = dev_get_drvdata(pdev->dev.parent);
706706
if (!ec)
707707
return -EPROBE_DEFER;
708+
/*
709+
* Even if the cros_ec_device pointer is available, still need to check
710+
* if the device is fully registered before using it.
711+
*/
712+
if (!cros_ec_device_registered(ec))
713+
return -EPROBE_DEFER;
708714

709715
ckdev = devm_kzalloc(dev, sizeof(*ckdev), GFP_KERNEL);
710716
if (!ckdev)

drivers/platform/chrome/cros_ec.c

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* battery charging and regulator control, firmware update.
1010
*/
1111

12+
#include <linux/cleanup.h>
1213
#include <linux/interrupt.h>
1314
#include <linux/module.h>
1415
#include <linux/of_platform.h>
@@ -30,6 +31,56 @@ static struct cros_ec_platform pd_p = {
3031
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX),
3132
};
3233

34+
static void cros_ec_device_free(void *data)
35+
{
36+
struct cros_ec_device *ec_dev = data;
37+
38+
mutex_destroy(&ec_dev->lock);
39+
lockdep_unregister_key(&ec_dev->lockdep_key);
40+
}
41+
42+
struct cros_ec_device *cros_ec_device_alloc(struct device *dev)
43+
{
44+
struct cros_ec_device *ec_dev;
45+
46+
ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
47+
if (!ec_dev)
48+
return NULL;
49+
50+
ec_dev->din_size = sizeof(struct ec_host_response) +
51+
sizeof(struct ec_response_get_protocol_info) +
52+
EC_MAX_RESPONSE_OVERHEAD;
53+
ec_dev->dout_size = sizeof(struct ec_host_request) +
54+
sizeof(struct ec_params_rwsig_action) +
55+
EC_MAX_REQUEST_OVERHEAD;
56+
57+
ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
58+
if (!ec_dev->din)
59+
return NULL;
60+
61+
ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL);
62+
if (!ec_dev->dout)
63+
return NULL;
64+
65+
ec_dev->dev = dev;
66+
ec_dev->max_response = sizeof(struct ec_response_get_protocol_info);
67+
ec_dev->max_request = sizeof(struct ec_params_rwsig_action);
68+
ec_dev->suspend_timeout_ms = EC_HOST_SLEEP_TIMEOUT_DEFAULT;
69+
70+
BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
71+
BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->panic_notifier);
72+
73+
lockdep_register_key(&ec_dev->lockdep_key);
74+
mutex_init(&ec_dev->lock);
75+
lockdep_set_class(&ec_dev->lock, &ec_dev->lockdep_key);
76+
77+
if (devm_add_action_or_reset(dev, cros_ec_device_free, ec_dev))
78+
return NULL;
79+
80+
return ec_dev;
81+
}
82+
EXPORT_SYMBOL(cros_ec_device_alloc);
83+
3384
/**
3485
* cros_ec_irq_handler() - top half part of the interrupt handler
3586
* @irq: IRQ id
@@ -102,14 +153,13 @@ EXPORT_SYMBOL(cros_ec_irq_thread);
102153
static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event)
103154
{
104155
int ret;
105-
struct {
106-
struct cros_ec_command msg;
156+
TRAILING_OVERLAP(struct cros_ec_command, msg, data,
107157
union {
108158
struct ec_params_host_sleep_event req0;
109159
struct ec_params_host_sleep_event_v1 req1;
110160
struct ec_response_host_sleep_event_v1 resp1;
111161
} u;
112-
} __packed buf;
162+
) __packed buf;
113163

114164
memset(&buf, 0, sizeof(buf));
115165

@@ -180,29 +230,7 @@ static int cros_ec_ready_event(struct notifier_block *nb,
180230
int cros_ec_register(struct cros_ec_device *ec_dev)
181231
{
182232
struct device *dev = ec_dev->dev;
183-
int err = 0;
184-
185-
BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
186-
BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->panic_notifier);
187-
188-
ec_dev->max_request = sizeof(struct ec_params_hello);
189-
ec_dev->max_response = sizeof(struct ec_response_get_protocol_info);
190-
ec_dev->max_passthru = 0;
191-
ec_dev->ec = NULL;
192-
ec_dev->pd = NULL;
193-
ec_dev->suspend_timeout_ms = EC_HOST_SLEEP_TIMEOUT_DEFAULT;
194-
195-
ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
196-
if (!ec_dev->din)
197-
return -ENOMEM;
198-
199-
ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL);
200-
if (!ec_dev->dout)
201-
return -ENOMEM;
202-
203-
lockdep_register_key(&ec_dev->lockdep_key);
204-
mutex_init(&ec_dev->lock);
205-
lockdep_set_class(&ec_dev->lock, &ec_dev->lockdep_key);
233+
int err;
206234

207235
/* Send RWSIG continue to jump to RW for devices using RWSIG. */
208236
err = cros_ec_rwsig_continue(ec_dev);
@@ -289,6 +317,9 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
289317
goto exit;
290318
}
291319

320+
scoped_guard(mutex, &ec_dev->lock)
321+
ec_dev->registered = true;
322+
292323
dev_info(dev, "Chrome EC device registered\n");
293324

294325
/*
@@ -302,8 +333,6 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
302333
exit:
303334
platform_device_unregister(ec_dev->ec);
304335
platform_device_unregister(ec_dev->pd);
305-
mutex_destroy(&ec_dev->lock);
306-
lockdep_unregister_key(&ec_dev->lockdep_key);
307336
return err;
308337
}
309338
EXPORT_SYMBOL(cros_ec_register);
@@ -318,13 +347,14 @@ EXPORT_SYMBOL(cros_ec_register);
318347
*/
319348
void cros_ec_unregister(struct cros_ec_device *ec_dev)
320349
{
350+
scoped_guard(mutex, &ec_dev->lock)
351+
ec_dev->registered = false;
352+
321353
if (ec_dev->mkbp_event_supported)
322354
blocking_notifier_chain_unregister(&ec_dev->event_notifier,
323355
&ec_dev->notifier_ready);
324356
platform_device_unregister(ec_dev->pd);
325357
platform_device_unregister(ec_dev->ec);
326-
mutex_destroy(&ec_dev->lock);
327-
lockdep_unregister_key(&ec_dev->lockdep_key);
328358
}
329359
EXPORT_SYMBOL(cros_ec_unregister);
330360

drivers/platform/chrome/cros_ec.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include <linux/interrupt.h>
1212

1313
struct cros_ec_device;
14+
struct device;
15+
16+
struct cros_ec_device *cros_ec_device_alloc(struct device *dev);
1417

1518
int cros_ec_register(struct cros_ec_device *ec_dev);
1619
void cros_ec_unregister(struct cros_ec_device *ec_dev);

drivers/platform/chrome/cros_ec_chardev.c

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,14 @@
3131
/* Arbitrary bounded size for the event queue */
3232
#define CROS_MAX_EVENT_LEN PAGE_SIZE
3333

34-
struct chardev_data {
35-
struct cros_ec_dev *ec_dev;
36-
struct miscdevice misc;
37-
};
38-
3934
struct chardev_priv {
40-
struct cros_ec_dev *ec_dev;
35+
struct cros_ec_device *ec_dev;
4136
struct notifier_block notifier;
4237
wait_queue_head_t wait_event;
4338
unsigned long event_mask;
4439
struct list_head events;
4540
size_t event_len;
41+
u16 cmd_offset;
4642
};
4743

4844
struct ec_event {
@@ -52,7 +48,7 @@ struct ec_event {
5248
u8 data[];
5349
};
5450

55-
static int ec_get_version(struct cros_ec_dev *ec, char *str, int maxlen)
51+
static int ec_get_version(struct chardev_priv *priv, char *str, int maxlen)
5652
{
5753
static const char * const current_image_name[] = {
5854
"unknown", "read-only", "read-write", "invalid",
@@ -65,10 +61,10 @@ static int ec_get_version(struct cros_ec_dev *ec, char *str, int maxlen)
6561
if (!msg)
6662
return -ENOMEM;
6763

68-
msg->command = EC_CMD_GET_VERSION + ec->cmd_offset;
64+
msg->command = EC_CMD_GET_VERSION + priv->cmd_offset;
6965
msg->insize = sizeof(*resp);
7066

71-
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
67+
ret = cros_ec_cmd_xfer_status(priv->ec_dev, msg);
7268
if (ret < 0) {
7369
snprintf(str, maxlen,
7470
"Unknown EC version, returned error: %d\n",
@@ -96,7 +92,7 @@ static int cros_ec_chardev_mkbp_event(struct notifier_block *nb,
9692
{
9793
struct chardev_priv *priv = container_of(nb, struct chardev_priv,
9894
notifier);
99-
struct cros_ec_device *ec_dev = priv->ec_dev->ec_dev;
95+
struct cros_ec_device *ec_dev = priv->ec_dev;
10096
struct ec_event *event;
10197
unsigned long event_bit = 1 << ec_dev->event_data.event_type;
10298
int total_size = sizeof(*event) + ec_dev->event_size;
@@ -161,7 +157,8 @@ static struct ec_event *cros_ec_chardev_fetch_event(struct chardev_priv *priv,
161157
static int cros_ec_chardev_open(struct inode *inode, struct file *filp)
162158
{
163159
struct miscdevice *mdev = filp->private_data;
164-
struct cros_ec_dev *ec_dev = dev_get_drvdata(mdev->parent);
160+
struct cros_ec_dev *ec = dev_get_drvdata(mdev->parent);
161+
struct cros_ec_device *ec_dev = ec->ec_dev;
165162
struct chardev_priv *priv;
166163
int ret;
167164

@@ -170,13 +167,14 @@ static int cros_ec_chardev_open(struct inode *inode, struct file *filp)
170167
return -ENOMEM;
171168

172169
priv->ec_dev = ec_dev;
170+
priv->cmd_offset = ec->cmd_offset;
173171
filp->private_data = priv;
174172
INIT_LIST_HEAD(&priv->events);
175173
init_waitqueue_head(&priv->wait_event);
176174
nonseekable_open(inode, filp);
177175

178176
priv->notifier.notifier_call = cros_ec_chardev_mkbp_event;
179-
ret = blocking_notifier_chain_register(&ec_dev->ec_dev->event_notifier,
177+
ret = blocking_notifier_chain_register(&ec_dev->event_notifier,
180178
&priv->notifier);
181179
if (ret) {
182180
dev_err(ec_dev->dev, "failed to register event notifier\n");
@@ -204,7 +202,6 @@ static ssize_t cros_ec_chardev_read(struct file *filp, char __user *buffer,
204202
char msg[sizeof(struct ec_response_get_version) +
205203
sizeof(CROS_EC_DEV_VERSION)];
206204
struct chardev_priv *priv = filp->private_data;
207-
struct cros_ec_dev *ec_dev = priv->ec_dev;
208205
size_t count;
209206
int ret;
210207

@@ -238,7 +235,7 @@ static ssize_t cros_ec_chardev_read(struct file *filp, char __user *buffer,
238235
if (*offset != 0)
239236
return 0;
240237

241-
ret = ec_get_version(ec_dev, msg, sizeof(msg));
238+
ret = ec_get_version(priv, msg, sizeof(msg));
242239
if (ret)
243240
return ret;
244241

@@ -254,10 +251,10 @@ static ssize_t cros_ec_chardev_read(struct file *filp, char __user *buffer,
254251
static int cros_ec_chardev_release(struct inode *inode, struct file *filp)
255252
{
256253
struct chardev_priv *priv = filp->private_data;
257-
struct cros_ec_dev *ec_dev = priv->ec_dev;
254+
struct cros_ec_device *ec_dev = priv->ec_dev;
258255
struct ec_event *event, *e;
259256

260-
blocking_notifier_chain_unregister(&ec_dev->ec_dev->event_notifier,
257+
blocking_notifier_chain_unregister(&ec_dev->event_notifier,
261258
&priv->notifier);
262259

263260
list_for_each_entry_safe(event, e, &priv->events, node) {
@@ -272,7 +269,7 @@ static int cros_ec_chardev_release(struct inode *inode, struct file *filp)
272269
/*
273270
* Ioctls
274271
*/
275-
static long cros_ec_chardev_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg)
272+
static long cros_ec_chardev_ioctl_xcmd(struct chardev_priv *priv, void __user *arg)
276273
{
277274
struct cros_ec_command *s_cmd;
278275
struct cros_ec_command u_cmd;
@@ -301,8 +298,8 @@ static long cros_ec_chardev_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg)
301298
goto exit;
302299
}
303300

304-
s_cmd->command += ec->cmd_offset;
305-
ret = cros_ec_cmd_xfer(ec->ec_dev, s_cmd);
301+
s_cmd->command += priv->cmd_offset;
302+
ret = cros_ec_cmd_xfer(priv->ec_dev, s_cmd);
306303
/* Only copy data to userland if data was received. */
307304
if (ret < 0)
308305
goto exit;
@@ -314,10 +311,9 @@ static long cros_ec_chardev_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg)
314311
return ret;
315312
}
316313

317-
static long cros_ec_chardev_ioctl_readmem(struct cros_ec_dev *ec,
318-
void __user *arg)
314+
static long cros_ec_chardev_ioctl_readmem(struct chardev_priv *priv, void __user *arg)
319315
{
320-
struct cros_ec_device *ec_dev = ec->ec_dev;
316+
struct cros_ec_device *ec_dev = priv->ec_dev;
321317
struct cros_ec_readmem s_mem = { };
322318
long num;
323319

@@ -346,16 +342,15 @@ static long cros_ec_chardev_ioctl(struct file *filp, unsigned int cmd,
346342
unsigned long arg)
347343
{
348344
struct chardev_priv *priv = filp->private_data;
349-
struct cros_ec_dev *ec = priv->ec_dev;
350345

351346
if (_IOC_TYPE(cmd) != CROS_EC_DEV_IOC)
352347
return -ENOTTY;
353348

354349
switch (cmd) {
355350
case CROS_EC_DEV_IOCXCMD:
356-
return cros_ec_chardev_ioctl_xcmd(ec, (void __user *)arg);
351+
return cros_ec_chardev_ioctl_xcmd(priv, (void __user *)arg);
357352
case CROS_EC_DEV_IOCRDMEM:
358-
return cros_ec_chardev_ioctl_readmem(ec, (void __user *)arg);
353+
return cros_ec_chardev_ioctl_readmem(priv, (void __user *)arg);
359354
case CROS_EC_DEV_IOCEVENTMASK:
360355
priv->event_mask = arg;
361356
return 0;
@@ -377,31 +372,30 @@ static const struct file_operations chardev_fops = {
377372

378373
static int cros_ec_chardev_probe(struct platform_device *pdev)
379374
{
380-
struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
381-
struct cros_ec_platform *ec_platform = dev_get_platdata(ec_dev->dev);
382-
struct chardev_data *data;
375+
struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent);
376+
struct cros_ec_platform *ec_platform = dev_get_platdata(ec->dev);
377+
struct miscdevice *misc;
383378

384379
/* Create a char device: we want to create it anew */
385-
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
386-
if (!data)
380+
misc = devm_kzalloc(&pdev->dev, sizeof(*misc), GFP_KERNEL);
381+
if (!misc)
387382
return -ENOMEM;
388383

389-
data->ec_dev = ec_dev;
390-
data->misc.minor = MISC_DYNAMIC_MINOR;
391-
data->misc.fops = &chardev_fops;
392-
data->misc.name = ec_platform->ec_name;
393-
data->misc.parent = pdev->dev.parent;
384+
misc->minor = MISC_DYNAMIC_MINOR;
385+
misc->fops = &chardev_fops;
386+
misc->name = ec_platform->ec_name;
387+
misc->parent = pdev->dev.parent;
394388

395-
dev_set_drvdata(&pdev->dev, data);
389+
dev_set_drvdata(&pdev->dev, misc);
396390

397-
return misc_register(&data->misc);
391+
return misc_register(misc);
398392
}
399393

400394
static void cros_ec_chardev_remove(struct platform_device *pdev)
401395
{
402-
struct chardev_data *data = dev_get_drvdata(&pdev->dev);
396+
struct miscdevice *misc = dev_get_drvdata(&pdev->dev);
403397

404-
misc_deregister(&data->misc);
398+
misc_deregister(misc);
405399
}
406400

407401
static const struct platform_device_id cros_ec_chardev_id[] = {

0 commit comments

Comments
 (0)