diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2013-01-08 16:07:22 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-01-08 19:40:46 -0500 |
commit | 781d0d89224bbbc438c2c0360cfd4822bb35d280 (patch) | |
tree | ccda09fa57cd18a9f875bf46d0ce35b925cd9219 /drivers/misc/mei | |
parent | 1a1aca42c989051dce34d49b4e04a25dafe01d74 (diff) |
mei: normalize me host client linking routines
In order we can use the same code pattern for in-kernel
and user space host clients we replace mei_cl_link_to_me
with mei_cl_link function.
We then have to keep me client lookupout of the new link function.
The unlinking cannot be yet symetric due to amthif connection
handling
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei')
-rw-r--r-- | drivers/misc/mei/amthif.c | 42 | ||||
-rw-r--r-- | drivers/misc/mei/client.c | 53 | ||||
-rw-r--r-- | drivers/misc/mei/client.h | 2 | ||||
-rw-r--r-- | drivers/misc/mei/init.c | 4 | ||||
-rw-r--r-- | drivers/misc/mei/main.c | 27 | ||||
-rw-r--r-- | drivers/misc/mei/mei_dev.h | 10 | ||||
-rw-r--r-- | drivers/misc/mei/wd.c | 35 |
7 files changed, 98 insertions, 75 deletions
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 64a9bfa5ad20..88e6aa0f6b4e 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c | |||
@@ -65,22 +65,22 @@ void mei_amthif_reset_params(struct mei_device *dev) | |||
65 | * @dev: the device structure | 65 | * @dev: the device structure |
66 | * | 66 | * |
67 | */ | 67 | */ |
68 | void mei_amthif_host_init(struct mei_device *dev) | 68 | int mei_amthif_host_init(struct mei_device *dev) |
69 | { | 69 | { |
70 | int i; | 70 | struct mei_cl *cl = &dev->iamthif_cl; |
71 | unsigned char *msg_buf; | 71 | unsigned char *msg_buf; |
72 | int ret, i; | ||
72 | 73 | ||
73 | mei_cl_init(&dev->iamthif_cl, dev); | 74 | mei_cl_init(cl, dev); |
74 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; | ||
75 | 75 | ||
76 | /* find ME amthif client */ | 76 | i = mei_me_cl_by_uuid(dev, &mei_amthif_guid); |
77 | i = mei_cl_link_me(&dev->iamthif_cl, | ||
78 | &mei_amthif_guid, MEI_IAMTHIF_HOST_CLIENT_ID); | ||
79 | if (i < 0) { | 77 | if (i < 0) { |
80 | dev_info(&dev->pdev->dev, "failed to find iamthif client.\n"); | 78 | dev_info(&dev->pdev->dev, "amthif: failed to find the client\n"); |
81 | return; | 79 | return -ENOENT; |
82 | } | 80 | } |
83 | 81 | ||
82 | cl->me_client_id = dev->me_clients[i].client_id; | ||
83 | |||
84 | /* Assign iamthif_mtu to the value received from ME */ | 84 | /* Assign iamthif_mtu to the value received from ME */ |
85 | 85 | ||
86 | dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length; | 86 | dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length; |
@@ -94,19 +94,29 @@ void mei_amthif_host_init(struct mei_device *dev) | |||
94 | msg_buf = kcalloc(dev->iamthif_mtu, | 94 | msg_buf = kcalloc(dev->iamthif_mtu, |
95 | sizeof(unsigned char), GFP_KERNEL); | 95 | sizeof(unsigned char), GFP_KERNEL); |
96 | if (!msg_buf) { | 96 | if (!msg_buf) { |
97 | dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n"); | 97 | dev_err(&dev->pdev->dev, "amthif: memory allocation for ME message buffer failed.\n"); |
98 | return; | 98 | return -ENOMEM; |
99 | } | 99 | } |
100 | 100 | ||
101 | dev->iamthif_msg_buf = msg_buf; | 101 | dev->iamthif_msg_buf = msg_buf; |
102 | 102 | ||
103 | if (mei_hbm_cl_connect_req(dev, &dev->iamthif_cl)) { | 103 | ret = mei_cl_link(cl, MEI_IAMTHIF_HOST_CLIENT_ID); |
104 | dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n"); | 104 | |
105 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; | 105 | if (ret < 0) { |
106 | dev->iamthif_cl.host_client_id = 0; | 106 | dev_err(&dev->pdev->dev, "amthif: failed link client\n"); |
107 | return -ENOENT; | ||
108 | } | ||
109 | |||
110 | cl->state = MEI_FILE_CONNECTING; | ||
111 | |||
112 | if (mei_hbm_cl_connect_req(dev, cl)) { | ||
113 | dev_dbg(&dev->pdev->dev, "amthif: Failed to connect to ME client\n"); | ||
114 | cl->state = MEI_FILE_DISCONNECTED; | ||
115 | cl->host_client_id = 0; | ||
107 | } else { | 116 | } else { |
108 | dev->iamthif_cl.timer_count = MEI_CONNECT_TIMEOUT; | 117 | cl->timer_count = MEI_CONNECT_TIMEOUT; |
109 | } | 118 | } |
119 | return 0; | ||
110 | } | 120 | } |
111 | 121 | ||
112 | /** | 122 | /** |
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 8103d94facb8..d566dd880eb0 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c | |||
@@ -258,54 +258,61 @@ struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl) | |||
258 | return NULL; | 258 | return NULL; |
259 | } | 259 | } |
260 | 260 | ||
261 | 261 | /** mei_cl_link: allocte host id in the host map | |
262 | /** | ||
263 | * mei_me_cl_link - create link between host and me clinet and add | ||
264 | * me_cl to the list | ||
265 | * | ||
266 | * @cl: link between me and host client assocated with opened file descriptor | ||
267 | * @uuid: uuid of ME client | ||
268 | * @client_id: id of the host client | ||
269 | * | 262 | * |
270 | * returns ME client index if ME client | 263 | * @cl - host client |
264 | * @id - fixed host id or -1 for genereting one | ||
265 | * returns 0 on success | ||
271 | * -EINVAL on incorrect values | 266 | * -EINVAL on incorrect values |
272 | * -ENONET if client not found | 267 | * -ENONET if client not found |
273 | */ | 268 | */ |
274 | int mei_cl_link_me(struct mei_cl *cl, const uuid_le *uuid, u8 host_cl_id) | 269 | int mei_cl_link(struct mei_cl *cl, int id) |
275 | { | 270 | { |
276 | struct mei_device *dev; | 271 | struct mei_device *dev; |
277 | int i; | ||
278 | 272 | ||
279 | if (WARN_ON(!cl || !cl->dev || !uuid)) | 273 | if (WARN_ON(!cl || !cl->dev)) |
280 | return -EINVAL; | 274 | return -EINVAL; |
281 | 275 | ||
282 | dev = cl->dev; | 276 | dev = cl->dev; |
283 | 277 | ||
284 | /* check for valid client id */ | 278 | /* If Id is not asigned get one*/ |
285 | i = mei_me_cl_by_uuid(dev, uuid); | 279 | if (id == MEI_HOST_CLIENT_ID_ANY) |
286 | if (i >= 0) { | 280 | id = find_first_zero_bit(dev->host_clients_map, |
287 | cl->me_client_id = dev->me_clients[i].client_id; | 281 | MEI_CLIENTS_MAX); |
288 | cl->state = MEI_FILE_CONNECTING; | ||
289 | cl->host_client_id = host_cl_id; | ||
290 | 282 | ||
291 | list_add_tail(&cl->link, &dev->file_list); | 283 | if (id >= MEI_CLIENTS_MAX) { |
292 | return (u8)i; | 284 | dev_err(&dev->pdev->dev, "id exceded %d", MEI_CLIENTS_MAX) ; |
285 | return -ENOENT; | ||
293 | } | 286 | } |
294 | 287 | ||
295 | return -ENOENT; | 288 | dev->open_handle_count++; |
289 | |||
290 | cl->host_client_id = id; | ||
291 | list_add_tail(&cl->link, &dev->file_list); | ||
292 | |||
293 | set_bit(id, dev->host_clients_map); | ||
294 | |||
295 | cl->state = MEI_FILE_INITIALIZING; | ||
296 | |||
297 | dev_dbg(&dev->pdev->dev, "link cl host id = %d\n", cl->host_client_id); | ||
298 | return 0; | ||
296 | } | 299 | } |
300 | |||
297 | /** | 301 | /** |
298 | * mei_cl_unlink - remove me_cl from the list | 302 | * mei_cl_unlink - remove me_cl from the list |
299 | * | 303 | * |
300 | * @dev: the device structure | 304 | * @dev: the device structure |
301 | * @host_client_id: host client id to be removed | ||
302 | */ | 305 | */ |
303 | int mei_cl_unlink(struct mei_cl *cl) | 306 | int mei_cl_unlink(struct mei_cl *cl) |
304 | { | 307 | { |
305 | struct mei_device *dev; | 308 | struct mei_device *dev; |
306 | struct mei_cl *pos, *next; | 309 | struct mei_cl *pos, *next; |
307 | 310 | ||
308 | if (WARN_ON(!cl || !cl->dev)) | 311 | /* don't shout on error exit path */ |
312 | if (!cl) | ||
313 | return 0; | ||
314 | |||
315 | if (WARN_ON(!cl->dev)) | ||
309 | return -EINVAL; | 316 | return -EINVAL; |
310 | 317 | ||
311 | dev = cl->dev; | 318 | dev = cl->dev; |
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 8dfd052dd0e6..240a1f321342 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h | |||
@@ -55,7 +55,7 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev); | |||
55 | void mei_cl_init(struct mei_cl *cl, struct mei_device *dev); | 55 | void mei_cl_init(struct mei_cl *cl, struct mei_device *dev); |
56 | 56 | ||
57 | 57 | ||
58 | int mei_cl_link_me(struct mei_cl *cl, const uuid_le *uuid, u8 host_cl_id); | 58 | int mei_cl_link(struct mei_cl *cl, int id); |
59 | int mei_cl_unlink(struct mei_cl *cl); | 59 | int mei_cl_unlink(struct mei_cl *cl); |
60 | 60 | ||
61 | int mei_cl_flush_queues(struct mei_cl *cl); | 61 | int mei_cl_flush_queues(struct mei_cl *cl); |
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 636639fbfc0a..9e4011ef8508 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
@@ -242,7 +242,11 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
242 | /* remove entry if already in list */ | 242 | /* remove entry if already in list */ |
243 | dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n"); | 243 | dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n"); |
244 | mei_cl_unlink(&dev->wd_cl); | 244 | mei_cl_unlink(&dev->wd_cl); |
245 | if (dev->open_handle_count > 0) | ||
246 | dev->open_handle_count--; | ||
245 | mei_cl_unlink(&dev->iamthif_cl); | 247 | mei_cl_unlink(&dev->iamthif_cl); |
248 | if (dev->open_handle_count > 0) | ||
249 | dev->open_handle_count--; | ||
246 | 250 | ||
247 | mei_amthif_reset_params(dev); | 251 | mei_amthif_reset_params(dev); |
248 | memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg)); | 252 | memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg)); |
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index d5d1a5957d5f..ec5fd7a0e289 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c | |||
@@ -103,7 +103,6 @@ static int mei_open(struct inode *inode, struct file *file) | |||
103 | { | 103 | { |
104 | struct mei_cl *cl; | 104 | struct mei_cl *cl; |
105 | struct mei_device *dev; | 105 | struct mei_device *dev; |
106 | unsigned long cl_id; | ||
107 | int err; | 106 | int err; |
108 | 107 | ||
109 | err = -ENODEV; | 108 | err = -ENODEV; |
@@ -133,24 +132,9 @@ static int mei_open(struct inode *inode, struct file *file) | |||
133 | goto out_unlock; | 132 | goto out_unlock; |
134 | } | 133 | } |
135 | 134 | ||
136 | cl_id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX); | 135 | err = mei_cl_link(cl, MEI_HOST_CLIENT_ID_ANY); |
137 | if (cl_id >= MEI_CLIENTS_MAX) { | 136 | if (err) |
138 | dev_err(&dev->pdev->dev, "client_id exceded %d", | ||
139 | MEI_CLIENTS_MAX) ; | ||
140 | goto out_unlock; | 137 | goto out_unlock; |
141 | } | ||
142 | |||
143 | cl->host_client_id = cl_id; | ||
144 | |||
145 | dev_dbg(&dev->pdev->dev, "client_id = %d\n", cl->host_client_id); | ||
146 | |||
147 | dev->open_handle_count++; | ||
148 | |||
149 | list_add_tail(&cl->link, &dev->file_list); | ||
150 | |||
151 | set_bit(cl->host_client_id, dev->host_clients_map); | ||
152 | cl->state = MEI_FILE_INITIALIZING; | ||
153 | cl->sm_state = 0; | ||
154 | 138 | ||
155 | file->private_data = cl; | 139 | file->private_data = cl; |
156 | mutex_unlock(&dev->device_lock); | 140 | mutex_unlock(&dev->device_lock); |
@@ -209,6 +193,7 @@ static int mei_release(struct inode *inode, struct file *file) | |||
209 | } | 193 | } |
210 | mei_cl_unlink(cl); | 194 | mei_cl_unlink(cl); |
211 | 195 | ||
196 | |||
212 | /* free read cb */ | 197 | /* free read cb */ |
213 | cb = NULL; | 198 | cb = NULL; |
214 | if (cl->read_cb) { | 199 | if (cl->read_cb) { |
@@ -991,7 +976,13 @@ static void mei_remove(struct pci_dev *pdev) | |||
991 | 976 | ||
992 | /* remove entry if already in list */ | 977 | /* remove entry if already in list */ |
993 | dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n"); | 978 | dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n"); |
979 | |||
980 | if (dev->open_handle_count > 0) | ||
981 | dev->open_handle_count--; | ||
994 | mei_cl_unlink(&dev->wd_cl); | 982 | mei_cl_unlink(&dev->wd_cl); |
983 | |||
984 | if (dev->open_handle_count > 0) | ||
985 | dev->open_handle_count--; | ||
995 | mei_cl_unlink(&dev->iamthif_cl); | 986 | mei_cl_unlink(&dev->iamthif_cl); |
996 | 987 | ||
997 | dev->iamthif_current_cb = NULL; | 988 | dev->iamthif_current_cb = NULL; |
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 285e8e01d429..dcd7a44a806e 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h | |||
@@ -67,16 +67,16 @@ extern const u8 mei_wd_state_independence_msg[3][4]; | |||
67 | * Number of File descriptors/handles | 67 | * Number of File descriptors/handles |
68 | * that can be opened to the driver. | 68 | * that can be opened to the driver. |
69 | * | 69 | * |
70 | * Limit to 253: 256 Total Clients | 70 | * Limit to 255: 256 Total Clients |
71 | * minus internal client for MEI Bus Messags | 71 | * minus internal client for MEI Bus Messags |
72 | * minus internal client for AMTHI | ||
73 | * minus internal client for Watchdog | ||
74 | */ | 72 | */ |
75 | #define MEI_MAX_OPEN_HANDLE_COUNT (MEI_CLIENTS_MAX - 3) | 73 | #define MEI_MAX_OPEN_HANDLE_COUNT (MEI_CLIENTS_MAX - 1) |
76 | 74 | ||
77 | /* | 75 | /* |
78 | * Internal Clients Number | 76 | * Internal Clients Number |
79 | */ | 77 | */ |
78 | #define MEI_HOST_CLIENT_ID_ANY (-1) | ||
79 | #define MEI_HBM_HOST_CLIENT_ID 0 /* not used, just for documentation */ | ||
80 | #define MEI_WD_HOST_CLIENT_ID 1 | 80 | #define MEI_WD_HOST_CLIENT_ID 1 |
81 | #define MEI_IAMTHIF_HOST_CLIENT_ID 2 | 81 | #define MEI_IAMTHIF_HOST_CLIENT_ID 2 |
82 | 82 | ||
@@ -339,7 +339,7 @@ void mei_timer(struct work_struct *work); | |||
339 | */ | 339 | */ |
340 | void mei_amthif_reset_params(struct mei_device *dev); | 340 | void mei_amthif_reset_params(struct mei_device *dev); |
341 | 341 | ||
342 | void mei_amthif_host_init(struct mei_device *dev); | 342 | int mei_amthif_host_init(struct mei_device *dev); |
343 | 343 | ||
344 | int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *priv_cb); | 344 | int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *priv_cb); |
345 | 345 | ||
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index bfcbcc8c028b..77b3820380b0 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c | |||
@@ -64,30 +64,41 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) | |||
64 | */ | 64 | */ |
65 | int mei_wd_host_init(struct mei_device *dev) | 65 | int mei_wd_host_init(struct mei_device *dev) |
66 | { | 66 | { |
67 | int id; | 67 | struct mei_cl *cl = &dev->wd_cl; |
68 | mei_cl_init(&dev->wd_cl, dev); | 68 | int i; |
69 | int ret; | ||
70 | |||
71 | mei_cl_init(cl, dev); | ||
69 | 72 | ||
70 | /* look for WD client and connect to it */ | ||
71 | dev->wd_cl.state = MEI_FILE_DISCONNECTED; | ||
72 | dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; | 73 | dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; |
73 | dev->wd_state = MEI_WD_IDLE; | 74 | dev->wd_state = MEI_WD_IDLE; |
74 | 75 | ||
75 | /* Connect WD ME client to the host client */ | ||
76 | id = mei_cl_link_me(&dev->wd_cl, | ||
77 | &mei_wd_guid, MEI_WD_HOST_CLIENT_ID); | ||
78 | 76 | ||
79 | if (id < 0) { | 77 | /* check for valid client id */ |
78 | i = mei_me_cl_by_uuid(dev, &mei_wd_guid); | ||
79 | if (i < 0) { | ||
80 | dev_info(&dev->pdev->dev, "wd: failed to find the client\n"); | 80 | dev_info(&dev->pdev->dev, "wd: failed to find the client\n"); |
81 | return -ENOENT; | 81 | return -ENOENT; |
82 | } | 82 | } |
83 | 83 | ||
84 | if (mei_hbm_cl_connect_req(dev, &dev->wd_cl)) { | 84 | cl->me_client_id = dev->me_clients[i].client_id; |
85 | |||
86 | ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID); | ||
87 | |||
88 | if (ret < 0) { | ||
89 | dev_info(&dev->pdev->dev, "wd: failed link client\n"); | ||
90 | return -ENOENT; | ||
91 | } | ||
92 | |||
93 | cl->state = MEI_FILE_CONNECTING; | ||
94 | |||
95 | if (mei_hbm_cl_connect_req(dev, cl)) { | ||
85 | dev_err(&dev->pdev->dev, "wd: failed to connect to the client\n"); | 96 | dev_err(&dev->pdev->dev, "wd: failed to connect to the client\n"); |
86 | dev->wd_cl.state = MEI_FILE_DISCONNECTED; | 97 | cl->state = MEI_FILE_DISCONNECTED; |
87 | dev->wd_cl.host_client_id = 0; | 98 | cl->host_client_id = 0; |
88 | return -EIO; | 99 | return -EIO; |
89 | } | 100 | } |
90 | dev->wd_cl.timer_count = MEI_CONNECT_TIMEOUT; | 101 | cl->timer_count = MEI_CONNECT_TIMEOUT; |
91 | 102 | ||
92 | return 0; | 103 | return 0; |
93 | } | 104 | } |