drivers/misc/mei/init.c

Source file repositories/reference/linux-study-clean/drivers/misc/mei/init.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/mei/init.c
Extension
.c
Size
10809 bytes
Lines
434
Domain
Driver Families
Bucket
drivers/misc
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (kind_is_gsc(dev) || kind_is_gscfi(dev)) {
			dev_dbg(&dev->dev, "unexpected reset: dev_state = %s fw status = %s\n",
				mei_dev_state_str(state), fw_sts_str);
		} else {
			dev_warn(&dev->dev, "unexpected reset: dev_state = %s fw status = %s\n",
				 mei_dev_state_str(state), fw_sts_str);
		}
	}

	mei_clear_interrupts(dev);

	/* we're already in reset, cancel the init timer
	 * if the reset was called due the hbm protocol error
	 * we need to call it before hw start
	 * so the hbm watchdog won't kick in
	 */
	mei_hbm_idle(dev);

	/* enter reset flow */
	interrupts_enabled = state != MEI_DEV_POWER_DOWN;
	mei_set_devstate(dev, MEI_DEV_RESETTING);

	dev->reset_count++;
	if (dev->reset_count > MEI_MAX_CONSEC_RESET) {
		dev_err(&dev->dev, "reset: reached maximal consecutive resets: disabling the device\n");
		mei_set_devstate(dev, MEI_DEV_DISABLED);
		return -ENODEV;
	}

	ret = mei_hw_reset(dev, interrupts_enabled);
	/* fall through and remove the sw state even if hw reset has failed */

	/* no need to clean up software state in case of power up */
	if (state != MEI_DEV_INITIALIZING && state != MEI_DEV_POWER_UP)
		mei_cl_all_disconnect(dev);

	mei_hbm_reset(dev);

	/* clean stale FW version */
	dev->fw_ver_received = 0;

	memset(dev->rd_msg_hdr, 0, sizeof(dev->rd_msg_hdr));

	if (ret) {
		dev_err(&dev->dev, "hw_reset failed ret = %d\n", ret);
		return ret;
	}

	if (state == MEI_DEV_POWER_DOWN) {
		dev_dbg(&dev->dev, "powering down: end of reset\n");
		mei_set_devstate(dev, MEI_DEV_DISABLED);
		return 0;
	}

	ret = mei_hw_start(dev);
	if (ret) {
		char fw_sts_str[MEI_FW_STATUS_STR_SZ];

		mei_fw_status_str(dev, fw_sts_str, MEI_FW_STATUS_STR_SZ);
		dev_err(&dev->dev, "hw_start failed ret = %d fw status = %s\n", ret, fw_sts_str);
		return ret;
	}

	if (dev->dev_state != MEI_DEV_RESETTING) {
		dev_dbg(&dev->dev, "wrong state = %d on link start\n", dev->dev_state);
		return 0;
	}

	dev_dbg(&dev->dev, "link is established start sending messages.\n");

	mei_set_devstate(dev, MEI_DEV_INIT_CLIENTS);
	ret = mei_hbm_start_req(dev);
	if (ret) {
		dev_err(&dev->dev, "hbm_start failed ret = %d\n", ret);
		mei_set_devstate(dev, MEI_DEV_RESETTING);
		return ret;
	}

	return 0;
}
EXPORT_SYMBOL_GPL(mei_reset);

/**
 * mei_start - initializes host and fw to start work.
 *
 * @dev: the device structure
 *
 * Return: 0 on success, <0 on failure.
 */
int mei_start(struct mei_device *dev)

Annotation

Implementation Notes