Re: [PATCH 4/9] EDAC/versalnet: Fix device_register() error handling in init_one_mc()
"Pandey, Radhey Shyam" <[email protected]> Fri, 31 Jul 2026 16:31:04 +0530
| Newsgroups | org.kernel.vger.linux-edac,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On 7/24/2026 10:49 PM, Shubhrajyoti Datta wrote: > From: Prasanna Kumar T S M <[email protected]> > > When device_register() fails, it must be followed by put_device() > rather than kfree(), because device_register() calls > device_initialize() which sets up the device refcount. The matching > release function versal_edac_release() handles the actual kfree(). > > To simplify error handling and avoid complex unwinding, split > device_register() into device_initialize() and device_add(). > Initialize the device early so put_device() can be used in all > error paths. > > Fixes: d5fe2fec6c40 ("EDAC: Add a driver for the AMD Versal NET DDR controller") > Cc: [email protected] > Signed-off-by: Prasanna Kumar T S M <[email protected]> > Co-authored-by: Copilot <[email protected]> checkpatch reports - warn. WARNING: Non-standard signature: Co-authored-by: #20: Co-authored-by: Copilot <[email protected]> > Signed-off-by: Shubhrajyoti Datta <[email protected]> Nit - this is Co-developed-by: candidate as you did changes on top. > --- > > drivers/edac/versalnet_edac.c | 28 ++++++++++++++-------------- > 1 file changed, 14 insertions(+), 14 deletions(-) > > diff --git a/drivers/edac/versalnet_edac.c b/drivers/edac/versalnet_edac.c > index 03b6e0958f17..3c9eaea5a106 100644 > --- a/drivers/edac/versalnet_edac.c > +++ b/drivers/edac/versalnet_edac.c > @@ -785,7 +785,7 @@ static int init_one_mc(struct mc_priv *priv, int i) > char name[MC_NAME_LEN]; > struct device *dev; > enum dev_type dt; > - int rc; > + int rc = -ENOMEM; > > config = priv->adec[CONF + i * ADEC_NUM]; > num_chans = FIELD_GET(MC5_NUM_CHANS_MASK, config); > @@ -817,23 +817,23 @@ static int init_one_mc(struct mc_priv *priv, int i) > layers[1].size = num_chans; > layers[1].is_virt_csrow = false; > > - rc = -ENOMEM; > dev = kzalloc(sizeof(*dev), GFP_KERNEL); > if (!dev) > return rc; > > - mci = edac_mc_alloc(i, ARRAY_SIZE(layers), layers, sizeof(struct mc_priv)); > - if (!mci) { > - edac_printk(KERN_ERR, EDAC_MC, "Failed memory allocation for MC%d\n", i); > - goto err_dev_free; > - } > - > sprintf(name, "versal-net-ddrmc5-edac-%d", i); > > dev->init_name = name; > dev->release = versal_edac_release; > + device_initialize(dev); > There was a comment earlier from sashiko: After splitting device_register(), the edac_mc_alloc() failure path calls put_device() with dev->init_name still pointing at a stack buffer before device_add() copies it. That's unsafe in principle (dev_name() would follow init_name) and worse with CONFIG_DEBUG_KOBJECT_RELEASE deferral. > - rc = device_register(dev); > + mci = edac_mc_alloc(i, ARRAY_SIZE(layers), layers, sizeof(struct mc_priv)); > + if (!mci) { > + edac_printk(KERN_ERR, EDAC_MC, "Failed memory allocation for MC%d\n", i); > + goto err_put_dev; > + } > + > + rc = device_add(dev); > if (rc) > goto err_mc_free; > > @@ -843,7 +843,7 @@ static int init_one_mc(struct mc_priv *priv, int i) > rc = edac_mc_add_mc(mci); > if (rc) { > edac_printk(KERN_ERR, EDAC_MC, "Failed to register MC%d with EDAC core\n", i); > - goto err_unreg; > + goto err_dev_del; > } > > priv->mci[i] = mci; > @@ -851,12 +851,12 @@ static int init_one_mc(struct mc_priv *priv, int i) > > return 0; > > -err_unreg: > - device_unregister(mci->pdev); > +err_dev_del: > + device_del(dev); > err_mc_free: > edac_mc_free(mci); > -err_dev_free: > - kfree(dev); > +err_put_dev: > + put_device(dev); > > return rc; > }