mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	MIPS: SGI-IP27: Fix platform-device leak in bridge_platform_create()
In error case in bridge_platform_create after calling
platform_device_add()/platform_device_add_data()/
platform_device_add_resources(), release the failed
'pdev' or it will be leak, call platform_device_put()
to fix this problem.
Besides, 'pdev' is divided into 'pdev_wd' and 'pdev_bd',
use platform_device_unregister() to release sgi_w1
resources when xtalk-bridge registration fails.
Fixes: 5dc76a96e9 ("MIPS: PCI: use information from 1-wire PROM for IOC3 detection")
Signed-off-by: Lin Yujun <linyujun809@huawei.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
			
			
This commit is contained in:
		
							parent
							
								
									1e6d11fe72
								
							
						
					
					
						commit
						11bec9cba4
					
				
					 1 changed files with 50 additions and 20 deletions
				
			
		|  | @ -27,15 +27,18 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid) | |||
| { | ||||
| 	struct xtalk_bridge_platform_data *bd; | ||||
| 	struct sgi_w1_platform_data *wd; | ||||
| 	struct platform_device *pdev; | ||||
| 	struct platform_device *pdev_wd; | ||||
| 	struct platform_device *pdev_bd; | ||||
| 	struct resource w1_res; | ||||
| 	unsigned long offset; | ||||
| 
 | ||||
| 	offset = NODE_OFFSET(nasid); | ||||
| 
 | ||||
| 	wd = kzalloc(sizeof(*wd), GFP_KERNEL); | ||||
| 	if (!wd) | ||||
| 		goto no_mem; | ||||
| 	if (!wd) { | ||||
| 		pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	snprintf(wd->dev_id, sizeof(wd->dev_id), "bridge-%012lx", | ||||
| 		 offset + (widget << SWIN_SIZE_BITS)); | ||||
|  | @ -46,24 +49,35 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid) | |||
| 	w1_res.end = w1_res.start + 3; | ||||
| 	w1_res.flags = IORESOURCE_MEM; | ||||
| 
 | ||||
| 	pdev = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO); | ||||
| 	if (!pdev) { | ||||
| 		kfree(wd); | ||||
| 		goto no_mem; | ||||
| 	pdev_wd = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO); | ||||
| 	if (!pdev_wd) { | ||||
| 		pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget); | ||||
| 		goto err_kfree_wd; | ||||
| 	} | ||||
| 	if (platform_device_add_resources(pdev_wd, &w1_res, 1)) { | ||||
| 		pr_warn("xtalk:n%d/%x bridge failed to add platform resources.\n", nasid, widget); | ||||
| 		goto err_put_pdev_wd; | ||||
| 	} | ||||
| 	if (platform_device_add_data(pdev_wd, wd, sizeof(*wd))) { | ||||
| 		pr_warn("xtalk:n%d/%x bridge failed to add platform data.\n", nasid, widget); | ||||
| 		goto err_put_pdev_wd; | ||||
| 	} | ||||
| 	if (platform_device_add(pdev_wd)) { | ||||
| 		pr_warn("xtalk:n%d/%x bridge failed to add platform device.\n", nasid, widget); | ||||
| 		goto err_put_pdev_wd; | ||||
| 	} | ||||
| 	platform_device_add_resources(pdev, &w1_res, 1); | ||||
| 	platform_device_add_data(pdev, wd, sizeof(*wd)); | ||||
| 	/* platform_device_add_data() duplicates the data */ | ||||
| 	kfree(wd); | ||||
| 	platform_device_add(pdev); | ||||
| 
 | ||||
| 	bd = kzalloc(sizeof(*bd), GFP_KERNEL); | ||||
| 	if (!bd) | ||||
| 		goto no_mem; | ||||
| 	pdev = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO); | ||||
| 	if (!pdev) { | ||||
| 		kfree(bd); | ||||
| 		goto no_mem; | ||||
| 	if (!bd) { | ||||
| 		pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget); | ||||
| 		goto err_unregister_pdev_wd; | ||||
| 	} | ||||
| 	pdev_bd = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO); | ||||
| 	if (!pdev_bd) { | ||||
| 		pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget); | ||||
| 		goto err_kfree_bd; | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
|  | @ -84,15 +98,31 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid) | |||
| 	bd->io.flags	= IORESOURCE_IO; | ||||
| 	bd->io_offset	= offset; | ||||
| 
 | ||||
| 	platform_device_add_data(pdev, bd, sizeof(*bd)); | ||||
| 	if (platform_device_add_data(pdev_bd, bd, sizeof(*bd))) { | ||||
| 		pr_warn("xtalk:n%d/%x bridge failed to add platform data.\n", nasid, widget); | ||||
| 		goto err_put_pdev_bd; | ||||
| 	} | ||||
| 	if (platform_device_add(pdev_bd)) { | ||||
| 		pr_warn("xtalk:n%d/%x bridge failed to add platform device.\n", nasid, widget); | ||||
| 		goto err_put_pdev_bd; | ||||
| 	} | ||||
| 	/* platform_device_add_data() duplicates the data */ | ||||
| 	kfree(bd); | ||||
| 	platform_device_add(pdev); | ||||
| 	pr_info("xtalk:n%d/%x bridge widget\n", nasid, widget); | ||||
| 	return; | ||||
| 
 | ||||
| no_mem: | ||||
| 	pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget); | ||||
| err_put_pdev_bd: | ||||
| 	platform_device_put(pdev_bd); | ||||
| err_kfree_bd: | ||||
| 	kfree(bd); | ||||
| err_unregister_pdev_wd: | ||||
| 	platform_device_unregister(pdev_wd); | ||||
| 	return; | ||||
| err_put_pdev_wd: | ||||
| 	platform_device_put(pdev_wd); | ||||
| err_kfree_wd: | ||||
| 	kfree(wd); | ||||
| 	return; | ||||
| } | ||||
| 
 | ||||
| static int probe_one_port(nasid_t nasid, int widget, int masterwid) | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Lin Yujun
						Lin Yujun