From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> To: Dan Scally <djrscally@gmail.com> Cc: Sakari Ailus <sakari.ailus@linux.intel.com>, yong.zhi@intel.com, bingbu.cao@intel.com, tian.shu.qiu@intel.com, mchehab@kernel.org, gregkh@linuxfoundation.org, davem@davemloft.net, robh@kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, devel@driverdev.osuosl.org, jorhand@linux.microsoft.com, kitakar@gmail.com, kieran.bingham@ideasonboard.com Subject: Re: [RFC PATCH] Add bridge driver to connect sensors to CIO2 device via software nodes on ACPI platforms Date: Thu, 17 Sep 2020 15:45:14 +0300 [thread overview] Message-ID: <20200917124514.GK3956970@smile.fi.intel.com> (raw) In-Reply-To: <8133a57d-ab4c-dccd-4325-9b10e7805648@gmail.com> On Thu, Sep 17, 2020 at 11:52:28AM +0100, Dan Scally wrote: > On 17/09/2020 11:33, Sakari Ailus wrote: I will do better review for next version, assuming you will Cc reviewers and TWIMC people. Below is like small part of comments I may give to the code. ... > > The ones I know require PMIC control done in software (not even > > sensors are accessible without that). > So far we've just been getting the sensor drivers themselves to toggle > the gpio pins that turn the PMIC on (those pins are listed against the > PMIC's _CRS, and we've been finding those by evaluating the sensor's > _DEP) - once that's done the cameras show up on i2c and,with the bridge > driver installed, you can use libcamera to take photos. Do I understand correctly that you are able to get pictures from the camera hardware? ... > > a module and not enlarge everyone's kernel, and the initialisation would at > > the same time take place before the rest of what the CIO2 driver does in > > probe. > I thought of that as well, but wasn't sure which was preferable. I can > compress it into the CIO2 driver though sure. Sakari, I tend to agree with Dan and have the board file separated from the driver and even framework. ... > > Cc Andy, too. Thanks! ... > >> I wanted to raise this as an RFC as although I don't think it's ready for > >> integration it has some things that I'd like feedback on, in particular the > >> method I chose to make the module be auto-inserted. A more ideal method would > >> have been to have the driver be an ACPI driver for the INT343E device, but each > > What do you think this device does represent? Devices whose status is > > always zero may exist in the table even if they would not be actually > > present. > > > > CIO2 is a PCI device and it has no ACPI (or PNP) ID, or at least should not > > have one. > This is the ACPI entry I mean: > > Device (CIO2) > { > Method (_STA, 0, NotSerialized) // _STA: Status > { > If ((CIOE == One)) > { > Return (0x0F) > } > Else > { > Return (Zero) > } > } > > Name (_HID, "INT343E") // _HID: Hardware ID > Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings > { > Name (CBUF, ResourceTemplate () > { > Interrupt (ResourceConsumer, Level, ActiveLow, Shared, ,, _Y15) > { > 0x00000010, > } > Memory32Fixed (ReadWrite, > 0xFE400000, // Address Base > 0x00010000, // Address Length > ) > }) > CreateDWordField (CBUF, \_SB.PCI0.CIO2._CRS._Y15._INT, CIOV) // _INT: Interrupts > CIOV = CIOI /* \CIOI */ > Return (CBUF) /* \_SB_.PCI0.CIO2._CRS.CBUF */ > } > } Ah, I think you misinterpreted the meaning of above. The above is a switch how camera device appears either as PCI or an ACPI. So, it effectively means you should *not* have any relation for this HID until you find a platform where the device is for real enumerated via ACPI. ... > >> +static int cio2_probe_can_progress(struct pci_dev *pci_dev) > >> +{ > >> + void *sensor; Why void? > >> + /* > >> + * On ACPI platforms, we need to probe _after_ sensors wishing to connect > >> + * to cio2 have added a device link. If there are no consumers yet, then > >> + * we need to defer. The .sync_state() callback will then be called after > >> + * all linked sensors have probed > >> + */ > >> + > >> + if (IS_ENABLED(CONFIG_ACPI)) { > >> + sensor = (struct device *)list_first_entry_or_null( Besides the fact that castings from or to void * are implicit in C, the proper use of list API should have pretty well defined type of lvalue. > >> + &pci_dev->dev.links.consumers, > >> + struct dev_links_info, > >> + consumers); > > Please wrap so it's under 80. > > > Will do > >> + > >> + if (!sensor) > >> + return -EPROBE_DEFER; > >> + } > >> + > >> + return 0; > >> +} ... > >> + if (!IS_ENABLED(CONFIG_ACPI)) { > >> + r = cio2_parse_firmware(cio2); > >> + if (r) > >> + goto fail_clean_notifier; > >> + } How comes? ... > >> \ No newline at end of file ??? Be sure you are using good editor. ... > >> +#include <acpi/acpi_bus.h> Redundant. ACPI headers are designed the way that you are using a single header in Linux kernel for all. It might be different in drivers/acpi stuff, but not in general. > >> +#include <linux/device.h> > >> +#include <linux/i2c.h> > >> +#include <linux/kernel.h> > >> +#include <linux/module.h> > >> +#include <linux/pci.h> > >> +#include <media/v4l2-subdev.h> > >> + > >> +#include <linux/fwnode.h> > >> +#include <linux/kref.h> Please, keep them sorted. And since it's for media, the media inclusion may be placed last in a separate group. ... > >> +#define PROPERTY_ENTRY_NULL \ > >> +((const struct property_entry) { }) > > Alignment. Same appears to apply to other macros (please indent). > Yep > > > >> +#define SOFTWARE_NODE_NULL \ > >> +((const struct software_node) { }) Why?! ... > >> +struct software_node cio2_hid_node = { CIO2_HID, }; static ? Same for other global variables. ... > >> +struct cio2_bridge bridge = { 0, }; When define as static the assignment will not be needed. ... > >> +static int read_acpi_block(struct device *dev, char *id, void *data, u32 size) > >> +{ > >> + union acpi_object *obj; > >> + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; > >> + struct acpi_handle *dev_handle = ACPI_HANDLE(dev); Usually we use simple handle if there is no ambiguous reading. > >> + int status; Should be acpi_status > >> + u32 buffer_length; > >> + > >> + status = acpi_evaluate_object(dev_handle, id, NULL, &buffer); > >> + if (!ACPI_SUCCESS(status)) ACPI_FAILURE() > >> + return -ENODEV; > >> + > >> + obj = (union acpi_object *)buffer.pointer; Why explicit casting? > >> + if (!obj || obj->type != ACPI_TYPE_BUFFER) { > >> + dev_err(dev, "Could't read acpi buffer\n"); > >> + status = -ENODEV; Should have different int type variable for that. > >> + goto err; If there is no obj, you may return directly without freeing. > >> + } > >> + > >> + if (obj->buffer.length > size) { > >> + dev_err(dev, "Given buffer is too small\n"); > >> + status = -ENODEV; > >> + goto err; > >> + } > >> + > >> + memcpy(data, obj->buffer.pointer, min(size, obj->buffer.length)); Does type of size and length the same? Otherwise you need min_t(). > >> + buffer_length = obj->buffer.length; > >> + kfree(buffer.pointer); > >> + > >> + return buffer_length; > >> +err: Consider naming labels by what they are about to do. Like err_free: here. > >> + kfree(buffer.pointer); > >> + return status; > >> +} > >> +static int get_acpi_ssdb_sensor_data(struct device *dev, > >> + struct sensor_bios_data *sensor) > >> +{ > >> + struct sensor_bios_data_packed sensor_data; > >> + int ret = read_acpi_block(dev, "SSDB", &sensor_data, > >> + sizeof(sensor_data)); Please, split declaration and assignment especially in the cases where it requires long lines. > >> + if (ret < 0) { > >> + dev_err(dev, "Failed to fetch SSDB data\n"); > >> + return ret; > >> + } > >> + > >> + sensor->link = sensor_data.link; > >> + sensor->lanes = sensor_data.lanes; > >> + sensor->mclkspeed = sensor_data.mclkspeed; > >> + > >> + return 0; > >> +} ... > >> + if (!dev->driver_data) { > >> + pr_info("ACPI match for %s, but it has no driver\n", > >> + supported_devices[i]); > >> + continue; > >> + } else { > >> + pr_info("Found supported device %s\n", > >> + supported_devices[i]); > >> + } Positive conditions are easier to read, but on the other hand 'else' is redundant in such conditionals (where if branch bails out from the flow). -- With Best Regards, Andy Shevchenko
WARNING: multiple messages have this Message-ID (diff)
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> To: Dan Scally <djrscally@gmail.com> Cc: devel@driverdev.osuosl.org, robh@kernel.org, jorhand@linux.microsoft.com, linux-media@vger.kernel.org, gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, kieran.bingham@ideasonboard.com, kitakar@gmail.com, Sakari Ailus <sakari.ailus@linux.intel.com>, bingbu.cao@intel.com, mchehab@kernel.org, davem@davemloft.net, tian.shu.qiu@intel.com, yong.zhi@intel.com Subject: Re: [RFC PATCH] Add bridge driver to connect sensors to CIO2 device via software nodes on ACPI platforms Date: Thu, 17 Sep 2020 15:45:14 +0300 [thread overview] Message-ID: <20200917124514.GK3956970@smile.fi.intel.com> (raw) In-Reply-To: <8133a57d-ab4c-dccd-4325-9b10e7805648@gmail.com> On Thu, Sep 17, 2020 at 11:52:28AM +0100, Dan Scally wrote: > On 17/09/2020 11:33, Sakari Ailus wrote: I will do better review for next version, assuming you will Cc reviewers and TWIMC people. Below is like small part of comments I may give to the code. ... > > The ones I know require PMIC control done in software (not even > > sensors are accessible without that). > So far we've just been getting the sensor drivers themselves to toggle > the gpio pins that turn the PMIC on (those pins are listed against the > PMIC's _CRS, and we've been finding those by evaluating the sensor's > _DEP) - once that's done the cameras show up on i2c and,with the bridge > driver installed, you can use libcamera to take photos. Do I understand correctly that you are able to get pictures from the camera hardware? ... > > a module and not enlarge everyone's kernel, and the initialisation would at > > the same time take place before the rest of what the CIO2 driver does in > > probe. > I thought of that as well, but wasn't sure which was preferable. I can > compress it into the CIO2 driver though sure. Sakari, I tend to agree with Dan and have the board file separated from the driver and even framework. ... > > Cc Andy, too. Thanks! ... > >> I wanted to raise this as an RFC as although I don't think it's ready for > >> integration it has some things that I'd like feedback on, in particular the > >> method I chose to make the module be auto-inserted. A more ideal method would > >> have been to have the driver be an ACPI driver for the INT343E device, but each > > What do you think this device does represent? Devices whose status is > > always zero may exist in the table even if they would not be actually > > present. > > > > CIO2 is a PCI device and it has no ACPI (or PNP) ID, or at least should not > > have one. > This is the ACPI entry I mean: > > Device (CIO2) > { > Method (_STA, 0, NotSerialized) // _STA: Status > { > If ((CIOE == One)) > { > Return (0x0F) > } > Else > { > Return (Zero) > } > } > > Name (_HID, "INT343E") // _HID: Hardware ID > Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings > { > Name (CBUF, ResourceTemplate () > { > Interrupt (ResourceConsumer, Level, ActiveLow, Shared, ,, _Y15) > { > 0x00000010, > } > Memory32Fixed (ReadWrite, > 0xFE400000, // Address Base > 0x00010000, // Address Length > ) > }) > CreateDWordField (CBUF, \_SB.PCI0.CIO2._CRS._Y15._INT, CIOV) // _INT: Interrupts > CIOV = CIOI /* \CIOI */ > Return (CBUF) /* \_SB_.PCI0.CIO2._CRS.CBUF */ > } > } Ah, I think you misinterpreted the meaning of above. The above is a switch how camera device appears either as PCI or an ACPI. So, it effectively means you should *not* have any relation for this HID until you find a platform where the device is for real enumerated via ACPI. ... > >> +static int cio2_probe_can_progress(struct pci_dev *pci_dev) > >> +{ > >> + void *sensor; Why void? > >> + /* > >> + * On ACPI platforms, we need to probe _after_ sensors wishing to connect > >> + * to cio2 have added a device link. If there are no consumers yet, then > >> + * we need to defer. The .sync_state() callback will then be called after > >> + * all linked sensors have probed > >> + */ > >> + > >> + if (IS_ENABLED(CONFIG_ACPI)) { > >> + sensor = (struct device *)list_first_entry_or_null( Besides the fact that castings from or to void * are implicit in C, the proper use of list API should have pretty well defined type of lvalue. > >> + &pci_dev->dev.links.consumers, > >> + struct dev_links_info, > >> + consumers); > > Please wrap so it's under 80. > > > Will do > >> + > >> + if (!sensor) > >> + return -EPROBE_DEFER; > >> + } > >> + > >> + return 0; > >> +} ... > >> + if (!IS_ENABLED(CONFIG_ACPI)) { > >> + r = cio2_parse_firmware(cio2); > >> + if (r) > >> + goto fail_clean_notifier; > >> + } How comes? ... > >> \ No newline at end of file ??? Be sure you are using good editor. ... > >> +#include <acpi/acpi_bus.h> Redundant. ACPI headers are designed the way that you are using a single header in Linux kernel for all. It might be different in drivers/acpi stuff, but not in general. > >> +#include <linux/device.h> > >> +#include <linux/i2c.h> > >> +#include <linux/kernel.h> > >> +#include <linux/module.h> > >> +#include <linux/pci.h> > >> +#include <media/v4l2-subdev.h> > >> + > >> +#include <linux/fwnode.h> > >> +#include <linux/kref.h> Please, keep them sorted. And since it's for media, the media inclusion may be placed last in a separate group. ... > >> +#define PROPERTY_ENTRY_NULL \ > >> +((const struct property_entry) { }) > > Alignment. Same appears to apply to other macros (please indent). > Yep > > > >> +#define SOFTWARE_NODE_NULL \ > >> +((const struct software_node) { }) Why?! ... > >> +struct software_node cio2_hid_node = { CIO2_HID, }; static ? Same for other global variables. ... > >> +struct cio2_bridge bridge = { 0, }; When define as static the assignment will not be needed. ... > >> +static int read_acpi_block(struct device *dev, char *id, void *data, u32 size) > >> +{ > >> + union acpi_object *obj; > >> + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; > >> + struct acpi_handle *dev_handle = ACPI_HANDLE(dev); Usually we use simple handle if there is no ambiguous reading. > >> + int status; Should be acpi_status > >> + u32 buffer_length; > >> + > >> + status = acpi_evaluate_object(dev_handle, id, NULL, &buffer); > >> + if (!ACPI_SUCCESS(status)) ACPI_FAILURE() > >> + return -ENODEV; > >> + > >> + obj = (union acpi_object *)buffer.pointer; Why explicit casting? > >> + if (!obj || obj->type != ACPI_TYPE_BUFFER) { > >> + dev_err(dev, "Could't read acpi buffer\n"); > >> + status = -ENODEV; Should have different int type variable for that. > >> + goto err; If there is no obj, you may return directly without freeing. > >> + } > >> + > >> + if (obj->buffer.length > size) { > >> + dev_err(dev, "Given buffer is too small\n"); > >> + status = -ENODEV; > >> + goto err; > >> + } > >> + > >> + memcpy(data, obj->buffer.pointer, min(size, obj->buffer.length)); Does type of size and length the same? Otherwise you need min_t(). > >> + buffer_length = obj->buffer.length; > >> + kfree(buffer.pointer); > >> + > >> + return buffer_length; > >> +err: Consider naming labels by what they are about to do. Like err_free: here. > >> + kfree(buffer.pointer); > >> + return status; > >> +} > >> +static int get_acpi_ssdb_sensor_data(struct device *dev, > >> + struct sensor_bios_data *sensor) > >> +{ > >> + struct sensor_bios_data_packed sensor_data; > >> + int ret = read_acpi_block(dev, "SSDB", &sensor_data, > >> + sizeof(sensor_data)); Please, split declaration and assignment especially in the cases where it requires long lines. > >> + if (ret < 0) { > >> + dev_err(dev, "Failed to fetch SSDB data\n"); > >> + return ret; > >> + } > >> + > >> + sensor->link = sensor_data.link; > >> + sensor->lanes = sensor_data.lanes; > >> + sensor->mclkspeed = sensor_data.mclkspeed; > >> + > >> + return 0; > >> +} ... > >> + if (!dev->driver_data) { > >> + pr_info("ACPI match for %s, but it has no driver\n", > >> + supported_devices[i]); > >> + continue; > >> + } else { > >> + pr_info("Found supported device %s\n", > >> + supported_devices[i]); > >> + } Positive conditions are easier to read, but on the other hand 'else' is redundant in such conditionals (where if branch bails out from the flow). -- With Best Regards, Andy Shevchenko _______________________________________________ devel mailing list devel@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
next prev parent reply other threads:[~2020-09-17 12:55 UTC|newest] Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-09-16 21:36 [RFC PATCH] Add bridge driver to connect sensors to CIO2 device via software nodes on ACPI platforms Daniel Scally 2020-09-16 21:36 ` Daniel Scally 2020-09-17 0:17 ` kernel test robot 2020-09-17 3:02 ` kernel test robot 2020-09-17 7:53 ` Greg KH 2020-09-17 7:53 ` Greg KH 2020-09-17 9:47 ` Dan Scally 2020-09-17 9:47 ` Dan Scally 2020-09-17 10:15 ` Dan Carpenter 2020-09-17 10:15 ` Dan Carpenter 2020-09-17 10:24 ` Dan Scally 2020-09-17 10:24 ` Dan Scally 2020-09-17 13:28 ` Kieran Bingham 2020-09-17 13:28 ` Kieran Bingham 2020-09-17 14:08 ` Andy Shevchenko 2020-09-17 14:08 ` Andy Shevchenko 2020-09-17 14:19 ` Kieran Bingham 2020-09-17 14:19 ` Kieran Bingham 2020-09-17 14:36 ` Andy Shevchenko 2020-09-17 14:36 ` Andy Shevchenko 2020-09-17 9:34 ` Dan Carpenter 2020-09-17 9:34 ` Dan Carpenter 2020-09-17 10:19 ` Joe Perches 2020-09-17 10:19 ` Joe Perches 2020-09-18 22:50 ` Dan Scally 2020-09-18 22:50 ` Dan Scally 2020-09-17 10:33 ` Sakari Ailus 2020-09-17 10:33 ` Sakari Ailus 2020-09-17 10:49 ` Dan Carpenter 2020-09-17 10:49 ` Dan Carpenter 2020-09-17 12:25 ` Andy Shevchenko 2020-09-17 12:25 ` Andy Shevchenko 2020-09-17 13:15 ` Dan Carpenter 2020-09-17 13:15 ` Dan Carpenter 2020-09-18 6:40 ` Sakari Ailus 2020-09-18 6:40 ` Sakari Ailus 2020-09-18 8:16 ` Dan Carpenter 2020-09-18 8:16 ` Dan Carpenter 2020-09-17 10:52 ` Dan Scally 2020-09-17 10:52 ` Dan Scally 2020-09-17 12:45 ` Andy Shevchenko [this message] 2020-09-17 12:45 ` Andy Shevchenko 2020-09-17 13:36 ` Dan Scally 2020-09-17 13:36 ` Dan Scally 2020-09-17 14:14 ` Andy Shevchenko 2020-09-17 14:14 ` Andy Shevchenko 2020-09-17 21:25 ` Daniel Scally 2020-09-17 21:25 ` Daniel Scally 2020-09-17 14:44 ` Andy Shevchenko 2020-09-17 14:44 ` Andy Shevchenko 2020-09-18 7:51 ` Sakari Ailus 2020-09-18 7:51 ` Sakari Ailus 2020-09-18 13:07 ` Andy Shevchenko 2020-09-18 13:07 ` Andy Shevchenko 2020-09-21 13:33 ` Dan Scally 2020-09-21 13:33 ` Dan Scally 2020-09-21 14:33 ` Andy Shevchenko 2020-09-21 14:33 ` Andy Shevchenko 2020-09-23 9:39 ` Dan Scally 2020-09-23 9:39 ` Dan Scally 2020-09-28 11:37 ` Dan Scally 2020-09-28 11:37 ` Dan Scally 2020-09-18 8:03 ` Dan Carpenter 2020-09-18 8:03 ` Dan Carpenter 2020-09-18 8:09 ` Dan Scally 2020-09-18 8:09 ` Dan Scally 2020-09-20 21:34 ` kernel test robot 2020-09-20 21:34 ` [RFC PATCH] cio2_sync_state() can be static kernel test robot
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200917124514.GK3956970@smile.fi.intel.com \ --to=andriy.shevchenko@linux.intel.com \ --cc=bingbu.cao@intel.com \ --cc=davem@davemloft.net \ --cc=devel@driverdev.osuosl.org \ --cc=djrscally@gmail.com \ --cc=gregkh@linuxfoundation.org \ --cc=jorhand@linux.microsoft.com \ --cc=kieran.bingham@ideasonboard.com \ --cc=kitakar@gmail.com \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-media@vger.kernel.org \ --cc=mchehab@kernel.org \ --cc=robh@kernel.org \ --cc=sakari.ailus@linux.intel.com \ --cc=tian.shu.qiu@intel.com \ --cc=yong.zhi@intel.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.