mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-19 10:44:14 +08:00
mei: expose device state in sysfs
Expose mei device state to user-space through sysfs. This gives indication to applications that driver is in transition, usefully mostly to detect link reset state. Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d65bf04200
commit
43b8a7ed47
@ -65,3 +65,18 @@ Description: Display the ME firmware version.
|
||||
<platform>:<major>.<minor>.<milestone>.<build_no>.
|
||||
There can be up to three such blocks for different
|
||||
FW components.
|
||||
|
||||
What: /sys/class/mei/meiN/dev_state
|
||||
Date: Mar 2019
|
||||
KernelVersion: 5.1
|
||||
Contact: Tomas Winkler <tomas.winkler@intel.com>
|
||||
Description: Display the ME device state.
|
||||
|
||||
The device state can have following values:
|
||||
INITIALIZING
|
||||
INIT_CLIENTS
|
||||
ENABLED
|
||||
RESETTING
|
||||
DISABLED
|
||||
POWER_DOWN
|
||||
POWER_UP
|
||||
|
@ -669,7 +669,7 @@ int mei_cl_unlink(struct mei_cl *cl)
|
||||
|
||||
void mei_host_client_init(struct mei_device *dev)
|
||||
{
|
||||
dev->dev_state = MEI_DEV_ENABLED;
|
||||
mei_set_devstate(dev, MEI_DEV_ENABLED);
|
||||
dev->reset_count = 0;
|
||||
|
||||
schedule_work(&dev->bus_rescan_work);
|
||||
|
@ -123,12 +123,12 @@ int mei_reset(struct mei_device *dev)
|
||||
|
||||
/* enter reset flow */
|
||||
interrupts_enabled = state != MEI_DEV_POWER_DOWN;
|
||||
dev->dev_state = MEI_DEV_RESETTING;
|
||||
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");
|
||||
dev->dev_state = MEI_DEV_DISABLED;
|
||||
mei_set_devstate(dev, MEI_DEV_DISABLED);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ int mei_reset(struct mei_device *dev)
|
||||
|
||||
if (state == MEI_DEV_POWER_DOWN) {
|
||||
dev_dbg(dev->dev, "powering down: end of reset\n");
|
||||
dev->dev_state = MEI_DEV_DISABLED;
|
||||
mei_set_devstate(dev, MEI_DEV_DISABLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -162,11 +162,11 @@ int mei_reset(struct mei_device *dev)
|
||||
|
||||
dev_dbg(dev->dev, "link is established start sending messages.\n");
|
||||
|
||||
dev->dev_state = MEI_DEV_INIT_CLIENTS;
|
||||
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);
|
||||
dev->dev_state = MEI_DEV_RESETTING;
|
||||
mei_set_devstate(dev, MEI_DEV_RESETTING);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -196,7 +196,7 @@ int mei_start(struct mei_device *dev)
|
||||
|
||||
dev->reset_count = 0;
|
||||
do {
|
||||
dev->dev_state = MEI_DEV_INITIALIZING;
|
||||
mei_set_devstate(dev, MEI_DEV_INITIALIZING);
|
||||
ret = mei_reset(dev);
|
||||
|
||||
if (ret == -ENODEV || dev->dev_state == MEI_DEV_DISABLED) {
|
||||
@ -231,7 +231,7 @@ int mei_start(struct mei_device *dev)
|
||||
return 0;
|
||||
err:
|
||||
dev_err(dev->dev, "link layer initialization failed.\n");
|
||||
dev->dev_state = MEI_DEV_DISABLED;
|
||||
mei_set_devstate(dev, MEI_DEV_DISABLED);
|
||||
mutex_unlock(&dev->device_lock);
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -250,7 +250,7 @@ int mei_restart(struct mei_device *dev)
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
||||
dev->dev_state = MEI_DEV_POWER_UP;
|
||||
mei_set_devstate(dev, MEI_DEV_POWER_UP);
|
||||
dev->reset_count = 0;
|
||||
|
||||
err = mei_reset(dev);
|
||||
@ -301,7 +301,7 @@ void mei_stop(struct mei_device *dev)
|
||||
dev_dbg(dev->dev, "stopping the device.\n");
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
dev->dev_state = MEI_DEV_POWER_DOWN;
|
||||
mei_set_devstate(dev, MEI_DEV_POWER_DOWN);
|
||||
mutex_unlock(&dev->device_lock);
|
||||
mei_cl_bus_remove_devices(dev);
|
||||
|
||||
@ -314,7 +314,7 @@ void mei_stop(struct mei_device *dev)
|
||||
|
||||
mei_reset(dev);
|
||||
/* move device to disabled state unconditionally */
|
||||
dev->dev_state = MEI_DEV_DISABLED;
|
||||
mei_set_devstate(dev, MEI_DEV_DISABLED);
|
||||
|
||||
mutex_unlock(&dev->device_lock);
|
||||
}
|
||||
|
@ -28,6 +28,12 @@
|
||||
#include "mei_dev.h"
|
||||
#include "client.h"
|
||||
|
||||
static struct class *mei_class;
|
||||
static dev_t mei_devt;
|
||||
#define MEI_MAX_DEVS MINORMASK
|
||||
static DEFINE_MUTEX(mei_minor_lock);
|
||||
static DEFINE_IDR(mei_idr);
|
||||
|
||||
/**
|
||||
* mei_open - the open function
|
||||
*
|
||||
@ -829,12 +835,65 @@ static ssize_t fw_ver_show(struct device *device,
|
||||
}
|
||||
static DEVICE_ATTR_RO(fw_ver);
|
||||
|
||||
/**
|
||||
* dev_state_show - display device state
|
||||
*
|
||||
* @device: device pointer
|
||||
* @attr: attribute pointer
|
||||
* @buf: char out buffer
|
||||
*
|
||||
* Return: number of the bytes printed into buf or error
|
||||
*/
|
||||
static ssize_t dev_state_show(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mei_device *dev = dev_get_drvdata(device);
|
||||
enum mei_dev_state dev_state;
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
dev_state = dev->dev_state;
|
||||
mutex_unlock(&dev->device_lock);
|
||||
|
||||
return sprintf(buf, "%s", mei_dev_state_str(dev_state));
|
||||
}
|
||||
static DEVICE_ATTR_RO(dev_state);
|
||||
|
||||
static int match_devt(struct device *dev, const void *data)
|
||||
{
|
||||
const dev_t *devt = data;
|
||||
|
||||
return dev->devt == *devt;
|
||||
}
|
||||
|
||||
/**
|
||||
* dev_set_devstate: set to new device state and notify sysfs file.
|
||||
*
|
||||
* @dev: mei_device
|
||||
* @state: new device state
|
||||
*/
|
||||
void mei_set_devstate(struct mei_device *dev, enum mei_dev_state state)
|
||||
{
|
||||
struct device *clsdev;
|
||||
|
||||
if (dev->dev_state == state)
|
||||
return;
|
||||
|
||||
dev->dev_state = state;
|
||||
|
||||
clsdev = class_find_device(mei_class, NULL, &dev->cdev.dev, match_devt);
|
||||
if (clsdev) {
|
||||
sysfs_notify(&clsdev->kobj, NULL, "dev_state");
|
||||
put_device(clsdev);
|
||||
}
|
||||
}
|
||||
|
||||
static struct attribute *mei_attrs[] = {
|
||||
&dev_attr_fw_status.attr,
|
||||
&dev_attr_hbm_ver.attr,
|
||||
&dev_attr_hbm_ver_drv.attr,
|
||||
&dev_attr_tx_queue_limit.attr,
|
||||
&dev_attr_fw_ver.attr,
|
||||
&dev_attr_dev_state.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(mei);
|
||||
@ -858,12 +917,6 @@ static const struct file_operations mei_fops = {
|
||||
.llseek = no_llseek
|
||||
};
|
||||
|
||||
static struct class *mei_class;
|
||||
static dev_t mei_devt;
|
||||
#define MEI_MAX_DEVS MINORMASK
|
||||
static DEFINE_MUTEX(mei_minor_lock);
|
||||
static DEFINE_IDR(mei_idr);
|
||||
|
||||
/**
|
||||
* mei_minor_get - obtain next free device minor number
|
||||
*
|
||||
|
@ -525,7 +525,6 @@ struct mei_device {
|
||||
struct dentry *dbgfs_dir;
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
|
||||
const struct mei_hw_ops *ops;
|
||||
char hw[0] __aligned(sizeof(void *));
|
||||
};
|
||||
@ -584,6 +583,8 @@ int mei_restart(struct mei_device *dev);
|
||||
void mei_stop(struct mei_device *dev);
|
||||
void mei_cancel_work(struct mei_device *dev);
|
||||
|
||||
void mei_set_devstate(struct mei_device *dev, enum mei_dev_state state);
|
||||
|
||||
int mei_dmam_ring_alloc(struct mei_device *dev);
|
||||
void mei_dmam_ring_free(struct mei_device *dev);
|
||||
bool mei_dma_ring_is_allocated(struct mei_device *dev);
|
||||
|
Loading…
Reference in New Issue
Block a user