From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
To: bingbu.cao@intel.com
Cc: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com,
laurent.pinchart@ideasonboard.com, ilpo.jarvinen@linux.intel.com,
tfiga@chromium.org, senozhatsky@chromium.org,
hdegoede@redhat.com, tomi.valkeinen@ideasonboard.com,
bingbu.cao@linux.intel.com, tian.shu.qiu@intel.com,
hongju.wang@intel.com
Subject: Re: [PATCH 01/15] media: intel/ipu6: add Intel IPU6 PCI device driver
Date: Thu, 27 Jul 2023 13:47:00 +0300 [thread overview]
Message-ID: <ZMJLJGfH3vZDLb6U@smile.fi.intel.com> (raw)
In-Reply-To: <20230727071558.1148653-2-bingbu.cao@intel.com>
On Thu, Jul 27, 2023 at 03:15:44PM +0800, bingbu.cao@intel.com wrote:
> From: Bingbu Cao <bingbu.cao@intel.com>
>
> Intel Image Processing Unit 6th Gen includes input and processing systems
> but the hardware presents itself as a single PCI device in system.
>
> IPU6 PCI device driver basically does PCI configurations and load
> the firmware binary, initialises IPU virtual bus, and sets up platform
> specific variants to support multiple IPU6 devices in single device
> driver.
> +#ifndef IPU6_PLATFORM_REGS_H
> +#define IPU6_PLATFORM_REGS_H
Missing
bits.h
...
> +#define IPU6_ISYS_CSI_PORT_IRQ(irq_num) (1 << (irq_num))
BIT() ?
...
> +#define S2M_PIXEL_SOC_PIXEL_REMAPPING_FLAG_NO_REMAPPING 0xE4o
Why capital?
...
> +/*
> + * csi_be_soc_pixel_remapping is for the enabling of the pixel remapping.
Is it reference to a function? Please use func() format everywhere.
> + * This remapping is exactly like the stream2mmio remapping.
> + */
> +#define CSI_BE_SOC_PIXEL_REMAPPING_FLAG_NO_REMAPPING 0xE4
Why capital?
> +enum nci_ab_access_mode {
> + NCI_AB_ACCESS_MODE_RW, /* read & write */
> + NCI_AB_ACCESS_MODE_RO, /* read only */
> + NCI_AB_ACCESS_MODE_WO, /* write only */
> + NCI_AB_ACCESS_MODE_NA /* No access at all */
Leave trailing comma, since it doesn't look like a terminating entry.
> +};
...
> +#define IPU6_PSYS_GPDEV_IRQ_FWIRQ(n) (1 << (n))
BIT() ?
> +#endif /* IPU6_PLATFORM_REGS_H */
...
> +#ifndef IPU6_PLATFORM_H
> +#define IPU6_PLATFORM_H
> +
> +#include "ipu6-fw-isys.h"
> +
> +#define IPU6_NAME "intel-ipu6"
> +
> +#define IPU6SE_FIRMWARE_NAME "intel/ipu6se_fw.bin"
> +#define IPU6EP_FIRMWARE_NAME "intel/ipu6ep_fw.bin"
> +#define IPU6_FIRMWARE_NAME "intel/ipu6_fw.bin"
> +#define IPU6EPMTL_FIRMWARE_NAME "intel/ipu6epmtl_fw.bin"
Maybe
#define IPU6_FIRMWARE_FOLDER "intel"
#define IPU6SE_FIRMWARE_NAME "ipu6se_fw.bin"
#define IPU6EP_FIRMWARE_NAME "ipu6ep_fw.bin"
#define IPU6_FIRMWARE_NAME "ipu6_fw.bin"
#define IPU6EPMTL_FIRMWARE_NAME "ipu6epmtl_fw.bin"
And then concatenate in the code?
Or
#define IPU6SE_FIRMWARE_NAME IPU6_FIRMWARE_FOLDER "/ipu6se_fw.bin"
#define IPU6EP_FIRMWARE_NAME IPU6_FIRMWARE_FOLDER "/ipu6ep_fw.bin"
#define IPU6_FIRMWARE_NAME IPU6_FIRMWARE_FOLDER "/ipu6_fw.bin"
#define IPU6EPMTL_FIRMWARE_NAME IPU6_FIRMWARE_FOLDER "/ipu6epmtl_fw.bin"
?
> +#endif
...
> +#include <linux/acpi.h>
Not used.
> +#include <linux/bitfield.h>
> +#include <linux/debugfs.h>
> +#include <linux/device.h>
> +#include <linux/interrupt.h>
> +#include <linux/firmware.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/pci.h>
> +#include <linux/pm_qos.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/timer.h>
Check this block if all of them are being used / needed and otherwise,
if something is missing (property.h and slab.h, for example).
> +#include "ipu6.h"
> +#include "ipu6-bus.h"
> +#include "ipu6-buttress.h"
> +#include "ipu6-cpd.h"
> +#include "ipu6-isys.h"
> +#include "ipu6-mmu.h"
> +#include "ipu6-platform.h"
> +#include "ipu6-platform-buttress-regs.h"
> +#include "ipu6-platform-isys-csi2-reg.h"
> +#include "ipu6-platform-regs.h"
> +#include "../ipu-bridge.h"
Ditto.
...
> +struct ipu6_cell_program_t {
No _t.
_t is used for typedef:s.
> + u32 magic_number;
> +
> + u32 blob_offset;
> + u32 blob_size;
> +
> + u32 start[3];
> +
> + u32 icache_source;
> + u32 icache_target;
> + u32 icache_size;
> +
> + u32 pmem_source;
> + u32 pmem_target;
> + u32 pmem_size;
> +
> + u32 data_source;
> + u32 data_target;
> + u32 data_size;
> +
> + u32 bss_target;
> + u32 bss_size;
> +
> + u32 cell_id;
> + u32 regs_addr;
> +
> + u32 cell_pmem_data_bus_address;
> + u32 cell_dmem_data_bus_address;
> + u32 cell_pmem_control_bus_address;
> + u32 cell_dmem_control_bus_address;
> +
> + u32 next;
> + u32 dummy[2];
> +} __packed;
Why?! Please justify this.
...
> + prog = (struct ipu6_cell_program_t *)((u64)isp->cpd_fw->data +
> + (server_fw_addr -
> + dma_addr));
This looks awful. Can you utilise something like offsetof()?
...
> +static int ipu6_isys_check_fwnode_graph(struct fwnode_handle *fwnode)
> +{
> + struct fwnode_handle *endpoint;
> + if (IS_ERR_OR_NULL(fwnode))
> + return -EINVAL;
Isn't this already embedded in the below call?
But okay, you probably know better what's going on here.
> + endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL);
> + if (endpoint) {
> + fwnode_handle_put(endpoint);
> + return 0;
> + }
> +
> + return ipu6_isys_check_fwnode_graph(fwnode->secondary);
> +}
...
> + ret = ipu6_isys_check_fwnode_graph(fwnode);
> + if (ret) {
> + if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary)) {
Why is this check not part of the above call?
> + dev_err(&pdev->dev,
> + "fwnode graph has no endpoints connection\n");
> + return ERR_PTR(-EINVAL);
> + }
> +
> + ret = ipu_bridge_init(pdev);
> + if (ret) {
> + dev_err_probe(&pdev->dev, ret,
> + "IPU6 bridge init failed\n");
> + return ERR_PTR(ret);
> + }
> + }
...
> + isys_adev = ipu6_bus_initialize_device(pdev, parent, pdata, ctrl,
> + IPU6_ISYS_NAME);
> + if (IS_ERR(isys_adev)) {
> + dev_err_probe(&pdev->dev, PTR_ERR(isys_adev),
> + "ipu6_bus_add_device(isys_adev) failed\n");
I read another call name above... What is this message about?
> + kfree(pdata);
> + return ERR_CAST(isys_adev);
> + }
...
> + ret = ipu6_bus_add_device(isys_adev);
> +
> + return ret ? ERR_PTR(ret) : isys_adev;
No memory cleanups?
...
> + ret = ipu6_bus_add_device(psys_adev);
> +
> + return ret ? ERR_PTR(ret) : psys_adev;
Ditto.
...
> +static int ipu6_pci_config_setup(struct pci_dev *dev, u8 hw_ver)
> +{
> + u16 pci_command;
> + int ret;
> +
> + pci_read_config_word(dev, PCI_COMMAND, &pci_command);
> + pci_command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
> + pci_write_config_word(dev, PCI_COMMAND, pci_command);
Huh?! Why is it needed and why PCI core is not enough for these?
> + /* No PCI msi capability for IPU6EP */
> + if (hw_ver == IPU6_VER_6EP || hw_ver == IPU6_VER_6EP_MTL) {
> + /* likely do nothing as msi not enabled by default */
> + pci_disable_msi(dev);
> + return 0;
> + }
> + ret = pci_enable_msi(dev);
> + if (ret)
> + dev_err(&dev->dev, "Failed to enable msi (%d)\n", ret);
> + return ret;
No, use pci_alloc_irq_vectors() and respective clean up.
> +}
...
> + ret = pcim_enable_device(pdev);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to enable PCI device (%d)\n", ret);
> + return ret;
return dev_err_probe(...);
> + }
> + dev_info(&pdev->dev, "Device 0x%x (rev: 0x%x)\n",
> + pdev->device, pdev->revision);
Useless noise. We have this in the kernel dmesg anyway.
Why do you need a dup?
...
> + ret = pcim_iomap_regions(pdev, 1 << IPU6_PCI_BAR, pci_name(pdev));
BIT()
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to I/O mem remapping (%d)\n", ret);
> + return ret;
dev_err_probe()
> + }
> + dev_dbg(&pdev->dev, "physical base address 0x%llx\n", phys);
Useless, see above.
...
> + iomap = pcim_iomap_table(pdev);
> + if (!iomap) {
> + dev_err(&pdev->dev, "Failed to iomap table (%d)\n", ret);
> + return -ENODEV;
> + }
Dead code.
> + isp->base = iomap[IPU6_PCI_BAR];
...
> + default:
> + dev_err(&pdev->dev, "Unsupported IPU6 device %x\n", id->device);
> + return -ENODEV;
dev_err_probe()
> + }
...
> + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(39));
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to set DMA mask (%d)\n", ret);
> + return ret;
Ditto.
> + }
...
> + ret = devm_request_threaded_irq(&pdev->dev, pdev->irq,
> + ipu6_buttress_isr,
> + ipu6_buttress_isr_threaded,
> + IRQF_SHARED, IPU6_NAME, isp);
> + if (ret) {
> + dev_err(&pdev->dev, "Requesting irq failed(%d)\n", ret);
> + return ret;
Ditto.
> + }
...
> + ret = request_cpd_fw(&isp->cpd_fw, isp->cpd_fw_name, &pdev->dev);
> + if (ret) {
> + dev_err(&isp->pdev->dev, "Requesting signed firmware failed\n");
Ditto.
ret = dev_err_probe(...);
...and so on below.
> + goto buttress_exit;
> + }
...
> + isys_ctrl = devm_kzalloc(&pdev->dev, sizeof(*isys_ctrl), GFP_KERNEL);
> + if (!isys_ctrl) {
> + ret = -ENOMEM;
> + goto out_ipu6_bus_del_devices;
> + }
> +
> + memcpy(isys_ctrl, &isys_buttress_ctrl, sizeof(*isys_ctrl));
devm_kmemdup()?
...
> + psys_ctrl = devm_kzalloc(&pdev->dev, sizeof(*psys_ctrl), GFP_KERNEL);
> + if (!psys_ctrl) {
> + ret = -ENOMEM;
> + goto out_ipu6_bus_del_devices;
> + }
> +
> + memcpy(psys_ctrl, &psys_buttress_ctrl, sizeof(*psys_ctrl));
Ditto?
...
> + ret = pm_runtime_get_sync(&isp->psys->auxdev.dev);
> + if (ret < 0) {
Leaking reference count.
> + dev_err(&isp->psys->auxdev.dev, "Failed to get runtime PM\n");
> + goto out_ipu6_bus_del_devices;
> + }
...
> + if (!IS_ERR_OR_NULL(isp->psys) && !IS_ERR_OR_NULL(isp->psys->mmu))
> + ipu6_mmu_cleanup(isp->psys->mmu);
> + if (!IS_ERR_OR_NULL(isp->isys) && !IS_ERR_OR_NULL(isp->isys->mmu))
> + ipu6_mmu_cleanup(isp->isys->mmu);
All these conditionals should be hidden in the callee.
> + if (!IS_ERR_OR_NULL(isp->psys))
Why it doesn't cover all above?
> + pm_runtime_put(&isp->psys->auxdev.dev);
...
> +static void ipu6_pci_reset_prepare(struct pci_dev *pdev)
> +{
> + struct ipu6_device *isp = pci_get_drvdata(pdev);
> +
> + dev_warn(&pdev->dev, "FLR prepare\n");
???
> + pm_runtime_forbid(&isp->pdev->dev);
> +}
> +static void ipu6_pci_reset_done(struct pci_dev *pdev)
> +{
> + struct ipu6_device *isp = pci_get_drvdata(pdev);
> +
> + ipu6_buttress_restore(isp);
> + if (isp->secure_mode)
> + ipu6_buttress_reset_authentication(isp);
> +
> + isp->need_ipc_reset = true;
> + pm_runtime_allow(&isp->pdev->dev);
> +
> + dev_info(&pdev->dev, "IPU6 PCI FLR completed\n");
???
Are these debug leftovers?
> +}
...
> +static const struct dev_pm_ops ipu6_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(&ipu6_suspend, &ipu6_resume)
> + SET_RUNTIME_PM_OPS(&ipu6_suspend, &ipu6_runtime_resume, NULL)
Use new macros instead of obsolete ones.
> +};
...
> +static const struct pci_device_id ipu6_pci_tbl[] = {
> + { PCI_VDEVICE(INTEL, IPU6_PCI_ID) },
> + { PCI_VDEVICE(INTEL, IPU6SE_PCI_ID) },
> + { PCI_VDEVICE(INTEL, IPU6EP_ADL_P_PCI_ID) },
> + { PCI_VDEVICE(INTEL, IPU6EP_ADL_N_PCI_ID) },
> + { PCI_VDEVICE(INTEL, IPU6EP_RPL_P_PCI_ID) },
> + { PCI_VDEVICE(INTEL, IPU6EP_MTL_PCI_ID) },
> + { }
> +};
Can you make sure the device IDs are in the standard format?
PCI_DEVICE_ID_INTEL_... (if I remember correctly the template)
> +static struct pci_driver ipu6_pci_driver = {
> + .name = IPU6_NAME,
> + .id_table = ipu6_pci_tbl,
> + .probe = ipu6_pci_probe,
> + .remove = ipu6_pci_remove,
> + .driver = {
> + .pm = &ipu6_pm_ops,
pm_ptr()
> + },
> + .err_handler = &pci_err_handlers,
> +};
...
> +static int __init ipu6_init(void)
> +{
> + int ret;
> +
> + ret = pci_register_driver(&ipu6_pci_driver);
> + if (ret)
> + pr_warn("can't register PCI driver (%d)\n", ret);
> +
> + return ret;
> +}
> +
> +static void __exit ipu6_exit(void)
> +{
> + pci_unregister_driver(&ipu6_pci_driver);
> +}
> +
> +module_init(ipu6_init);
> +module_exit(ipu6_exit);
Use module_pci_driver().
...
> +MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
> +MODULE_AUTHOR("Tianshu Qiu <tian.shu.qiu@intel.com>");
> +MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
> +MODULE_AUTHOR("Qingwu Zhang <qingwu.zhang@intel.com>");
> +MODULE_AUTHOR("Yunliang Ding <yunliang.ding@intel.com>");
> +MODULE_AUTHOR("Hongju Wang <hongju.wang@intel.com>");
So many authors and so many issues with the code.
Did you pass an internal review?
...
> +#ifndef IPU6_H
> +#define IPU6_H
> +
> +#include <linux/firmware.h>
> +#include <linux/ioport.h>
> +#include <linux/list.h>
> +#include <linux/pci.h>
> +
> +#include "ipu6-buttress.h"
As usual, missing headers and not used one. Internally we have a wiki page that
describes hints and tricks for driver programming, please find it and read and
fix your series accordingly. Maybe you need to go for a new round(s) of
internal review.
I'm stopping here for now.
> +#endif /* IPU6_H */
--
With Best Regards,
Andy Shevchenko
next prev parent reply other threads:[~2023-07-27 10:47 UTC|newest]
Thread overview: 80+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-27 7:15 [PATCH 00/15] Intel IPU6 and IPU6 input system drivers bingbu.cao
2023-07-27 7:15 ` [PATCH 01/15] media: intel/ipu6: add Intel IPU6 PCI device driver bingbu.cao
2023-07-27 10:47 ` Andy Shevchenko [this message]
2023-10-03 10:12 ` Andreas Helbech Kleist
2023-10-16 9:39 ` Andreas Helbech Kleist
2023-10-19 8:23 ` Bingbu Cao
2023-10-20 10:48 ` Andreas Helbech Kleist
2023-10-20 10:48 ` Andreas Helbech Kleist
2023-07-27 7:15 ` [PATCH 02/15] media: intel/ipu6: add IPU auxiliary devices bingbu.cao
2023-10-03 10:13 ` Andreas Helbech Kleist
2023-10-19 8:24 ` Bingbu Cao
2023-07-27 7:15 ` [PATCH 03/15] media: intel/ipu6: add IPU6 buttress interface driver bingbu.cao
2023-07-27 7:15 ` [PATCH 04/15] media: intel/ipu6: CPD parsing for get firmware components bingbu.cao
2023-07-27 7:15 ` [PATCH 05/15] media: intel/ipu6: add IPU6 DMA mapping API and MMU table bingbu.cao
2023-07-27 7:15 ` [PATCH 06/15] media: intel/ipu6: add syscom interfaces between firmware and driver bingbu.cao
2023-07-27 7:15 ` [PATCH 07/15] media: intel/ipu6: input system ABI " bingbu.cao
2023-07-27 7:15 ` [PATCH 08/15] media: intel/ipu6: add IPU6 CSI2 receiver v4l2 sub-device bingbu.cao
2023-07-27 7:15 ` [PATCH 09/15] media: intel/ipu6: add the CSI2 DPHY implementation bingbu.cao
2023-07-27 7:15 ` [PATCH 10/15] media: intel/ipu6: add input system driver bingbu.cao
2023-10-03 10:13 ` Andreas Helbech Kleist
2023-10-19 8:28 ` Bingbu Cao
2023-10-19 12:22 ` Andy Shevchenko
2023-10-20 2:21 ` Cao, Bingbu
2023-10-20 10:20 ` Andy Shevchenko
2023-10-20 10:47 ` Andreas Helbech Kleist
2023-10-20 14:39 ` Hans de Goede
2023-10-23 6:23 ` Andreas Helbech Kleist
2023-10-23 7:44 ` Hans de Goede
2023-10-23 8:23 ` Bingbu Cao
2023-10-23 11:29 ` Andy Shevchenko
2023-12-20 12:53 ` RFC: Intel IPU4 driver proof of concept Andreas Helbech Kleist
2026-02-22 19:57 ` Ruslan Bay
2026-03-04 11:03 ` Ruslan Bay
2026-03-04 12:16 ` johannes.goede
2026-04-20 7:48 ` Antti Laakso
2023-10-23 11:29 ` [PATCH 10/15] media: intel/ipu6: add input system driver Andy Shevchenko
2023-07-27 7:15 ` [PATCH 11/15] media: intel/ipu6: input system video capture nodes bingbu.cao
2023-10-23 11:36 ` Andreas Helbech Kleist
2023-12-07 9:28 ` Andreas Helbech Kleist
2023-12-20 3:42 ` Bingbu Cao
2023-12-20 6:51 ` Laurent Pinchart
2023-12-20 9:25 ` Bingbu Cao
2023-07-27 7:15 ` [PATCH 12/15] media: add Kconfig and Makefile for IPU6 bingbu.cao
2023-10-03 10:13 ` Andreas Helbech Kleist
2023-10-19 8:28 ` Bingbu Cao
2023-07-27 7:15 ` [PATCH 13/15] MAINTAINERS: add maintainers for Intel IPU6 input system driver bingbu.cao
2023-07-27 10:19 ` Andy Shevchenko
2023-07-27 7:15 ` [PATCH 14/15] Documentation: add Intel IPU6 ISYS driver admin-guide doc bingbu.cao
2023-07-27 7:15 ` [PATCH 15/15] Documentation: add documentation of Intel IPU6 driver and hardware overview bingbu.cao
2023-08-20 15:09 ` [PATCH 00/15] Intel IPU6 and IPU6 input system drivers Claus Stovgaard
2023-08-21 3:14 ` Bingbu Cao
2023-08-21 6:22 ` Bingbu Cao
2023-08-21 6:55 ` Claus Stovgaard
2023-08-21 10:07 ` Claus Stovgaard
2023-08-21 12:19 ` Laurent Pinchart
2023-08-22 12:52 ` claus.stovgaard
2023-08-22 14:22 ` Laurent Pinchart
2023-08-24 20:35 ` Claus Stovgaard
2023-08-22 3:05 ` Bingbu Cao
2023-08-24 20:19 ` Claus Stovgaard
2023-08-31 21:24 ` Hans de Goede
2023-09-02 14:54 ` Hans de Goede
2023-09-03 14:32 ` Hans de Goede
2023-09-04 3:13 ` Cao, Bingbu
2023-09-04 7:35 ` Hans de Goede
2023-10-02 17:19 ` Hans de Goede
2023-10-02 17:38 ` Laurent Pinchart
2023-10-02 17:41 ` Hans de Goede
2023-10-09 6:23 ` Bingbu Cao
2023-10-09 12:25 ` Bingbu Cao
2023-10-09 12:53 ` Hans de Goede
2023-10-10 2:54 ` Bingbu Cao
2023-10-10 8:10 ` Hans de Goede
2023-10-10 8:35 ` Bingbu Cao
2023-09-04 6:12 ` Bingbu Cao
2023-09-04 9:16 ` Andy Shevchenko
2023-09-19 10:23 ` Hans de Goede
2023-09-20 4:46 ` Bingbu Cao
2023-09-20 8:52 ` Hans de Goede
2023-09-20 12:32 ` Claus Stovgaard
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=ZMJLJGfH3vZDLb6U@smile.fi.intel.com \
--to=andriy.shevchenko@linux.intel.com \
--cc=bingbu.cao@intel.com \
--cc=bingbu.cao@linux.intel.com \
--cc=hdegoede@redhat.com \
--cc=hongju.wang@intel.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-media@vger.kernel.org \
--cc=sakari.ailus@linux.intel.com \
--cc=senozhatsky@chromium.org \
--cc=tfiga@chromium.org \
--cc=tian.shu.qiu@intel.com \
--cc=tomi.valkeinen@ideasonboard.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: link
Be 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.