/**
 * mei_wd_host_init - connect to the watchdog client
 *
 * @dev: the device structure
 *
 * returns -ENENT if wd client cannot be found
 *         -EIO if write has failed
 *         0 on success
 */
int mei_wd_host_init(struct mei_device *dev)
{
	struct mei_cl *cl = &dev->wd_cl;
	int i;
	int ret;

	mei_cl_init(cl, dev);

	dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT;
	dev->wd_state = MEI_WD_IDLE;


	/* check for valid client id */
	i = mei_me_cl_by_uuid(dev, &mei_wd_guid);
	if (i < 0) {
		dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
		return -ENOENT;
	}

	cl->me_client_id = dev->me_clients[i].client_id;

	ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID);

	if (ret < 0) {
		dev_info(&dev->pdev->dev, "wd: failed link client\n");
		return -ENOENT;
	}

	cl->state = MEI_FILE_CONNECTING;

	ret = mei_cl_connect(cl, NULL);

	if (ret) {
		dev_err(&dev->pdev->dev, "wd: failed to connect = %d\n", ret);
		mei_cl_unlink(cl);
		return ret;
	}

	ret = mei_watchdog_register(dev);
	if (ret) {
		mei_cl_disconnect(cl);
		mei_cl_unlink(cl);
	}
	return ret;
}
Esempio n. 2
0
File: nfc.c Progetto: Abioy/kasan
static void mei_nfc_init(struct work_struct *work)
{
	struct mei_device *dev;
	struct mei_cl_device *cldev;
	struct mei_nfc_dev *ndev;
	struct mei_cl *cl_info;

	ndev = container_of(work, struct mei_nfc_dev, init_work);

	cl_info = ndev->cl_info;
	dev = cl_info->dev;

	mutex_lock(&dev->device_lock);

	if (mei_cl_connect(cl_info, NULL) < 0) {
		mutex_unlock(&dev->device_lock);
		dev_err(dev->dev, "Could not connect to the NFC INFO ME client");

		goto err;
	}

	mutex_unlock(&dev->device_lock);

	if (mei_nfc_if_version(ndev) < 0) {
		dev_err(dev->dev, "Could not get the NFC interface version");

		goto err;
	}

	dev_info(dev->dev, "NFC MEI VERSION: IVN 0x%x Vendor ID 0x%x Type 0x%x\n",
		ndev->fw_ivn, ndev->vendor_id, ndev->radio_type);

	mutex_lock(&dev->device_lock);

	if (mei_cl_disconnect(cl_info) < 0) {
		mutex_unlock(&dev->device_lock);
		dev_err(dev->dev, "Could not disconnect the NFC INFO ME client");

		goto err;
	}

	mutex_unlock(&dev->device_lock);

	if (mei_nfc_build_bus_name(ndev) < 0) {
		dev_err(dev->dev, "Could not build the bus ID name\n");
		return;
	}

	cldev = mei_cl_add_device(dev, mei_nfc_guid, ndev->bus_name, &nfc_ops);
	if (!cldev) {
		dev_err(dev->dev, "Could not add the NFC device to the MEI bus\n");

		goto err;
	}

	cldev->priv_data = ndev;


	return;

err:
	mutex_lock(&dev->device_lock);
	mei_nfc_free(ndev);
	mutex_unlock(&dev->device_lock);

}
Esempio n. 3
0
/**
 * mei_release - the release function
 *
 * @inode: pointer to inode structure
 * @file: pointer to file structure
 *
 * returns 0 on success, <0 on error
 */
static int mei_release(struct inode *inode, struct file *file)
{
	struct mei_cl *cl = file->private_data;
	struct mei_cl_cb *cb;
	struct mei_device *dev;
	int rets = 0;

	if (WARN_ON(!cl || !cl->dev))
		return -ENODEV;

	dev = cl->dev;

	mutex_lock(&dev->device_lock);
	if (cl == &dev->iamthif_cl) {
		rets = mei_amthif_release(dev, file);
		goto out;
	}
	if (cl->state == MEI_FILE_CONNECTED) {
		cl->state = MEI_FILE_DISCONNECTING;
		dev_dbg(&dev->pdev->dev,
			"disconnecting client host client = %d, "
		    "ME client = %d\n",
		    cl->host_client_id,
		    cl->me_client_id);
		rets = mei_cl_disconnect(cl);
	}
	mei_cl_flush_queues(cl);
	dev_dbg(&dev->pdev->dev, "remove client host client = %d, ME client = %d\n",
	    cl->host_client_id,
	    cl->me_client_id);

	if (dev->open_handle_count > 0) {
		clear_bit(cl->host_client_id, dev->host_clients_map);
		dev->open_handle_count--;
	}
	mei_cl_unlink(cl);


	/* free read cb */
	cb = NULL;
	if (cl->read_cb) {
		cb = mei_cl_find_read_cb(cl);
		/* Remove entry from read list */
		if (cb)
			list_del(&cb->list);

		cb = cl->read_cb;
		cl->read_cb = NULL;
	}

	file->private_data = NULL;

	if (cb) {
		mei_io_cb_free(cb);
		cb = NULL;
	}

	kfree(cl);
out:
	mutex_unlock(&dev->device_lock);
	return rets;
}