static void fw_device_refresh()

in core-device.c [1129:1194]


static void fw_device_refresh(struct work_struct *work)
{
	struct fw_device *device =
		container_of(work, struct fw_device, work.work);
	struct fw_card *card = device->card;
	int ret, node_id = device->node_id;
	bool changed;

	ret = reread_config_rom(device, device->generation, &changed);
	if (ret != RCODE_COMPLETE)
		goto failed_config_rom;

	if (!changed) {
		if (atomic_cmpxchg(&device->state,
				   FW_DEVICE_INITIALIZING,
				   FW_DEVICE_RUNNING) == FW_DEVICE_GONE)
			goto gone;

		fw_device_update(work);
		device->config_rom_retries = 0;
		goto out;
	}

	/*
	 * Something changed.  We keep things simple and don't investigate
	 * further.  We just destroy all previous units and create new ones.
	 */
	device_for_each_child(&device->device, NULL, shutdown_unit);

	ret = read_config_rom(device, device->generation);
	if (ret != RCODE_COMPLETE)
		goto failed_config_rom;

	fw_device_cdev_update(device);
	create_units(device);

	/* Userspace may want to re-read attributes. */
	kobject_uevent(&device->device.kobj, KOBJ_CHANGE);

	if (atomic_cmpxchg(&device->state,
			   FW_DEVICE_INITIALIZING,
			   FW_DEVICE_RUNNING) == FW_DEVICE_GONE)
		goto gone;

	fw_notice(card, "refreshed device %s\n", dev_name(&device->device));
	device->config_rom_retries = 0;
	goto out;

 failed_config_rom:
	if (device->config_rom_retries < MAX_RETRIES &&
	    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
		device->config_rom_retries++;
		fw_schedule_device_work(device, RETRY_DELAY);
		return;
	}

	fw_notice(card, "giving up on refresh of device %s: %s\n",
		  dev_name(&device->device), fw_rcode_string(ret));
 gone:
	atomic_set(&device->state, FW_DEVICE_GONE);
	device->workfn = fw_device_shutdown;
	fw_schedule_device_work(device, SHUTDOWN_DELAY);
 out:
	if (node_id == card->root_node->node_id)
		fw_schedule_bm_work(card, 0);
}