lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAHp75VdOnUW6kftkD1zGR345fJUPPv9zfi0YitYJOb1BPxQcPw@mail.gmail.com>
Date:   Mon, 16 Nov 2020 15:33:29 +0200
From:   Andy Shevchenko <andy.shevchenko@...il.com>
To:     Maximilian Luz <luzmaximilian@...il.com>
Cc:     Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
        Hans de Goede <hdegoede@...hat.com>,
        Mark Gross <mgross@...ux.intel.com>,
        Arnd Bergmann <arnd@...db.de>,
        Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
        Rob Herring <robh@...nel.org>,
        Jiri Slaby <jirislaby@...nel.org>,
        "Rafael J . Wysocki" <rjw@...ysocki.net>,
        Len Brown <lenb@...nel.org>,
        Blaž Hrastnik <blaz@...n.io>,
        Dorian Stoll <dorian.stoll@...p.io>,
        Platform Driver <platform-driver-x86@...r.kernel.org>,
        "open list:SERIAL DRIVERS" <linux-serial@...r.kernel.org>,
        ACPI Devel Maling List <linux-acpi@...r.kernel.org>
Subject: Re: [PATCH 1/9] platform/surface: Add Surface Aggregator subsystem

On Sun, Nov 15, 2020 at 9:25 PM Maximilian Luz <luzmaximilian@...il.com> wrote:
>
> Add Surface System Aggregator Module core and Surface Serial Hub driver,
> required for the embedded controller found on Microsoft Surface devices.
>
> The Surface System Aggregator Module (SSAM, SAM or Surface Aggregator)
> is an embedded controller (EC) found on 4th and later generation
> Microsoft Surface devices, with the exception of the Surface Go series.
> This EC provides various functionality, depending on the device in
> question. This can include battery status and thermal reporting (5th and
> later generations), but also HID keyboard (6th+) and touchpad input
> (7th+) on Surface Laptop and Surface Book 3 series devices.
>
> This patch provides the basic necessities for communication with the SAM
> EC on 5th and later generation devices. On these devices, the EC
> provides an interface that acts as serial device, called the Surface
> Serial Hub (SSH). 4th generation devices, on which the EC interface is
> provided via an HID-over-I2C device, are not supported by this patch.
>
> Specifically, this patch adds a driver for the SSH device (device HID
> MSHW0084 in ACPI), as well as a controller structure and associated API.
> This represents the functional core of the Surface Aggregator kernel
> subsystem, introduced with this patch, and will be expanded upon in
> subsequent commits.
>
> The SSH driver acts as the main attachment point for this subsystem and
> sets-up and manages the controller structure. The controller in turn
> provides a basic communication interface, allowing to send requests from
> host to EC and receiving the corresponding responses, as well as
> managing and receiving events, sent from EC to host. It is structured
> into multiple layers, with the top layer presenting the API used by
> other kernel drivers and the lower layers modeled after the serial
> protocol used for communication.
>
> Said other drivers are then responsible for providing the (Surface model
> specific) functionality accessible through the EC (e.g. battery status
> reporting, thermal information, ...) via said controller structure and
> API, and will be added in future commits.

...

> +menuconfig SURFACE_AGGREGATOR
> +       tristate "Microsoft Surface System Aggregator Module Subsystem and Drivers"
> +       depends on SERIAL_DEV_BUS
> +       depends on ACPI
> +       select CRC_CCITT
> +       help
> +         The Surface System Aggregator Module (Surface SAM or SSAM) is an
> +         embedded controller (EC) found on 5th- and later-generation Microsoft
> +         Surface devices (i.e. Surface Pro 5, Surface Book 2, Surface Laptop,
> +         and newer, with exception of Surface Go series devices).
> +
> +         Depending on the device in question, this EC provides varying
> +         functionality, including:
> +         - EC access from ACPI via Surface ACPI Notify (5th- and 6th-generation)
> +         - battery status information (all devices)
> +         - thermal sensor access (all devices)
> +         - performance mode / cooling mode control (all devices)
> +         - clipboard detachment system control (Surface Book 2 and 3)
> +         - HID / keyboard input (Surface Laptops, Surface Book 3)
> +
> +         This option controls whether the Surface SAM subsystem core will be
> +         built. This includes a driver for the Surface Serial Hub (SSH), which
> +         is the device responsible for the communication with the EC, and a
> +         basic kernel interface exposing the EC functionality to other client
> +         drivers, i.e. allowing them to make requests to the EC and receive
> +         events from it. Selecting this option alone will not provide any
> +         client drivers and therefore no functionality beyond the in-kernel
> +         interface. Said functionality is the responsibility of the respective
> +         client drivers.
> +
> +         Note: While 4th-generation Surface devices also make use of a SAM EC,
> +         due to a difference in the communication interface of the controller,
> +         only 5th and later generations are currently supported. Specifically,
> +         devices using SAM-over-SSH are supported, whereas devices using
> +         SAM-over-HID, which is used on the 4th generation, are currently not
> +         supported.

>From this help text I didn't get if it will be a module or what if I
chose the above?

...

> +/* -- Safe counters. -------------------------------------------------------- */

Why can't XArray be used here?

...

> +
> +

One blank line is enough

...

> +static bool ssam_event_matches_notifier(
> +               const struct ssam_event_notifier *notif,
> +               const struct ssam_event *event)

Perhaps

static bool
ssam_event_matches_notifier(const struct ssam_event_notifier *n,
               const struct ssam_event *event)

(or even switch to 100 limit, also note notif ->n — no need to repeat same word)

...

> +       nb = rcu_dereference_raw(nh->head);
> +       while (nb) {
> +               nf = container_of(nb, struct ssam_event_notifier, base);
> +               next_nb = rcu_dereference_raw(nb->next);
> +
> +               if (ssam_event_matches_notifier(nf, event)) {
> +                       ret = (ret & SSAM_NOTIF_STATE_MASK) | nb->fn(nf, event);
> +                       if (ret & SSAM_NOTIF_STOP)
> +                               break;

The returned value is a bitmask?!
What are you returning at the end?

> +               }
> +
> +               nb = next_nb;
> +       }

...

> +static int __ssam_nfblk_insert(struct ssam_nf_head *nh, struct ssam_notifier_block *nb)
> +{
> +       struct ssam_notifier_block **link = &nh->head;
> +
> +       while ((*link) != NULL) {
> +               if (unlikely((*link) == nb)) {
> +                       WARN(1, "double register detected");
> +                       return -EINVAL;
> +               }
> +
> +               if (nb->priority > (*link)->priority)
> +                       break;
> +
> +               link = &((*link)->next);
> +       }
> +
> +       nb->next = *link;
> +       rcu_assign_pointer(*link, nb);
> +
> +       return 0;
> +}

If you need RCU (which is also the Q per se), why not use RCU list?

...

> +       while ((*link) != NULL) {

Redundant parentheses, redundant ' != NULL' part.

> +               if ((*link) == nb)
> +                       return link;
> +
> +               link = &((*link)->next);
> +       }

...

> + * struct ssam_nf_refcount_entry - RB-tree entry for referecnce counting event

In above you mistyped 'which' as 'whic' or so, and here reference.
Perhaps go thru spell checker?

...

> + * registered, or ``ERR_PTR(-ENOMEM)`` if the entry could not be allocated.

Better to spell out "error pointer" instead of cryptic ERR_PTR().

...

> + * Executa registered callbacks in order of their priority until either no
> + * callback is left or a callback returned a value with the %SSAM_NOTIF_STOP

returns

> + * bit set. Note that this bit is set automatically when converting non.zero
> + * error values via ssam_notifier_from_errno() to notifier values.

...

> +               for (i = i - 1; i >= 0; i--)

while (i--)

> +                       ssam_nf_head_destroy(&nf->head[i]);

...

> +       // limit number of processed events to avoid livelocking
> +       for (i = 0; i < 10; i++) {

Magic number! Also, this will be better to read in a form of

unsigned int iterations = 10;

do {
...
} while (--iterations);

> +               item = ssam_event_queue_pop(queue);
> +               if (item == NULL)
> +                       return;
> +
> +               ssam_nf_call(nf, dev, item->rqid, &item->event);
> +               kfree(item);
> +       }

...

> +static const guid_t SSAM_SSH_DSM_GUID = GUID_INIT(0xd5e383e1, 0xd892, 0x4a76,
> +               0x89, 0xfc, 0xf6, 0xaa, 0xae, 0x7e, 0xd5, 0xb5);

Can you use usual pattern for these UIDs, like
static const guid_t SSAM_SSH_DSM_GUID =
        GUID_INIT(0xd5e383e1, 0xd892, 0x4a76,
                 0x89, 0xfc, 0xf6, 0xaa, 0xae, 0x7e, 0xd5, 0xb5);
?

Also put a comment how this UID will look like in a string representation.

...

> +       if (!acpi_has_method(handle, "_DSM"))
> +               return 0;

Hmm... What's the expectation?

> +       obj = acpi_evaluate_dsm_typed(handle, &SSAM_SSH_DSM_GUID,
> +                                     SSAM_SSH_DSM_REVISION, 0, NULL,
> +                                     ACPI_TYPE_BUFFER);
> +       if (!obj)
> +               return -EFAULT;

EFAULT?! Perhaps you can simply return 0 here, no?

> +       for (i = 0; i < obj->buffer.length && i < 8; i++)
> +               mask |= (((u64)obj->buffer.pointer[i]) << (i * 8));

Don't we have some helpers for this? At least I remember similar code
went to one of PDx86 drivers like intel-vbtn or so.

> +       if (mask & 0x01)

BIT(0) ?

> +               *funcs = mask;

...

> +       caps->ssh_power_profile = (u32)-1;
> +       caps->screen_on_sleep_idle_timeout = (u32)-1;
> +       caps->screen_off_sleep_idle_timeout = (u32)-1;
> +       caps->d3_closes_handle = false;
> +       caps->ssh_buffer_size = (u32)-1;

Use proper types and their limits (limits.h missed?).

...

> +       // initialize request and packet transport layers

Inconsistent style of comments.

...

> + * In the course of this shutdown procedure, all currently registered
> + * notifiers will be unregistered. It is, however, strongly recommended to not
> + * rely on this behavior, and instead the party registring the notifier should

registering

> + * unregister it before the controller gets shut down, e.g. via the SSAM bus
> + * which guarantees client devices to be removed before a shutdown.

> + * Note that events may still be pending after this call, but due to the
> + * notifiers being unregistered, the will be dropped when the controller is

the?!

> + * subsequently being destroyed via ssam_controller_destroy().

...

> + * Ensures that all resources associated with the controller get freed. This
> + * function should only be called after the controller has been stopped via
> + * ssam_controller_shutdown(). In general, this function should not be called
> + * directly. The only valid place to call this function direclty is during

directly

> + * initialization, before the controller has been fully initialized and passed
> + * to other processes. This function is called automatically when the
> + * reference count of the controller reaches zero.

...

> + * ssam_request_sync_free() - Free a synchronous request.
> + * @rqst: The request to free.

to be freed?

...

> + * Allocates a synchronous request struct on the stack, fully initializes it
> + * using the provided buffer as message data buffer, submits it, and then
> + * waits for its completion before returning its staus. The

status

> + * SSH_COMMAND_MESSAGE_LENGTH() macro can be used to compute the required
> + * message buffer size.

...

> + * This is a wrapper for the raw SAM request to enable an event, thus it does
> + * not handle referecnce counting for enable/disable of events. If an event
> + * has already been enabled, the EC will ignore this request.

Grammar and English language style somehow feels not okay.

...

> +       u8 buf[1] = { 0x00 };

Can't be simply buf ?

...

> + * This function will only send the display-off notification command if
> + * display noticications are supported by the EC. Currently all known devices
> + * support these notification.

Spell check!

...

> + * This function will only send the display-on notification command if display
> + * noticications are supported by the EC. Currently all known devices support
> + * these notification.

Ditto.

...

> +               ssam_err(ctrl, "unexpected response from D0-exit notification:"
> +                        " 0x%02x\n", response);

Don't split string literals. Had you run a checkpatch?
Please do and use strict mode.


...

Overall impression of this submission:
 - it's quite huge as for a single patch
 - it feels like quite an overengineered solution: READ_ONCE, RCU,
list + spin_lock, RB tree of notifiers, my head!
 - where is the architectural document of all these?

-- 
With Best Regards,
Andy Shevchenko

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ