mei: Simplify the ME client enumeration code
authorSamuel Ortiz <sameo@linux.intel.com>
Sun, 18 Nov 2012 13:13:20 +0000 (15:13 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Nov 2012 20:43:58 +0000 (12:43 -0800)
After enumerating all ME clients we call the client init functions for
all matching UUIDs from a separate context.
This remove the hackish cascading client initialisation process that was
interleaving properties and connection command replies.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/mei/init.c
drivers/misc/mei/interrupt.c
drivers/misc/mei/main.c
drivers/misc/mei/mei_dev.h

index 49600d6e37265976b31ab80231aacaa6dcea914f..a54cd5567ca20bc78a9a823fb63b227a4592264a 100644 (file)
@@ -423,54 +423,87 @@ void mei_allocate_me_clients_storage(struct mei_device *dev)
        dev->me_clients = clients;
        return ;
 }
-/**
- * host_client_properties - reads properties for client
- *
- * @dev: the device structure
- *
- * returns:
- *     < 0 - Error.
- *  = 0 - no more clients.
- *  = 1 - still have clients to send properties request.
- */
-int mei_host_client_properties(struct mei_device *dev)
+
+void mei_host_client_init(struct work_struct *work)
+{
+       struct mei_device *dev = container_of(work,
+                                             struct mei_device, init_work);
+       struct mei_client_properties *client_props;
+       int i;
+
+       mutex_lock(&dev->device_lock);
+
+       bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
+       dev->open_handle_count = 0;
+
+       /*
+        * Reserving the first three client IDs
+        * 0: Reserved for MEI Bus Message communications
+        * 1: Reserved for Watchdog
+        * 2: Reserved for AMTHI
+        */
+       bitmap_set(dev->host_clients_map, 0, 3);
+
+       for (i = 0; i < dev->me_clients_num; i++) {
+               client_props = &dev->me_clients[i].props;
+
+               if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid))
+                       mei_amthif_host_init(dev);
+               else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid))
+                       mei_wd_host_init(dev);
+       }
+
+       dev->dev_state = MEI_DEV_ENABLED;
+
+       mutex_unlock(&dev->device_lock);
+}
+
+int mei_host_client_enumerate(struct mei_device *dev)
 {
 
        struct mei_msg_hdr *mei_hdr;
        struct hbm_props_request *prop_req;
        const size_t len = sizeof(struct hbm_props_request);
+       unsigned long next_client_index;
+       u8 client_num;
 
-       int b;
-       u8 client_num = dev->me_client_presentation_num;
 
-       prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
+       client_num = dev->me_client_presentation_num;
 
-       b = dev->me_client_index;
-       b = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, b);
-       if (b < MEI_CLIENTS_MAX) {
-               dev->me_clients[client_num].client_id = b;
-               dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
-               mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
+       next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX,
+                                         dev->me_client_index);
 
+       /* We got all client properties */
+       if (next_client_index == MEI_CLIENTS_MAX) {
+               schedule_work(&dev->init_work);
 
-               memset(prop_req, 0, sizeof(struct hbm_props_request));
+               return 0;
+       }
 
-               prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
-               prop_req->address = b;
+       dev->me_clients[client_num].client_id = next_client_index;
+       dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
+
+       mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
+       prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
+
+       memset(prop_req, 0, sizeof(struct hbm_props_request));
 
-               if (mei_write_message(dev, mei_hdr,
-                               (unsigned char *)prop_req, len)) {
-                       dev->dev_state = MEI_DEV_RESETING;
-                       dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
-                       mei_reset(dev, 1);
-                       return -EIO;
-               }
 
-               dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
-               dev->me_client_index = b;
-               return 1;
+       prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
+       prop_req->address = next_client_index;
+
+       if (mei_write_message(dev, mei_hdr, (unsigned char *) prop_req,
+                             mei_hdr->length)) {
+               dev->dev_state = MEI_DEV_RESETING;
+               dev_err(&dev->pdev->dev, "Properties request command failed\n");
+               mei_reset(dev, 1);
+
+               return -EIO;
        }
 
+       dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
+       dev->me_client_index = next_client_index;
+
        return 0;
 }
 
index e5aa0ed3b8eb849cd9d03cc7bc8f68a2d9b0ed65..04fa2134615eb490be4e2c20a50bccfc39ad5f75 100644 (file)
@@ -252,8 +252,6 @@ static void mei_client_connect_response(struct mei_device *dev,
                dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
                mei_watchdog_register(dev);
 
-               /* next step in the state maching */
-               mei_amthif_host_init(dev);
                return;
        }
 
@@ -470,6 +468,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
                struct mei_msg_hdr *mei_hdr)
 {
        struct mei_bus_message *mei_msg;
+       struct mei_me_client *me_client;
        struct hbm_host_version_response *version_res;
        struct hbm_client_connect_response *connect_res;
        struct hbm_client_connect_response *disconnect_res;
@@ -478,8 +477,6 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
        struct hbm_props_response *props_res;
        struct hbm_host_enum_response *enum_res;
        struct hbm_host_stop_request *stop_req;
-       int res;
-
 
        /* read the message to our buffer */
        BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf));
@@ -547,64 +544,37 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
 
        case HOST_CLIENT_PROPERTIES_RES_CMD:
                props_res = (struct hbm_props_response *)mei_msg;
+               me_client = &dev->me_clients[dev->me_client_presentation_num];
+
                if (props_res->status || !dev->me_clients) {
                        dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n");
                        mei_reset(dev, 1);
                        return;
                }
-               if (dev->me_clients[dev->me_client_presentation_num]
-                                       .client_id == props_res->address) {
 
-                       dev->me_clients[dev->me_client_presentation_num].props
-                                               = props_res->client_properties;
+               if (me_client->client_id != props_res->address) {
+                       dev_err(&dev->pdev->dev,
+                               "Host client properties reply mismatch\n");
+                       mei_reset(dev, 1);
 
-                       if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
-                           dev->init_clients_state ==
-                                       MEI_CLIENT_PROPERTIES_MESSAGE) {
-                               dev->me_client_index++;
-                               dev->me_client_presentation_num++;
-
-                               /** Send Client Properties request **/
-                               res = mei_host_client_properties(dev);
-                               if (res < 0) {
-                                       dev_dbg(&dev->pdev->dev, "mei_host_client_properties() failed");
-                                       return;
-                               } else if (!res) {
-                                       /*
-                                        * No more clients to send to.
-                                        * Clear Map for indicating now ME clients
-                                        * with associated host client
-                                        */
-                                       bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
-                                       dev->open_handle_count = 0;
-
-                                       /*
-                                        * Reserving the first three client IDs
-                                        * Client Id 0 - Reserved for MEI Bus Message communications
-                                        * Client Id 1 - Reserved for Watchdog
-                                        * Client ID 2 - Reserved for AMTHI
-                                        */
-                                       bitmap_set(dev->host_clients_map, 0, 3);
-                                       dev->dev_state = MEI_DEV_ENABLED;
-
-                                       /* if wd initialization fails, initialization the AMTHI client,
-                                        * otherwise the AMTHI client will be initialized after the WD client connect response
-                                        * will be received
-                                        */
-                                       if (mei_wd_host_init(dev))
-                                               mei_amthif_host_init(dev);
-                               }
+                       return;
+               }
 
-                       } else {
-                               dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message");
-                               mei_reset(dev, 1);
-                               return;
-                       }
-               } else {
-                       dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message for wrong client ID\n");
+               if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
+                   dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) {
+                       dev_err(&dev->pdev->dev,
+                               "Unexpected client properties reply\n");
                        mei_reset(dev, 1);
+
                        return;
                }
+
+               me_client->props = props_res->client_properties;
+               dev->me_client_index++;
+               dev->me_client_presentation_num++;
+
+               mei_host_client_enumerate(dev);
+
                break;
 
        case HOST_ENUM_RES_CMD:
@@ -618,7 +588,8 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
                                mei_allocate_me_clients_storage(dev);
                                dev->init_clients_state =
                                        MEI_CLIENT_PROPERTIES_MESSAGE;
-                               mei_host_client_properties(dev);
+
+                               mei_host_client_enumerate(dev);
                } else {
                        dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
                        mei_reset(dev, 1);
index 251aafff54928c1d619fdd7a956b8779f005715b..7c9c381e5c9affc4740fe403916ef44fbd0e64ed 100644 (file)
@@ -829,6 +829,8 @@ static int __devinit mei_probe(struct pci_dev *pdev,
                goto disable_msi;
        }
        INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
+       INIT_WORK(&dev->init_work, mei_host_client_init);
+
        if (mei_hw_init(dev)) {
                dev_err(&pdev->dev, "init hw failure.\n");
                err = -ENODEV;
index 17d00aae74e6e4d75c8a5682b02f2393f7cb70ca..25da04549d04070746463dddabc8f40b71c65e26 100644 (file)
@@ -287,6 +287,8 @@ struct mei_device {
        bool iamthif_flow_control_pending;
        bool iamthif_ioctl;
        bool iamthif_canceled;
+
+       struct work_struct init_work;
 };
 
 static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
@@ -363,7 +365,8 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
  */
 void mei_host_start_message(struct mei_device *dev);
 void mei_host_enum_clients_message(struct mei_device *dev);
-int mei_host_client_properties(struct mei_device *dev);
+int mei_host_client_enumerate(struct mei_device *dev);
+void mei_host_client_init(struct work_struct *work);
 
 /*
  *  MEI interrupt functions prototype