Re: [PATCH v2 4/8] ACPI: property: Generate camera swnodes for ACPI and DisCo for Imaging

Sakari Ailus
2023-01-25T08:57:14Z

Hi Andy,

On Tue, Jan 24, 2023 at 09:26:31PM +0200, Andy Shevchenko wrote:
> On Mon, Jan 23, 2023 at 03:46:13PM +0200, Sakari Ailus wrote:
>
> As promised the idea of bitmap APIs.
>
> Also I have stumbled over couple of suspicious places. See below.
>
> ...
>
> > +static void init_port_csi2_common(struct acpi_device *device,
> > + struct fwnode_handle *mipi_port_fwnode,
> > + unsigned int *ep_prop_index,
> > + unsigned int port_nr)
> > +{
> > + unsigned int port_index = next_csi2_port_index(device->swnodes, port_nr);
> > + struct acpi_device_software_nodes *ads = device->swnodes;
> > + struct acpi_device_software_node_port *port = &ads->ports[port_index];
> > + unsigned int num_lanes = 0;
> > + union {
> > + u32 val;
>
> // Not sure why this even exists.
> // And hence why do we need union?

We could remove the union, yes, with one more u32 of stack used.

>
> > + /* Data lanes + the clock lane */
> > + u8 val8[BITS_TO_BYTES(ARRAY_SIZE(port->data_lanes) + 1)];
> > + } u;
>
> Somewhere
>
> #define MAX_LANES(port) (ARRAY_SIZE((port)->data_lanes) + 1)
>
> u8 val8[BITS_TO_BYTES(MAX_LANES(port))];
>
> ...
>
> /* Data lanes + the clock lane */
> DECLARE_BITMAP(polarity, MAX_LANES(port)));
>
> > + int ret;
> > +
> > + *ep_prop_index = ACPI_DEVICE_SWNODE_EP_CLOCK_LANES;
> > +
> > + if (GRAPH_PORT_NAME(port->port_name, port_nr))
> > + return;
> > +
> > + ads->nodes[ACPI_DEVICE_SWNODE_PRT(port_index)] =
> > + SOFTWARE_NODE(port->port_name, port->port_props,
> > + &ads->nodes[ACPI_DEVICE_SWNODE_ROOT]);
> > +
> > + ret = fwnode_property_read_u8(mipi_port_fwnode, "mipi-img-clock-lane", u.val8);
> > + if (!ret) {
> > + port->ep_props[NEXT_PROPERTY(*ep_prop_index, EP_CLOCK_LANES)] =
> > + PROPERTY_ENTRY_U32("clock-lanes", *u.val8);
> > + }
>
> > + ret = fwnode_property_count_u8(mipi_port_fwnode, "mipi-img-data-lanes");
> > + if (ret > 0) {
> > + num_lanes = ret;
> > +
> > + if (num_lanes > ARRAY_SIZE(port->data_lanes)) {
>
> >= MAX_LANES(port)

I find the original better: it does this by referring to the array itself.

>
> > + acpi_handle_warn(acpi_device_handle(device),
> > + "too many data lanes (%u)\n",
> > + num_lanes);
> > + num_lanes = ARRAY_SIZE(port->data_lanes);
>
> = MAX_LANES(port) - 1;
>
> > + }
> > +
> > + ret = fwnode_property_read_u8_array(mipi_port_fwnode, "mipi-img-data-lanes",
> > + u.val8, num_lanes);
>
> > + if (!ret) {
> > + unsigned int i;
> > +
> > + for (i = 0; i < num_lanes; i++)
> > + port->data_lanes[i] = u.val8[i];
> > +
> > + port->ep_props[NEXT_PROPERTY(*ep_prop_index, EP_DATA_LANES)] =
> > + PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes", port->data_lanes,
> > + num_lanes);
> > + }
> > + }
>
> > + ret = fwnode_property_read_u8_array(mipi_port_fwnode,
> > + "mipi-img-lane-polarities",
> > + u.val8, sizeof(u.val8));
> > + if (ret > 0) {
>
> How is it supposed to work?!

Hmm. I think in the past, some of these functions have returned the number
of the entries even when the buffer is provided
(acpi_copy_property_array_string() still does!). Good catch, I'll fix this
for v3.

>
> > + unsigned int bytes = ret;
> > +
> > + /* Total number of lanes here is clock lane + data lanes */
> > + if (bytes * BITS_PER_TYPE(u8) >= 1 + num_lanes) {
> > + unsigned int i;
> > +
> > + /* Move polarity bits to the lane polarity u32 array */
> > + for (i = 0; i < 1 + num_lanes; i++)
> > + port->lane_polarities[i] =
> > + (u.val8[i >> 3] & (1 << (i & 7))) ?
> > + 1U : 0U;
> > +
> > + port->ep_props[NEXT_PROPERTY(*ep_prop_index, EP_LANE_POLARITIES)] =
> > + PROPERTY_ENTRY_U32_ARRAY_LEN("lane-polarities",
> > + port->lane_polarities,
> > + 1 + num_lanes);
> > + } else {
> > + acpi_handle_warn(acpi_device_handle(device),
> > + "too few lane polarity bytes (%u)\n",
> > + bytes);
> > + }
> > + }
>
> ret = fwnode_property_count_u8(mipi_port_fwnode, "mipi-img-dlane-polarities");
> if (ret < 0) {
> acpi_handle_debug(acpi_device_handle(device),
> "no lane polarity provided\n");
> } else if (ret < 1 + num_lanes) {
> acpi_handle_warn(acpi_device_handle(device),
> "too few lane polarity bytes (%u)\n", bytes);
> } else {
> // assuming we dropped the union and renamed to val...
> ret = fwnode_property_read_u8_array(mipi_port_fwnode,
> "mipi-img-lane-polarities",
> val, sizeof(val));
> if (ret) {
> ...can't read... (debug message?)
> } else {
> unsigned int i;
>
> for (i = 0; i < 1 + num_lanes; i++)
> bitmap_set_value8(polarity, val[i], i * BITS_PER_BYTE);

You'll still needed to access invididual bits in val.

>
> // assuming that lane_polarities is zeroed by default...
> for_each_set_bit(i, polarity, 1 + num_lanes)
> port->lane_polarities[i] = 1;
> }
> }
>
> > + ads->nodes[ACPI_DEVICE_SWNODE_EP(port_index)] =
> > + SOFTWARE_NODE("endpoint@0", ads->ports[port_index].ep_props,
> > + &ads->nodes[ACPI_DEVICE_SWNODE_PRT(port_index)]);
> > +}

--
Kind regards,

Sakari Ailus