public inbox for linux-staging@lists.linux.dev
 help / color / mirror / Atom feed
* [PATCH 0/1] media: atomisp: mt9m114: Graceful teardown atomisp
@ 2026-04-18 10:31 Robert Mast
  2026-04-18 10:31 ` [PATCH v2 1/1] media: atomisp: mt9m114: Graceful teardown atomisp and mt9m114 Robert Mast
  0 siblings, 1 reply; 3+ messages in thread
From: Robert Mast @ 2026-04-18 10:31 UTC (permalink / raw)
  To: hdegoede
  Cc: mchehab, sakari.ailus, linux-media, linux-staging, andy, gregkh,
	linux-kernel, laurent.pinchart, Robert Mast

During the many iterations on mt9m114 and atomisp on my T100ta baytrail
I was annoyed by having to reboot each time, as modprobe -r/modprobe
wasn't able to fully reinitialize mt9m114 and atomisp, resulting in cpu
core hang ups. I asked Github Copilot Enterprise to fix it for me, and
the fix looks quite good and has served me well since. I'm not able to
distinguish any structural flaw, so please review.


Robert Mast (1):
  media: atomisp: mt9m114: Graceful teardown atomisp and mt9m114

 drivers/media/i2c/mt9m114.c                   | 118 ++++++++++++++++--
 .../media/atomisp/pci/atomisp_csi2_bridge.c   |   1 +
 .../staging/media/atomisp/pci/atomisp_v4l2.c  |   3 +
 3 files changed, 110 insertions(+), 12 deletions(-)

-- 
2.53.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v2 1/1] media: atomisp: mt9m114: Graceful teardown atomisp and mt9m114
  2026-04-18 10:31 [PATCH 0/1] media: atomisp: mt9m114: Graceful teardown atomisp Robert Mast
@ 2026-04-18 10:31 ` Robert Mast
  2026-04-19  5:37   ` Greg KH
  0 siblings, 1 reply; 3+ messages in thread
From: Robert Mast @ 2026-04-18 10:31 UTC (permalink / raw)
  To: hdegoede
  Cc: mchehab, sakari.ailus, linux-media, linux-staging, andy, gregkh,
	linux-kernel, laurent.pinchart, Robert Mast

Signed-off-by: Robert Mast <rn.mast@zonnet.nl>
---
 drivers/media/i2c/mt9m114.c                   | 118 ++++++++++++++++--
 .../media/atomisp/pci/atomisp_csi2_bridge.c   |   1 +
 .../staging/media/atomisp/pci/atomisp_v4l2.c  |   3 +
 3 files changed, 110 insertions(+), 12 deletions(-)

diff --git a/drivers/media/i2c/mt9m114.c b/drivers/media/i2c/mt9m114.c
index 16b0ace15813..27432a9c683d 100644
--- a/drivers/media/i2c/mt9m114.c
+++ b/drivers/media/i2c/mt9m114.c
@@ -10,6 +10,8 @@
  */
 
 #include <linux/clk.h>
+#include <linux/acpi.h>
+#include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/gpio/consumer.h>
@@ -416,6 +418,7 @@ struct mt9m114 {
 		unsigned int frame_rate;
 
 		struct v4l2_ctrl *tpg[4];
+		struct completion unregistered;
 	} ifp;
 };
 
@@ -1467,6 +1470,8 @@ static int mt9m114_pa_init(struct mt9m114 *sensor)
 
 	sd->ctrl_handler = hdl;
 
+	init_completion(&sensor->ifp.unregistered);
+
 	return 0;
 
 error:
@@ -2056,8 +2061,13 @@ static int mt9m114_ifp_set_selection(struct v4l2_subdev *sd,
 static void mt9m114_ifp_unregistered(struct v4l2_subdev *sd)
 {
 	struct mt9m114 *sensor = ifp_to_mt9m114(sd);
+	struct device *dev = &sensor->client->dev;
+
+	dev_dbg(dev, "ifp unregistered callback (ifp.v4l2_dev=%p, pa.v4l2_dev=%p)\n",
+		sensor->ifp.sd.v4l2_dev, sensor->pa.sd.v4l2_dev);
 
 	v4l2_device_unregister_subdev(&sensor->pa.sd);
+	complete(&sensor->ifp.unregistered);
 }
 
 static int mt9m114_ifp_registered(struct v4l2_subdev *sd)
@@ -2149,12 +2159,15 @@ static int mt9m114_ifp_init(struct mt9m114 *sensor)
 			       V4L2_EXPOSURE_MANUAL, 0,
 			       V4L2_EXPOSURE_AUTO);
 
-	link_freq = v4l2_ctrl_new_int_menu(hdl, &mt9m114_ifp_ctrl_ops,
-					   V4L2_CID_LINK_FREQ,
-					   sensor->bus_cfg.nr_of_link_frequencies - 1,
-					   0, sensor->bus_cfg.link_frequencies);
-	if (link_freq)
-		link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+	if (sensor->bus_cfg.nr_of_link_frequencies) {
+		link_freq = v4l2_ctrl_new_int_menu(hdl, &mt9m114_ifp_ctrl_ops,
+						   V4L2_CID_LINK_FREQ,
+						   sensor->bus_cfg.nr_of_link_frequencies - 1,
+						   0,
+						   sensor->bus_cfg.link_frequencies);
+		if (link_freq)
+			link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+	}
 
 	v4l2_ctrl_new_std(hdl, &mt9m114_ifp_ctrl_ops,
 			  V4L2_CID_PIXEL_RATE,
@@ -2339,14 +2352,19 @@ static const struct dev_pm_ops mt9m114_pm_ops = {
 static int mt9m114_verify_link_frequency(struct mt9m114 *sensor,
 					 unsigned int pixrate)
 {
+	u32 i;
 	unsigned int link_freq = sensor->bus_cfg.bus_type == V4L2_MBUS_CSI2_DPHY
 			       ? pixrate * 8 : pixrate * 2;
 
-	if (sensor->bus_cfg.nr_of_link_frequencies != 1 ||
-	    sensor->bus_cfg.link_frequencies[0] != link_freq)
+	if (!sensor->bus_cfg.nr_of_link_frequencies)
 		return -EINVAL;
 
-	return 0;
+	for (i = 0; i < sensor->bus_cfg.nr_of_link_frequencies; i++) {
+		if (sensor->bus_cfg.link_frequencies[i] == link_freq)
+			return 0;
+	}
+
+	return -EINVAL;
 }
 
 /*
@@ -2383,6 +2401,29 @@ static int mt9m114_clk_init(struct mt9m114 *sensor)
 	unsigned int pixrate;
 	int ret;
 
+	if (!sensor->bus_cfg.nr_of_link_frequencies) {
+		/*
+		 * ACPI fallback path: no reliable endpoint link frequency available.
+		 * Use the default PLL target instead of EXTCLK bypass to avoid
+		 * under-clocking the sensor and getting blank/timeout streams.
+		 */
+		sensor->pll.ext_clock = clk_get_rate(sensor->clk);
+		sensor->pll.pix_clock = MT9M114_DEF_PIXCLOCK;
+
+		ret = aptina_pll_calculate(&sensor->client->dev, &limits,
+					  &sensor->pll);
+		if (ret)
+			return ret;
+
+		sensor->pixrate = sensor->pll.ext_clock * sensor->pll.m
+			/ (sensor->pll.n * sensor->pll.p1);
+		sensor->bypass_pll = false;
+
+		dev_warn(&sensor->client->dev,
+			 "no link-frequencies provided, using default PLL clocking\n");
+		return 0;
+	}
+
 	/*
 	 * Calculate the pixel rate and link frequency. The CSI-2 bus is clocked
 	 * for 16-bit per pixel, transmitted in DDR over a single lane. For
@@ -2456,10 +2497,25 @@ static int mt9m114_identify(struct mt9m114 *sensor)
 
 static int mt9m114_parse_dt(struct mt9m114 *sensor)
 {
-	struct fwnode_handle *fwnode = dev_fwnode(&sensor->client->dev);
+	struct fwnode_handle *fwnode;
 	struct fwnode_handle *ep;
 	int ret;
 
+#if IS_ENABLED(CONFIG_ACPI)
+	if (has_acpi_companion(&sensor->client->dev)) {
+		/*
+		 * On some reload sequences a stale software-node graph can be
+		 * observed for this ACPI-enumerated sensor. Use the known safe
+		 * default bus configuration and skip endpoint graph parsing.
+		 */
+		memset(&sensor->bus_cfg, 0, sizeof(sensor->bus_cfg));
+		sensor->bus_cfg.bus_type = V4L2_MBUS_CSI2_DPHY;
+		sensor->bus_cfg.bus.mipi_csi2.num_data_lanes = 1;
+		goto read_slew_rate;
+	}
+#endif
+	fwnode = dev_fwnode(&sensor->client->dev);
+
 	/*
 	 * On ACPI systems the fwnode graph can be initialized by a bridge
 	 * driver, which may not have probed yet. Wait for this.
@@ -2468,6 +2524,9 @@ static int mt9m114_parse_dt(struct mt9m114 *sensor)
 	 * to the ACPI core.
 	 */
 	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
+	if (IS_ERR(ep))
+		return dev_err_probe(&sensor->client->dev, PTR_ERR(ep),
+				     "failed to get fwnode graph endpoint\n");
 	if (!ep)
 		return dev_err_probe(&sensor->client->dev, -EPROBE_DEFER,
 				     "waiting for fwnode graph endpoint\n");
@@ -2492,6 +2551,7 @@ static int mt9m114_parse_dt(struct mt9m114 *sensor)
 		goto error;
 	}
 
+read_slew_rate:
 	sensor->pad_slew_rate = MT9M114_PAD_SLEW_DEFAULT;
 	device_property_read_u32(&sensor->client->dev, "slew-rate",
 				 &sensor->pad_slew_rate);
@@ -2629,8 +2689,22 @@ static void mt9m114_remove(struct i2c_client *client)
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
 	struct mt9m114 *sensor = ifp_to_mt9m114(sd);
 	struct device *dev = &client->dev;
-
-	v4l2_async_unregister_subdev(&sensor->ifp.sd);
+	bool ifp_async_registered = sensor->ifp.sd.async_list.next;
+	bool ifp_bound = sensor->ifp.sd.v4l2_dev;
+
+	dev_dbg(dev,
+		"remove start (ifp_bound=%u ifp_async_registered=%u ifp.v4l2_dev=%p pa.v4l2_dev=%p)\n",
+		ifp_bound, ifp_async_registered,
+		sensor->ifp.sd.v4l2_dev, sensor->pa.sd.v4l2_dev);
+
+	if (ifp_async_registered) {
+		reinit_completion(&sensor->ifp.unregistered);
+		v4l2_async_unregister_subdev(&sensor->ifp.sd);
+		if (ifp_bound)
+			wait_for_completion(&sensor->ifp.unregistered);
+	} else {
+		dev_warn(dev, "ifp async subdev already unregistered, skipping\n");
+	}
 
 	mt9m114_ifp_cleanup(sensor);
 	mt9m114_pa_cleanup(sensor);
@@ -2646,6 +2720,25 @@ static void mt9m114_remove(struct i2c_client *client)
 	pm_runtime_set_suspended(dev);
 }
 
+static void mt9m114_shutdown(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct mt9m114 *sensor;
+
+	if (!sd)
+		return;
+
+	sensor = ifp_to_mt9m114(sd);
+
+	if (sensor->streaming)
+		mt9m114_stop_streaming(sensor);
+
+	pm_runtime_disable(&client->dev);
+	if (!pm_runtime_status_suspended(&client->dev))
+		mt9m114_power_off(sensor);
+	pm_runtime_set_suspended(&client->dev);
+}
+
 static const struct of_device_id mt9m114_of_ids[] = {
 	{ .compatible = "onnn,mt9m114" },
 	{ /* sentinel */ },
@@ -2667,6 +2760,7 @@ static struct i2c_driver mt9m114_driver = {
 	},
 	.probe		= mt9m114_probe,
 	.remove		= mt9m114_remove,
+	.shutdown	= mt9m114_shutdown,
 };
 
 module_i2c_driver(mt9m114_driver);
diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c
index 2a90f86e515f..87f8ddcd6651 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c
@@ -547,6 +547,7 @@ int atomisp_csi2_bridge_parse_firmware(struct atomisp_device *isp)
 
 err_parse:
 		fwnode_handle_put(ep);
+		v4l2_async_nf_cleanup(&isp->notifier);
 		return ret;
 	}
 
diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
index 900a67552d6a..32a1f85ab598 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
@@ -805,6 +805,9 @@ static void atomisp_unregister_entities(struct atomisp_device *isp)
 	unsigned int i;
 	struct v4l2_subdev *sd, *next;
 
+	v4l2_async_nf_unregister(&isp->notifier);
+	v4l2_async_nf_cleanup(&isp->notifier);
+
 	atomisp_subdev_unregister_entities(&isp->asd);
 	for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++)
 		atomisp_mipi_csi2_unregister_entities(&isp->csi2_port[i]);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2 1/1] media: atomisp: mt9m114: Graceful teardown atomisp and mt9m114
  2026-04-18 10:31 ` [PATCH v2 1/1] media: atomisp: mt9m114: Graceful teardown atomisp and mt9m114 Robert Mast
@ 2026-04-19  5:37   ` Greg KH
  0 siblings, 0 replies; 3+ messages in thread
From: Greg KH @ 2026-04-19  5:37 UTC (permalink / raw)
  To: Robert Mast
  Cc: hdegoede, mchehab, sakari.ailus, linux-media, linux-staging, andy,
	linux-kernel, laurent.pinchart

On Sat, Apr 18, 2026 at 12:31:09PM +0200, Robert Mast wrote:
> Signed-off-by: Robert Mast <rn.mast@zonnet.nl>
> ---
>  drivers/media/i2c/mt9m114.c                   | 118 ++++++++++++++++--
>  .../media/atomisp/pci/atomisp_csi2_bridge.c   |   1 +
>  .../staging/media/atomisp/pci/atomisp_v4l2.c  |   3 +
>  3 files changed, 110 insertions(+), 12 deletions(-)

Hi,

This is the friendly patch-bot of Greg Kroah-Hartman.  You have sent him
a patch that has triggered this response.  He used to manually respond
to these common problems, but in order to save his sanity (he kept
writing the same thing over and over, yet to different people), I was
created.  Hopefully you will not take offence and will fix the problem
in your patch and resubmit it so that it can be accepted into the Linux
kernel tree.

You are receiving this message because of the following common error(s)
as indicated below:

- You did not specify a description of why the patch is needed, or
  possibly, any description at all, in the email body.  Please read the
  section entitled "The canonical patch format" in the kernel file,
  Documentation/process/submitting-patches.rst for what is needed in
  order to properly describe the change.

If you wish to discuss this problem further, or you have questions about
how to resolve this issue, please feel free to respond to this email and
Greg will reply once he has dug out from the pending patches received
from other developers.

thanks,

greg k-h's patch email bot

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-04-19  5:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-18 10:31 [PATCH 0/1] media: atomisp: mt9m114: Graceful teardown atomisp Robert Mast
2026-04-18 10:31 ` [PATCH v2 1/1] media: atomisp: mt9m114: Graceful teardown atomisp and mt9m114 Robert Mast
2026-04-19  5:37   ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox