Print this page
5253 kmem_alloc/kmem_zalloc won't fail with KM_SLEEP
5254 getrbuf won't fail with KM_SLEEP
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/intel/io/heci/heci_init.c
+++ new/usr/src/uts/intel/io/heci/heci_init.c
1 1 /*
2 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 3 * Use is subject to license terms.
4 4 */
5 5
6 6 /*
7 7 * Part of Intel(R) Manageability Engine Interface Linux driver
8 8 *
9 9 * Copyright (c) 2003 - 2008 Intel Corp.
10 10 * All rights reserved.
11 11 *
12 12 * Redistribution and use in source and binary forms, with or without
13 13 * modification, are permitted provided that the following conditions
14 14 * are met:
15 15 * 1. Redistributions of source code must retain the above copyright
16 16 * notice, this list of conditions, and the following disclaimer,
17 17 * without modification.
18 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 19 * substantially similar to the "NO WARRANTY" disclaimer below
20 20 * ("Disclaimer") and any redistribution must be conditioned upon
21 21 * including a substantially similar Disclaimer requirement for further
22 22 * binary redistribution.
23 23 * 3. Neither the names of the above-listed copyright holders nor the names
24 24 * of any contributors may be used to endorse or promote products derived
25 25 * from this software without specific prior written permission.
26 26 *
27 27 * Alternatively, this software may be distributed under the terms of the
28 28 * GNU General Public License ("GPL") version 2 as published by the Free
29 29 * Software Foundation.
30 30 *
31 31 * NO WARRANTY
32 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 42 * POSSIBILITY OF SUCH DAMAGES.
43 43 *
44 44 */
45 45
46 46 #include <sys/types.h>
47 47 #include <sys/cmn_err.h>
48 48 #include <sys/conf.h>
49 49 #include <sys/ddi.h>
50 50 #include <sys/ddi_impldefs.h>
51 51 #include <sys/devops.h>
52 52 #include <sys/instance.h>
53 53 #include <sys/modctl.h>
54 54 #include <sys/open.h>
55 55 #include <sys/stat.h>
56 56 #include <sys/sunddi.h>
57 57 #include <sys/sunndi.h>
58 58 #include <sys/systm.h>
59 59 #include <sys/mkdev.h>
60 60 #include <sys/list.h>
61 61 #include <sys/note.h>
62 62 #include "heci_data_structures.h"
63 63 #include "heci_interface.h"
64 64 #include "heci.h"
65 65
66 66
67 67 const uint8_t watch_dog_data[] = {
68 68 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
69 69 };
70 70 const uint8_t start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
71 71 const uint8_t stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 };
72 72
73 73 const uint8_t heci_wd_state_independence_msg[3][4] = {
74 74 {0x05, 0x02, 0x51, 0x10},
75 75 {0x05, 0x02, 0x52, 0x10},
76 76 {0x07, 0x02, 0x01, 0x10}
77 77 };
78 78
79 79 const struct guid heci_asf_guid = {
80 80 0x75B30CD6, 0xA29E, 0x4AF7,
81 81 {0xA7, 0x12, 0xE6, 0x17, 0x43, 0x93, 0xC8, 0xA6}
82 82 };
83 83 const struct guid heci_wd_guid = {
84 84 0x05B79A6F, 0x4628, 0x4D7F,
85 85 {0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB}
86 86 };
87 87 const struct guid heci_pthi_guid = {
88 88 0x12f80028, 0xb4b7, 0x4b2d,
89 89 {0xac, 0xa8, 0x46, 0xe0, 0xff, 0x65, 0x81, 0x4c}
90 90 };
91 91
92 92
93 93 /*
94 94 * heci init function prototypes
95 95 */
96 96 static void heci_check_asf_mode(struct iamt_heci_device *dev);
97 97 static int host_start_message(struct iamt_heci_device *dev);
98 98 static int host_enum_clients_message(struct iamt_heci_device *dev);
99 99 static int allocate_me_clients_storage(struct iamt_heci_device *dev);
100 100 static void host_init_wd(struct iamt_heci_device *dev);
101 101 static void host_init_iamthif(struct iamt_heci_device *dev);
102 102 static inline int heci_fe_same_id(struct heci_file_private *fe1,
103 103 struct heci_file_private *fe2);
104 104
105 105
106 106
107 107 /*
108 108 * heci_initialize_list - Sets up a queue list.
109 109 *
110 110 * @list: An instance of our list structure
111 111 * @dev: Device object for our driver
112 112 */
113 113 void
114 114 heci_initialize_list(struct io_heci_list *list,
115 115 struct iamt_heci_device *dev)
116 116 {
117 117 /* initialize our queue list */
118 118 LIST_INIT_HEAD(&list->heci_cb.cb_list);
119 119 list->status = 0;
120 120 list->device_extension = dev;
121 121 }
122 122
123 123 /*
124 124 * heci_flush_queues - flush our queues list belong to file_ext.
125 125 *
126 126 * @dev: Device object for our driver
127 127 * @file_ext: private data of the file object
128 128 *
129 129 */
130 130 void
131 131 heci_flush_queues(struct iamt_heci_device *dev,
132 132 struct heci_file_private *file_ext)
133 133 {
134 134 int i;
135 135
136 136 if (!dev || !file_ext)
137 137 return;
138 138
139 139 /* flush our queue list belong to file_ext */
140 140 for (i = 0; i < HECI_IO_LISTS_NUMBER; i++) {
141 141 DBG("remove list entry belong to file_ext\n");
142 142 heci_flush_list(dev->io_list_array[i], file_ext);
143 143 }
144 144 }
145 145
146 146
147 147 /*
148 148 * heci_flush_list - remove list entry belong to file_ext.
149 149 *
150 150 * @list: An instance of our list structure
151 151 * @file_ext: private data of the file object
152 152 */
153 153 void
154 154 heci_flush_list(struct io_heci_list *list,
155 155 struct heci_file_private *file_ext)
156 156 {
157 157 struct heci_file_private *file_ext_tmp;
158 158 struct heci_cb_private *priv_cb_pos = NULL;
159 159 struct heci_cb_private *priv_cb_next = NULL;
160 160
161 161 if (!list || !file_ext)
162 162 return;
163 163
164 164 if (list->status != 0)
165 165 return;
166 166
167 167 if (list_empty(&list->heci_cb.cb_list))
168 168 return;
169 169
170 170 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
171 171 &list->heci_cb.cb_list, cb_list, struct heci_cb_private) {
172 172 if (priv_cb_pos) {
173 173 file_ext_tmp = (struct heci_file_private *)
174 174 priv_cb_pos->file_private;
175 175 if (file_ext_tmp) {
176 176 if (heci_fe_same_id(file_ext, file_ext_tmp))
177 177 list_del(&priv_cb_pos->cb_list);
178 178 }
179 179 }
180 180 }
181 181 }
182 182
183 183 /*
184 184 * heci_reset_iamthif_params - initializes heci device iamthif
185 185 * @dev: The heci device structure
186 186 */
187 187 static void heci_reset_iamthif_params(struct iamt_heci_device *dev)
188 188 {
189 189 /* reset iamthif parameters. */
190 190 dev->iamthif_current_cb = NULL;
191 191 dev->iamthif_msg_buf_size = 0;
192 192 dev->iamthif_msg_buf_index = 0;
193 193 dev->iamthif_canceled = 0;
194 194 dev->iamthif_file_ext.file = NULL;
195 195 dev->iamthif_ioctl = 0;
196 196 dev->iamthif_state = HECI_IAMTHIF_IDLE;
197 197 dev->iamthif_timer = 0;
198 198 }
199 199
200 200 /*
201 201 * fini_heci_device - release resources allocated in init_heci_device()
202 202 */
203 203 void
204 204 fini_heci_device(struct iamt_heci_device *device)
205 205 {
206 206 mutex_destroy(&device->device_lock);
207 207 cv_destroy(&device->wait_recvd_msg);
208 208 cv_destroy(&device->wait_stop_wd);
209 209 if (device->work)
210 210 ddi_taskq_destroy(device->work);
211 211 if (device->reinit_tsk)
212 212 ddi_taskq_destroy(device->reinit_tsk);
213 213
214 214 }
215 215
216 216 /*
217 217 * init_heci_device - initializes the heci device structure
218 218 *
219 219 */
220 220 void
221 221 init_heci_device(dev_info_t *dip,
222 222 struct iamt_heci_device *device)
223 223 {
224 224 int i;
225 225
226 226 if (!device)
227 227 return;
228 228
229 229 /* setup our list array */
230 230 device->io_list_array[0] = &device->read_list;
231 231 device->io_list_array[1] = &device->write_list;
232 232 device->io_list_array[2] = &device->write_waiting_list;
233 233 device->io_list_array[3] = &device->ctrl_wr_list;
234 234 device->io_list_array[4] = &device->ctrl_rd_list;
235 235 device->io_list_array[5] = &device->pthi_cmd_list;
236 236 device->io_list_array[6] = &device->pthi_read_complete_list;
237 237 LIST_INIT_HEAD(&device->file_list);
238 238 LIST_INIT_HEAD(&device->wd_file_ext.link);
239 239 LIST_INIT_HEAD(&device->iamthif_file_ext.link);
240 240 mutex_init(&device->device_lock, NULL, MUTEX_DRIVER, NULL);
241 241 cv_init(&device->wait_recvd_msg, NULL, CV_DRIVER, NULL);
242 242 cv_init(&device->wait_stop_wd, NULL, CV_DRIVER, NULL);
243 243 device->open_handle_count = 0;
244 244 device->num_heci_me_clients = 0;
245 245 device->extra_write_index = 0;
246 246 device->rd_msg_hdr = 0;
247 247 device->mem_addr = NULL;
248 248 device->asf_mode = B_FALSE;
249 249 device->need_reset = B_FALSE;
250 250 device->recvd_msg = B_FALSE;
251 251 device->heci_state = HECI_INITIALIZING;
252 252 device->iamthif_state = HECI_IAMTHIF_IDLE;
253 253
254 254 device->work = ddi_taskq_create(dip, "heci_bh_handler", 1,
255 255 TASKQ_DEFAULTPRI, 0);
256 256 if (device->work == NULL)
257 257 cmn_err(CE_WARN, "taskq_create failed for heci_bh_handler");
258 258 device->reinit_tsk = ddi_taskq_create(dip, "heci_reinit_tsk", 1,
259 259 TASKQ_DEFAULTPRI, 0);
260 260 if (device->reinit_tsk == NULL)
261 261 cmn_err(CE_WARN, "taskq_create failed for reinit_tsk");
262 262
263 263 device->wd_pending = B_FALSE;
264 264 device->wd_stoped = B_FALSE;
265 265
266 266 device->me_clients = NULL;
267 267 for (i = 0; i < HECI_IO_LISTS_NUMBER; i++)
268 268 heci_initialize_list(device->io_list_array[i], device);
269 269 device->dip = dip;
270 270 }
271 271
272 272 /*
273 273 * heci_hw_init - init host and fw to start work.
274 274 *
275 275 * @dev: Device object for our driver
276 276 *
277 277 * @return 0 on success, <0 on failure.
278 278 */
279 279 int
280 280 heci_hw_init(struct iamt_heci_device *dev)
281 281 {
282 282 int err = 0;
283 283
284 284 mutex_enter(&dev->device_lock);
285 285 dev->host_hw_state = read_heci_register(dev, H_CSR);
286 286 dev->me_hw_state = read_heci_register(dev, ME_CSR_HA);
287 287 DBG("host_hw_state = 0x%08x, mestate = 0x%08x.\n",
288 288 dev->host_hw_state, dev->me_hw_state);
289 289
290 290 if ((dev->host_hw_state & H_IS) == H_IS) {
291 291 /* acknowledge interrupt and stop interupts */
292 292 heci_set_csr_register(dev);
293 293 }
294 294 dev->recvd_msg = 0;
295 295 DBG("reset in start the heci device.\n");
296 296
297 297 heci_reset(dev, 1);
298 298
299 299 DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
300 300 dev->host_hw_state, dev->me_hw_state);
301 301
302 302 /* wait for ME to turn on ME_RDY */
303 303 err = 0;
304 304 while (!dev->recvd_msg && err != -1) {
305 305 err = cv_reltimedwait(&dev->wait_recvd_msg,
306 306 &dev->device_lock, HECI_INTEROP_TIMEOUT, TR_CLOCK_TICK);
307 307 }
308 308
309 309 if (err == -1 && !dev->recvd_msg) {
310 310 dev->heci_state = HECI_DISABLED;
311 311 DBG("wait_event_interruptible_timeout failed"
312 312 "on wait for ME to turn on ME_RDY.\n");
313 313 mutex_exit(&dev->device_lock);
314 314 return (-ENODEV);
315 315 } else {
316 316 if (!(((dev->host_hw_state & H_RDY) == H_RDY) &&
317 317 ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) {
318 318 dev->heci_state = HECI_DISABLED;
319 319 DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
320 320 dev->host_hw_state,
321 321 dev->me_hw_state);
322 322
323 323 if (!(dev->host_hw_state & H_RDY) != H_RDY)
324 324 DBG("host turn off H_RDY.\n");
325 325
326 326 if (!(dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
327 327 DBG("ME turn off ME_RDY.\n");
328 328
329 329 cmn_err(CE_WARN,
330 330 "heci: link layer initialization failed.\n");
331 331 mutex_exit(&dev->device_lock);
332 332 return (-ENODEV);
333 333 }
334 334 }
335 335 dev->recvd_msg = 0;
336 336 DBG("host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
337 337 dev->host_hw_state, dev->me_hw_state);
338 338 DBG("ME turn on ME_RDY and host turn on H_RDY.\n");
339 339 DBG("heci: link layer has been established.\n");
340 340 mutex_exit(&dev->device_lock);
341 341 return (0);
342 342 }
343 343
344 344 /*
345 345 * heci_hw_reset - reset fw via heci csr register.
346 346 *
347 347 * @dev: Device object for our driver
348 348 * @interrupts: if interrupt should be enable after reset.
349 349 */
350 350 static void heci_hw_reset(struct iamt_heci_device *dev, int interrupts)
351 351 {
352 352 dev->host_hw_state |= (H_RST | H_IG);
353 353
354 354 if (interrupts)
355 355 heci_csr_enable_interrupts(dev);
356 356 else
357 357 heci_csr_disable_interrupts(dev);
358 358
359 359 }
360 360
361 361 /*
362 362 * heci_reset - reset host and fw.
363 363 *
364 364 * @dev: Device object for our driver
365 365 * @interrupts: if interrupt should be enable after reset.
366 366 */
367 367 void
368 368 heci_reset(struct iamt_heci_device *dev, int interrupts)
369 369 {
370 370 struct heci_file_private *file_pos = NULL;
371 371 struct heci_file_private *file_next = NULL;
372 372 struct heci_cb_private *priv_cb_pos = NULL;
373 373 struct heci_cb_private *priv_cb_next = NULL;
374 374 int unexpected = 0;
375 375
376 376 if (dev->heci_state == HECI_RECOVERING_FROM_RESET) {
377 377 dev->need_reset = 1;
378 378 return;
379 379 }
380 380
381 381 if (dev->heci_state != HECI_INITIALIZING &&
382 382 dev->heci_state != HECI_DISABLED &&
383 383 dev->heci_state != HECI_POWER_DOWN &&
384 384 dev->heci_state != HECI_POWER_UP)
385 385 unexpected = 1;
386 386
387 387 if (dev->reinit_tsk != NULL) {
388 388 mutex_exit(&dev->device_lock);
389 389 (void) ddi_taskq_wait(dev->reinit_tsk);
390 390 mutex_enter(&dev->device_lock);
391 391 }
392 392
393 393 dev->host_hw_state = read_heci_register(dev, H_CSR);
394 394
395 395 DBG("before reset host_hw_state = 0x%08x.\n",
396 396 dev->host_hw_state);
397 397
398 398 heci_hw_reset(dev, interrupts);
399 399
400 400 dev->host_hw_state &= ~H_RST;
401 401 dev->host_hw_state |= H_IG;
402 402
403 403 write_heci_register(dev, H_CSR, dev->host_hw_state);
404 404
405 405 DBG("currently saved host_hw_state = 0x%08x.\n",
406 406 dev->host_hw_state);
407 407
408 408 dev->need_reset = 0;
409 409
410 410 if (dev->heci_state != HECI_INITIALIZING) {
411 411 if ((dev->heci_state != HECI_DISABLED) &&
412 412 (dev->heci_state != HECI_POWER_DOWN))
413 413 dev->heci_state = HECI_RESETING;
414 414
415 415 list_for_each_entry_safe(file_pos,
416 416 file_next, &dev->file_list, link,
417 417 struct heci_file_private) {
418 418 file_pos->state = HECI_FILE_DISCONNECTED;
419 419 file_pos->flow_ctrl_creds = 0;
420 420 file_pos->read_cb = NULL;
421 421 file_pos->timer_count = 0;
422 422 }
423 423 /* remove entry if already in list */
424 424 DBG("list del iamthif and wd file list.\n");
425 425 heci_remove_client_from_file_list(dev,
426 426 dev->wd_file_ext.host_client_id);
427 427
428 428 heci_remove_client_from_file_list(dev,
429 429 dev->iamthif_file_ext.host_client_id);
430 430
431 431 heci_reset_iamthif_params(dev);
432 432 dev->wd_due_counter = 0;
433 433 dev->extra_write_index = 0;
434 434 }
435 435
436 436 dev->num_heci_me_clients = 0;
437 437 dev->rd_msg_hdr = 0;
438 438 dev->stop = 0;
439 439 dev->wd_pending = 0;
440 440
441 441 /* update the state of the registers after reset */
442 442 dev->host_hw_state = read_heci_register(dev, H_CSR);
443 443 dev->me_hw_state = read_heci_register(dev, ME_CSR_HA);
444 444
445 445 DBG("after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
446 446 dev->host_hw_state, dev->me_hw_state);
447 447
448 448 if (unexpected)
449 449 cmn_err(CE_WARN, "unexpected heci reset.\n");
450 450
451 451 /* Wake up all readings so they can be interrupted */
452 452 list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link,
453 453 struct heci_file_private) {
454 454 cmn_err(CE_NOTE, "heci: Waking up client!\n");
455 455 cv_broadcast(&file_pos->rx_wait);
456 456 }
457 457 /* remove all waiting requests */
458 458 if (dev->write_list.status == 0 &&
459 459 !list_empty(&dev->write_list.heci_cb.cb_list)) {
460 460 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
461 461 &dev->write_list.heci_cb.cb_list, cb_list,
462 462 struct heci_cb_private) {
463 463 if (priv_cb_pos) {
464 464 list_del(&priv_cb_pos->cb_list);
465 465 heci_free_cb_private(priv_cb_pos);
466 466 }
467 467 }
468 468 }
469 469 }
470 470
471 471 /*
472 472 * heci_initialize_clients - routine.
473 473 *
474 474 * @dev: Device object for our driver
475 475 *
476 476 */
477 477 int
478 478 heci_initialize_clients(struct iamt_heci_device *dev)
479 479 {
480 480 int status;
481 481
482 482 /* msleep(100) FW needs time to be ready to talk with us */
483 483 delay(drv_usectohz(100000));
484 484 DBG("link is established start sending messages.\n");
485 485 /* link is established start sending messages. */
486 486 status = host_start_message(dev);
487 487 if (status != 0) {
488 488 mutex_enter(&dev->device_lock);
489 489 dev->heci_state = HECI_DISABLED;
490 490 mutex_exit(&dev->device_lock);
491 491 DBG("start sending messages failed.\n");
492 492 return (status);
493 493 }
494 494 /* enumerate clients */
495 495
496 496 status = host_enum_clients_message(dev);
497 497 if (status != 0) {
498 498 mutex_enter(&dev->device_lock);
499 499 dev->heci_state = HECI_DISABLED;
500 500 mutex_exit(&dev->device_lock);
501 501 DBG("enum clients failed.\n");
502 502 return (status);
503 503 }
504 504 /* allocate storage for ME clients representation */
505 505 status = allocate_me_clients_storage(dev);
506 506 if (status != 0) {
507 507 mutex_enter(&dev->device_lock);
508 508 dev->num_heci_me_clients = 0;
509 509 dev->heci_state = HECI_DISABLED;
510 510 mutex_exit(&dev->device_lock);
511 511 DBG("allocate clients failed.\n");
512 512 return (status);
513 513 }
514 514
515 515 heci_check_asf_mode(dev);
516 516 /* heci initialization wd */
517 517 host_init_wd(dev);
518 518 /* heci initialization iamthif client */
519 519 host_init_iamthif(dev);
520 520
521 521 mutex_enter(&dev->device_lock);
522 522 if (dev->need_reset) {
523 523 dev->need_reset = 0;
524 524 dev->heci_state = HECI_DISABLED;
525 525 mutex_exit(&dev->device_lock);
526 526 return (-ENODEV);
527 527 }
528 528
529 529 (void) memset(dev->heci_host_clients, 0,
530 530 sizeof (dev->heci_host_clients));
531 531 dev->open_handle_count = 0;
532 532 dev->heci_host_clients[0] |= 7;
533 533 dev->current_host_client_id = 3;
534 534 dev->heci_state = HECI_ENABLED;
535 535 mutex_exit(&dev->device_lock);
536 536 DBG("initialization heci clients successful.\n");
537 537 return (0);
538 538 }
539 539
540 540 /*
541 541 * heci_task_initialize_clients - routine.
542 542 *
543 543 * @data: Device object for our driver
544 544 *
545 545 */
546 546 void
547 547 heci_task_initialize_clients(void *data)
548 548 {
549 549 int ret;
550 550 struct iamt_heci_device *dev = (struct iamt_heci_device *)data;
551 551
552 552 ret = heci_initialize_clients(dev);
553 553 if (ret)
554 554 cmn_err(CE_WARN, "heci_initialize_clients() failed\n");
555 555 }
556 556
557 557 /*
558 558 * host_start_message - heci host send start message.
559 559 *
560 560 * @dev: Device object for our driver
561 561 *
562 562 * @return 0 on success, <0 on failure.
563 563 */
564 564 static int
565 565 host_start_message(struct iamt_heci_device *dev)
566 566 {
567 567 long timeout = 60; /* 60 second */
568 568 struct heci_msg_hdr *heci_hdr;
569 569 struct hbm_host_version_request *host_start_req;
570 570 struct hbm_host_stop_request *host_stop_req;
571 571 int err = 0;
572 572 clock_t delta = (clock_t)(timeout * HZ);
573 573
574 574 /* host start message */
575 575 mutex_enter(&dev->device_lock);
576 576 heci_hdr = (struct heci_msg_hdr *)&dev->wr_msg_buf[0];
577 577 heci_hdr->host_addr = 0;
578 578 heci_hdr->me_addr = 0;
579 579 heci_hdr->length = sizeof (struct hbm_host_version_request);
580 580 heci_hdr->msg_complete = 1;
581 581 heci_hdr->reserved = 0;
582 582
583 583 host_start_req =
584 584 (struct hbm_host_version_request *)&dev->wr_msg_buf[1];
585 585 (void) memset(host_start_req, 0,
586 586 sizeof (struct hbm_host_version_request));
587 587 host_start_req->cmd.cmd = HOST_START_REQ_CMD;
588 588 host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
589 589 host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
590 590 dev->recvd_msg = 0;
591 591 if (!heci_write_message(dev, heci_hdr,
592 592 (unsigned char *)(host_start_req),
593 593 heci_hdr->length)) {
594 594 DBG("send version to fw fail.\n");
595 595 mutex_exit(&dev->device_lock);
596 596 return (-ENODEV);
597 597 }
598 598 DBG("call wait_event_interruptible_timeout for response message.\n");
599 599 err = 0;
600 600 while (err != -1 && !dev->recvd_msg) {
601 601 err = cv_reltimedwait(&dev->wait_recvd_msg, &dev->device_lock,
602 602 delta, TR_CLOCK_TICK);
603 603 }
604 604 if (err == -1 && !dev->recvd_msg) {
605 605 DBG("wait_timeout failed on host start response message.\n");
606 606 mutex_exit(&dev->device_lock);
607 607 return (-ENODEV);
608 608 }
609 609 dev->recvd_msg = 0;
610 610 DBG("wait_timeout successful on host start response message.\n");
611 611 if ((dev->version.major_version != HBM_MAJOR_VERSION) ||
612 612 (dev->version.minor_version != HBM_MINOR_VERSION)) {
613 613 /* send stop message */
614 614 heci_hdr->host_addr = 0;
615 615 heci_hdr->me_addr = 0;
616 616 heci_hdr->length = sizeof (struct hbm_host_stop_request);
617 617 heci_hdr->msg_complete = 1;
618 618 heci_hdr->reserved = 0;
619 619
620 620 host_stop_req =
621 621 (struct hbm_host_stop_request *)&dev->wr_msg_buf[1];
622 622
623 623 (void) memset(host_stop_req, 0,
624 624 sizeof (struct hbm_host_stop_request));
625 625 host_stop_req->cmd.cmd = HOST_STOP_REQ_CMD;
626 626 host_stop_req->reason = DRIVER_STOP_REQUEST;
627 627 if (!heci_write_message(dev, heci_hdr,
628 628 (unsigned char *)(host_stop_req),
629 629 heci_hdr->length)) {
630 630 DBG("sending stop msg to fw failed.\n");
631 631 }
632 632 DBG("version mismatch.\n");
633 633 mutex_exit(&dev->device_lock);
634 634 return (-ENODEV);
635 635 }
636 636 mutex_exit(&dev->device_lock);
637 637 return (0);
638 638 }
639 639
640 640 /*
641 641 * host_enum_clients_message - host send enumeration client request message.
642 642 *
643 643 * @dev: Device object for our driver
644 644 * @return 0 on success, <0 on failure.
645 645 */
646 646 static int
647 647 host_enum_clients_message(struct iamt_heci_device *dev)
648 648 {
649 649 long timeout = 5; /* 5 second */
650 650 struct heci_msg_hdr *heci_hdr;
651 651 struct hbm_host_enum_request *host_enum_req;
652 652 int err = 0;
653 653 uint8_t i, j;
654 654 clock_t delta = (clock_t)(timeout * HZ);
655 655
656 656 mutex_enter(&dev->device_lock);
657 657
658 658 heci_hdr = (struct heci_msg_hdr *)&dev->wr_msg_buf[0];
659 659 /* enumerate clients */
660 660 heci_hdr->host_addr = 0;
661 661 heci_hdr->me_addr = 0;
662 662 heci_hdr->length = sizeof (struct hbm_host_enum_request);
663 663 heci_hdr->msg_complete = 1;
664 664 heci_hdr->reserved = 0;
665 665
666 666 host_enum_req = (struct hbm_host_enum_request *)&dev->wr_msg_buf[1];
667 667 (void) memset(host_enum_req, 0, sizeof (struct hbm_host_enum_request));
668 668 host_enum_req->cmd.cmd = HOST_ENUM_REQ_CMD;
669 669 if (!heci_write_message(dev, heci_hdr,
670 670 (unsigned char *)(host_enum_req),
671 671 heci_hdr->length)) {
672 672 DBG("send enumeration request failed.\n");
673 673 mutex_exit(&dev->device_lock);
674 674 return (-ENODEV);
675 675 }
676 676 /* wait for response */
677 677 dev->recvd_msg = 0;
678 678 err = 0;
679 679 while (!dev->recvd_msg && err != -1) {
680 680 err = cv_reltimedwait(&dev->wait_recvd_msg, &dev->device_lock,
681 681 delta, TR_CLOCK_TICK);
682 682 }
683 683 if (err == -1 && !dev->recvd_msg) {
684 684 DBG("wait_event_interruptible_timeout failed "
685 685 "on enumeration clients response message.\n");
686 686 mutex_exit(&dev->device_lock);
687 687 return (-ENODEV);
688 688 }
689 689 dev->recvd_msg = 0;
690 690
691 691 /* count how many ME clients we have */
692 692 for (i = 0; i < sizeof (dev->heci_me_clients); i++) {
693 693 for (j = 0; j < 8; j++) {
694 694 if ((dev->heci_me_clients[i] & (1 << j)) != 0)
695 695 dev->num_heci_me_clients++;
696 696
697 697 }
698 698 }
699 699 mutex_exit(&dev->device_lock);
700 700
701 701 return (0);
702 702 }
703 703
704 704 /*
705 705 * host_client_properties - reads properties for client
706 706 *
707 707 * @dev: Device object for our driver
708 708 * @idx: client index in me client array
709 709 * @client_id: id of the client
710 710 *
711 711 * @return 0 on success, <0 on failure.
712 712 */
713 713 static int
714 714 host_client_properties(struct iamt_heci_device *dev,
715 715 struct heci_me_client *client)
716 716 {
717 717 struct heci_msg_hdr *heci_hdr;
718 718 struct hbm_props_request *host_cli_req;
719 719 int err;
720 720 clock_t delta = 10 * HZ;
721 721
722 722 mutex_enter(&dev->device_lock);
723 723 heci_hdr = (struct heci_msg_hdr *)&dev->wr_msg_buf[0];
724 724 heci_hdr->host_addr = 0;
725 725 heci_hdr->me_addr = 0;
726 726 heci_hdr->length = sizeof (struct hbm_props_request);
727 727 heci_hdr->msg_complete = 1;
728 728 heci_hdr->reserved = 0;
729 729
730 730 host_cli_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
731 731 (void) memset(host_cli_req, 0, sizeof (struct hbm_props_request));
732 732 host_cli_req->cmd.cmd = HOST_CLIENT_PROPERTEIS_REQ_CMD;
733 733 host_cli_req->address = client->client_id;
734 734 if (!heci_write_message(dev, heci_hdr,
735 735 (unsigned char *)(host_cli_req), heci_hdr->length)) {
736 736 DBG("send props request failed.\n");
737 737 mutex_exit(&dev->device_lock);
738 738 return (-ENODEV);
739 739 }
740 740 /* wait for response */
741 741 dev->recvd_msg = 0;
742 742
743 743 err = 0;
744 744 while (!dev->recvd_msg && err != -1) {
745 745 err = cv_reltimedwait(&dev->wait_recvd_msg, &dev->device_lock,
746 746 delta, TR_CLOCK_TICK);
747 747 }
748 748 if (err == -1 && !dev->recvd_msg) {
749 749 DBG("wait failed on props resp msg.\n");
750 750 mutex_exit(&dev->device_lock);
751 751 return (-ENODEV);
752 752 }
753 753 dev->recvd_msg = 0;
754 754 mutex_exit(&dev->device_lock);
755 755 return (0);
756 756 }
757 757
758 758 /*
759 759 * allocate_me_clients_storage - allocate storage for me clients
760 760 *
761 761 * @dev: Device object for our driver
762 762 *
763 763 * @return 0 on success, <0 on failure.
764 764 */
765 765 static int
766 766 allocate_me_clients_storage(struct iamt_heci_device *dev)
767 767 {
768 768 struct heci_me_client *clients;
769 769 struct heci_me_client *client;
770 770 uint8_t num, i, j;
771 771 int err;
772 772
773 773 if (dev->num_heci_me_clients == 0)
774 774 return (0);
775 775
776 776 mutex_enter(&dev->device_lock);
↓ open down ↓ |
776 lines elided |
↑ open up ↑ |
777 777 if (dev->me_clients) {
778 778 kmem_free(dev->me_clients, dev->num_heci_me_clients*
779 779 sizeof (struct heci_me_client));
780 780 dev->me_clients = NULL;
781 781 }
782 782 mutex_exit(&dev->device_lock);
783 783
784 784 /* allocate storage for ME clients representation */
785 785 clients = kmem_zalloc(dev->num_heci_me_clients*
786 786 sizeof (struct heci_me_client), KM_SLEEP);
787 - if (!clients) {
788 - DBG("memory allocation for ME clients failed.\n");
789 - return (-ENOMEM);
790 - }
791 787
792 788 mutex_enter(&dev->device_lock);
793 789 dev->me_clients = clients;
794 790 mutex_exit(&dev->device_lock);
795 791
796 792 num = 0;
797 793 for (i = 0; i < sizeof (dev->heci_me_clients); i++) {
798 794 for (j = 0; j < 8; j++) {
799 795 if ((dev->heci_me_clients[i] & (1 << j)) != 0) {
800 796 client = &dev->me_clients[num];
801 797 client->client_id = (i * 8) + j;
802 798 client->flow_ctrl_creds = 0;
803 799 err = host_client_properties(dev, client);
804 800 if (err != 0) {
805 801 mutex_enter(&dev->device_lock);
806 802 kmem_free(dev->me_clients,
807 803 dev->num_heci_me_clients*
808 804 sizeof (struct heci_me_client));
809 805 dev->me_clients = NULL;
810 806 mutex_exit(&dev->device_lock);
811 807 return (err);
812 808 }
813 809 num++;
814 810 }
815 811 }
816 812 }
817 813
818 814 return (0);
819 815 }
820 816
821 817 /*
822 818 * heci_init_file_private - initializes private file structure.
823 819 *
824 820 * @priv: private file structure to be initialized
825 821 * @file: the file structure
826 822 *
827 823 */
828 824 static void
829 825 heci_init_file_private(struct heci_file_private *priv,
830 826 struct heci_file *file)
831 827 {
832 828 _NOTE(ARGUNUSED(file));
833 829
834 830 (void) memset(priv, 0, sizeof (struct heci_file_private));
835 831 mutex_init(&priv->file_lock, NULL, MUTEX_DRIVER, NULL);
836 832 mutex_init(&priv->read_io_lock, NULL, MUTEX_DRIVER, NULL);
837 833 mutex_init(&priv->write_io_lock, NULL, MUTEX_DRIVER, NULL);
838 834 cv_init(&priv->rx_wait, NULL, CV_DRIVER, NULL);
839 835 DBG("priv->rx_wait =%p\n", (void *)&priv->rx_wait);
840 836 LIST_INIT_HEAD(&priv->link);
841 837 priv->reading_state = HECI_IDLE;
842 838 priv->writing_state = HECI_IDLE;
843 839 }
844 840
845 841 /*
846 842 * heci_find_me_client - search for ME client guid
847 843 * sets client_id in heci_file_private if found
848 844 * @dev: Device object for our driver
849 845 * @priv: private file structure to set client_id in
850 846 * @cguid: searched guid of ME client
851 847 * @client_id: id of host client to be set in file private structure
852 848 *
853 849 * @return ME client index
854 850 */
855 851 static uint8_t
856 852 heci_find_me_client(struct iamt_heci_device *dev,
857 853 struct heci_file_private *priv,
858 854 const struct guid *cguid, uint8_t client_id)
859 855 {
860 856 uint8_t i;
861 857
862 858 if ((dev == NULL) || (priv == NULL) || (cguid == NULL))
863 859 return (0);
864 860
865 861 for (i = 0; i < dev->num_heci_me_clients; i++) {
866 862 if (memcmp(cguid,
867 863 &dev->me_clients[i].props.protocol_name,
868 864 sizeof (struct guid)) == 0) {
869 865 priv->me_client_id = dev->me_clients[i].client_id;
870 866 priv->state = HECI_FILE_CONNECTING;
871 867 priv->host_client_id = client_id;
872 868
873 869 list_add_tail(&priv->link, &dev->file_list);
874 870 return (i);
875 871 }
876 872 }
877 873 return (0);
878 874 }
879 875
880 876 /*
881 877 * heci_check_asf_mode - check for ASF client
882 878 *
883 879 * @dev: Device object for our driver
884 880 *
885 881 */
886 882 static void
887 883 heci_check_asf_mode(struct iamt_heci_device *dev)
888 884 {
889 885 uint8_t i;
890 886
891 887 mutex_enter(&dev->device_lock);
892 888 dev->asf_mode = 0;
893 889 /* find ME ASF client - otherwise assume AMT mode */
894 890 DBG("find ME ASF client - otherwise assume AMT mode.\n");
895 891 for (i = 0; i < dev->num_heci_me_clients; i++) {
896 892 if (memcmp(&heci_asf_guid,
897 893 &dev->me_clients[i].props.protocol_name,
898 894 sizeof (struct guid)) == 0) {
899 895 dev->asf_mode = 1;
900 896 mutex_exit(&dev->device_lock);
901 897 DBG("found ME ASF client.\n");
902 898 return;
903 899 }
904 900 }
905 901 mutex_exit(&dev->device_lock);
906 902 DBG("assume AMT mode.\n");
907 903 }
908 904
909 905 /*
910 906 * heci_connect_me_client - connect ME client
911 907 * @dev: Device object for our driver
912 908 * @priv: private file structure
913 909 * @timeout: connect timeout in seconds
914 910 *
915 911 * @return 1 - if connected, 0 - if not
916 912 */
917 913 static uint8_t
918 914 heci_connect_me_client(struct iamt_heci_device *dev,
919 915 struct heci_file_private *priv,
920 916 long timeout)
921 917 {
922 918 int err = 0;
923 919 clock_t delta = (clock_t)(timeout * HZ);
924 920
925 921 if ((dev == NULL) || (priv == NULL))
926 922 return (0);
927 923
928 924 if (!heci_connect(dev, priv)) {
929 925 DBG("failed to call heci_connect for client_id=%d.\n",
930 926 priv->host_client_id);
931 927 heci_remove_client_from_file_list(dev, priv->host_client_id);
932 928 priv->state = HECI_FILE_DISCONNECTED;
933 929 return (0);
934 930 }
935 931 err = 0;
936 932 while (!(HECI_FILE_CONNECTED == priv->state ||
937 933 HECI_FILE_DISCONNECTED == priv->state) &&
938 934 err != -1) {
939 935 err = cv_reltimedwait(&dev->wait_recvd_msg, &dev->device_lock,
940 936 delta, TR_CLOCK_TICK);
941 937 }
942 938 if (HECI_FILE_CONNECTED != priv->state) {
943 939 heci_remove_client_from_file_list(dev, priv->host_client_id);
944 940 DBG("failed to connect client_id=%d state=%d.\n",
945 941 priv->host_client_id, priv->state);
946 942 if (err)
947 943 DBG("failed connect err=%08x\n", err);
948 944 priv->state = HECI_FILE_DISCONNECTED;
949 945 return (0);
950 946 }
951 947 DBG("successfully connected client_id=%d.\n",
952 948 priv->host_client_id);
953 949 return (1);
954 950 }
955 951
956 952 /*
957 953 * host_init_wd - heci initialization wd.
958 954 *
959 955 * @dev: Device object for our driver
960 956 *
961 957 */
962 958 static void host_init_wd(struct iamt_heci_device *dev)
963 959 {
964 960
965 961 mutex_enter(&dev->device_lock);
966 962
967 963 heci_init_file_private(&dev->wd_file_ext, NULL);
968 964
969 965 /* look for WD client and connect to it */
970 966 dev->wd_file_ext.state = HECI_FILE_DISCONNECTED;
971 967 dev->wd_timeout = 0;
972 968
973 969 if (dev->asf_mode) {
974 970 (void) memcpy(dev->wd_data, stop_wd_params,
975 971 HECI_WD_PARAMS_SIZE);
976 972 } else {
977 973 /* AMT mode */
978 974 dev->wd_timeout = AMT_WD_VALUE;
979 975 DBG("dev->wd_timeout=%d.\n", dev->wd_timeout);
980 976 (void) memcpy(dev->wd_data, start_wd_params,
981 977 HECI_WD_PARAMS_SIZE);
982 978 (void) memcpy(dev->wd_data + HECI_WD_PARAMS_SIZE,
983 979 &dev->wd_timeout, sizeof (uint16_t));
984 980 }
985 981
986 982 /* find ME WD client */
987 983 (void) heci_find_me_client(dev, &dev->wd_file_ext,
988 984 &heci_wd_guid, HECI_WD_HOST_CLIENT_ID);
989 985
990 986 DBG("check wd_file_ext\n");
991 987 if (HECI_FILE_CONNECTING == dev->wd_file_ext.state) {
992 988 if (heci_connect_me_client(dev, &dev->wd_file_ext, 15) == 1) {
993 989 DBG("dev->wd_timeout=%d.\n", dev->wd_timeout);
994 990 if (dev->wd_timeout != 0)
995 991 dev->wd_due_counter = 1;
996 992 else
997 993 dev->wd_due_counter = 0;
998 994 DBG("successfully connected to WD client.\n");
999 995 }
1000 996 } else
1001 997 DBG("failed to find WD client.\n");
1002 998
1003 999
1004 1000 mutex_exit(&dev->device_lock);
1005 1001 }
1006 1002
1007 1003
1008 1004 /*
1009 1005 * host_init_iamthif - heci initialization iamthif client.
1010 1006 *
1011 1007 * @dev: Device object for our driver
1012 1008 *
1013 1009 */
1014 1010 static void
1015 1011 host_init_iamthif(struct iamt_heci_device *dev)
1016 1012 {
1017 1013 uint8_t i;
1018 1014
1019 1015 mutex_enter(&dev->device_lock);
1020 1016
1021 1017 heci_init_file_private(&dev->iamthif_file_ext, NULL);
1022 1018 dev->iamthif_file_ext.state = HECI_FILE_DISCONNECTED;
1023 1019
1024 1020 /* find ME PTHI client */
1025 1021 i = heci_find_me_client(dev, &dev->iamthif_file_ext,
1026 1022 &heci_pthi_guid, HECI_IAMTHIF_HOST_CLIENT_ID);
1027 1023 if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTING) {
1028 1024 DBG("failed to find iamthif client.\n");
1029 1025 mutex_exit(&dev->device_lock);
1030 1026 return;
1031 1027 }
1032 1028
1033 1029 ASSERT(dev->me_clients[i].props.max_msg_length == IAMTHIF_MTU);
1034 1030
1035 1031 if (heci_connect_me_client(dev, &dev->iamthif_file_ext, 15) == 1) {
1036 1032 DBG("connected to iamthif client.\n");
1037 1033 dev->iamthif_state = HECI_IAMTHIF_IDLE;
1038 1034 }
1039 1035 mutex_exit(&dev->device_lock);
1040 1036 }
1041 1037
1042 1038 /*
1043 1039 * heci_alloc_file_private - allocates a private file structure and set it up.
↓ open down ↓ |
243 lines elided |
↑ open up ↑ |
1044 1040 * @file: the file structure
1045 1041 *
1046 1042 * @return The allocated file or NULL on failure
1047 1043 */
1048 1044 struct heci_file_private *
1049 1045 heci_alloc_file_private(struct heci_file *file)
1050 1046 {
1051 1047 struct heci_file_private *priv;
1052 1048
1053 1049 priv = kmem_zalloc(sizeof (struct heci_file_private), KM_SLEEP);
1054 - if (!priv)
1055 - return (NULL);
1056 1050
1057 1051 heci_init_file_private(priv, file);
1058 1052
1059 1053 return (priv);
1060 1054 }
1061 1055
1062 1056 /*
1063 1057 * heci_free_file_private - free a private file structure that were previously
1064 1058 * allocated by heci_alloc_file_private
1065 1059 */
1066 1060 void
1067 1061 heci_free_file_private(struct heci_file_private *priv)
1068 1062 {
1069 1063 mutex_destroy(&priv->file_lock);
1070 1064 mutex_destroy(&priv->read_io_lock);
1071 1065 mutex_destroy(&priv->write_io_lock);
1072 1066 cv_destroy(&priv->rx_wait);
1073 1067 kmem_free(priv, sizeof (struct heci_file_private));
1074 1068
1075 1069 }
1076 1070
1077 1071 /*
1078 1072 * heci_disconnect_host_client - send disconnect message to fw from host
1079 1073 * client.
1080 1074 *
1081 1075 * @dev: Device object for our driver
1082 1076 * @file_ext: private data of the file object
1083 1077 *
1084 1078 * @return 0 on success, <0 on failure.
1085 1079 */
1086 1080 int
1087 1081 heci_disconnect_host_client(struct iamt_heci_device *dev,
1088 1082 struct heci_file_private *file_ext)
1089 1083 {
1090 1084 int rets, err;
1091 1085 long timeout = 15; /* 15 seconds */
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
1092 1086 struct heci_cb_private *priv_cb;
1093 1087 clock_t delta = (clock_t)(timeout * HZ);
1094 1088
1095 1089 if ((!dev) || (!file_ext))
1096 1090 return (-ENODEV);
1097 1091
1098 1092 if (file_ext->state != HECI_FILE_DISCONNECTING)
1099 1093 return (0);
1100 1094
1101 1095 priv_cb = kmem_zalloc(sizeof (struct heci_cb_private), KM_SLEEP);
1102 - if (!priv_cb)
1103 - return (-ENOMEM);
1104 1096
1105 1097 LIST_INIT_HEAD(&priv_cb->cb_list);
1106 1098 priv_cb->file_private = file_ext;
1107 1099 priv_cb->major_file_operations = HECI_CLOSE;
1108 1100 mutex_enter(&dev->device_lock);
1109 1101 if (dev->host_buffer_is_empty) {
1110 1102 dev->host_buffer_is_empty = 0;
1111 1103 if (heci_disconnect(dev, file_ext)) {
1112 1104 list_add_tail(&priv_cb->cb_list,
1113 1105 &dev->ctrl_rd_list.heci_cb.cb_list);
1114 1106 } else {
1115 1107 mutex_exit(&dev->device_lock);
1116 1108 rets = -ENODEV;
1117 1109 DBG("failed to call heci_disconnect.\n");
1118 1110 goto free;
1119 1111 }
1120 1112 } else {
1121 1113 DBG("add disconnect cb to control write list\n");
1122 1114 list_add_tail(&priv_cb->cb_list,
1123 1115 &dev->ctrl_wr_list.heci_cb.cb_list);
1124 1116 }
1125 1117
1126 1118 err = 0;
1127 1119 while (err != -1 &&
1128 1120 (HECI_FILE_DISCONNECTED != file_ext->state)) {
1129 1121
1130 1122 err = cv_reltimedwait(&dev->wait_recvd_msg, &dev->device_lock,
1131 1123 delta, TR_CLOCK_TICK);
1132 1124 }
1133 1125 mutex_exit(&dev->device_lock);
1134 1126
1135 1127 if (HECI_FILE_DISCONNECTED == file_ext->state) {
1136 1128 rets = 0;
1137 1129 DBG("successfully disconnected from fw client."
1138 1130 " me_client_id:%d, host_client_id:%d\n",
1139 1131 file_ext->me_client_id,
1140 1132 file_ext->host_client_id);
1141 1133 } else {
1142 1134 rets = -ENODEV;
1143 1135 if (HECI_FILE_DISCONNECTED != file_ext->state)
1144 1136 DBG("wrong status client disconnect.\n");
1145 1137
1146 1138 if (err)
1147 1139 DBG("wait failed disconnect err=%08x\n", err);
1148 1140
1149 1141 DBG("failed to disconnect from fw client.\n"
1150 1142 " me_client_id:%d, host_client_id:%d\n",
1151 1143 file_ext->me_client_id,
1152 1144 file_ext->host_client_id);
1153 1145 }
1154 1146
1155 1147 mutex_enter(&dev->device_lock);
1156 1148 heci_flush_list(&dev->ctrl_rd_list, file_ext);
1157 1149 heci_flush_list(&dev->ctrl_wr_list, file_ext);
1158 1150 mutex_exit(&dev->device_lock);
1159 1151 free:
1160 1152 heci_free_cb_private(priv_cb);
1161 1153 return (rets);
1162 1154 }
1163 1155
1164 1156 /*
1165 1157 * heci_remove_client_from_file_list -
1166 1158 * remove file private data from device file list
1167 1159 *
1168 1160 * @dev: Device object for our driver
1169 1161 * @host_client_id: host client id to be removed
1170 1162 *
1171 1163 */
1172 1164 void
1173 1165 heci_remove_client_from_file_list(struct iamt_heci_device *dev,
1174 1166 uint8_t host_client_id)
1175 1167 {
1176 1168 struct heci_file_private *file_pos = NULL;
1177 1169 struct heci_file_private *file_next = NULL;
1178 1170 list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link,
1179 1171 struct heci_file_private) {
1180 1172 if (host_client_id == file_pos->host_client_id) {
1181 1173 DBG("remove host client = %d, ME client = %d\n",
1182 1174 file_pos->host_client_id,
1183 1175 file_pos->me_client_id);
1184 1176 list_del_init(&file_pos->link);
1185 1177 break;
1186 1178 }
1187 1179 }
1188 1180 }
1189 1181
1190 1182 /*
1191 1183 * heci_fe_same_id - tell if file private data have same id
1192 1184 *
1193 1185 * @fe1: private data of 1. file object
1194 1186 * @fe2: private data of 2. file object
1195 1187 *
1196 1188 * @return !=0 - if ids are the same, 0 - if differ.
1197 1189 */
1198 1190 static inline int heci_fe_same_id(struct heci_file_private *fe1,
1199 1191 struct heci_file_private *fe2)
1200 1192 {
1201 1193 return ((fe1->host_client_id == fe2->host_client_id) &&
1202 1194 (fe1->me_client_id == fe2->me_client_id));
1203 1195 }
↓ open down ↓ |
90 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX