122.rk3399 uboot(2017.09) 源码分析2-initf_dm(2024-09-09)

news2024/11/15 8:06:09

这里接着上一篇来吧:

https://blog.csdn.net/zhaozhi0810/article/details/141927053

本文主要是dm_init_and_scan函数的分析,这个内容比较复杂,我也是第一次阅读,错误之处在所难免,请多指教。

uboot的dm框架需要了解一下,看了几行代码发现看不下去了,有点深啊。

(这篇没有写完,有点偷懒了,先发出来,后面再编辑更新吧。因为发现后面的函数都比较简单,要不先把后面的写了。)

我慢慢琢磨一下。

一、c的入口 board_init_f

1.3.11 initf_dm (common/board_f.c)

1.3.11.1 dm_init_and_scan (drivers/core/root.c)

参数 pre_reloc_only 为true

int dm_init_and_scan(bool pre_reloc_only)
{
	int ret;

	ret = dm_init(IS_ENABLED(CONFIG_OF_LIVE));    //初始化
	if (ret) {
		debug("dm_init() failed: %d\n", ret);
		return ret;
	}
	ret = dm_scan_platdata(pre_reloc_only);  //扫描
	if (ret) {
		debug("dm_scan_platdata() failed: %d\n", ret);
		return ret;
	}

	if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
		ret = dm_extended_scan_fdt(gd->fdt_blob, pre_reloc_only);
		if (ret) {
			debug("dm_extended_scan_dt() failed: %d\n", ret);
			return ret;
		}
	}

	ret = dm_scan_other(pre_reloc_only);  //其他设备扫描
	if (ret)
		return ret;

	return 0;
}

1.3.11.1.1  dm_init

参数of_live 等于true

int dm_init(bool of_live)
{
	int ret;

	if (gd->dm_root) {   //指针不为空则报出警告,并返回
		dm_warn("Virtual root driver already exists!\n");
		return -EINVAL;
	}
	INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);   //初始化队列((gd_t *)gd)->uclass_root

#if defined(CONFIG_NEEDS_MANUAL_RELOC)  //宏没有定义,略过
	fix_drivers();
	fix_uclass();
	fix_devices();
#endif

	ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);  //使用名字绑定设备?
	if (ret)
		return ret;
#if CONFIG_IS_ENABLED(OF_CONTROL)   //宏有效
# if CONFIG_IS_ENABLED(OF_LIVE)   //宏有效
	if (of_live)
		DM_ROOT_NON_CONST->node = np_to_ofnode(gd->of_root);  //执行
	else
#endif
		DM_ROOT_NON_CONST->node = offset_to_ofnode(0);
#endif
	ret = device_probe(DM_ROOT_NON_CONST);  //设备探索,这里是个递归函数。貌似比较复杂
	if (ret)
		return ret;

	return 0;
}

1.3.11.1.1.1  device_bind_by_name

从函数名来看,是通过名称来绑定设备。

参数parent = NULL;

pre_reloc_only = false;

info = &root_info

devp = &DM_ROOT_NON_CONST  实际就是 &((((gd_t *)gd)->dm_root))

int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
			const struct driver_info *info, struct udevice **devp)
{
	struct driver *drv;
	uint platdata_size = 0;

	drv = lists_driver_lookup_name(info->name);   //参数为“root_driver”
	if (!drv)
		return -ENOENT;
	if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))//pre_reloc_only  为false,不执行
		return -EPERM;

#if CONFIG_IS_ENABLED(OF_PLATDATA)   //宏未定义,跳过
	platdata_size = info->platdata_size;
#endif
	return device_bind_common(parent, drv, info->name,
			(void *)info->platdata, 0, ofnode_null(), platdata_size,
			devp);
}

1.3.11.1.1.1.1 lists_driver_lookup_name函数

参数为:root_driver

这里发现找代码属性段的时候,需要用到的是u-boot.map文件,刚刚也把前面的文章改了过来。

 .u_boot_list_2_driver_1  
                0x00000000002d25c0        0x0 drivers/built-in.o
 .u_boot_list_2_driver_2_analogix_dp
                0x00000000002d25c0       0x78 drivers/built-in.o
                0x00000000002d25c0                _u_boot_list_2_driver_2_analogix_dp
 .u_boot_list_2_driver_2_arasan_sdhci_drv
                0x00000000002d2638       0x78 drivers/built-in.o
                0x00000000002d2638                _u_boot_list_2_driver_2_arasan_sdhci_drv
 .u_boot_list_2_driver_2_clk_fixed_rate
                0x00000000002d26b0       0x78 drivers/built-in.o
                0x00000000002d26b0                _u_boot_list_2_driver_2_clk_fixed_rate
 .u_boot_list_2_driver_2_clk_rk3399
                0x00000000002d2728       0x78 drivers/built-in.o
                0x00000000002d2728                _u_boot_list_2_driver_2_clk_rk3399
 .u_boot_list_2_driver_2_dmc_rk3399
                0x00000000002d27a0       0x78 drivers/built-in.o
                0x00000000002d27a0                _u_boot_list_2_driver_2_dmc_rk3399
 .u_boot_list_2_driver_2_dw_mipi_dsi
                0x00000000002d2818       0x78 drivers/built-in.o
                0x00000000002d2818                _u_boot_list_2_driver_2_dw_mipi_dsi
 .u_boot_list_2_driver_2_ehci_generic
                0x00000000002d2890       0x78 drivers/usb/host/built-in.o
                0x00000000002d2890                _u_boot_list_2_driver_2_ehci_generic
 .u_boot_list_2_driver_2_eth_designware
                0x00000000002d2908       0x78 drivers/net/built-in.o
                0x00000000002d2908                _u_boot_list_2_driver_2_eth_designware
 .u_boot_list_2_driver_2_eth_gmac_rockchip
                0x00000000002d2980       0x78 drivers/net/built-in.o
                0x00000000002d2980                _u_boot_list_2_driver_2_eth_gmac_rockchip
 .u_boot_list_2_driver_2_fixed_regulator
                0x00000000002d29f8       0x78 drivers/power/regulator/built-in.o
                0x00000000002d29f8                _u_boot_list_2_driver_2_fixed_regulator
 .u_boot_list_2_driver_2_generic_syscon
                0x00000000002d2a70       0x78 drivers/built-in.o
                0x00000000002d2a70                _u_boot_list_2_driver_2_generic_syscon
 .u_boot_list_2_driver_2_gpio_rockchip
                0x00000000002d2ae8       0x78 drivers/gpio/built-in.o
                0x00000000002d2ae8                _u_boot_list_2_driver_2_gpio_rockchip
 .u_boot_list_2_driver_2_i2c_generic_chip_drv
                0x00000000002d2b60       0x78 drivers/i2c/built-in.o
                0x00000000002d2b60                _u_boot_list_2_driver_2_i2c_generic_chip_drv
 .u_boot_list_2_driver_2_i2c_rockchip
                0x00000000002d2bd8       0x78 drivers/i2c/built-in.o
                0x00000000002d2bd8                _u_boot_list_2_driver_2_i2c_rockchip
 .u_boot_list_2_driver_2_mmc
                0x00000000002d2c50       0x78 drivers/built-in.o
                0x00000000002d2c50                _u_boot_list_2_driver_2_mmc
 .u_boot_list_2_driver_2_mmc_blk
                0x00000000002d2cc8       0x78 drivers/built-in.o
                0x00000000002d2cc8                _u_boot_list_2_driver_2_mmc_blk
 .u_boot_list_2_driver_2_ns16550_serial
                0x00000000002d2d40       0x78 drivers/serial/built-in.o
                0x00000000002d2d40                _u_boot_list_2_driver_2_ns16550_serial
 .u_boot_list_2_driver_2_ohci_generic
                0x00000000002d2db8       0x78 drivers/usb/host/built-in.o
                0x00000000002d2db8                _u_boot_list_2_driver_2_ohci_generic
 .u_boot_list_2_driver_2_pinconfig_generic
                0x00000000002d2e30       0x78 drivers/built-in.o
                0x00000000002d2e30                _u_boot_list_2_driver_2_pinconfig_generic
 .u_boot_list_2_driver_2_pinctrl_rockchip
                0x00000000002d2ea8       0x78 drivers/built-in.o
                0x00000000002d2ea8                _u_boot_list_2_driver_2_pinctrl_rockchip
 .u_boot_list_2_driver_2_pmic_rk8xx
                0x00000000002d2f20       0x78 drivers/power/pmic/built-in.o
                0x00000000002d2f20                _u_boot_list_2_driver_2_pmic_rk8xx
 .u_boot_list_2_driver_2_psci
                0x00000000002d2f98       0x78 drivers/built-in.o
                0x00000000002d2f98                _u_boot_list_2_driver_2_psci
 .u_boot_list_2_driver_2_psci_sysreset
                0x00000000002d3010       0x78 drivers/built-in.o
                0x00000000002d3010                _u_boot_list_2_driver_2_psci_sysreset
 .u_boot_list_2_driver_2_pwm_backlight
                0x00000000002d3088       0x78 drivers/built-in.o
                0x00000000002d3088                _u_boot_list_2_driver_2_pwm_backlight
 .u_boot_list_2_driver_2_pwm_regulator
                0x00000000002d3100       0x78 drivers/power/regulator/built-in.o
                0x00000000002d3100                _u_boot_list_2_driver_2_pwm_regulator
 .u_boot_list_2_driver_2_rk8xx_buck
                0x00000000002d3178       0x78 drivers/power/regulator/built-in.o
                0x00000000002d3178                _u_boot_list_2_driver_2_rk8xx_buck
 .u_boot_list_2_driver_2_rk8xx_ldo
                0x00000000002d31f0       0x78 drivers/power/regulator/built-in.o
                0x00000000002d31f0                _u_boot_list_2_driver_2_rk8xx_ldo
 .u_boot_list_2_driver_2_rk8xx_switch
                0x00000000002d3268       0x78 drivers/power/regulator/built-in.o
                0x00000000002d3268                _u_boot_list_2_driver_2_rk8xx_switch
 .u_boot_list_2_driver_2_rk_pwm
                0x00000000002d32e0       0x78 drivers/built-in.o
                0x00000000002d32e0                _u_boot_list_2_driver_2_rk_pwm
 .u_boot_list_2_driver_2_rockchip_crypto_v1
                0x00000000002d3358       0x78 drivers/built-in.o
                0x00000000002d3358                _u_boot_list_2_driver_2_rockchip_crypto_v1
 .u_boot_list_2_driver_2_rockchip_display
                0x00000000002d33d0       0x78 drivers/built-in.o
                0x00000000002d33d0                _u_boot_list_2_driver_2_rockchip_display
 .u_boot_list_2_driver_2_rockchip_dw_hdmi
                0x00000000002d3448       0x78 drivers/built-in.o
                0x00000000002d3448                _u_boot_list_2_driver_2_rockchip_dw_hdmi
 .u_boot_list_2_driver_2_rockchip_dwmmc_drv
                0x00000000002d34c0       0x78 drivers/built-in.o
                0x00000000002d34c0                _u_boot_list_2_driver_2_rockchip_dwmmc_drv
 .u_boot_list_2_driver_2_rockchip_efuse
                0x00000000002d3538       0x78 drivers/built-in.o
                0x00000000002d3538                _u_boot_list_2_driver_2_rockchip_efuse
 .u_boot_list_2_driver_2_rockchip_lvds
                0x00000000002d35b0       0x78 drivers/built-in.o
                0x00000000002d35b0                _u_boot_list_2_driver_2_rockchip_lvds
 .u_boot_list_2_driver_2_rockchip_panel
                0x00000000002d3628       0x78 drivers/built-in.o
                0x00000000002d3628                _u_boot_list_2_driver_2_rockchip_panel
 .u_boot_list_2_driver_2_rockchip_reset
                0x00000000002d36a0       0x78 drivers/built-in.o
                0x00000000002d36a0                _u_boot_list_2_driver_2_rockchip_reset
 .u_boot_list_2_driver_2_rockchip_rgb
                0x00000000002d3718       0x78 drivers/built-in.o
                0x00000000002d3718                _u_boot_list_2_driver_2_rockchip_rgb
 .u_boot_list_2_driver_2_rockchip_rk3399_pmuclk
                0x00000000002d3790       0x78 drivers/built-in.o
                0x00000000002d3790                _u_boot_list_2_driver_2_rockchip_rk3399_pmuclk
 .u_boot_list_2_driver_2_rockchip_saradc
                0x00000000002d3808       0x78 drivers/built-in.o
                0x00000000002d3808                _u_boot_list_2_driver_2_rockchip_saradc
 .u_boot_list_2_driver_2_rockchip_usb2phy
                0x00000000002d3880       0x78 drivers/built-in.o
                0x00000000002d3880                _u_boot_list_2_driver_2_rockchip_usb2phy
 .u_boot_list_2_driver_2_rockchip_usb2phy_port
                0x00000000002d38f8       0x78 drivers/built-in.o
                0x00000000002d38f8                _u_boot_list_2_driver_2_rockchip_usb2phy_port
 .u_boot_list_2_driver_2_rockchip_vop
                0x00000000002d3970       0x78 drivers/built-in.o
                0x00000000002d3970                _u_boot_list_2_driver_2_rockchip_vop
 .u_boot_list_2_driver_2_root_driver
                0x00000000002d39e8       0x78 drivers/built-in.o
                0x00000000002d39e8                _u_boot_list_2_driver_2_root_driver
 .u_boot_list_2_driver_2_simple_bus_drv
                0x00000000002d3a60       0x78 drivers/built-in.o
                0x00000000002d3a60                _u_boot_list_2_driver_2_simple_bus_drv
 .u_boot_list_2_driver_2_simple_panel
                0x00000000002d3ad8       0x78 drivers/built-in.o
                0x00000000002d3ad8                _u_boot_list_2_driver_2_simple_panel
 .u_boot_list_2_driver_2_spi_generic_drv
                0x00000000002d3b50       0x78 drivers/spi/built-in.o
                0x00000000002d3b50                _u_boot_list_2_driver_2_spi_generic_drv
 .u_boot_list_2_driver_2_syscon_rk3399
                0x00000000002d3bc8       0x78 arch/arm/mach-rockchip/built-in.o
                0x00000000002d3bc8                _u_boot_list_2_driver_2_syscon_rk3399
 .u_boot_list_2_driver_2_sysreset_rockchip
                0x00000000002d3c40       0x78 drivers/built-in.o
                0x00000000002d3c40                _u_boot_list_2_driver_2_sysreset_rockchip
 .u_boot_list_2_driver_2_sysreset_syscon_reboot
                0x00000000002d3cb8       0x78 drivers/built-in.o
                0x00000000002d3cb8                _u_boot_list_2_driver_2_sysreset_syscon_reboot
 .u_boot_list_2_driver_2_usb_dev_generic_drv
                0x00000000002d3d30       0x78 drivers/usb/host/built-in.o
                0x00000000002d3d30                _u_boot_list_2_driver_2_usb_dev_generic_drv
 .u_boot_list_2_driver_2_usb_generic_hub
                0x00000000002d3da8       0x78 common/built-in.o
                0x00000000002d3da8                _u_boot_list_2_driver_2_usb_generic_hub
 .u_boot_list_2_driver_2_usb_mass_storage
                0x00000000002d3e20       0x78 common/built-in.o
                0x00000000002d3e20                _u_boot_list_2_driver_2_usb_mass_storage
 .u_boot_list_2_driver_2_usb_storage_blk
                0x00000000002d3e98       0x78 common/built-in.o
                0x00000000002d3e98                _u_boot_list_2_driver_2_usb_storage_blk
 .u_boot_list_2_driver_2_vidconsole_normal
                0x00000000002d3f10       0x78 drivers/built-in.o
                0x00000000002d3f10                _u_boot_list_2_driver_2_vidconsole_normal
 .u_boot_list_2_driver_2_xhci_dwc3
                0x00000000002d3f88       0x78 drivers/usb/host/built-in.o
                0x00000000002d3f88                _u_boot_list_2_driver_2_xhci_dwc3
 .u_boot_list_2_driver_3
                0x00000000002d4000        0x0 drivers/built-in.o

.u_boot_list_2_driver_1 是驱动开始标记

.u_boot_list_2_driver_3 是驱动结束标记

.u_boot_list_2_driver_2_xx  就是加入的设备驱动。(粗略数了一下,有56个驱动)。

要查找的root_driver也是存在的!!

结构体的首地址,很有可能就是0x00000000002d39e8

用这几个驱动的地址相减得到的差值0x78来看,应该就是结构体的首地址。

1.3.11.1.1.1.2  device_bind_common 函数

稍微看了一下代码之后,这次这个函数的目的是新建root_driver的设备。

参数:

parent --> NULL

drv --> drv指针,应该就是root_driver 的首地址

name --> root_driver

platdata --> info.platdata --> NULL

driver_data --> 0

node --> 一个空的node (ofnode类型)

of_platdata_size -->platdata_size --> 0

devp --> &(((gd_t *)gd)->dm_root)

static int device_bind_common(struct udevice *parent, const struct driver *drv,
			      const char *name, void *platdata,
			      ulong driver_data, ofnode node,
			      uint of_platdata_size, struct udevice **devp)
{
	struct udevice *dev;
	struct uclass *uc;
	int size, ret = 0;

	if (devp)   //指针不为空,执行
		*devp = NULL;   //指向空,在函数最后会赋值
	if (!name)   //有一个字符串“root_driver”
		return -EINVAL;

	ret = uclass_get(drv->id, &uc);  //id也是有的,在结构体中,UCLASS_ROOT,在文件root.c中
	if (ret) {
		debug("Missing uclass for driver %s\n", drv->name);
		return ret;
	}

#ifdef CONFIG_USING_KERNEL_DTB  //这个宏定义了。
	if (gd->flags & GD_FLG_RELOC) {   //这个flag没有设置,需要到board_r.c的阶段,这个if不执行
		/* For mmc/nand/spiflash, just update from kernel dtb instead bind again*/
		if (drv->id == UCLASS_MMC || drv->id == UCLASS_RKNAND ||
		    drv->id == UCLASS_SPI_FLASH || drv->id == UCLASS_MTD) {
			list_for_each_entry(dev, &uc->dev_head, uclass_node) {
				if (!strcmp(name, dev->name)) {
					debug("%s do not bind dev already in list %s\n",
					      __func__, dev->name);
					/*
					 * There is no clearly reason for this
					 * legacy code, but remain it here since
					 * everything seems fine with or without
					 * this. Maybe removed in the future.
					 */
					dev->node = node;
					return 0;
				}
			}
		}

		/* Use other nodes from kernel dtb */
		struct udevice *n;

		list_for_each_entry_safe(dev, n, &uc->dev_head, uclass_node) {
			if (!strcmp(name, dev->name) &&
			    (dev_read_bool(dev, "u-boot,dm-pre-reloc") ||
			     dev_read_bool(dev, "u-boot,dm-spl"))) {

				/* Always use crypto node from U-Boot dtb */
				if (drv->id == UCLASS_CRYPTO) {
					debug("%s do not delete uboot dev: %s\n",
					      __func__, dev->name);
					return 0;
				} else {
					list_del_init(&dev->uclass_node);
				}
			}
		}
	}
#endif
	dev = calloc(1, sizeof(struct udevice));  //分配struct udevice空间
	if (!dev)
		return -ENOMEM;

	INIT_LIST_HEAD(&dev->sibling_node);  //初始化列表
	INIT_LIST_HEAD(&dev->child_head);
	INIT_LIST_HEAD(&dev->uclass_node);
#ifdef CONFIG_DEVRES     //宏未定义
	INIT_LIST_HEAD(&dev->devres_head);
#endif
	dev->platdata = platdata;   //赋值,NULL
	dev->driver_data = driver_data; //0
	dev->name = name;  //“root_driver”
	dev->node = node;   //一个空的node
	dev->parent = parent;  //NULL,
	dev->driver = drv;  //对应root_driver结构体首地址
	dev->uclass = uc;  //前文中获取,id对应UCLASS_ROOT

	dev->seq = -1;   //-1==none
	dev->req_seq = -1;  //-1==any
	if (CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_SEQ_ALIAS)) {  //查看.config,两个宏都有定义
		/*
		 * Some devices, such as a SPI bus, I2C bus and serial ports
		 * are numbered using aliases.
		 *
		 * This is just a 'requested' sequence, and will be
		 * resolved (and ->seq updated) when the device is probed.
		 */
		if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {  //没有设置该flag
			if (uc->uc_drv->name && ofnode_valid(node)) {
				dev_read_alias_seq(dev, &dev->req_seq);
			}
		}
	}

	if (drv->platdata_auto_alloc_size) {  //没有设置,root.c
		bool alloc = !platdata;

		if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
			if (of_platdata_size) {
				dev->flags |= DM_FLAG_OF_PLATDATA;
				if (of_platdata_size <
						drv->platdata_auto_alloc_size)
					alloc = true;
			}
		}
		if (alloc) {
			dev->flags |= DM_FLAG_ALLOC_PDATA;
			dev->platdata = calloc(1,
					       drv->platdata_auto_alloc_size);
			if (!dev->platdata) {
				ret = -ENOMEM;
				goto fail_alloc1;
			}
			if (CONFIG_IS_ENABLED(OF_PLATDATA) && platdata) {
				memcpy(dev->platdata, platdata,
				       of_platdata_size);
			}
		}
	}

	size = uc->uc_drv->per_device_platdata_auto_alloc_size; //没有设置,root.c
	if (size) {
		dev->flags |= DM_FLAG_ALLOC_UCLASS_PDATA;
		dev->uclass_platdata = calloc(1, size);
		if (!dev->uclass_platdata) {
			ret = -ENOMEM;
			goto fail_alloc2;
		}
	}

	if (parent) { //parent = NULL,不执行
		size = parent->driver->per_child_platdata_auto_alloc_size;
		if (!size) {
			size = parent->uclass->uc_drv->
					per_child_platdata_auto_alloc_size;
		}
		if (size) {
			dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
			dev->parent_platdata = calloc(1, size);
			if (!dev->parent_platdata) {
				ret = -ENOMEM;
				goto fail_alloc3;
			}
		}
	}

	/* put dev into parent's successor list */
	if (parent)//parent = NULL,不执行
		list_add_tail(&dev->sibling_node, &parent->child_head);

	ret = uclass_bind_device(dev);  //插入到链表中
	if (ret)
		goto fail_uclass_bind;

	/* if we fail to bind we remove device from successors and free it */
	if (drv->bind) {  //没有实现该函数
		ret = drv->bind(dev);
		if (ret)
			goto fail_bind;
	}
	if (parent && parent->driver->child_post_bind) { //parent = NULL,不执行 
		ret = parent->driver->child_post_bind(dev);
		if (ret)
			goto fail_child_post_bind;
	}
	if (uc->uc_drv->post_bind) {//驱动中没有,不执行
		ret = uc->uc_drv->post_bind(dev);
		if (ret)
			goto fail_uclass_post_bind;
	}

	if (parent)//parent = NULL,不执行
		pr_debug("Bound device %s to %s\n", dev->name, parent->name);
	if (devp)
		*devp = dev;   //dev通过参数返回

	dev->flags |= DM_FLAG_BOUND;

	return 0;

fail_uclass_post_bind:
	/* There is no child unbind() method, so no clean-up required */
fail_child_post_bind:
	if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
		if (drv->unbind && drv->unbind(dev)) {
			dm_warn("unbind() method failed on dev '%s' on error path\n",
				dev->name);
		}
	}

fail_bind:
	if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
		if (uclass_unbind_device(dev)) {
			dm_warn("Failed to unbind dev '%s' on error path\n",
				dev->name);
		}
	}
fail_uclass_bind:
	if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
		list_del(&dev->sibling_node);
		if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
			free(dev->parent_platdata);
			dev->parent_platdata = NULL;
		}
	}
fail_alloc3:
	if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
		free(dev->uclass_platdata);
		dev->uclass_platdata = NULL;
	}
fail_alloc2:
	if (dev->flags & DM_FLAG_ALLOC_PDATA) {
		free(dev->platdata);
		dev->platdata = NULL;
	}
fail_alloc1:
	devres_release_all(dev);

	free(dev);

	return ret;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2135039.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

去除单细胞数据中环境游离的RNA污染-decontX工具学习

DecontX 是一种用于单细胞 RNA 测序数据的去除环境污染物&#xff08;decontamination&#xff09;的工具&#xff0c;主要用于减少由细胞外RNA造成的污染效应。 开发者在20年的文章中已经把这个工具适用的情况说的非常清楚了&#xff1a;简单来说就是基于微流控的单细胞技术会…

解决PowerAutomate日期处理报错

问题来源 今天尝试做一个简单到到不能再简单的PowerAutomate流&#xff0c;就是读取一个Sharepoint上的Excle表格里的每一行&#xff0c;然后更新到一个list。然鹅确收到了一个意想不到的报错&#xff0c; 报错信息如下&#xff1a; The runtime value "" to be c…

Android 签名、空包签名 、jarsigner、apksigner

jarsigner是JDK提供的针对jar包签名的通用工具, 位于JDK/bin/jarsigner.exe apksigner是Google官方提供的针对Android apk签名及验证的专用工具, 位于Android SDK/build-tools/SDK版本/apksigner.bat jarsigner&#xff1a; jarsigner签名空包执行的命令&#xff1a; jar…

关于Spring Cloud Gateway中 Filters的理解

Spring Cloud Gateway中 Filters的理解 Filters Filters拦截器的作用是,对请求进行处理 可以进行流量染色 ⭐增加请求头 例子 spring:cloud:gateway:routes:- id: add_request_header_routeuri: http://localhost:8123predicates:- Path=/api/**filters:- AddRequestHea…

嵌入式软件工程师:科技浪潮中的关键角色

嵌入式软件工程师&#xff1a;科技浪潮中的关键角色 一、嵌入式软件工程师的职业魅力 &#xff08;一&#xff09;市场需求旺盛 嵌入式软件工程师在当今科技领域中扮演着至关重要的角色。随着智能化时代的到来&#xff0c;嵌入式系统在各个行业的应用越来越广泛&#xff0c;市…

Java API 搜索引擎测试报告

一、测试项目介绍 基于SpringBoot开发的 Java API 文档搜索引擎&#xff0c;输入具体的类名或包名就能找到对应相关的搜索结果&#xff0c;点击标题即可跳转到对应官方网页。 二、测试 测试环境&#xff1a;Windows11&#xff0c;Google chrome浏览器 128.0.6613.138 (正式版…

jmeter 录制APP脚本

一、手机 1、修改网络 代理选择手动→填写服务器主机名&#xff08;电脑IP&#xff0c;如&#xff1a;192.1xx.x.xx&#xff09;→服务器端口&#xff08;任意未被占用端口&#xff0c;如&#xff1a;8888&#xff09; 2、安装证书 手机浏览器访问服务器主机名:服务器端口&a…

通过mqtt通信远程控制大疆无人机

一、控制大疆无人机通信链路如上图所示 二、大疆无人机pilot指令飞行通信交互逻辑如上图所示 三、实现远程控制步骤 3.1前端单独实现&#xff1a;只通过后端获取控制权&#xff0c;然后前端单独发送mqtt指令&#xff0c;延时较低。 3.2前后端一起实现&#xff1a;前端发送ht…

Leetcode - 周赛414

目录 一&#xff0c;3280. 将日期转换为二进制表示 二&#xff0c;3281. 范围内整数的最大得分 三&#xff0c;3282. 到达数组末尾的最大得分 四&#xff0c;3283. 吃掉所有兵需要的最多移动次数 一&#xff0c;3280. 将日期转换为二进制表示 本题就是简单的字符串和整数之…

产品密封防水设计技术、工艺标准及实施方案解培训

一、课程背景&#xff1a; 当前智能产品密封防水能力成为电子产品营销的重要卖点&#xff0c;虽然我们不需长期带着某种电子设备在水下工作和生活&#xff0c;意外却会令价值不菲的电子产品瞬间报废。时下智能手表和耳机成了慢跑伴侣&#xff0c;汗水或雨水长期的侵润腐蚀&…

查谷歌流量什么最准确,服务商提供的工具为什么不能用?

查网站的SEO流量&#xff0c;Google Search Console是最准确的工具&#xff0c;因为这就是谷歌官方提供的工具&#xff0c;谷歌这方面没必要造假&#xff0c;GSC能直接展示你的网站在谷歌搜索中的表现&#xff0c;包括点击次数、展示次数、点击率和平均排名。因为这些数据直接来…

项目需求 | MySQL增量备份与恢复的完整操作指南

目录 一、MySql数据库增量备份的工作原理 1、全量备份与增量备份 2、增量备份原理 二、进行增量备份 步骤1&#xff1a;启用二进制日志 使用 SHOW VARIABLES 命令查看二进制日志状态 步骤2&#xff1a;执行增量备份脚本 三、使用增量备份恢复损坏的数据库 步骤1&#…

[数据集][目标检测]男女性别检测数据集VOC+YOLO格式9769张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;9769 标注数量(xml文件个数)&#xff1a;9769 标注数量(txt文件个数)&#xff1a;9769 标注…

《程序猿之设计模式实战 · 池化思想》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

春意盎然:SpringBoot在线教育平台设计

第五章 系统实现 5.1用户功能模块 用户点击进入到系统操作界面&#xff0c;可以对首页、个人中心、课程信息管理、我的收藏管理、订单管理等功能模块&#xff0c;个人信息&#xff1a;通过列表可以获取账号、密码、姓名、性别、手机、邮箱、照片、备注并进行修改操作&#xff…

网络药理学:15、草稿暂存区(autodock vina)

TCMSP 韦恩图在线网站 https://bioinfogp.cnb.csic.es/tools/venny/index.html String数据库参数详解&#xff1a;https://www.bilibili.com/video/BV1q64y1k7Zf?p16&vd_sourceaed4c634975918b14b7354ec93ce5389 David数据库可以用基因ID或者基因名。 KEGG数据库使用&am…

大雪纷飞的视频素材去哪里找啊?雪景素材库分享

当冬季的银装素裹覆盖大地&#xff0c;无数抖音创作者便开始寻找那些可以捕捉到大雪纷飞的壮观画面。无论是为了制作节日主题的视频、记录下雪天的活动&#xff0c;还是单纯展示雪的清新美&#xff0c;优质的大雪视频素材都显得尤为重要。如果你正为寻找这类素材而苦恼&#xf…

软件测试面试题,精选100 道,内附答案

精挑细选&#xff0c;整理了100道软件测试面试题&#xff0c;都是非常常见的面试题&#xff0c;篇幅较长&#xff0c;所以只放出了题目&#xff0c;答案在评论区&#xff01; 测试技术面试题 1、什么是兼容性测试&#xff1f;兼容性测试侧重哪些方面&#xff1f; 2、我现在有…

设计模式篇--抽象工厂模式

/*** 主要思路&#xff1a;先构建一个总工厂&#xff0c;包含许多分工厂&#xff0c;再从分工厂中&#xff0c;取出自己想要的类型的物品*/ public class main {public static void main(String[] args) {FactoryProducer factoryProducer new FactoryProducer();//获取手机工…

计算机网络(六) —— http协议详解

目录 一&#xff0c;预备知识 1.1 关于域名 1.2 关于URL 1.3 urlencode和urldecode 二&#xff0c;关于http 2.1 什么是http 2.2 http协议格式 2.2.1 网络协议栈 2.2.2 http请求协议格式* 2.2.3 http响应协议格式* 三&#xff0c;http细节字段 3.1 http方法 3.2 …