.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
| 3 | + * Copyright (c) 2012-2019, Intel Corporation. All rights reserved. |
---|
2 | 4 | * Intel Management Engine Interface (Intel MEI) Linux driver |
---|
3 | | - * Copyright (c) 2012-2013, Intel Corporation. |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms and conditions of the GNU General Public License, |
---|
7 | | - * version 2, as published by the Free Software Foundation. |
---|
8 | | - * |
---|
9 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
---|
10 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
11 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
12 | | - * more details. |
---|
13 | | - * |
---|
14 | 5 | */ |
---|
15 | 6 | |
---|
16 | 7 | #include <linux/module.h> |
---|
.. | .. |
---|
28 | 19 | #include "client.h" |
---|
29 | 20 | |
---|
30 | 21 | #define to_mei_cl_driver(d) container_of(d, struct mei_cl_driver, driver) |
---|
31 | | -#define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev) |
---|
32 | 22 | |
---|
33 | 23 | /** |
---|
34 | 24 | * __mei_cl_send - internal client send (write) |
---|
.. | .. |
---|
162 | 152 | if (timeout) { |
---|
163 | 153 | rets = wait_event_interruptible_timeout |
---|
164 | 154 | (cl->rx_wait, |
---|
165 | | - (!list_empty(&cl->rd_completed)) || |
---|
| 155 | + mei_cl_read_cb(cl, NULL) || |
---|
166 | 156 | (!mei_cl_is_connected(cl)), |
---|
167 | 157 | msecs_to_jiffies(timeout)); |
---|
168 | 158 | if (rets == 0) |
---|
.. | .. |
---|
175 | 165 | } else { |
---|
176 | 166 | if (wait_event_interruptible |
---|
177 | 167 | (cl->rx_wait, |
---|
178 | | - (!list_empty(&cl->rd_completed)) || |
---|
| 168 | + mei_cl_read_cb(cl, NULL) || |
---|
179 | 169 | (!mei_cl_is_connected(cl)))) { |
---|
180 | 170 | if (signal_pending(current)) |
---|
181 | 171 | return -EINTR; |
---|
.. | .. |
---|
208 | 198 | rets = r_length; |
---|
209 | 199 | |
---|
210 | 200 | free: |
---|
211 | | - mei_io_cb_free(cb); |
---|
| 201 | + mei_cl_del_rd_completed(cl, cb); |
---|
212 | 202 | out: |
---|
213 | 203 | mutex_unlock(&bus->device_lock); |
---|
214 | 204 | |
---|
.. | .. |
---|
506 | 496 | } |
---|
507 | 497 | |
---|
508 | 498 | /** |
---|
| 499 | + * mei_cl_bus_vtag - get bus vtag entry wrapper |
---|
| 500 | + * The tag for bus client is always first. |
---|
| 501 | + * |
---|
| 502 | + * @cl: host client |
---|
| 503 | + * |
---|
| 504 | + * Return: bus vtag or NULL |
---|
| 505 | + */ |
---|
| 506 | +static inline struct mei_cl_vtag *mei_cl_bus_vtag(struct mei_cl *cl) |
---|
| 507 | +{ |
---|
| 508 | + return list_first_entry_or_null(&cl->vtag_map, |
---|
| 509 | + struct mei_cl_vtag, list); |
---|
| 510 | +} |
---|
| 511 | + |
---|
| 512 | +/** |
---|
| 513 | + * mei_cl_bus_vtag_alloc - add bus client entry to vtag map |
---|
| 514 | + * |
---|
| 515 | + * @cldev: me client device |
---|
| 516 | + * |
---|
| 517 | + * Return: |
---|
| 518 | + * * 0 on success |
---|
| 519 | + * * -ENOMEM if memory allocation failed |
---|
| 520 | + */ |
---|
| 521 | +static int mei_cl_bus_vtag_alloc(struct mei_cl_device *cldev) |
---|
| 522 | +{ |
---|
| 523 | + struct mei_cl *cl = cldev->cl; |
---|
| 524 | + struct mei_cl_vtag *cl_vtag; |
---|
| 525 | + |
---|
| 526 | + /* |
---|
| 527 | + * Bail out if the client does not supports vtags |
---|
| 528 | + * or has already allocated one |
---|
| 529 | + */ |
---|
| 530 | + if (mei_cl_vt_support_check(cl) || mei_cl_bus_vtag(cl)) |
---|
| 531 | + return 0; |
---|
| 532 | + |
---|
| 533 | + cl_vtag = mei_cl_vtag_alloc(NULL, 0); |
---|
| 534 | + if (IS_ERR(cl_vtag)) |
---|
| 535 | + return -ENOMEM; |
---|
| 536 | + |
---|
| 537 | + list_add_tail(&cl_vtag->list, &cl->vtag_map); |
---|
| 538 | + |
---|
| 539 | + return 0; |
---|
| 540 | +} |
---|
| 541 | + |
---|
| 542 | +/** |
---|
| 543 | + * mei_cl_bus_vtag_free - remove the bus entry from vtag map |
---|
| 544 | + * |
---|
| 545 | + * @cldev: me client device |
---|
| 546 | + */ |
---|
| 547 | +static void mei_cl_bus_vtag_free(struct mei_cl_device *cldev) |
---|
| 548 | +{ |
---|
| 549 | + struct mei_cl *cl = cldev->cl; |
---|
| 550 | + struct mei_cl_vtag *cl_vtag; |
---|
| 551 | + |
---|
| 552 | + cl_vtag = mei_cl_bus_vtag(cl); |
---|
| 553 | + if (!cl_vtag) |
---|
| 554 | + return; |
---|
| 555 | + |
---|
| 556 | + list_del(&cl_vtag->list); |
---|
| 557 | + kfree(cl_vtag); |
---|
| 558 | +} |
---|
| 559 | + |
---|
| 560 | +/** |
---|
509 | 561 | * mei_cldev_enable - enable me client device |
---|
510 | 562 | * create connection with me client |
---|
511 | 563 | * |
---|
.. | .. |
---|
541 | 593 | goto out; |
---|
542 | 594 | } |
---|
543 | 595 | |
---|
| 596 | + ret = mei_cl_bus_vtag_alloc(cldev); |
---|
| 597 | + if (ret) |
---|
| 598 | + goto out; |
---|
| 599 | + |
---|
544 | 600 | ret = mei_cl_connect(cl, cldev->me_cl, NULL); |
---|
545 | | - if (ret < 0) |
---|
| 601 | + if (ret < 0) { |
---|
546 | 602 | dev_err(&cldev->dev, "cannot connect\n"); |
---|
| 603 | + mei_cl_bus_vtag_free(cldev); |
---|
| 604 | + } |
---|
547 | 605 | |
---|
548 | 606 | out: |
---|
549 | 607 | mutex_unlock(&bus->device_lock); |
---|
.. | .. |
---|
595 | 653 | mei_cldev_unregister_callbacks(cldev); |
---|
596 | 654 | |
---|
597 | 655 | mutex_lock(&bus->device_lock); |
---|
| 656 | + |
---|
| 657 | + mei_cl_bus_vtag_free(cldev); |
---|
598 | 658 | |
---|
599 | 659 | if (!mei_cl_is_connected(cl)) { |
---|
600 | 660 | dev_dbg(bus->dev, "Already disconnected\n"); |
---|
.. | .. |
---|
774 | 834 | struct mei_cl_device *cldev = to_mei_cl_device(dev); |
---|
775 | 835 | const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl); |
---|
776 | 836 | |
---|
777 | | - return scnprintf(buf, PAGE_SIZE, "%pUl", uuid); |
---|
| 837 | + return sprintf(buf, "%pUl", uuid); |
---|
778 | 838 | } |
---|
779 | 839 | static DEVICE_ATTR_RO(uuid); |
---|
780 | 840 | |
---|
.. | .. |
---|
784 | 844 | struct mei_cl_device *cldev = to_mei_cl_device(dev); |
---|
785 | 845 | u8 version = mei_me_cl_ver(cldev->me_cl); |
---|
786 | 846 | |
---|
787 | | - return scnprintf(buf, PAGE_SIZE, "%02X", version); |
---|
| 847 | + return sprintf(buf, "%02X", version); |
---|
788 | 848 | } |
---|
789 | 849 | static DEVICE_ATTR_RO(version); |
---|
790 | 850 | |
---|
.. | .. |
---|
800 | 860 | } |
---|
801 | 861 | static DEVICE_ATTR_RO(modalias); |
---|
802 | 862 | |
---|
| 863 | +static ssize_t max_conn_show(struct device *dev, struct device_attribute *a, |
---|
| 864 | + char *buf) |
---|
| 865 | +{ |
---|
| 866 | + struct mei_cl_device *cldev = to_mei_cl_device(dev); |
---|
| 867 | + u8 maxconn = mei_me_cl_max_conn(cldev->me_cl); |
---|
| 868 | + |
---|
| 869 | + return sprintf(buf, "%d", maxconn); |
---|
| 870 | +} |
---|
| 871 | +static DEVICE_ATTR_RO(max_conn); |
---|
| 872 | + |
---|
| 873 | +static ssize_t fixed_show(struct device *dev, struct device_attribute *a, |
---|
| 874 | + char *buf) |
---|
| 875 | +{ |
---|
| 876 | + struct mei_cl_device *cldev = to_mei_cl_device(dev); |
---|
| 877 | + u8 fixed = mei_me_cl_fixed(cldev->me_cl); |
---|
| 878 | + |
---|
| 879 | + return sprintf(buf, "%d", fixed); |
---|
| 880 | +} |
---|
| 881 | +static DEVICE_ATTR_RO(fixed); |
---|
| 882 | + |
---|
| 883 | +static ssize_t vtag_show(struct device *dev, struct device_attribute *a, |
---|
| 884 | + char *buf) |
---|
| 885 | +{ |
---|
| 886 | + struct mei_cl_device *cldev = to_mei_cl_device(dev); |
---|
| 887 | + bool vt = mei_me_cl_vt(cldev->me_cl); |
---|
| 888 | + |
---|
| 889 | + return sprintf(buf, "%d", vt); |
---|
| 890 | +} |
---|
| 891 | +static DEVICE_ATTR_RO(vtag); |
---|
| 892 | + |
---|
| 893 | +static ssize_t max_len_show(struct device *dev, struct device_attribute *a, |
---|
| 894 | + char *buf) |
---|
| 895 | +{ |
---|
| 896 | + struct mei_cl_device *cldev = to_mei_cl_device(dev); |
---|
| 897 | + u32 maxlen = mei_me_cl_max_len(cldev->me_cl); |
---|
| 898 | + |
---|
| 899 | + return sprintf(buf, "%u", maxlen); |
---|
| 900 | +} |
---|
| 901 | +static DEVICE_ATTR_RO(max_len); |
---|
| 902 | + |
---|
803 | 903 | static struct attribute *mei_cldev_attrs[] = { |
---|
804 | 904 | &dev_attr_name.attr, |
---|
805 | 905 | &dev_attr_uuid.attr, |
---|
806 | 906 | &dev_attr_version.attr, |
---|
807 | 907 | &dev_attr_modalias.attr, |
---|
| 908 | + &dev_attr_max_conn.attr, |
---|
| 909 | + &dev_attr_fixed.attr, |
---|
| 910 | + &dev_attr_vtag.attr, |
---|
| 911 | + &dev_attr_max_len.attr, |
---|
808 | 912 | NULL, |
---|
809 | 913 | }; |
---|
810 | 914 | ATTRIBUTE_GROUPS(mei_cldev); |
---|
.. | .. |
---|
908 | 1012 | struct mei_cl_device *cldev; |
---|
909 | 1013 | struct mei_cl *cl; |
---|
910 | 1014 | |
---|
911 | | - cldev = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL); |
---|
| 1015 | + cldev = kzalloc(sizeof(*cldev), GFP_KERNEL); |
---|
912 | 1016 | if (!cldev) |
---|
913 | 1017 | return NULL; |
---|
914 | 1018 | |
---|