mei: add async event notification ioctls

Add ioctl IOCTL_MEI_NOTIFY_SET for enabling and disabling
async event notification.
Add ioctl IOCTL_MEI_NOTIFY_GET for receiving and acking
an event notification.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Tomas Winkler 2015-07-26 09:54:20 +03:00 committed by Greg Kroah-Hartman
parent b38a362fad
commit 3c7c8468e5
4 changed files with 132 additions and 1 deletions

View File

@ -124,6 +124,8 @@ Code Seq#(hex) Include File Comments
'H' 00-7F linux/hiddev.h conflict!
'H' 00-0F linux/hidraw.h conflict!
'H' 01 linux/mei.h conflict!
'H' 02 linux/mei.h conflict!
'H' 03 linux/mei.h conflict!
'H' 00-0F sound/asound.h conflict!
'H' 20-40 sound/asound_fm.h conflict!
'H' 80-8F sound/sfnt_info.h conflict!

View File

@ -96,7 +96,7 @@ A code snippet for an application communicating with Intel AMTHI client:
IOCTL
=====
The Intel MEI Driver supports the following IOCTL command:
The Intel MEI Driver supports the following IOCTL commands:
IOCTL_MEI_CONNECT_CLIENT Connect to firmware Feature (client).
usage:
@ -125,6 +125,49 @@ The Intel MEI Driver supports the following IOCTL command:
data that can be sent or received. (e.g. if MTU=2K, can send
requests up to bytes 2k and received responses up to 2k bytes).
IOCTL_MEI_NOTIFY_SET: enable or disable event notifications
Usage:
uint32_t enable;
ioctl(fd, IOCTL_MEI_NOTIFY_SET, &enable);
Inputs:
uint32_t enable = 1;
or
uint32_t enable[disable] = 0;
Error returns:
EINVAL Wrong IOCTL Number
ENODEV Device is not initialized or the client not connected
ENOMEM Unable to allocate memory to client internal data.
EFAULT Fatal Error (e.g. Unable to access user input data)
EOPNOTSUPP if the device doesn't support the feature
Notes:
The client must be connected in order to enable notification events
IOCTL_MEI_NOTIFY_GET : retrieve event
Usage:
uint32_t event;
ioctl(fd, IOCTL_MEI_NOTIFY_GET, &event);
Outputs:
1 - if an event is pending
0 - if there is no even pending
Error returns:
EINVAL Wrong IOCTL Number
ENODEV Device is not initialized or the client not connected
ENOMEM Unable to allocate memory to client internal data.
EFAULT Fatal Error (e.g. Unable to access user input data)
EOPNOTSUPP if the device doesn't support the feature
Notes:
The client must be connected and event notification has to be enabled
in order to receive an event
Intel ME Applications
=====================

View File

@ -445,6 +445,45 @@ static int mei_ioctl_connect_client(struct file *file,
return rets;
}
/**
* mei_ioctl_client_notify_request -
* propagate event notification request to client
*
* @file: pointer to file structure
* @request: 0 - disable, 1 - enable
*
* Return: 0 on success , <0 on error
*/
static int mei_ioctl_client_notify_request(struct file *file, u32 request)
{
struct mei_cl *cl = file->private_data;
return mei_cl_notify_request(cl, file, request);
}
/**
* mei_ioctl_client_notify_get - wait for notification request
*
* @file: pointer to file structure
* @notify_get: 0 - disable, 1 - enable
*
* Return: 0 on success , <0 on error
*/
static int mei_ioctl_client_notify_get(struct file *file, u32 *notify_get)
{
struct mei_cl *cl = file->private_data;
bool notify_ev;
bool block = (file->f_flags & O_NONBLOCK) == 0;
int rets;
rets = mei_cl_notify_get(cl, block, &notify_ev);
if (rets)
return rets;
*notify_get = notify_ev ? 1 : 0;
return 0;
}
/**
* mei_ioctl - the IOCTL function
*
@ -459,6 +498,7 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
struct mei_device *dev;
struct mei_cl *cl = file->private_data;
struct mei_connect_client_data connect_data;
u32 notify_get, notify_req;
int rets;
@ -499,6 +539,33 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
break;
case IOCTL_MEI_NOTIFY_SET:
dev_dbg(dev->dev, ": IOCTL_MEI_NOTIFY_SET.\n");
if (copy_from_user(&notify_req,
(char __user *)data, sizeof(notify_req))) {
dev_dbg(dev->dev, "failed to copy data from userland\n");
rets = -EFAULT;
goto out;
}
rets = mei_ioctl_client_notify_request(file, notify_req);
break;
case IOCTL_MEI_NOTIFY_GET:
dev_dbg(dev->dev, ": IOCTL_MEI_NOTIFY_GET.\n");
rets = mei_ioctl_client_notify_get(file, &notify_get);
if (rets)
goto out;
dev_dbg(dev->dev, "copy connect data to user\n");
if (copy_to_user((char __user *)data,
&notify_get, sizeof(notify_get))) {
dev_dbg(dev->dev, "failed to copy data to userland\n");
rets = -EFAULT;
goto out;
}
break;
default:
dev_err(dev->dev, ": unsupported ioctl %d.\n", cmd);
rets = -ENOIOCTLCMD;

View File

@ -107,4 +107,23 @@ struct mei_connect_client_data {
};
};
/**
* DOC: set and unset event notification for a connected client
*
* The IOCTL argument is 1 for enabling event notification and 0 for
* disabling the service
* Return: -EOPNOTSUPP if the devices doesn't support the feature
*/
#define IOCTL_MEI_NOTIFY_SET _IOW('H', 0x02, __u32)
/**
* DOC: retrieve notification
*
* The IOCTL output argument is 1 if an event was is pending and 0 otherwise
* the ioctl has to be called in order to acknowledge pending event
*
* Return: -EOPNOTSUPP if the devices doesn't support the feature
*/
#define IOCTL_MEI_NOTIFY_GET _IOR('H', 0x03, __u32)
#endif /* _LINUX_MEI_H */