Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/hotplug/hpcsvc/hpcsvc.c
+++ new/usr/src/uts/common/io/hotplug/hpcsvc/hpcsvc.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 27 * hot-plug services module
28 28 */
29 29
30 30 #include <sys/modctl.h>
31 31 #include <sys/kmem.h>
32 32 #include <sys/sunddi.h>
33 33 #include <sys/sunndi.h>
34 34 #include <sys/disp.h>
35 35 #include <sys/stat.h>
36 36 #include <sys/hotplug/hpcsvc.h>
37 37 #include <sys/callb.h>
38 38
39 39 /*
40 40 * debug macros:
41 41 */
42 42 #if defined(DEBUG)
43 43
44 44 int hpcsvc_debug = 0;
45 45
46 46 static void debug(char *, uintptr_t, uintptr_t, uintptr_t,
47 47 uintptr_t, uintptr_t);
48 48
49 49 #define DEBUG0(fmt) \
50 50 debug(fmt, 0, 0, 0, 0, 0);
51 51 #define DEBUG1(fmt, a1) \
52 52 debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0);
53 53 #define DEBUG2(fmt, a1, a2) \
54 54 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0);
55 55 #define DEBUG3(fmt, a1, a2, a3) \
56 56 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), (uintptr_t)(a3), 0, 0);
57 57 #else
58 58 #define DEBUG0(fmt)
59 59 #define DEBUG1(fmt, a1)
60 60 #define DEBUG2(fmt, a1, a2)
61 61 #define DEBUG3(fmt, a1, a2, a3)
62 62 #endif
63 63
64 64 /*
65 65 * Definitions for the bus node registration list:
66 66 *
67 67 * The hot-plug service module maintains a linked list of items
68 68 * representing the device bus nodes that have been registered via
69 69 * hpc_nexus_register, or identified as candidates for registration
70 70 * by the bus argument to hpc_slot_register.
71 71 *
72 72 * The head of the linked listed is stored in hpc_bus_list_head. Insertions
73 73 * and removals from the list should be locked with mutex hpc_bus_mutex.
74 74 *
75 75 * Items in the list are allocated/freed with the macros hpc_alloc_bus_entry()
76 76 * and hpc_free_bus_entry().
77 77 *
78 78 * Each item in the list contains the following fields:
79 79 *
80 80 * bus_dip - pointer to devinfo node of the registering bus
81 81 *
82 82 * bus_name - device path name of the bus (ie /pci@1f,4000)
83 83 *
84 84 * bus_callback - bus nexus driver callback function registered
85 85 * with the bus
86 86 *
87 87 * bus_registered - a boolean value which is true if the bus has
88 88 * been registered with hpc_nexus_register, false otherwise
89 89 *
90 90 * bus_mutex - mutex lock to be held while updating this list entry
91 91 *
92 92 * bus_slot_list - linked list of the slots registered for this
93 93 * bus node (see slot list details below)
94 94 *
95 95 * bus_thread - kernel thread for running slot event handlers for
96 96 * slots associated with this bus
97 97 *
98 98 * bus_thread_cv - condition variable for synchronization between
99 99 * the service routines and the thread for running slot
100 100 * event handlers
101 101 *
102 102 * bus_thread_exit - a boolean value used to instruct the thread
103 103 * for invoking the slot event handlers to exit
104 104 *
105 105 * bus_slot_event_list_head - the head of the linked list of instances
106 106 * of slot event handlers to be run
107 107 * handlers to be invoked
108 108 *
109 109 * bus_next - pointer to next list entry
110 110 */
111 111
112 112 typedef struct hpc_bus_entry hpc_bus_entry_t;
113 113 typedef struct hpc_slot_entry hpc_slot_entry_t;
114 114 typedef struct hpc_event_entry hpc_event_entry_t;
115 115
116 116 struct hpc_event_entry {
117 117 hpc_slot_entry_t *slotp;
118 118 int event;
119 119 hpc_event_entry_t *next;
120 120 };
121 121
122 122 #define hpc_alloc_event_entry() \
123 123 (hpc_event_entry_t *)kmem_zalloc(sizeof (hpc_event_entry_t), KM_SLEEP)
124 124
125 125 #define hpc_free_event_entry(a) \
126 126 kmem_free((a), sizeof (hpc_event_entry_t))
127 127
128 128 struct hpc_bus_entry {
129 129 dev_info_t *bus_dip;
130 130 char bus_name[MAXPATHLEN + 1];
131 131 boolean_t bus_registered;
132 132 kmutex_t bus_mutex;
133 133 int (* bus_callback)(dev_info_t *dip, hpc_slot_t hdl,
134 134 hpc_slot_info_t *slot_info, int slot_state);
135 135 hpc_slot_entry_t *bus_slot_list;
136 136 kthread_t *bus_thread;
137 137 kcondvar_t bus_thread_cv;
138 138 boolean_t bus_thread_exit;
139 139 hpc_event_entry_t *bus_slot_event_list_head;
140 140 hpc_bus_entry_t *bus_next;
141 141 };
142 142
143 143 #define hpc_alloc_bus_entry() \
144 144 (hpc_bus_entry_t *)kmem_zalloc(sizeof (hpc_bus_entry_t), KM_SLEEP)
145 145
146 146 #define hpc_free_bus_entry(a) \
147 147 kmem_free((a), sizeof (hpc_bus_entry_t))
148 148
149 149
150 150 /*
151 151 * Definitions for the per-bus node slot registration list:
152 152 *
153 153 * For each bus node in the bus list, the hot-plug service module maintains
154 154 * a doubly linked link list of items representing the slots that have been
155 155 * registered (by hot-plug controllers) for that bus.
156 156 *
157 157 * The head of the linked listed is stored in bus_slot_list field of the bus
158 158 * node. Insertions and removals from this list should locked with the mutex
159 159 * in the bus_mutex field of the bus node.
160 160 *
161 161 * Items in the list are allocated/freed with the macros hpc_alloc_slot_entry()
162 162 * and hpc_free_slot_entry().
163 163 *
164 164 * Each item in the list contains the following fields:
165 165 *
166 166 * slot_handle - handle for slot (hpc_slot_t)
167 167 *
168 168 * slot_info - information registered with the slot (hpc_slot_info_t)
169 169 *
170 170 * slot_ops - ops vector registered with the slot (hpc_slot_ops_t)
171 171 *
172 172 * slot_ops_arg - argument to be passed to ops routines (caddr_t)
173 173 *
174 174 * slot_event_handler - handler registered for slot events
175 175 *
176 176 * slot_event_handler_arg - argument to be passed to event handler
177 177 *
178 178 * slot_event_mask - the set of events for which the event handler
179 179 * gets invoked
180 180 *
181 181 * slot_bus - pointer to bus node for the slot
182 182 *
183 183 * slot_hpc_dip - devinfo node pointer to the HPC driver instance
184 184 * that controls this slot
185 185 *
186 186 * slot_{prev,next} - point to {previous,next} node in the list
187 187 */
188 188
189 189 struct hpc_slot_entry {
190 190 hpc_slot_t slot_handle;
191 191 hpc_slot_info_t slot_info; /* should be static & copied */
192 192 hpc_slot_ops_t slot_ops;
193 193 caddr_t slot_ops_arg;
194 194 int (* slot_event_handler)(caddr_t, uint_t);
195 195 caddr_t slot_event_handler_arg;
196 196 uint_t slot_event_mask;
197 197 hpc_bus_entry_t *slot_bus;
198 198 dev_info_t *slot_hpc_dip;
199 199 hpc_slot_entry_t *slot_next, *slot_prev;
200 200 };
201 201
202 202 #define hpc_alloc_slot_entry() \
203 203 (hpc_slot_entry_t *)kmem_zalloc(sizeof (hpc_slot_entry_t), KM_SLEEP)
204 204
205 205 #define hpc_free_slot_entry(a) \
206 206 kmem_free((a), sizeof (hpc_slot_entry_t))
207 207
208 208
209 209 /*
210 210 * Definitions for slot registration callback table.
211 211 */
212 212
213 213 typedef struct hpc_callback_entry hpc_callback_entry_t;
214 214
215 215 struct hpc_callback_entry {
216 216 int (* callback)(dev_info_t *dip, hpc_slot_t hdl,
217 217 hpc_slot_info_t *slot_info, int slot_state);
218 218 dev_info_t *dip;
219 219 hpc_slot_t hdl;
220 220 hpc_slot_info_t *slot_info;
221 221 int slot_state;
222 222 hpc_callback_entry_t *next;
223 223 };
224 224
225 225 #define hpc_alloc_callback_entry() \
226 226 (hpc_callback_entry_t *) \
227 227 kmem_zalloc(sizeof (hpc_callback_entry_t), KM_SLEEP)
228 228
229 229 #define hpc_free_callback_entry(a) \
230 230 kmem_free((a), sizeof (hpc_callback_entry_t))
231 231
232 232
233 233
234 234 /*
235 235 * Mutex lock for bus registration table and table head.
236 236 */
237 237 static kmutex_t hpc_bus_mutex;
238 238 static hpc_bus_entry_t *hpc_bus_list_head;
239 239
240 240
241 241 /*
242 242 * Forward function declarations.
243 243 */
244 244 static hpc_bus_entry_t *hpc_find_bus_by_name(char *name);
245 245 static void hpc_slot_event_dispatcher(hpc_bus_entry_t *busp);
246 246
247 247
248 248 /*
↓ open down ↓ |
248 lines elided |
↑ open up ↑ |
249 249 * loadable module definitions:
250 250 */
251 251 extern struct mod_ops mod_miscops;
252 252
253 253 static struct modlmisc modlmisc = {
254 254 &mod_miscops, /* Type of module */
255 255 "hot-plug controller services"
256 256 };
257 257
258 258 static struct modlinkage modlinkage = {
259 - MODREV_1, (void *)&modlmisc, NULL
259 + MODREV_1, { (void *)&modlmisc, NULL }
260 260 };
261 261
262 262 int
263 263 _init(void)
264 264 {
265 265 int e;
266 266
267 267 mutex_init(&hpc_bus_mutex, NULL, MUTEX_DRIVER, NULL);
268 268
269 269 /*
270 270 * Install the module.
271 271 */
272 272 e = mod_install(&modlinkage);
273 273 if (e != 0) {
274 274 mutex_destroy(&hpc_bus_mutex);
275 275 }
276 276 return (e);
277 277 }
278 278
279 279 int
280 280 _fini(void)
281 281 {
282 282 int e;
283 283
284 284 e = mod_remove(&modlinkage);
285 285 if (e == 0) {
286 286 mutex_destroy(&hpc_bus_mutex);
287 287 }
288 288 return (e);
289 289 }
290 290
291 291 int
292 292 _info(struct modinfo *modinfop)
293 293 {
294 294 return (mod_info(&modlinkage, modinfop));
295 295 }
296 296
297 297
298 298
299 299 hpc_slot_ops_t *
300 300 hpc_alloc_slot_ops(int flag)
301 301 {
302 302 hpc_slot_ops_t *ops;
303 303
304 304 ops = (hpc_slot_ops_t *)kmem_zalloc(sizeof (hpc_slot_ops_t), flag);
305 305 return (ops);
306 306 }
307 307
308 308
309 309 void
310 310 hpc_free_slot_ops(hpc_slot_ops_t *ops)
311 311 {
312 312 kmem_free((void *)ops, sizeof (hpc_slot_ops_t));
313 313 }
314 314
315 315
316 316 /*ARGSUSED2*/
317 317 int
318 318 hpc_nexus_register_bus(dev_info_t *dip,
319 319 int (* callback)(dev_info_t *dip, hpc_slot_t hdl,
320 320 hpc_slot_info_t *slot_info, int slot_state), uint_t flags)
321 321 {
322 322 hpc_bus_entry_t *busp;
323 323 hpc_slot_entry_t *slotp;
324 324 char bus_path[MAXPATHLEN + 1];
325 325
326 326 DEBUG2("hpc_nexus_register_bus: %s%d",
327 327 ddi_node_name(dip), ddi_get_instance(dip));
328 328 mutex_enter(&hpc_bus_mutex);
329 329 (void) ddi_pathname(dip, bus_path);
330 330 busp = hpc_find_bus_by_name(bus_path);
331 331 if (busp == NULL) {
332 332
333 333 /*
334 334 * Initialize the new bus node and link it at the head
335 335 * of the bus list.
336 336 */
337 337 DEBUG0("hpc_nexus_register_bus: not in bus list");
338 338 busp = hpc_alloc_bus_entry();
339 339 busp->bus_dip = dip;
340 340 busp->bus_registered = B_TRUE;
341 341 (void) strcpy(busp->bus_name, bus_path);
342 342 mutex_init(&busp->bus_mutex, NULL, MUTEX_DRIVER, NULL);
343 343 busp->bus_callback = callback;
344 344 busp->bus_slot_list = NULL;
345 345 busp->bus_next = hpc_bus_list_head;
346 346 hpc_bus_list_head = busp;
347 347
348 348 } else {
349 349
350 350 /*
351 351 * The bus is in the bus list but isn't registered yet.
352 352 * Mark it as registered, and run the registration callbacks
353 353 * for it slots.
354 354 */
355 355 DEBUG0("hpc_nexus_register_bus: in list, but not registered");
356 356 mutex_enter(&busp->bus_mutex);
357 357 if (busp->bus_registered == B_TRUE) {
358 358 mutex_exit(&busp->bus_mutex);
359 359 mutex_exit(&hpc_bus_mutex);
360 360 return (HPC_ERR_BUS_DUPLICATE);
361 361 }
362 362 busp->bus_dip = dip;
363 363 busp->bus_callback = callback;
364 364 busp->bus_registered = B_TRUE;
365 365
366 366 mutex_exit(&busp->bus_mutex);
367 367 mutex_exit(&hpc_bus_mutex);
368 368 if (callback) {
369 369 DEBUG0("hpc_nexus_register_bus: running callbacks");
370 370 for (slotp = busp->bus_slot_list; slotp;
371 371 slotp = slotp->slot_next) {
372 372 (void) callback(dip, slotp, &slotp->slot_info,
373 373 HPC_SLOT_ONLINE);
374 374 }
375 375 }
376 376 return (HPC_SUCCESS);
377 377 }
378 378 mutex_exit(&hpc_bus_mutex);
379 379 return (HPC_SUCCESS);
380 380 }
381 381
382 382
383 383 int
384 384 hpc_nexus_unregister_bus(dev_info_t *dip)
385 385 {
386 386 hpc_bus_entry_t *busp, *busp_prev;
387 387 hpc_slot_entry_t *slotp;
388 388
389 389 /*
390 390 * Search the list for the bus node and remove it.
391 391 */
392 392 DEBUG2("hpc_nexus_unregister_bus: %s%d",
393 393 ddi_node_name(dip), ddi_get_instance(dip));
394 394 mutex_enter(&hpc_bus_mutex);
395 395 for (busp = hpc_bus_list_head; busp != NULL; busp_prev = busp,
396 396 busp = busp->bus_next) {
397 397 if (busp->bus_dip == dip)
398 398 break;
399 399 }
400 400 if (busp == NULL) {
401 401 mutex_exit(&hpc_bus_mutex);
402 402 return (HPC_ERR_BUS_NOTREGISTERED);
403 403 }
404 404
405 405 /*
406 406 * If the bus has slots, mark the bus as unregistered, otherwise
407 407 * remove the bus entry from the list.
408 408 */
409 409 mutex_enter(&busp->bus_mutex);
410 410 if (busp->bus_slot_list == NULL) {
411 411 if (busp == hpc_bus_list_head)
412 412 hpc_bus_list_head = busp->bus_next;
413 413 else
414 414 busp_prev->bus_next = busp->bus_next;
415 415 mutex_exit(&busp->bus_mutex);
416 416 mutex_destroy(&busp->bus_mutex);
417 417 hpc_free_bus_entry(busp);
418 418 mutex_exit(&hpc_bus_mutex);
419 419 return (HPC_SUCCESS);
420 420 }
421 421
422 422 /*
423 423 * unregister event handlers for all the slots on this bus.
424 424 */
425 425 for (slotp = busp->bus_slot_list; slotp != NULL;
426 426 slotp = slotp->slot_next) {
427 427 slotp->slot_event_handler = NULL;
428 428 slotp->slot_event_handler_arg = NULL;
429 429 }
430 430 busp->bus_registered = B_FALSE;
431 431 mutex_exit(&busp->bus_mutex);
432 432 mutex_exit(&hpc_bus_mutex);
433 433 return (HPC_SUCCESS);
434 434 }
435 435
436 436
437 437 /*ARGSUSED5*/
438 438 int
439 439 hpc_slot_register(dev_info_t *hpc_dip, char *bus, hpc_slot_info_t *infop,
440 440 hpc_slot_t *handlep, hpc_slot_ops_t *opsp,
441 441 caddr_t ops_arg, uint_t flags)
442 442 {
443 443 hpc_bus_entry_t *busp;
444 444 hpc_slot_entry_t *slotp, *slot_list_head;
445 445 boolean_t run_callback = B_FALSE;
446 446 int (* callback)(dev_info_t *dip, hpc_slot_t hdl,
447 447 hpc_slot_info_t *slot_info, int slot_state);
448 448 dev_info_t *dip;
449 449 kthread_t *t;
450 450
451 451 /*
452 452 * Validate the arguments.
453 453 */
454 454 DEBUG1("hpc_slot_register: %s", bus);
455 455 if (handlep == NULL || infop == NULL || opsp == NULL || hpc_dip == NULL)
456 456 return (HPC_ERR_INVALID);
457 457
458 458 /*
459 459 * The bus for the slot may or may not be in the bus list. If it's
460 460 * not, we create a node for the bus in the bus list and mark it as
461 461 * not registered.
462 462 */
463 463 mutex_enter(&hpc_bus_mutex);
464 464 busp = hpc_find_bus_by_name(bus);
465 465 if (busp == NULL) {
466 466
467 467 /*
468 468 * Initialize the new bus node and link it at the
469 469 * head of the bus list.
470 470 */
471 471 DEBUG1("hpc_slot_register: %s not in bus list", bus);
472 472 busp = hpc_alloc_bus_entry();
473 473 busp->bus_registered = B_FALSE;
474 474 (void) strcpy(busp->bus_name, bus);
475 475 mutex_init(&busp->bus_mutex, NULL, MUTEX_DRIVER, NULL);
476 476 busp->bus_slot_list = NULL;
477 477 busp->bus_next = hpc_bus_list_head;
478 478 hpc_bus_list_head = busp;
479 479
480 480 } else {
481 481 if (busp->bus_registered == B_TRUE) {
482 482 run_callback = B_TRUE;
483 483 callback = busp->bus_callback;
484 484 dip = busp->bus_dip;
485 485 }
486 486 }
487 487
488 488 mutex_enter(&busp->bus_mutex);
489 489 slot_list_head = busp->bus_slot_list;
490 490 if (slot_list_head == NULL) {
491 491
492 492 /*
493 493 * The slot list was empty, so this is the first slot
494 494 * registered for the bus. Create a per-bus thread
495 495 * for running the slot event handlers.
496 496 */
497 497 DEBUG0("hpc_slot_register: creating event callback thread");
498 498 cv_init(&busp->bus_thread_cv, NULL, CV_DRIVER, NULL);
499 499 busp->bus_thread_exit = B_FALSE;
500 500 t = thread_create(NULL, 0, hpc_slot_event_dispatcher,
501 501 (caddr_t)busp, 0, &p0, TS_RUN, minclsyspri);
502 502 busp->bus_thread = t;
503 503 }
504 504
505 505 /*
506 506 * Create and initialize a new entry in the slot list for the bus.
507 507 */
508 508 slotp = hpc_alloc_slot_entry();
509 509 slotp->slot_handle = (hpc_slot_t)slotp;
510 510 slotp->slot_info = *infop;
511 511 slotp->slot_ops = *opsp;
512 512 slotp->slot_ops_arg = ops_arg;
513 513 slotp->slot_bus = busp;
514 514 slotp->slot_hpc_dip = hpc_dip;
515 515 slotp->slot_prev = NULL;
516 516 busp->bus_slot_list = slotp;
517 517 slotp->slot_next = slot_list_head;
518 518 if (slot_list_head != NULL)
519 519 slot_list_head->slot_prev = slotp;
520 520 mutex_exit(&busp->bus_mutex);
521 521 mutex_exit(&hpc_bus_mutex);
522 522
523 523 /*
524 524 * Return the handle to the caller prior to return to avoid recursion.
525 525 */
526 526 *handlep = (hpc_slot_t)slotp;
527 527
528 528 /*
529 529 * If the bus was registered, we run the callback registered by
530 530 * the bus node.
531 531 */
532 532 if (run_callback) {
533 533 DEBUG0("hpc_slot_register: running callback");
534 534
535 535 (void) callback(dip, slotp, infop, HPC_SLOT_ONLINE);
536 536 }
537 537
538 538 /*
539 539 * Keep hpc driver in memory
540 540 */
541 541 (void) ndi_hold_driver(hpc_dip);
542 542
543 543 return (HPC_SUCCESS);
544 544 }
545 545
546 546
547 547 int
548 548 hpc_slot_unregister(hpc_slot_t *handlep)
549 549 {
550 550 hpc_slot_entry_t *slotp;
551 551 hpc_bus_entry_t *busp, *busp_prev;
552 552 boolean_t run_callback;
553 553 int (* callback)(dev_info_t *dip, hpc_slot_t hdl,
554 554 hpc_slot_info_t *slot_info, int slot_state);
555 555 int r;
556 556 dev_info_t *dip;
557 557 char *bus_name;
558 558
559 559 DEBUG0("hpc_slot_unregister:");
560 560
561 561 ASSERT(handlep != NULL);
562 562
563 563 /* validate the handle */
564 564 slotp = (hpc_slot_entry_t *)*handlep;
565 565 if ((slotp == NULL) || slotp->slot_handle != *handlep)
566 566 return (HPC_ERR_INVALID);
567 567
568 568 /*
569 569 * Get the bus list entry from the slot to grap the mutex for
570 570 * the slot list of the bus.
571 571 */
572 572 mutex_enter(&hpc_bus_mutex);
573 573 busp = slotp->slot_bus;
574 574 DEBUG2("hpc_slot_unregister: handlep=%x, slotp=%x", handlep, slotp);
575 575 if (busp == NULL) {
576 576 mutex_exit(&hpc_bus_mutex);
577 577 return (HPC_ERR_SLOT_NOTREGISTERED);
578 578 }
579 579
580 580 /*
581 581 * Determine if we need to run the slot offline callback and
582 582 * save the data necessary to do so.
583 583 */
584 584 callback = busp->bus_callback;
585 585 run_callback = (busp->bus_registered == B_TRUE) && (callback != NULL);
586 586 dip = busp->bus_dip;
587 587 bus_name = busp->bus_name;
588 588
589 589 /*
590 590 * Run the slot offline callback if necessary.
591 591 */
592 592 if (run_callback) {
593 593 mutex_exit(&hpc_bus_mutex);
594 594 DEBUG0("hpc_slot_unregister: running callback");
595 595 r = callback(dip, (hpc_slot_t)slotp, &slotp->slot_info,
596 596 HPC_SLOT_OFFLINE);
597 597 DEBUG1("hpc_slot_unregister: callback returned %x", r);
598 598 if (r != HPC_SUCCESS)
599 599 return (HPC_ERR_FAILED);
600 600 mutex_enter(&hpc_bus_mutex);
601 601 }
602 602
603 603 /*
604 604 * Remove the slot from list and free the memory associated with it.
605 605 */
606 606 mutex_enter(&busp->bus_mutex);
607 607 DEBUG1("hpc_slot_unregister: freeing slot, bus_slot_list=%x",
608 608 busp->bus_slot_list);
609 609 if (slotp->slot_prev != NULL)
610 610 slotp->slot_prev->slot_next = slotp->slot_next;
611 611 if (slotp->slot_next != NULL)
612 612 slotp->slot_next->slot_prev = slotp->slot_prev;
613 613 if (slotp == busp->bus_slot_list)
614 614 busp->bus_slot_list = slotp->slot_next;
615 615
616 616 /*
617 617 * Release hold from slot registration
618 618 */
619 619 ndi_rele_driver(slotp->slot_hpc_dip);
620 620
621 621 /* Free the memory associated with the slot entry structure */
622 622 hpc_free_slot_entry(slotp);
623 623
624 624 /*
625 625 * If the slot list is empty then stop the event handler thread.
626 626 */
627 627 if (busp->bus_slot_list == NULL) {
628 628 DEBUG0("hpc_slot_unregister: stopping thread");
629 629 busp->bus_thread_exit = B_TRUE;
630 630 cv_signal(&busp->bus_thread_cv);
631 631 DEBUG0("hpc_slot_unregister: waiting for thread to exit");
632 632 cv_wait(&busp->bus_thread_cv, &busp->bus_mutex);
633 633 DEBUG0("hpc_slot_unregister: thread exit");
634 634 cv_destroy(&busp->bus_thread_cv);
635 635 }
636 636
637 637 /*
638 638 * If the bus is unregistered and this is the last slot for this bus
639 639 * then remove the entry from the bus list.
640 640 */
641 641 if (busp->bus_registered == B_FALSE && busp->bus_slot_list == NULL) {
642 642 /* locate the previous entry in the bus list */
643 643 for (busp = hpc_bus_list_head; busp != NULL; busp_prev = busp,
644 644 busp = busp->bus_next)
645 645 if (strcmp(bus_name, busp->bus_name) == 0)
646 646 break;
647 647
648 648 if (busp == hpc_bus_list_head)
649 649 hpc_bus_list_head = busp->bus_next;
650 650 else
651 651 busp_prev->bus_next = busp->bus_next;
652 652
653 653 mutex_exit(&busp->bus_mutex);
654 654 mutex_destroy(&busp->bus_mutex);
655 655 hpc_free_bus_entry(busp);
656 656 } else
657 657 mutex_exit(&busp->bus_mutex);
658 658 mutex_exit(&hpc_bus_mutex);
659 659
660 660 /*
661 661 * reset the slot handle.
662 662 */
663 663 *handlep = NULL;
664 664 return (HPC_SUCCESS);
665 665 }
666 666
667 667
668 668 int
669 669 hpc_install_event_handler(hpc_slot_t handle, uint_t event_mask,
670 670 int (*event_handler)(caddr_t, uint_t), caddr_t arg)
671 671 {
672 672 hpc_slot_entry_t *slotp;
673 673 hpc_bus_entry_t *busp;
674 674
675 675 DEBUG3("hpc_install_event_handler: handle=%x, mask=%x, arg=%x",
676 676 handle, event_mask, arg);
677 677 ASSERT((handle != NULL) && (event_handler != NULL));
678 678 slotp = (hpc_slot_entry_t *)handle;
679 679 busp = slotp->slot_bus;
680 680 ASSERT(slotp == slotp->slot_handle);
681 681 mutex_enter(&busp->bus_mutex);
682 682 slotp->slot_event_mask = event_mask;
683 683 slotp->slot_event_handler = event_handler;
684 684 slotp->slot_event_handler_arg = arg;
685 685 mutex_exit(&busp->bus_mutex);
686 686 return (HPC_SUCCESS);
687 687 }
688 688
689 689
690 690 int
691 691 hpc_remove_event_handler(hpc_slot_t handle)
692 692 {
693 693 hpc_slot_entry_t *slotp;
694 694 hpc_bus_entry_t *busp;
695 695
696 696 DEBUG1("hpc_remove_event_handler: handle=%x", handle);
697 697 ASSERT(handle != NULL);
698 698 slotp = (hpc_slot_entry_t *)handle;
699 699 ASSERT(slotp == slotp->slot_handle);
700 700 busp = slotp->slot_bus;
701 701 mutex_enter(&busp->bus_mutex);
702 702 slotp->slot_event_mask = 0;
703 703 slotp->slot_event_handler = NULL;
704 704 slotp->slot_event_handler_arg = NULL;
705 705 mutex_exit(&busp->bus_mutex);
706 706 return (HPC_SUCCESS);
707 707 }
708 708
709 709
710 710 /*ARGSUSED2*/
711 711 int
712 712 hpc_slot_event_notify(hpc_slot_t handle, uint_t event, uint_t flags)
713 713 {
714 714 hpc_slot_entry_t *slotp;
715 715 hpc_bus_entry_t *busp;
716 716 hpc_event_entry_t *eventp;
717 717
718 718 DEBUG2("hpc_slot_event_notify: handle=%x event=%x", handle, event);
719 719 ASSERT(handle != NULL);
720 720 slotp = (hpc_slot_entry_t *)handle;
721 721 ASSERT(slotp == slotp->slot_handle);
722 722
723 723 if (slotp->slot_event_handler == NULL)
724 724 return (HPC_EVENT_UNCLAIMED);
725 725
726 726 /*
727 727 * If the request is to handle the event synchronously, then call
728 728 * the event handler without queuing the event.
729 729 */
730 730 if (flags == HPC_EVENT_SYNCHRONOUS) {
731 731 caddr_t arg;
732 732 int (* func)(caddr_t, uint_t);
733 733
734 734 func = slotp->slot_event_handler;
735 735 arg = slotp->slot_event_handler_arg;
736 736 return (func(arg, event));
737 737 }
738 738 /*
739 739 * Insert the event into the bus slot event handler list and
740 740 * signal the bus slot event handler dispatch thread.
741 741 */
742 742 busp = slotp->slot_bus;
743 743 mutex_enter(&busp->bus_mutex);
744 744
745 745 if (busp->bus_slot_event_list_head == NULL) {
746 746 eventp = busp->bus_slot_event_list_head =
747 747 hpc_alloc_event_entry();
748 748 } else {
749 749 for (eventp = busp->bus_slot_event_list_head;
750 750 eventp->next != NULL; eventp = eventp->next)
751 751 ;
752 752 eventp->next = hpc_alloc_event_entry();
753 753 eventp = eventp->next;
754 754 }
755 755 eventp->slotp = slotp;
756 756 eventp->event = event;
757 757 eventp->next = NULL;
758 758 DEBUG2("hpc_slot_event_notify: busp=%x event=%x", busp, event);
759 759 cv_signal(&busp->bus_thread_cv);
760 760 mutex_exit(&busp->bus_mutex);
761 761 return (HPC_EVENT_CLAIMED);
762 762 }
763 763
764 764
765 765 int
766 766 hpc_nexus_connect(hpc_slot_t handle, void *data, uint_t flags)
767 767 {
768 768 hpc_slot_entry_t *slotp;
769 769
770 770 ASSERT(handle != NULL);
771 771 slotp = (hpc_slot_entry_t *)handle;
772 772 if (slotp->slot_ops.hpc_op_connect)
773 773 return (slotp->slot_ops.hpc_op_connect(slotp->slot_ops_arg,
774 774 handle, data, flags));
775 775 return (HPC_ERR_FAILED);
776 776 }
777 777
778 778
779 779 int
780 780 hpc_nexus_disconnect(hpc_slot_t handle, void *data, uint_t flags)
781 781 {
782 782 hpc_slot_entry_t *slotp;
783 783
784 784 ASSERT(handle != NULL);
785 785 slotp = (hpc_slot_entry_t *)handle;
786 786 if (slotp->slot_ops.hpc_op_disconnect)
787 787 return (slotp->slot_ops.hpc_op_disconnect(slotp->slot_ops_arg,
788 788 handle, data, flags));
789 789 return (HPC_ERR_FAILED);
790 790 }
791 791
792 792
793 793 int
794 794 hpc_nexus_insert(hpc_slot_t handle, void *data, uint_t flags)
795 795 {
796 796 hpc_slot_entry_t *slotp;
797 797
798 798 ASSERT(handle != NULL);
799 799 slotp = (hpc_slot_entry_t *)handle;
800 800 if (slotp->slot_ops.hpc_op_insert)
801 801 return (slotp->slot_ops.hpc_op_insert(slotp->slot_ops_arg,
802 802 handle, data, flags));
803 803 return (HPC_ERR_FAILED);
804 804 }
805 805
806 806
807 807 int
808 808 hpc_nexus_remove(hpc_slot_t handle, void *data, uint_t flags)
809 809 {
810 810 hpc_slot_entry_t *slotp;
811 811
812 812 ASSERT(handle != NULL);
813 813 slotp = (hpc_slot_entry_t *)handle;
814 814 if (slotp->slot_ops.hpc_op_remove)
815 815 return (slotp->slot_ops.hpc_op_remove(slotp->slot_ops_arg,
816 816 handle, data, flags));
817 817 return (HPC_ERR_FAILED);
818 818 }
819 819
820 820
821 821 int
822 822 hpc_nexus_control(hpc_slot_t handle, int request, caddr_t arg)
823 823 {
824 824 hpc_slot_entry_t *slotp;
825 825
826 826 ASSERT(handle != NULL);
827 827 slotp = (hpc_slot_entry_t *)handle;
828 828 if (slotp->slot_ops.hpc_op_control)
829 829 return (slotp->slot_ops.hpc_op_control(slotp->slot_ops_arg,
830 830 handle, request, arg));
831 831 return (HPC_ERR_FAILED);
832 832 }
833 833
834 834 /*
835 835 * The following function is run from the bus entries slot event handling
836 836 * thread.
837 837 */
838 838 static void
839 839 hpc_slot_event_dispatcher(hpc_bus_entry_t *busp)
840 840 {
841 841 hpc_event_entry_t *eventp;
842 842 hpc_slot_entry_t *slotp;
843 843 int event;
844 844 caddr_t arg;
845 845 int (* func)(caddr_t, uint_t);
846 846 callb_cpr_t cprinfo;
847 847
848 848 /*
849 849 * The creator of this thread is waiting to be signaled that
850 850 * the thread has been started.
851 851 */
852 852 DEBUG1("hpc_slot_event_dispatcher: busp=%x", busp);
853 853
854 854 CALLB_CPR_INIT(&cprinfo, &busp->bus_mutex, callb_generic_cpr,
855 855 "hpc_slot_event_dispatcher");
856 856
857 857 mutex_enter(&busp->bus_mutex);
858 858 /*
859 859 * Wait for events to queue and then process them.
860 860 */
861 861 for (;;) {
862 862
863 863 /*
864 864 * Note we only hold the mutex while determining
865 865 * the number of entries that have been added to
866 866 * the event list, while updating the event list
867 867 * after processing the event list entries.
868 868 */
869 869 if (busp->bus_slot_event_list_head == NULL) {
870 870 CALLB_CPR_SAFE_BEGIN(&cprinfo);
871 871 cv_wait(&busp->bus_thread_cv, &busp->bus_mutex);
872 872 CALLB_CPR_SAFE_END(&cprinfo, &busp->bus_mutex);
873 873 if (busp->bus_thread_exit)
874 874 break;
875 875 continue;
876 876 }
877 877
878 878 /*
879 879 * We have an event handler instance in the list to
880 880 * process. Remove the head of the list, saving the
881 881 * information required to run the event handler.
882 882 * Then run the event handler while the bus mutex
883 883 * is released.
884 884 */
885 885 eventp = busp->bus_slot_event_list_head;
886 886 slotp = eventp->slotp;
887 887 event = eventp->event;
888 888 func = slotp->slot_event_handler;
889 889 arg = slotp->slot_event_handler_arg;
890 890 busp->bus_slot_event_list_head = eventp->next;
891 891 hpc_free_event_entry(eventp);
892 892 mutex_exit(&busp->bus_mutex);
893 893 func(arg, event);
894 894 mutex_enter(&busp->bus_mutex);
895 895
896 896 if (busp->bus_thread_exit)
897 897 break;
898 898 }
899 899
900 900 DEBUG0("hpc_slot_event_dispatcher: thread_exit");
901 901 cv_signal(&busp->bus_thread_cv);
902 902 CALLB_CPR_EXIT(&cprinfo);
903 903 thread_exit();
904 904 }
905 905
906 906
907 907 static hpc_bus_entry_t *
908 908 hpc_find_bus_by_name(char *path)
909 909 {
910 910 hpc_bus_entry_t *busp;
911 911
912 912 for (busp = hpc_bus_list_head; busp != NULL; busp = busp->bus_next) {
913 913 if (strcmp(path, busp->bus_name) == 0)
914 914 break;
915 915 }
916 916 return (busp);
917 917 }
918 918
919 919 boolean_t
920 920 hpc_bus_registered(hpc_slot_t slot_hdl)
921 921 {
922 922 hpc_slot_entry_t *slotp;
923 923 hpc_bus_entry_t *busp;
924 924
925 925 slotp = (hpc_slot_entry_t *)slot_hdl;
926 926 busp = slotp->slot_bus;
927 927 return (busp->bus_registered);
928 928 }
929 929
930 930
931 931 #ifdef DEBUG
932 932
933 933 extern void prom_printf(const char *, ...);
934 934
935 935 static void
936 936 debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3,
937 937 uintptr_t a4, uintptr_t a5)
938 938 {
939 939 if (hpcsvc_debug != 0) {
940 940 cmn_err(CE_CONT, "hpcsvc: ");
941 941 cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5);
942 942 cmn_err(CE_CONT, "\n");
943 943 }
944 944 }
945 945 #endif
↓ open down ↓ |
676 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX