Message ID | 1b41531de02ee029628d9b0ec2cf1ee7f180fe10.1663482259.git.christophe.jaillet@wanadoo.fr |
---|---|
State | New |
Headers | show |
Series | [1/3] misc: microchip: pci1xxxx: Do not disable the pci device twice in gp_aux_bus_remove() | expand |
Hi Christophe, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on char-misc/char-misc-testing] [also build test WARNING on next-20220916] [cannot apply to linus/master v6.0-rc5] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Christophe-JAILLET/misc-microchip-pci1xxxx-Fix-the-error-handling-path-of-gp_aux_bus_probe/20220918-143022 base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git ceecbbddbf549fe0b7ffa3804a6e255b3360030f config: xtensa-randconfig-r022-20220918 compiler: xtensa-linux-gcc (GCC) 12.1.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/089c1639fdebdad9be8de56c1546308eac15747d git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Christophe-JAILLET/misc-microchip-pci1xxxx-Fix-the-error-handling-path-of-gp_aux_bus_probe/20220918-143022 git checkout 089c1639fdebdad9be8de56c1546308eac15747d # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=xtensa SHELL=/bin/bash drivers/misc/mchp_pci1xxxx/ If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c: In function 'gp_aux_bus_probe': >> drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c:35:13: warning: variable 'irq' set but not used [-Wunused-but-set-variable] 35 | int irq, retval; | ^~~ vim +/irq +35 drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c 31 32 static int gp_aux_bus_probe(struct pci_dev *pdev, const struct pci_device_id *id) 33 { 34 struct aux_bus_device *aux_bus; > 35 int irq, retval; 36 37 retval = pcim_enable_device(pdev); 38 if (retval) 39 return retval; 40 41 aux_bus = devm_kzalloc(&pdev->dev, sizeof(*aux_bus), GFP_KERNEL); 42 if (!aux_bus) 43 return -ENOMEM; 44 45 aux_bus->aux_device_wrapper[0] = kzalloc(sizeof(*aux_bus->aux_device_wrapper[0]), 46 GFP_KERNEL); 47 if (!aux_bus->aux_device_wrapper[0]) 48 return -ENOMEM; 49 50 retval = ida_alloc(&gp_client_ida, GFP_KERNEL); 51 if (retval < 0) { 52 kfree(aux_bus->aux_device_wrapper[0]); 53 return retval; 54 } 55 56 aux_bus->aux_device_wrapper[0]->aux_dev.name = aux_dev_otp_e2p_name; 57 aux_bus->aux_device_wrapper[0]->aux_dev.dev.parent = &pdev->dev; 58 aux_bus->aux_device_wrapper[0]->aux_dev.dev.release = gp_auxiliary_device_release; 59 aux_bus->aux_device_wrapper[0]->aux_dev.id = retval; 60 61 aux_bus->aux_device_wrapper[0]->gp_aux_data.region_start = pci_resource_start(pdev, 0); 62 aux_bus->aux_device_wrapper[0]->gp_aux_data.region_length = pci_resource_end(pdev, 0); 63 64 retval = auxiliary_device_init(&aux_bus->aux_device_wrapper[0]->aux_dev); 65 if (retval < 0) { 66 ida_free(&gp_client_ida, aux_bus->aux_device_wrapper[0]->aux_dev.id); 67 kfree(aux_bus->aux_device_wrapper[0]); 68 goto err_aux_dev_uninit_0; 69 } 70 71 retval = auxiliary_device_add(&aux_bus->aux_device_wrapper[0]->aux_dev); 72 if (retval) 73 goto err_aux_dev_uninit_0; 74 75 76 retval = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 77 if (retval < 0) 78 goto err_aux_dev_del_0; 79 80 retval = pci_irq_vector(pdev, 0); 81 if (retval < 0) 82 goto err_aux_dev_del_0; 83 irq = retval; 84 85 aux_bus->aux_device_wrapper[1] = kzalloc(sizeof(*aux_bus->aux_device_wrapper[1]), 86 GFP_KERNEL); 87 if (!aux_bus->aux_device_wrapper[1]) { 88 retval = -ENOMEM; 89 goto err_aux_dev_del_0; 90 } 91 92 retval = ida_alloc(&gp_client_ida, GFP_KERNEL); 93 if (retval < 0) { 94 kfree(aux_bus->aux_device_wrapper[1]); 95 goto err_aux_dev_del_0; 96 } 97 98 aux_bus->aux_device_wrapper[1]->aux_dev.name = aux_dev_gpio_name; 99 aux_bus->aux_device_wrapper[1]->aux_dev.dev.parent = &pdev->dev; 100 aux_bus->aux_device_wrapper[1]->aux_dev.dev.release = gp_auxiliary_device_release; 101 aux_bus->aux_device_wrapper[1]->aux_dev.id = retval; 102 103 aux_bus->aux_device_wrapper[1]->gp_aux_data.region_start = pci_resource_start(pdev, 0); 104 aux_bus->aux_device_wrapper[1]->gp_aux_data.region_length = pci_resource_end(pdev, 0); 105 106 pdev->irq = retval; 107 aux_bus->aux_device_wrapper[1]->gp_aux_data.irq_num = pdev->irq; 108 109 retval = auxiliary_device_init(&aux_bus->aux_device_wrapper[1]->aux_dev); 110 if (retval < 0) { 111 ida_free(&gp_client_ida, aux_bus->aux_device_wrapper[1]->aux_dev.id); 112 kfree(aux_bus->aux_device_wrapper[1]); 113 goto err_aux_dev_del_0; 114 } 115 116 retval = auxiliary_device_add(&aux_bus->aux_device_wrapper[1]->aux_dev); 117 if (retval) 118 goto err_aux_dev_uninit_1; 119 120 pci_set_drvdata(pdev, aux_bus); 121 pci_set_master(pdev); 122 123 return 0; 124 125 err_aux_dev_uninit_1: 126 auxiliary_device_uninit(&aux_bus->aux_device_wrapper[1]->aux_dev); 127 128 err_aux_dev_del_0: 129 auxiliary_device_delete(&aux_bus->aux_device_wrapper[0]->aux_dev); 130 131 err_aux_dev_uninit_0: 132 auxiliary_device_uninit(&aux_bus->aux_device_wrapper[0]->aux_dev); 133 134 return retval; 135 } 136
> -----Original Message----- > From: Christophe JAILLET <christophe.jaillet@wanadoo.fr> > Sent: Sunday, September 18, 2022 11:58 AM > To: Kumaravel Thiagarajan - I21417 > <Kumaravel.Thiagarajan@microchip.com>; Arnd Bergmann > <arnd@arndb.de>; Greg Kroah-Hartman <gregkh@linuxfoundation.org> > Cc: linux-kernel@vger.kernel.org; kernel-janitors@vger.kernel.org; > Christophe JAILLET <christophe.jaillet@wanadoo.fr>; linux- > gpio@vger.kernel.org > Subject: [PATCH 3/3] misc: microchip: pci1xxxx: Fix the error handling paths > of gp_aux_bus_probe() > > There are several issues related to the error handling paths of > gp_aux_bus_probe(): > - some resources may be released twice. Once explicitly in the error > handling path, and once via the release() function > - auxiliary_device_delete() should be called after the first successful > auxiliary_device_add() Thanks for your patch. I had noticed this after one of the reviewers had only partially fixed them up. I need some time to review and test your patch with the hardware before approving them. > > To fix them, reorder the code: > - move the place where we get the irq for the 2nd wrapper. > - call kfree() and ida_free() after error checks, rather then in the > error handling path. > - have the error handling path look like the remove function > > Fixes: 393fc2f5948f ("misc: microchip: pci1xxxx: load auxiliary bus driver for > the PIO function in the multi-function endpoint of pci1xxxx device.") > Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> > --- > This patch is speculative and untested, review with care. > > Other solutions are possible. > For example, we could use devm_kzalloc() to simplify the error handling path > and the release function. I thought about this but had some doubts whether it will work with the auxiliary bus architecture as the memory allocated will get tagged with the same device pointer. I need to do some experiments before taking up this path. Thank You. Regards, Kumar
Hi Christophe, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on char-misc/char-misc-testing] [also build test WARNING on next-20220921] [cannot apply to linus/master v6.0-rc6] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Christophe-JAILLET/misc-microchip-pci1xxxx-Fix-the-error-handling-path-of-gp_aux_bus_probe/20220918-143022 base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git ceecbbddbf549fe0b7ffa3804a6e255b3360030f config: riscv-randconfig-r032-20220921 compiler: clang version 16.0.0 (https://github.com/llvm/llvm-project 791a7ae1ba3efd6bca96338e10ffde557ba83920) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install riscv cross compiling tool for clang build # apt-get install binutils-riscv64-linux-gnu # https://github.com/intel-lab-lkp/linux/commit/089c1639fdebdad9be8de56c1546308eac15747d git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Christophe-JAILLET/misc-microchip-pci1xxxx-Fix-the-error-handling-path-of-gp_aux_bus_probe/20220918-143022 git checkout 089c1639fdebdad9be8de56c1546308eac15747d # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash drivers/clk/ drivers/misc/mchp_pci1xxxx/ drivers/pinctrl/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): >> drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c:35:6: warning: variable 'irq' set but not used [-Wunused-but-set-variable] int irq, retval; ^ 1 warning generated. vim +/irq +35 drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c 31 32 static int gp_aux_bus_probe(struct pci_dev *pdev, const struct pci_device_id *id) 33 { 34 struct aux_bus_device *aux_bus; > 35 int irq, retval; 36 37 retval = pcim_enable_device(pdev); 38 if (retval) 39 return retval; 40 41 aux_bus = devm_kzalloc(&pdev->dev, sizeof(*aux_bus), GFP_KERNEL); 42 if (!aux_bus) 43 return -ENOMEM; 44 45 aux_bus->aux_device_wrapper[0] = kzalloc(sizeof(*aux_bus->aux_device_wrapper[0]), 46 GFP_KERNEL); 47 if (!aux_bus->aux_device_wrapper[0]) 48 return -ENOMEM; 49 50 retval = ida_alloc(&gp_client_ida, GFP_KERNEL); 51 if (retval < 0) { 52 kfree(aux_bus->aux_device_wrapper[0]); 53 return retval; 54 } 55 56 aux_bus->aux_device_wrapper[0]->aux_dev.name = aux_dev_otp_e2p_name; 57 aux_bus->aux_device_wrapper[0]->aux_dev.dev.parent = &pdev->dev; 58 aux_bus->aux_device_wrapper[0]->aux_dev.dev.release = gp_auxiliary_device_release; 59 aux_bus->aux_device_wrapper[0]->aux_dev.id = retval; 60 61 aux_bus->aux_device_wrapper[0]->gp_aux_data.region_start = pci_resource_start(pdev, 0); 62 aux_bus->aux_device_wrapper[0]->gp_aux_data.region_length = pci_resource_end(pdev, 0); 63 64 retval = auxiliary_device_init(&aux_bus->aux_device_wrapper[0]->aux_dev); 65 if (retval < 0) { 66 ida_free(&gp_client_ida, aux_bus->aux_device_wrapper[0]->aux_dev.id); 67 kfree(aux_bus->aux_device_wrapper[0]); 68 goto err_aux_dev_uninit_0; 69 } 70 71 retval = auxiliary_device_add(&aux_bus->aux_device_wrapper[0]->aux_dev); 72 if (retval) 73 goto err_aux_dev_uninit_0; 74 75 76 retval = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 77 if (retval < 0) 78 goto err_aux_dev_del_0; 79 80 retval = pci_irq_vector(pdev, 0); 81 if (retval < 0) 82 goto err_aux_dev_del_0; 83 irq = retval; 84 85 aux_bus->aux_device_wrapper[1] = kzalloc(sizeof(*aux_bus->aux_device_wrapper[1]), 86 GFP_KERNEL); 87 if (!aux_bus->aux_device_wrapper[1]) { 88 retval = -ENOMEM; 89 goto err_aux_dev_del_0; 90 } 91 92 retval = ida_alloc(&gp_client_ida, GFP_KERNEL); 93 if (retval < 0) { 94 kfree(aux_bus->aux_device_wrapper[1]); 95 goto err_aux_dev_del_0; 96 } 97 98 aux_bus->aux_device_wrapper[1]->aux_dev.name = aux_dev_gpio_name; 99 aux_bus->aux_device_wrapper[1]->aux_dev.dev.parent = &pdev->dev; 100 aux_bus->aux_device_wrapper[1]->aux_dev.dev.release = gp_auxiliary_device_release; 101 aux_bus->aux_device_wrapper[1]->aux_dev.id = retval; 102 103 aux_bus->aux_device_wrapper[1]->gp_aux_data.region_start = pci_resource_start(pdev, 0); 104 aux_bus->aux_device_wrapper[1]->gp_aux_data.region_length = pci_resource_end(pdev, 0); 105 106 pdev->irq = retval; 107 aux_bus->aux_device_wrapper[1]->gp_aux_data.irq_num = pdev->irq; 108 109 retval = auxiliary_device_init(&aux_bus->aux_device_wrapper[1]->aux_dev); 110 if (retval < 0) { 111 ida_free(&gp_client_ida, aux_bus->aux_device_wrapper[1]->aux_dev.id); 112 kfree(aux_bus->aux_device_wrapper[1]); 113 goto err_aux_dev_del_0; 114 } 115 116 retval = auxiliary_device_add(&aux_bus->aux_device_wrapper[1]->aux_dev); 117 if (retval) 118 goto err_aux_dev_uninit_1; 119 120 pci_set_drvdata(pdev, aux_bus); 121 pci_set_master(pdev); 122 123 return 0; 124 125 err_aux_dev_uninit_1: 126 auxiliary_device_uninit(&aux_bus->aux_device_wrapper[1]->aux_dev); 127 128 err_aux_dev_del_0: 129 auxiliary_device_delete(&aux_bus->aux_device_wrapper[0]->aux_dev); 130 131 err_aux_dev_uninit_0: 132 auxiliary_device_uninit(&aux_bus->aux_device_wrapper[0]->aux_dev); 133 134 return retval; 135 } 136
diff --git a/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c b/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c index 32af2b14ff34..d3253e98f2ec 100644 --- a/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c +++ b/drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c @@ -32,7 +32,7 @@ static void gp_auxiliary_device_release(struct device *dev) static int gp_aux_bus_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct aux_bus_device *aux_bus; - int retval; + int irq, retval; retval = pcim_enable_device(pdev); if (retval) @@ -48,8 +48,10 @@ static int gp_aux_bus_probe(struct pci_dev *pdev, const struct pci_device_id *id return -ENOMEM; retval = ida_alloc(&gp_client_ida, GFP_KERNEL); - if (retval < 0) - goto err_ida_alloc_0; + if (retval < 0) { + kfree(aux_bus->aux_device_wrapper[0]); + return retval; + } aux_bus->aux_device_wrapper[0]->aux_dev.name = aux_dev_otp_e2p_name; aux_bus->aux_device_wrapper[0]->aux_dev.dev.parent = &pdev->dev; @@ -60,21 +62,38 @@ static int gp_aux_bus_probe(struct pci_dev *pdev, const struct pci_device_id *id aux_bus->aux_device_wrapper[0]->gp_aux_data.region_length = pci_resource_end(pdev, 0); retval = auxiliary_device_init(&aux_bus->aux_device_wrapper[0]->aux_dev); - if (retval < 0) - goto err_aux_dev_init_0; + if (retval < 0) { + ida_free(&gp_client_ida, aux_bus->aux_device_wrapper[0]->aux_dev.id); + kfree(aux_bus->aux_device_wrapper[0]); + goto err_aux_dev_uninit_0; + } retval = auxiliary_device_add(&aux_bus->aux_device_wrapper[0]->aux_dev); if (retval) - goto err_aux_dev_add_0; + goto err_aux_dev_uninit_0; + + + retval = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (retval < 0) + goto err_aux_dev_del_0; + + retval = pci_irq_vector(pdev, 0); + if (retval < 0) + goto err_aux_dev_del_0; + irq = retval; aux_bus->aux_device_wrapper[1] = kzalloc(sizeof(*aux_bus->aux_device_wrapper[1]), GFP_KERNEL); - if (!aux_bus->aux_device_wrapper[1]) - return -ENOMEM; + if (!aux_bus->aux_device_wrapper[1]) { + retval = -ENOMEM; + goto err_aux_dev_del_0; + } retval = ida_alloc(&gp_client_ida, GFP_KERNEL); - if (retval < 0) - goto err_ida_alloc_1; + if (retval < 0) { + kfree(aux_bus->aux_device_wrapper[1]); + goto err_aux_dev_del_0; + } aux_bus->aux_device_wrapper[1]->aux_dev.name = aux_dev_gpio_name; aux_bus->aux_device_wrapper[1]->aux_dev.dev.parent = &pdev->dev; @@ -84,49 +103,34 @@ static int gp_aux_bus_probe(struct pci_dev *pdev, const struct pci_device_id *id aux_bus->aux_device_wrapper[1]->gp_aux_data.region_start = pci_resource_start(pdev, 0); aux_bus->aux_device_wrapper[1]->gp_aux_data.region_length = pci_resource_end(pdev, 0); - retval = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); - - if (retval < 0) - goto err_aux_dev_init_1; - - retval = pci_irq_vector(pdev, 0); - if (retval < 0) - goto err_aux_dev_init_1; - pdev->irq = retval; aux_bus->aux_device_wrapper[1]->gp_aux_data.irq_num = pdev->irq; retval = auxiliary_device_init(&aux_bus->aux_device_wrapper[1]->aux_dev); - if (retval < 0) - goto err_aux_dev_init_1; + if (retval < 0) { + ida_free(&gp_client_ida, aux_bus->aux_device_wrapper[1]->aux_dev.id); + kfree(aux_bus->aux_device_wrapper[1]); + goto err_aux_dev_del_0; + } retval = auxiliary_device_add(&aux_bus->aux_device_wrapper[1]->aux_dev); if (retval) - goto err_aux_dev_add_1; + goto err_aux_dev_uninit_1; pci_set_drvdata(pdev, aux_bus); pci_set_master(pdev); return 0; -err_aux_dev_add_1: +err_aux_dev_uninit_1: auxiliary_device_uninit(&aux_bus->aux_device_wrapper[1]->aux_dev); -err_aux_dev_init_1: - ida_free(&gp_client_ida, aux_bus->aux_device_wrapper[1]->aux_dev.id); - -err_ida_alloc_1: - kfree(aux_bus->aux_device_wrapper[1]); +err_aux_dev_del_0: + auxiliary_device_delete(&aux_bus->aux_device_wrapper[0]->aux_dev); -err_aux_dev_add_0: +err_aux_dev_uninit_0: auxiliary_device_uninit(&aux_bus->aux_device_wrapper[0]->aux_dev); -err_aux_dev_init_0: - ida_free(&gp_client_ida, aux_bus->aux_device_wrapper[0]->aux_dev.id); - -err_ida_alloc_0: - kfree(aux_bus->aux_device_wrapper[0]); - return retval; }
There are several issues related to the error handling paths of gp_aux_bus_probe(): - some resources may be released twice. Once explicitly in the error handling path, and once via the release() function - auxiliary_device_delete() should be called after the first successful auxiliary_device_add() To fix them, reorder the code: - move the place where we get the irq for the 2nd wrapper. - call kfree() and ida_free() after error checks, rather then in the error handling path. - have the error handling path look like the remove function Fixes: 393fc2f5948f ("misc: microchip: pci1xxxx: load auxiliary bus driver for the PIO function in the multi-function endpoint of pci1xxxx device.") Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> --- This patch is speculative and untested, review with care. Other solutions are possible. For example, we could use devm_kzalloc() to simplify the error handling path and the release function. --- drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c | 74 ++++++++++--------- 1 file changed, 39 insertions(+), 35 deletions(-)