EXPORT_SYMBOL_GPL(mei_cldev_recv);
/**
- * mei_cl_bus_event_work - dispatch rx event for a bus device
- * and schedule new work
+ * mei_cl_bus_rx_work - dispatch rx event for a bus device
*
* @work: work
*/
-static void mei_cl_bus_event_work(struct work_struct *work)
+static void mei_cl_bus_rx_work(struct work_struct *work)
{
struct mei_cl_device *cldev;
struct mei_device *bus;
- cldev = container_of(work, struct mei_cl_device, event_work);
+ cldev = container_of(work, struct mei_cl_device, rx_work);
bus = cldev->bus;
- if (cldev->event_cb)
- cldev->event_cb(cldev, cldev->events);
+ if (cldev->rx_cb)
+ cldev->rx_cb(cldev);
- cldev->events = 0;
+ mutex_lock(&bus->device_lock);
+ mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
+ mutex_unlock(&bus->device_lock);
+}
- /* Prepare for the next read */
- if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
- mutex_lock(&bus->device_lock);
- mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
- mutex_unlock(&bus->device_lock);
- }
+/**
+ * mei_cl_bus_notif_work - dispatch FW notif event for a bus device
+ *
+ * @work: work
+ */
+static void mei_cl_bus_notif_work(struct work_struct *work)
+{
+ struct mei_cl_device *cldev;
+
+ cldev = container_of(work, struct mei_cl_device, notif_work);
+
+ if (cldev->notif_cb)
+ cldev->notif_cb(cldev);
}
/**
{
struct mei_cl_device *cldev = cl->cldev;
- if (!cldev || !cldev->event_cb)
- return false;
-
- if (!(cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)))
+ if (!cldev || !cldev->notif_cb)
return false;
if (!cl->notify_ev)
return false;
- set_bit(MEI_CL_EVENT_NOTIF, &cldev->events);
-
- schedule_work(&cldev->event_work);
+ schedule_work(&cldev->notif_work);
cl->notify_ev = false;
}
/**
- * mei_cl_bus_rx_event - schedule rx event
+ * mei_cl_bus_rx_event - schedule rx event
*
* @cl: host client
*
{
struct mei_cl_device *cldev = cl->cldev;
- if (!cldev || !cldev->event_cb)
- return false;
-
- if (!(cldev->events_mask & BIT(MEI_CL_EVENT_RX)))
+ if (!cldev || !cldev->rx_cb)
return false;
- set_bit(MEI_CL_EVENT_RX, &cldev->events);
-
- schedule_work(&cldev->event_work);
+ schedule_work(&cldev->rx_work);
return true;
}
/**
- * mei_cldev_register_event_cb - register event callback
+ * mei_cldev_register_rx_cb - register Rx event callback
*
* @cldev: me client devices
- * @event_cb: callback function
- * @events_mask: requested events bitmask
+ * @rx_cb: callback function
*
* Return: 0 on success
* -EALREADY if an callback is already registered
* <0 on other errors
*/
-int mei_cldev_register_event_cb(struct mei_cl_device *cldev,
- unsigned long events_mask,
- mei_cldev_event_cb_t event_cb)
+int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb)
{
struct mei_device *bus = cldev->bus;
int ret;
- if (cldev->event_cb)
+ if (!rx_cb)
+ return -EINVAL;
+ if (cldev->rx_cb)
return -EALREADY;
- cldev->events = 0;
- cldev->events_mask = events_mask;
- cldev->event_cb = event_cb;
- INIT_WORK(&cldev->event_work, mei_cl_bus_event_work);
+ cldev->rx_cb = rx_cb;
+ INIT_WORK(&cldev->rx_work, mei_cl_bus_rx_work);
- if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
- mutex_lock(&bus->device_lock);
- ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
- mutex_unlock(&bus->device_lock);
- if (ret && ret != -EBUSY)
- return ret;
- }
+ mutex_lock(&bus->device_lock);
+ ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
+ mutex_unlock(&bus->device_lock);
+ if (ret && ret != -EBUSY)
+ return ret;
- if (cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)) {
- mutex_lock(&bus->device_lock);
- ret = mei_cl_notify_request(cldev->cl, NULL, event_cb ? 1 : 0);
- mutex_unlock(&bus->device_lock);
- if (ret)
- return ret;
- }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mei_cldev_register_rx_cb);
+
+/**
+ * mei_cldev_register_notif_cb - register FW notification event callback
+ *
+ * @cldev: me client devices
+ * @notif_cb: callback function
+ *
+ * Return: 0 on success
+ * -EALREADY if an callback is already registered
+ * <0 on other errors
+ */
+int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,
+ mei_cldev_cb_t notif_cb)
+{
+ struct mei_device *bus = cldev->bus;
+ int ret;
+
+ if (!notif_cb)
+ return -EINVAL;
+
+ if (cldev->notif_cb)
+ return -EALREADY;
+
+ cldev->notif_cb = notif_cb;
+ INIT_WORK(&cldev->notif_work, mei_cl_bus_notif_work);
+
+ mutex_lock(&bus->device_lock);
+ ret = mei_cl_notify_request(cldev->cl, NULL, 1);
+ mutex_unlock(&bus->device_lock);
+ if (ret)
+ return ret;
return 0;
}
-EXPORT_SYMBOL_GPL(mei_cldev_register_event_cb);
+EXPORT_SYMBOL_GPL(mei_cldev_register_notif_cb);
/**
* mei_cldev_get_drvdata - driver data getter
bus = cldev->bus;
- cldev->event_cb = NULL;
-
mutex_lock(&bus->device_lock);
if (!mei_cl_is_connected(cl)) {
if (!cldev || !dev->driver)
return 0;
- if (cldev->event_cb) {
- cldev->event_cb = NULL;
- cancel_work_sync(&cldev->event_work);
+ if (cldev->rx_cb) {
+ cancel_work_sync(&cldev->rx_work);
+ cldev->rx_cb = NULL;
+ }
+ if (cldev->notif_cb) {
+ cancel_work_sync(&cldev->notif_work);
+ cldev->notif_cb = NULL;
}
cldrv = to_mei_cl_driver(dev->driver);
list_del_init(&cl->link);
cl->state = MEI_FILE_UNINITIALIZED;
+ cl->writing_state = MEI_IDLE;
+
+ WARN_ON(!list_empty(&cl->rd_completed) ||
+ !list_empty(&cl->rd_pending) ||
+ !list_empty(&cl->link));
return 0;
}
}
-static void nfc_mei_event_cb(struct mei_cl_device *cldev, u32 events)
+static void nfc_mei_rx_cb(struct mei_cl_device *cldev)
{
struct nfc_mei_phy *phy = mei_cldev_get_drvdata(cldev);
+ struct sk_buff *skb;
+ int reply_size;
if (!phy)
return;
if (phy->hard_fault != 0)
return;
- if (events & BIT(MEI_CL_EVENT_RX)) {
- struct sk_buff *skb;
- int reply_size;
-
- skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL);
- if (!skb)
- return;
+ skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL);
+ if (!skb)
+ return;
- reply_size = mei_nfc_recv(phy, skb->data, MEI_NFC_MAX_READ);
- if (reply_size < MEI_NFC_HEADER_SIZE) {
- kfree_skb(skb);
- return;
- }
+ reply_size = mei_nfc_recv(phy, skb->data, MEI_NFC_MAX_READ);
+ if (reply_size < MEI_NFC_HEADER_SIZE) {
+ kfree_skb(skb);
+ return;
+ }
- skb_put(skb, reply_size);
- skb_pull(skb, MEI_NFC_HEADER_SIZE);
+ skb_put(skb, reply_size);
+ skb_pull(skb, MEI_NFC_HEADER_SIZE);
- MEI_DUMP_SKB_IN("mei frame read", skb);
+ MEI_DUMP_SKB_IN("mei frame read", skb);
- nfc_hci_recv_frame(phy->hdev, skb);
- }
+ nfc_hci_recv_frame(phy->hdev, skb);
}
static int nfc_mei_phy_enable(void *phy_id)
goto err;
}
- r = mei_cldev_register_event_cb(phy->cldev, BIT(MEI_CL_EVENT_RX),
- nfc_mei_event_cb);
+ r = mei_cldev_register_rx_cb(phy->cldev, nfc_mei_rx_cb);
if (r) {
pr_err("Event cb registration failed %d\n", r);
goto err;
}
/**
- * mei_wdt_event_rx - callback for data receive
+ * mei_wdt_rx - callback for data receive
*
* @cldev: bus device
*/
-static void mei_wdt_event_rx(struct mei_cl_device *cldev)
+static void mei_wdt_rx(struct mei_cl_device *cldev)
{
struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev);
struct mei_wdt_start_response res;
}
/*
- * mei_wdt_notify_event - callback for event notification
+ * mei_wdt_notif - callback for event notification
*
* @cldev: bus device
*/
-static void mei_wdt_notify_event(struct mei_cl_device *cldev)
+static void mei_wdt_notif(struct mei_cl_device *cldev)
{
struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev);
mei_wdt_register(wdt);
}
-/**
- * mei_wdt_event - callback for event receive
- *
- * @cldev: bus device
- * @events: event mask
- */
-static void mei_wdt_event(struct mei_cl_device *cldev, u32 events)
-{
- if (events & BIT(MEI_CL_EVENT_RX))
- mei_wdt_event_rx(cldev);
-
- if (events & BIT(MEI_CL_EVENT_NOTIF))
- mei_wdt_notify_event(cldev);
-}
-
#if IS_ENABLED(CONFIG_DEBUG_FS)
static ssize_t mei_dbgfs_read_activation(struct file *file, char __user *ubuf,
goto err_out;
}
- ret = mei_cldev_register_event_cb(wdt->cldev,
- BIT(MEI_CL_EVENT_RX) |
- BIT(MEI_CL_EVENT_NOTIF),
- mei_wdt_event);
+ ret = mei_cldev_register_rx_cb(wdt->cldev, mei_wdt_rx);
+ if (ret) {
+ dev_err(&cldev->dev, "Could not reg rx event ret=%d\n", ret);
+ goto err_disable;
+ }
+ ret = mei_cldev_register_notif_cb(wdt->cldev, mei_wdt_notif);
/* on legacy devices notification is not supported
- * this doesn't fail the registration for RX event
*/
if (ret && ret != -EOPNOTSUPP) {
- dev_err(&cldev->dev, "Could not register event ret=%d\n", ret);
+ dev_err(&cldev->dev, "Could not reg notif event ret=%d\n", ret);
goto err_disable;
}
struct mei_cl_device;
struct mei_device;
-typedef void (*mei_cldev_event_cb_t)(struct mei_cl_device *cldev,
- u32 events);
+typedef void (*mei_cldev_cb_t)(struct mei_cl_device *cldev);
/**
* struct mei_cl_device - MEI device handle
* @me_cl: me client
* @cl: mei client
* @name: device name
- * @event_work: async work to execute event callback
- * @event_cb: Drivers register this callback to get asynchronous ME
- * events (e.g. Rx buffer pending) notifications.
- * @events_mask: Events bit mask requested by driver.
- * @events: Events bitmask sent to the driver.
+ * @rx_work: async work to execute Rx event callback
+ * @rx_cb: Drivers register this callback to get asynchronous ME
+ * Rx buffer pending notifications.
+ * @notif_work: async work to execute FW notif event callback
+ * @notif_cb: Drivers register this callback to get asynchronous ME
+ * FW notification pending notifications.
*
* @do_match: wheather device can be matched with a driver
* @is_added: device is already scanned
struct mei_cl *cl;
char name[MEI_CL_NAME_SIZE];
- struct work_struct event_work;
- mei_cldev_event_cb_t event_cb;
- unsigned long events_mask;
- unsigned long events;
+ struct work_struct rx_work;
+ mei_cldev_cb_t rx_cb;
+ struct work_struct notif_work;
+ mei_cldev_cb_t notif_cb;
unsigned int do_match:1;
unsigned int is_added:1;
ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length);
ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length);
-int mei_cldev_register_event_cb(struct mei_cl_device *cldev,
- unsigned long event_mask,
- mei_cldev_event_cb_t read_cb);
-
-#define MEI_CL_EVENT_RX 0
-#define MEI_CL_EVENT_TX 1
-#define MEI_CL_EVENT_NOTIF 2
+int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb);
+int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,
+ mei_cldev_cb_t notif_cb);
const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev);
u8 mei_cldev_ver(const struct mei_cl_device *cldev);