static ssize_t firmware_loading_store()

in firmware_loader/fallback.c [237:301]


static ssize_t firmware_loading_store(struct device *dev,
				      struct device_attribute *attr,
				      const char *buf, size_t count)
{
	struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev);
	struct fw_priv *fw_priv;
	ssize_t written = count;
	int loading = simple_strtol(buf, NULL, 10);

	mutex_lock(&fw_lock);
	fw_priv = fw_sysfs->fw_priv;
	if (fw_state_is_aborted(fw_priv))
		goto out;

	switch (loading) {
	case 1:
		/* discarding any previous partial load */
		if (!fw_sysfs_done(fw_priv)) {
			fw_free_paged_buf(fw_priv);
			fw_state_start(fw_priv);
		}
		break;
	case 0:
		if (fw_sysfs_loading(fw_priv)) {
			int rc;

			/*
			 * Several loading requests may be pending on
			 * one same firmware buf, so let all requests
			 * see the mapped 'buf->data' once the loading
			 * is completed.
			 * */
			rc = fw_map_paged_buf(fw_priv);
			if (rc)
				dev_err(dev, "%s: map pages failed\n",
					__func__);
			else
				rc = security_kernel_post_load_data(fw_priv->data,
						fw_priv->size,
						LOADING_FIRMWARE, "blob");

			/*
			 * Same logic as fw_load_abort, only the DONE bit
			 * is ignored and we set ABORT only on failure.
			 */
			if (rc) {
				fw_state_aborted(fw_priv);
				written = rc;
			} else {
				fw_state_done(fw_priv);
			}
			break;
		}
		fallthrough;
	default:
		dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading);
		fallthrough;
	case -1:
		fw_load_abort(fw_sysfs);
		break;
	}
out:
	mutex_unlock(&fw_lock);
	return written;
}