Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/intel/io/pci/pci_pci.c
+++ new/usr/src/uts/intel/io/pci/pci_pci.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 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25 /*
26 26 * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
27 27 */
28 28
29 29 /*
30 30 * PCI to PCI bus bridge nexus driver
31 31 */
32 32
33 33 #include <sys/conf.h>
34 34 #include <sys/kmem.h>
35 35 #include <sys/debug.h>
36 36 #include <sys/modctl.h>
37 37 #include <sys/autoconf.h>
38 38 #include <sys/ddi_impldefs.h>
39 39 #include <sys/pci.h>
40 40 #include <sys/pci_impl.h>
41 41 #include <sys/pcie_impl.h>
42 42 #include <sys/ddi.h>
43 43 #include <sys/sunddi.h>
44 44 #include <sys/sunndi.h>
45 45 #include <sys/ddifm.h>
46 46 #include <sys/ndifm.h>
47 47 #include <sys/fm/protocol.h>
48 48 #include <sys/hotplug/pci/pcie_hp.h>
49 49 #include <sys/hotplug/pci/pcihp.h>
50 50 #include <sys/pci_intr_lib.h>
51 51 #include <sys/psm.h>
52 52 #include <sys/pci_cap.h>
53 53
54 54 /*
55 55 * The variable controls the default setting of the command register
56 56 * for pci devices. See ppb_initchild() for details.
57 57 */
58 58 static ushort_t ppb_command_default = PCI_COMM_ME | PCI_COMM_MAE | PCI_COMM_IO;
59 59
60 60
61 61 static int ppb_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
62 62 off_t, off_t, caddr_t *);
63 63 static int ppb_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
64 64 void *, void *);
65 65 static int ppb_fm_init(dev_info_t *, dev_info_t *, int,
66 66 ddi_iblock_cookie_t *);
67 67 static int ppb_fm_callback(dev_info_t *, ddi_fm_error_t *, const void *);
68 68 static int ppb_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
69 69 ddi_intr_handle_impl_t *, void *);
70 70
71 71 /*
72 72 * ppb_support_msi: Flag that controls MSI support across P2P Bridges.
73 73 * By default, MSI is not supported except for special cases like HT
74 74 * bridges/tunnels that have HT MSI mapping enabled.
75 75 *
76 76 * However, MSI support behavior can be patched on a system by changing
77 77 * the value of this flag as shown below:-
78 78 * 0 = default value, MSI is allowed by this driver for special cases
79 79 * 1 = MSI supported without any checks for this driver
80 80 * -1 = MSI not supported at all
81 81 */
82 82 int ppb_support_msi = 0;
83 83
84 84 /*
85 85 * Controls the usage of the Hypertransport MSI mapping capability
86 86 * 0 = default value, leave hardware function as it is
87 87 * 1 = always enable HT MSI mapping
88 88 * -1 = always disable HT MSI mapping
89 89 */
90 90 int ppb_support_ht_msimap = 0;
91 91
92 92 struct bus_ops ppb_bus_ops = {
93 93 BUSO_REV,
94 94 ppb_bus_map,
95 95 0,
96 96 0,
97 97 0,
98 98 i_ddi_map_fault,
99 99 0,
100 100 ddi_dma_allochdl,
101 101 ddi_dma_freehdl,
102 102 ddi_dma_bindhdl,
103 103 ddi_dma_unbindhdl,
104 104 ddi_dma_flush,
105 105 ddi_dma_win,
106 106 ddi_dma_mctl,
107 107 ppb_ctlops,
108 108 ddi_bus_prop_op,
109 109 0, /* (*bus_get_eventcookie)(); */
110 110 0, /* (*bus_add_eventcall)(); */
111 111 0, /* (*bus_remove_eventcall)(); */
112 112 0, /* (*bus_post_event)(); */
113 113 0, /* (*bus_intr_ctl)(); */
114 114 0, /* (*bus_config)(); */
115 115 0, /* (*bus_unconfig)(); */
116 116 ppb_fm_init, /* (*bus_fm_init)(); */
117 117 NULL, /* (*bus_fm_fini)(); */
118 118 NULL, /* (*bus_fm_access_enter)(); */
119 119 NULL, /* (*bus_fm_access_exit)(); */
120 120 NULL, /* (*bus_power)(); */
121 121 ppb_intr_ops, /* (*bus_intr_op)(); */
122 122 pcie_hp_common_ops /* (*bus_hp_op)(); */
123 123 };
124 124
125 125 /*
126 126 * The goal here is to leverage off of the pcihp.c source without making
127 127 * changes to it. Call into it's cb_ops directly if needed.
128 128 */
129 129 static int ppb_open(dev_t *, int, int, cred_t *);
130 130 static int ppb_close(dev_t, int, int, cred_t *);
131 131 static int ppb_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
132 132 static int ppb_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
133 133 caddr_t, int *);
134 134 static int ppb_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
135 135 static void ppb_peekpoke_cb(dev_info_t *, ddi_fm_error_t *);
136 136
137 137 struct cb_ops ppb_cb_ops = {
138 138 ppb_open, /* open */
139 139 ppb_close, /* close */
140 140 nodev, /* strategy */
141 141 nodev, /* print */
142 142 nodev, /* dump */
143 143 nodev, /* read */
144 144 nodev, /* write */
145 145 ppb_ioctl, /* ioctl */
146 146 nodev, /* devmap */
147 147 nodev, /* mmap */
148 148 nodev, /* segmap */
149 149 nochpoll, /* poll */
150 150 ppb_prop_op, /* cb_prop_op */
151 151 NULL, /* streamtab */
152 152 D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */
153 153 CB_REV, /* rev */
154 154 nodev, /* int (*cb_aread)() */
155 155 nodev /* int (*cb_awrite)() */
156 156 };
157 157
158 158
159 159 static int ppb_probe(dev_info_t *);
160 160 static int ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
161 161 static int ppb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
162 162
163 163 struct dev_ops ppb_ops = {
164 164 DEVO_REV, /* devo_rev */
165 165 0, /* refcnt */
166 166 ppb_info, /* info */
167 167 nulldev, /* identify */
168 168 ppb_probe, /* probe */
169 169 ppb_attach, /* attach */
170 170 ppb_detach, /* detach */
171 171 nulldev, /* reset */
172 172 &ppb_cb_ops, /* driver operations */
173 173 &ppb_bus_ops, /* bus operations */
174 174 NULL, /* power */
175 175 ddi_quiesce_not_needed, /* quiesce */
176 176 };
177 177
178 178 /*
179 179 * Module linkage information for the kernel.
↓ open down ↓ |
179 lines elided |
↑ open up ↑ |
180 180 */
181 181
182 182 static struct modldrv modldrv = {
183 183 &mod_driverops, /* Type of module */
184 184 "Standard PCI to PCI bridge nexus driver",
185 185 &ppb_ops, /* driver ops */
186 186 };
187 187
188 188 static struct modlinkage modlinkage = {
189 189 MODREV_1,
190 - (void *)&modldrv,
191 - NULL
190 + { (void *)&modldrv, NULL }
192 191 };
193 192
194 193 /*
195 194 * soft state pointer and structure template:
196 195 */
197 196 static void *ppb_state;
198 197
199 198 typedef struct {
200 199 dev_info_t *dip;
201 200 int ppb_fmcap;
202 201 ddi_iblock_cookie_t ppb_fm_ibc;
203 202 kmutex_t ppb_mutex;
204 203 kmutex_t ppb_peek_poke_mutex;
205 204 kmutex_t ppb_err_mutex;
206 205
207 206 /*
208 207 * cpr support:
209 208 */
210 209 uint_t config_state_index;
211 210 struct {
212 211 dev_info_t *dip;
213 212 ushort_t command;
214 213 uchar_t cache_line_size;
215 214 uchar_t latency_timer;
216 215 uchar_t header_type;
217 216 uchar_t sec_latency_timer;
218 217 ushort_t bridge_control;
219 218 } config_state[PCI_MAX_CHILDREN];
220 219
221 220 uint16_t parent_bus;
222 221 } ppb_devstate_t;
223 222
224 223
225 224 /*
226 225 * forward function declarations:
227 226 */
228 227 static void ppb_removechild(dev_info_t *);
229 228 static int ppb_initchild(dev_info_t *child);
230 229 static void ppb_save_config_regs(ppb_devstate_t *ppb_p);
231 230 static void ppb_restore_config_regs(ppb_devstate_t *ppb_p);
232 231 static boolean_t ppb_ht_msimap_check(ddi_acc_handle_t cfg_hdl);
233 232 static int ppb_ht_msimap_set(ddi_acc_handle_t cfg_hdl, int cmd);
234 233
235 234 /*
236 235 * for <cmd> in ppb_ht_msimap_set
237 236 */
238 237 #define HT_MSIMAP_ENABLE 1
239 238 #define HT_MSIMAP_DISABLE 0
240 239
241 240
242 241 int
243 242 _init(void)
244 243 {
245 244 int e;
246 245
247 246 if ((e = ddi_soft_state_init(&ppb_state, sizeof (ppb_devstate_t),
248 247 1)) == 0 && (e = mod_install(&modlinkage)) != 0)
249 248 ddi_soft_state_fini(&ppb_state);
250 249 return (e);
251 250 }
252 251
253 252 int
254 253 _fini(void)
255 254 {
256 255 int e;
257 256
258 257 if ((e = mod_remove(&modlinkage)) == 0)
259 258 ddi_soft_state_fini(&ppb_state);
260 259 return (e);
261 260 }
262 261
263 262 int
264 263 _info(struct modinfo *modinfop)
265 264 {
266 265 return (mod_info(&modlinkage, modinfop));
267 266 }
268 267
269 268 /*ARGSUSED*/
270 269 static int
271 270 ppb_probe(dev_info_t *devi)
272 271 {
273 272 return (DDI_PROBE_SUCCESS);
274 273 }
275 274
276 275 /*ARGSUSED*/
277 276 static int
278 277 ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
279 278 {
280 279 dev_info_t *root = ddi_root_node();
281 280 int instance;
282 281 ppb_devstate_t *ppb;
283 282 dev_info_t *pdip;
284 283 ddi_acc_handle_t config_handle;
285 284 char *bus;
286 285 int ret;
287 286
288 287 switch (cmd) {
289 288 case DDI_ATTACH:
290 289
291 290 /*
292 291 * Make sure the "device_type" property exists.
293 292 */
294 293 (void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
295 294 "device_type", "pci");
296 295
297 296 /*
298 297 * Allocate and get soft state structure.
299 298 */
300 299 instance = ddi_get_instance(devi);
301 300 if (ddi_soft_state_zalloc(ppb_state, instance) != DDI_SUCCESS)
302 301 return (DDI_FAILURE);
303 302 ppb = ddi_get_soft_state(ppb_state, instance);
304 303 ppb->dip = devi;
305 304
306 305 /*
307 306 * don't enable ereports if immediate child of npe
308 307 */
309 308 if (strcmp(ddi_driver_name(ddi_get_parent(devi)), "npe") == 0)
310 309 ppb->ppb_fmcap = DDI_FM_ERRCB_CAPABLE |
311 310 DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
312 311 else
313 312 ppb->ppb_fmcap = DDI_FM_EREPORT_CAPABLE |
314 313 DDI_FM_ERRCB_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
315 314 DDI_FM_DMACHK_CAPABLE;
316 315
317 316 ddi_fm_init(devi, &ppb->ppb_fmcap, &ppb->ppb_fm_ibc);
318 317 mutex_init(&ppb->ppb_mutex, NULL, MUTEX_DRIVER, NULL);
319 318 mutex_init(&ppb->ppb_err_mutex, NULL, MUTEX_DRIVER,
320 319 (void *)ppb->ppb_fm_ibc);
321 320 mutex_init(&ppb->ppb_peek_poke_mutex, NULL, MUTEX_DRIVER,
322 321 (void *)ppb->ppb_fm_ibc);
323 322
324 323 if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
325 324 DDI_FM_EREPORT_CAPABLE))
326 325 pci_ereport_setup(devi);
327 326 if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
328 327 ddi_fm_handler_register(devi, ppb_fm_callback, NULL);
329 328
330 329 if (pci_config_setup(devi, &config_handle) != DDI_SUCCESS) {
331 330 if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
332 331 ddi_fm_handler_unregister(devi);
333 332 if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
334 333 DDI_FM_EREPORT_CAPABLE))
335 334 pci_ereport_teardown(devi);
336 335 ddi_fm_fini(devi);
337 336 ddi_soft_state_free(ppb_state, instance);
338 337 return (DDI_FAILURE);
339 338 }
340 339
341 340 ppb->parent_bus = PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO;
342 341 for (pdip = ddi_get_parent(devi); pdip && (pdip != root) &&
343 342 (ppb->parent_bus != PCIE_PCIECAP_DEV_TYPE_PCIE_DEV);
344 343 pdip = ddi_get_parent(pdip)) {
345 344 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
346 345 DDI_PROP_DONTPASS, "device_type", &bus) !=
347 346 DDI_PROP_SUCCESS)
348 347 break;
349 348
350 349 if (strcmp(bus, "pciex") == 0)
351 350 ppb->parent_bus =
352 351 PCIE_PCIECAP_DEV_TYPE_PCIE_DEV;
353 352
354 353 ddi_prop_free(bus);
355 354 }
356 355
357 356 if (ppb_support_ht_msimap == 1)
358 357 (void) ppb_ht_msimap_set(config_handle,
359 358 HT_MSIMAP_ENABLE);
360 359 else if (ppb_support_ht_msimap == -1)
361 360 (void) ppb_ht_msimap_set(config_handle,
362 361 HT_MSIMAP_DISABLE);
363 362
364 363 pci_config_teardown(&config_handle);
365 364
366 365 /*
367 366 * Initialize hotplug support on this bus.
368 367 */
369 368 if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
370 369 ret = pcie_init(devi, NULL);
371 370 else
372 371 ret = pcihp_init(devi);
373 372
374 373 if (ret != DDI_SUCCESS) {
375 374 cmn_err(CE_WARN,
376 375 "pci: Failed to setup hotplug framework");
377 376 (void) ppb_detach(devi, DDI_DETACH);
378 377 return (ret);
379 378 }
380 379
381 380 ddi_report_dev(devi);
382 381 return (DDI_SUCCESS);
383 382
384 383 case DDI_RESUME:
385 384
386 385 /*
387 386 * Get the soft state structure for the bridge.
388 387 */
389 388 ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
390 389 ppb_restore_config_regs(ppb);
391 390 return (DDI_SUCCESS);
392 391
393 392 default:
394 393 break;
395 394 }
396 395 return (DDI_FAILURE);
397 396 }
398 397
399 398 /*ARGSUSED*/
400 399 static int
401 400 ppb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
402 401 {
403 402 ppb_devstate_t *ppb;
404 403 int ret;
405 404
406 405 switch (cmd) {
407 406 case DDI_DETACH:
408 407 (void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "device_type");
409 408
410 409 ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
411 410 if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
412 411 ddi_fm_handler_unregister(devi);
413 412 if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
414 413 DDI_FM_EREPORT_CAPABLE))
415 414 pci_ereport_teardown(devi);
416 415
417 416 /*
418 417 * Uninitialize hotplug support on this bus.
419 418 */
420 419 ret = (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) ?
421 420 pcie_uninit(devi) : pcihp_uninit(devi);
422 421 if (ret != DDI_SUCCESS)
423 422 return (DDI_FAILURE);
424 423
425 424 mutex_destroy(&ppb->ppb_peek_poke_mutex);
426 425 mutex_destroy(&ppb->ppb_err_mutex);
427 426 mutex_destroy(&ppb->ppb_mutex);
428 427 ddi_fm_fini(devi);
429 428
430 429 /*
431 430 * And finally free the per-pci soft state.
432 431 */
433 432 ddi_soft_state_free(ppb_state, ddi_get_instance(devi));
434 433
435 434 return (DDI_SUCCESS);
436 435
437 436 case DDI_SUSPEND:
438 437 ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
439 438 ppb_save_config_regs(ppb);
440 439 return (DDI_SUCCESS);
441 440
442 441 default:
443 442 break;
444 443 }
445 444 return (DDI_FAILURE);
446 445 }
447 446
448 447 /*ARGSUSED*/
449 448 static int
450 449 ppb_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
451 450 off_t offset, off_t len, caddr_t *vaddrp)
452 451 {
453 452 dev_info_t *pdip;
454 453 ppb_devstate_t *ppb = ddi_get_soft_state(ppb_state,
455 454 ddi_get_instance(dip));
456 455
457 456 if (strcmp(ddi_driver_name(ddi_get_parent(dip)), "npe") == 0 &&
458 457 mp->map_handlep != NULL) {
459 458 ddi_acc_impl_t *hdlp =
460 459 (ddi_acc_impl_t *)(mp->map_handlep)->ah_platform_private;
461 460 hdlp->ahi_err_mutexp = &ppb->ppb_err_mutex;
462 461 hdlp->ahi_peekpoke_mutexp = &ppb->ppb_peek_poke_mutex;
463 462 hdlp->ahi_scan_dip = dip;
464 463 hdlp->ahi_scan = ppb_peekpoke_cb;
465 464 }
466 465 pdip = (dev_info_t *)DEVI(dip)->devi_parent;
467 466 return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)(pdip,
468 467 rdip, mp, offset, len, vaddrp));
469 468 }
470 469
471 470 /*ARGSUSED*/
472 471 static int
473 472 ppb_ctlops(dev_info_t *dip, dev_info_t *rdip,
474 473 ddi_ctl_enum_t ctlop, void *arg, void *result)
475 474 {
476 475 pci_regspec_t *drv_regp;
477 476 int reglen;
478 477 int rn;
479 478 int totreg;
480 479 ppb_devstate_t *ppb = ddi_get_soft_state(ppb_state,
481 480 ddi_get_instance(dip));
482 481 struct detachspec *dsp;
483 482 struct attachspec *asp;
484 483
485 484 switch (ctlop) {
486 485 case DDI_CTLOPS_REPORTDEV:
487 486 if (rdip == (dev_info_t *)0)
488 487 return (DDI_FAILURE);
489 488 cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
490 489 ddi_node_name(rdip), ddi_get_name_addr(rdip),
491 490 ddi_driver_name(rdip),
492 491 ddi_get_instance(rdip));
493 492 return (DDI_SUCCESS);
494 493
495 494 case DDI_CTLOPS_INITCHILD:
496 495 return (ppb_initchild((dev_info_t *)arg));
497 496
498 497 case DDI_CTLOPS_UNINITCHILD:
499 498 ppb_removechild((dev_info_t *)arg);
500 499 return (DDI_SUCCESS);
501 500
502 501 case DDI_CTLOPS_SIDDEV:
503 502 return (DDI_SUCCESS);
504 503
505 504 case DDI_CTLOPS_REGSIZE:
506 505 case DDI_CTLOPS_NREGS:
507 506 if (rdip == (dev_info_t *)0)
508 507 return (DDI_FAILURE);
509 508 break;
510 509
511 510 /* X86 systems support PME wakeup from suspend */
512 511 case DDI_CTLOPS_ATTACH:
513 512 if (!pcie_is_child(dip, rdip))
514 513 return (DDI_SUCCESS);
515 514
516 515 asp = (struct attachspec *)arg;
517 516 if ((ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) &&
518 517 (asp->when == DDI_POST) && (asp->result == DDI_SUCCESS))
519 518 pf_init(rdip, (void *)ppb->ppb_fm_ibc, asp->cmd);
520 519
521 520 if (asp->cmd == DDI_RESUME && asp->when == DDI_PRE)
522 521 if (pci_pre_resume(rdip) != DDI_SUCCESS)
523 522 return (DDI_FAILURE);
524 523
525 524 return (DDI_SUCCESS);
526 525
527 526 case DDI_CTLOPS_DETACH:
528 527 if (!pcie_is_child(dip, rdip))
529 528 return (DDI_SUCCESS);
530 529
531 530 dsp = (struct detachspec *)arg;
532 531 if ((ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) &&
533 532 (dsp->when == DDI_PRE))
534 533 pf_fini(rdip, dsp->cmd);
535 534
536 535 if (dsp->cmd == DDI_SUSPEND && dsp->when == DDI_POST)
537 536 if (pci_post_suspend(rdip) != DDI_SUCCESS)
538 537 return (DDI_FAILURE);
539 538
540 539 return (DDI_SUCCESS);
541 540
542 541 case DDI_CTLOPS_PEEK:
543 542 case DDI_CTLOPS_POKE:
544 543 if (strcmp(ddi_driver_name(ddi_get_parent(dip)), "npe") != 0)
545 544 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
546 545 return (pci_peekpoke_check(dip, rdip, ctlop, arg, result,
547 546 ddi_ctlops, &ppb->ppb_err_mutex,
548 547 &ppb->ppb_peek_poke_mutex, ppb_peekpoke_cb));
549 548
550 549 default:
551 550 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
552 551 }
553 552
554 553 *(int *)result = 0;
555 554 if (ddi_getlongprop(DDI_DEV_T_ANY, rdip,
556 555 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg",
557 556 (caddr_t)&drv_regp, ®len) != DDI_SUCCESS)
558 557 return (DDI_FAILURE);
559 558
560 559 totreg = reglen / sizeof (pci_regspec_t);
561 560 if (ctlop == DDI_CTLOPS_NREGS)
562 561 *(int *)result = totreg;
563 562 else if (ctlop == DDI_CTLOPS_REGSIZE) {
564 563 rn = *(int *)arg;
565 564 if (rn >= totreg) {
566 565 kmem_free(drv_regp, reglen);
567 566 return (DDI_FAILURE);
568 567 }
569 568 *(off_t *)result = drv_regp[rn].pci_size_low;
570 569 }
571 570
572 571 kmem_free(drv_regp, reglen);
573 572 return (DDI_SUCCESS);
574 573 }
575 574
576 575 static int
577 576 ppb_name_child(dev_info_t *child, char *name, int namelen)
578 577 {
579 578 pci_regspec_t *pci_rp;
580 579 uint_t slot, func;
581 580 char **unit_addr;
582 581 uint_t n;
583 582
584 583 /*
585 584 * For .conf nodes, use unit-address property as name
586 585 */
587 586 if (ndi_dev_is_persistent_node(child) == 0) {
588 587 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child,
589 588 DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) !=
590 589 DDI_PROP_SUCCESS) {
591 590 cmn_err(CE_WARN,
592 591 "cannot find unit-address in %s.conf",
593 592 ddi_driver_name(child));
594 593 return (DDI_FAILURE);
595 594 }
596 595 if (n != 1 || *unit_addr == NULL || **unit_addr == 0) {
597 596 cmn_err(CE_WARN, "unit-address property in %s.conf"
598 597 " not well-formed", ddi_driver_name(child));
599 598 ddi_prop_free(unit_addr);
600 599 return (DDI_SUCCESS);
601 600 }
602 601 (void) snprintf(name, namelen, "%s", *unit_addr);
603 602 ddi_prop_free(unit_addr);
604 603 return (DDI_SUCCESS);
605 604 }
606 605
607 606 /* get child "reg" property */
608 607 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child,
609 608 DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, &n) != DDI_SUCCESS) {
610 609 return (DDI_FAILURE);
611 610 }
612 611
613 612 /* copy the device identifications */
614 613 slot = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
615 614 func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
616 615
617 616 if (func != 0)
618 617 (void) snprintf(name, namelen, "%x,%x", slot, func);
619 618 else
620 619 (void) snprintf(name, namelen, "%x", slot);
621 620
622 621 ddi_prop_free(pci_rp);
623 622 return (DDI_SUCCESS);
624 623 }
625 624
626 625 static int
627 626 ppb_initchild(dev_info_t *child)
628 627 {
629 628 struct ddi_parent_private_data *pdptr;
630 629 ppb_devstate_t *ppb;
631 630 char name[MAXNAMELEN];
632 631 ddi_acc_handle_t config_handle;
633 632 ushort_t command_preserve, command;
634 633
635 634 ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state,
636 635 ddi_get_instance(ddi_get_parent(child)));
637 636
638 637 if (ppb_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS)
639 638 return (DDI_FAILURE);
640 639 ddi_set_name_addr(child, name);
641 640
642 641 /*
643 642 * Pseudo nodes indicate a prototype node with per-instance
644 643 * properties to be merged into the real h/w device node.
645 644 * The interpretation of the unit-address is DD[,F]
646 645 * where DD is the device id and F is the function.
647 646 */
648 647 if (ndi_dev_is_persistent_node(child) == 0) {
649 648 extern int pci_allow_pseudo_children;
650 649
651 650 ddi_set_parent_data(child, NULL);
652 651
653 652 /*
654 653 * Try to merge the properties from this prototype
655 654 * node into real h/w nodes.
656 655 */
657 656 if (ndi_merge_node(child, ppb_name_child) == DDI_SUCCESS) {
658 657 /*
659 658 * Merged ok - return failure to remove the node.
660 659 */
661 660 ddi_set_name_addr(child, NULL);
662 661 return (DDI_FAILURE);
663 662 }
664 663
665 664 /* workaround for ddivs to run under PCI */
666 665 if (pci_allow_pseudo_children)
667 666 return (DDI_SUCCESS);
668 667
669 668 /*
670 669 * The child was not merged into a h/w node,
671 670 * but there's not much we can do with it other
672 671 * than return failure to cause the node to be removed.
673 672 */
674 673 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
675 674 ddi_driver_name(child), ddi_get_name_addr(child),
676 675 ddi_driver_name(child));
677 676 ddi_set_name_addr(child, NULL);
678 677 return (DDI_NOT_WELL_FORMED);
679 678 }
680 679
681 680 ddi_set_parent_data(child, NULL);
682 681
683 682 /*
684 683 * PCIe FMA specific
685 684 *
686 685 * Note: parent_data for parent is created only if this is PCI-E
687 686 * platform, for which, SG take a different route to handle device
688 687 * errors.
689 688 */
690 689 if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) {
691 690 if (pcie_init_cfghdl(child) != DDI_SUCCESS)
692 691 return (DDI_FAILURE);
693 692 pcie_init_dom(child);
694 693 }
695 694
696 695 /* transfer select properties from PROM to kernel */
697 696 if (ddi_getprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS,
698 697 "interrupts", -1) != -1) {
699 698 pdptr = kmem_zalloc((sizeof (struct ddi_parent_private_data) +
700 699 sizeof (struct intrspec)), KM_SLEEP);
701 700 pdptr->par_intr = (struct intrspec *)(pdptr + 1);
702 701 pdptr->par_nintr = 1;
703 702 ddi_set_parent_data(child, pdptr);
704 703 } else
705 704 ddi_set_parent_data(child, NULL);
706 705
707 706 if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) {
708 707 pcie_fini_dom(child);
709 708 return (DDI_FAILURE);
710 709 }
711 710
712 711 /*
713 712 * Support for the "command-preserve" property.
714 713 */
715 714 command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
716 715 DDI_PROP_DONTPASS, "command-preserve", 0);
717 716 command = pci_config_get16(config_handle, PCI_CONF_COMM);
718 717 command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
719 718 command |= (ppb_command_default & ~command_preserve);
720 719 pci_config_put16(config_handle, PCI_CONF_COMM, command);
721 720
722 721 pci_config_teardown(&config_handle);
723 722 return (DDI_SUCCESS);
724 723 }
725 724
726 725 static void
727 726 ppb_removechild(dev_info_t *dip)
728 727 {
729 728 struct ddi_parent_private_data *pdptr;
730 729 ppb_devstate_t *ppb;
731 730
732 731 ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state,
733 732 ddi_get_instance(ddi_get_parent(dip)));
734 733
735 734 if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) {
736 735 pcie_fini_dom(dip);
737 736 pcie_fini_cfghdl(dip);
738 737 } else if ((pdptr = ddi_get_parent_data(dip)) != NULL) {
739 738 kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec)));
740 739 ddi_set_parent_data(dip, NULL);
741 740 }
742 741 ddi_set_name_addr(dip, NULL);
743 742
744 743 /*
745 744 * Strip the node to properly convert it back to prototype form
746 745 */
747 746 ddi_remove_minor_node(dip, NULL);
748 747
749 748 impl_rem_dev_props(dip);
750 749 }
751 750
752 751 /*
753 752 * ppb_save_config_regs
754 753 *
755 754 * This routine saves the state of the configuration registers of all
756 755 * the child nodes of each PBM.
757 756 *
758 757 * used by: ppb_detach() on suspends
759 758 *
760 759 * return value: none
761 760 */
762 761 static void
763 762 ppb_save_config_regs(ppb_devstate_t *ppb_p)
764 763 {
765 764 int i;
766 765 dev_info_t *dip;
767 766 ddi_acc_handle_t config_handle;
768 767
769 768 for (i = 0, dip = ddi_get_child(ppb_p->dip); dip != NULL;
770 769 i++, dip = ddi_get_next_sibling(dip)) {
771 770
772 771 if (pci_config_setup(dip, &config_handle) != DDI_SUCCESS) {
773 772 cmn_err(CE_WARN, "%s%d: can't config space for %s%d\n",
774 773 ddi_driver_name(ppb_p->dip),
775 774 ddi_get_instance(ppb_p->dip),
776 775 ddi_driver_name(dip),
777 776 ddi_get_instance(dip));
778 777 continue;
779 778 }
780 779
781 780 ppb_p->config_state[i].dip = dip;
782 781 ppb_p->config_state[i].command =
783 782 pci_config_get16(config_handle, PCI_CONF_COMM);
784 783 pci_config_teardown(&config_handle);
785 784 }
786 785 ppb_p->config_state_index = i;
787 786 }
788 787
789 788
790 789 /*
791 790 * ppb_restore_config_regs
792 791 *
793 792 * This routine restores the state of the configuration registers of all
794 793 * the child nodes of each PBM.
795 794 *
796 795 * used by: ppb_attach() on resume
797 796 *
798 797 * return value: none
799 798 */
800 799 static void
801 800 ppb_restore_config_regs(ppb_devstate_t *ppb_p)
802 801 {
803 802 int i;
804 803 dev_info_t *dip;
805 804 ddi_acc_handle_t config_handle;
806 805
807 806 for (i = 0; i < ppb_p->config_state_index; i++) {
808 807 dip = ppb_p->config_state[i].dip;
809 808 if (pci_config_setup(dip, &config_handle) != DDI_SUCCESS) {
810 809 cmn_err(CE_WARN, "%s%d: can't config space for %s%d\n",
811 810 ddi_driver_name(ppb_p->dip),
812 811 ddi_get_instance(ppb_p->dip),
813 812 ddi_driver_name(dip),
814 813 ddi_get_instance(dip));
815 814 continue;
816 815 }
817 816 pci_config_put16(config_handle, PCI_CONF_COMM,
818 817 ppb_p->config_state[i].command);
819 818 pci_config_teardown(&config_handle);
820 819 }
821 820 }
822 821
823 822
824 823 static boolean_t
825 824 ppb_ht_msimap_check(ddi_acc_handle_t cfg_hdl)
826 825 {
827 826 uint16_t ptr;
828 827
829 828 if (pci_htcap_locate(cfg_hdl,
830 829 PCI_HTCAP_TYPE_MASK | PCI_HTCAP_MSIMAP_ENABLE_MASK,
831 830 PCI_HTCAP_MSIMAP_TYPE | PCI_HTCAP_MSIMAP_ENABLE, &ptr) !=
832 831 DDI_SUCCESS)
833 832 return (B_FALSE);
834 833
835 834 return (B_TRUE);
836 835 }
837 836
838 837
839 838 static int
840 839 ppb_ht_msimap_set(ddi_acc_handle_t cfg_hdl, int cmd)
841 840 {
842 841 uint16_t ptr;
843 842 uint16_t reg;
844 843
845 844 if (pci_htcap_locate(cfg_hdl, PCI_HTCAP_TYPE_MASK,
846 845 PCI_HTCAP_MSIMAP_TYPE, &ptr) != DDI_SUCCESS)
847 846 return (0);
848 847
849 848 reg = pci_config_get16(cfg_hdl, ptr + PCI_CAP_ID_REGS_OFF);
850 849 switch (cmd) {
851 850 case HT_MSIMAP_ENABLE:
852 851 reg |= PCI_HTCAP_MSIMAP_ENABLE;
853 852 break;
854 853 case HT_MSIMAP_DISABLE:
855 854 default:
856 855 reg &= ~(uint16_t)PCI_HTCAP_MSIMAP_ENABLE;
857 856 }
858 857
859 858 pci_config_put16(cfg_hdl, ptr + PCI_CAP_ID_REGS_OFF, reg);
860 859 return (1);
861 860 }
862 861
863 862
864 863 /*
865 864 * intercept certain interrupt services to handle special cases
866 865 */
867 866 static int
868 867 ppb_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
869 868 ddi_intr_handle_impl_t *hdlp, void *result)
870 869 {
871 870 ddi_acc_handle_t cfg_hdl;
872 871 int rv = DDI_SUCCESS;
873 872
874 873 if (intr_op != DDI_INTROP_SUPPORTED_TYPES)
875 874 return (i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result));
876 875
877 876 DDI_INTR_NEXDBG((CE_CONT,
878 877 "ppb_intr_ops: pdip 0x%p, rdip 0x%p, op %x handle 0x%p\n",
879 878 (void *)pdip, (void *)rdip, intr_op, (void *)hdlp));
880 879
881 880 /* Fixed interrupt is supported by default */
882 881 *(int *)result = DDI_INTR_TYPE_FIXED;
883 882
884 883 if (ppb_support_msi == -1) {
885 884 DDI_INTR_NEXDBG((CE_CONT,
886 885 "ppb_intr_ops: MSI is not allowed\n"));
887 886 goto OUT;
888 887 }
889 888
890 889 if (ppb_support_msi == 1) {
891 890 DDI_INTR_NEXDBG((CE_CONT,
892 891 "ppb_intr_ops: MSI is always allowed\n"));
893 892 rv = i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result);
894 893 goto OUT;
895 894 }
896 895
897 896 if (pci_config_setup(pdip, &cfg_hdl) != DDI_SUCCESS) {
898 897 DDI_INTR_NEXDBG((CE_CONT,
899 898 "ppb_intr_ops: pci_config_setup() failed\n"));
900 899 goto OUT;
901 900 }
902 901
903 902 /*
904 903 * check for hypertransport msi mapping capability
905 904 */
906 905 if (ppb_ht_msimap_check(cfg_hdl)) {
907 906 DDI_INTR_NEXDBG((CE_CONT,
908 907 "ppb_intr_ops: HT MSI mapping enabled\n"));
909 908 rv = i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result);
910 909 }
911 910
912 911 /*
913 912 * if we add failure conditions after pci_config_setup, move this to
914 913 * OUT and use an extra flag to indicate the need to teardown cfg_hdl
915 914 */
916 915 pci_config_teardown(&cfg_hdl);
917 916
918 917 OUT:
919 918 DDI_INTR_NEXDBG((CE_CONT,
920 919 "ppb_intr_ops: rdip 0x%p, returns supported types: 0x%x\n",
921 920 (void *)rdip, *(int *)result));
922 921 return (rv);
923 922 }
924 923
925 924 /* ARGSUSED */
926 925 static int
927 926 ppb_open(dev_t *devp, int flags, int otyp, cred_t *credp)
928 927 {
929 928 int instance = PCI_MINOR_NUM_TO_INSTANCE(getminor(*devp));
930 929 ppb_devstate_t *ppb_p = ddi_get_soft_state(ppb_state, instance);
931 930 int rv;
932 931
933 932 if (ppb_p == NULL)
934 933 return (ENXIO);
935 934
936 935 /*
937 936 * Ioctls will be handled by PCI Express framework for all
938 937 * PCIe platforms
939 938 */
940 939 if (ppb_p->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) {
941 940 mutex_enter(&ppb_p->ppb_mutex);
942 941 rv = pcie_open(ppb_p->dip, devp, flags, otyp, credp);
943 942 mutex_exit(&ppb_p->ppb_mutex);
944 943 return (rv);
945 944 }
946 945
947 946 return ((pcihp_get_cb_ops())->cb_open(devp, flags, otyp, credp));
948 947 }
949 948
950 949 /* ARGSUSED */
951 950 static int
952 951 ppb_close(dev_t dev, int flags, int otyp, cred_t *credp)
953 952 {
954 953 int instance = PCI_MINOR_NUM_TO_INSTANCE(getminor(dev));
955 954 ppb_devstate_t *ppb_p = ddi_get_soft_state(ppb_state, instance);
956 955 int rv;
957 956
958 957 if (ppb_p == NULL)
959 958 return (ENXIO);
960 959
961 960 mutex_enter(&ppb_p->ppb_mutex);
962 961 /*
963 962 * Ioctls will be handled by PCI Express framework for all
964 963 * PCIe platforms
965 964 */
966 965 if (ppb_p->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) {
967 966 rv = pcie_close(ppb_p->dip, dev, flags, otyp, credp);
968 967 mutex_exit(&ppb_p->ppb_mutex);
969 968 return (rv);
970 969 }
971 970
972 971 mutex_exit(&ppb_p->ppb_mutex);
973 972 return ((pcihp_get_cb_ops())->cb_close(dev, flags, otyp, credp));
974 973 }
975 974
976 975 /*
977 976 * ppb_ioctl: devctl hotplug controls
978 977 */
979 978 /* ARGSUSED */
980 979 static int
981 980 ppb_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
982 981 int *rvalp)
983 982 {
984 983 int instance = PCI_MINOR_NUM_TO_INSTANCE(getminor(dev));
985 984 ppb_devstate_t *ppb_p = ddi_get_soft_state(ppb_state, instance);
986 985
987 986 if (ppb_p == NULL)
988 987 return (ENXIO);
989 988
990 989 /*
991 990 * Ioctls will be handled by PCI Express framework for all
992 991 * PCIe platforms
993 992 */
994 993 if (ppb_p->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
995 994 return (pcie_ioctl(ppb_p->dip, dev, cmd, arg, mode, credp,
996 995 rvalp));
997 996
998 997 return ((pcihp_get_cb_ops())->cb_ioctl(dev, cmd, arg, mode, credp,
999 998 rvalp));
1000 999 }
1001 1000
1002 1001 static int
1003 1002 ppb_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int flags,
1004 1003 char *name, caddr_t valuep, int *lengthp)
1005 1004 {
1006 1005 int instance = PCI_MINOR_NUM_TO_INSTANCE(getminor(dev));
1007 1006 ppb_devstate_t *ppb_p = ddi_get_soft_state(ppb_state, instance);
1008 1007
1009 1008 if (ppb_p == NULL)
1010 1009 return (ENXIO);
1011 1010
1012 1011 if (ppb_p->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
1013 1012 return (pcie_prop_op(dev, dip, prop_op, flags, name,
1014 1013 valuep, lengthp));
1015 1014
1016 1015 return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags,
1017 1016 name, valuep, lengthp));
1018 1017 }
1019 1018
1020 1019 static int
1021 1020 ppb_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
1022 1021 {
1023 1022 minor_t minor = getminor((dev_t)arg);
1024 1023 int instance = PCI_MINOR_NUM_TO_INSTANCE(minor);
1025 1024 ppb_devstate_t *ppb_p = ddi_get_soft_state(ppb_state, instance);
1026 1025
1027 1026 if (ppb_p == NULL)
1028 1027 return (DDI_FAILURE);
1029 1028
1030 1029 if (ppb_p->parent_bus != PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
1031 1030 return (pcihp_info(dip, cmd, arg, result));
1032 1031
1033 1032 switch (cmd) {
1034 1033 default:
1035 1034 return (DDI_FAILURE);
1036 1035
1037 1036 case DDI_INFO_DEVT2INSTANCE:
1038 1037 *result = (void *)(uintptr_t)instance;
1039 1038 return (DDI_SUCCESS);
1040 1039
1041 1040 case DDI_INFO_DEVT2DEVINFO:
1042 1041 if (ppb_p == NULL)
1043 1042 return (DDI_FAILURE);
1044 1043 *result = (void *)ppb_p->dip;
1045 1044 return (DDI_SUCCESS);
1046 1045 }
1047 1046 }
1048 1047
1049 1048 void ppb_peekpoke_cb(dev_info_t *dip, ddi_fm_error_t *derr) {
1050 1049 (void) pci_ereport_post(dip, derr, NULL);
1051 1050 }
1052 1051
1053 1052 /*ARGSUSED*/
1054 1053 static int
1055 1054 ppb_fm_init(dev_info_t *dip, dev_info_t *tdip, int cap,
1056 1055 ddi_iblock_cookie_t *ibc)
1057 1056 {
1058 1057 ppb_devstate_t *ppb = ddi_get_soft_state(ppb_state,
1059 1058 ddi_get_instance(dip));
1060 1059
1061 1060 ASSERT(ibc != NULL);
1062 1061 *ibc = ppb->ppb_fm_ibc;
1063 1062
1064 1063 return (ppb->ppb_fmcap);
1065 1064 }
1066 1065
1067 1066 /*ARGSUSED*/
1068 1067 static int
1069 1068 ppb_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *no_used)
1070 1069 {
1071 1070 ppb_devstate_t *ppb = ddi_get_soft_state(ppb_state,
1072 1071 ddi_get_instance(dip));
1073 1072
1074 1073 mutex_enter(&ppb->ppb_err_mutex);
1075 1074 pci_ereport_post(dip, derr, NULL);
1076 1075 mutex_exit(&ppb->ppb_err_mutex);
1077 1076 return (derr->fme_status);
1078 1077 }
↓ open down ↓ |
877 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX