1 /*- 2 * Copyright (c) 2017 Alexander Motin <mav@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 /* 28 * The Non-Transparent Bridge (NTB) is a device that allows you to connect 29 * two or more systems using a PCI-e links, providing remote memory access. 30 * 31 * This module contains a driver for NTBs in PLX/Avago/Broadcom PCIe bridges. 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 #include <sys/param.h> 38 #include <sys/kernel.h> 39 #include <sys/systm.h> 40 #include <sys/bus.h> 41 #include <sys/interrupt.h> 42 #include <sys/module.h> 43 #include <sys/rman.h> 44 #include <sys/sysctl.h> 45 #include <vm/vm.h> 46 #include <vm/pmap.h> 47 #include <machine/bus.h> 48 #include <machine/intr_machdep.h> 49 #include <machine/resource.h> 50 #include <dev/pci/pcireg.h> 51 #include <dev/pci/pcivar.h> 52 53 #include "../ntb.h" 54 55 #define PLX_MAX_BARS 4 /* There are at most 4 data BARs. */ 56 #define PLX_NUM_SPAD 8 /* There are 8 scratchpads. */ 57 #define PLX_NUM_SPAD_PATT 4 /* Use test pattern as 4 more. */ 58 #define PLX_NUM_DB 16 /* There are 16 doorbells. */ 59 60 struct ntb_plx_mw_info { 61 int mw_bar; 62 int mw_64bit; 63 int mw_rid; 64 struct resource *mw_res; 65 vm_paddr_t mw_pbase; 66 caddr_t mw_vbase; 67 vm_size_t mw_size; 68 vm_memattr_t mw_map_mode; 69 bus_addr_t mw_xlat_addr; 70 size_t mw_xlat_size; 71 }; 72 73 struct ntb_plx_softc { 74 /* ntb.c context. Do not move! Must go first! */ 75 void *ntb_store; 76 77 device_t dev; 78 struct resource *conf_res; 79 int conf_rid; 80 u_int ntx; /* NTx number within chip. */ 81 u_int link; /* Link v/s Virtual side. */ 82 u_int port; /* Port number within chip. */ 83 u_int alut; /* A-LUT is enabled for NTx */ 84 85 int int_rid; 86 struct resource *int_res; 87 void *int_tag; 88 89 struct ntb_plx_mw_info mw_info[PLX_MAX_BARS]; 90 int mw_count; /* Number of memory windows. */ 91 92 int spad_count1; /* Number of standard spads. */ 93 int spad_count2; /* Number of extra spads. */ 94 uint32_t spad_off1; /* Offset of our spads. */ 95 uint32_t spad_off2; /* Offset of our extra spads. */ 96 uint32_t spad_offp1; /* Offset of peer spads. */ 97 uint32_t spad_offp2; /* Offset of peer extra spads. */ 98 99 /* Parameters of window shared with peer config access in B2B mode. */ 100 int b2b_mw; /* Shared window number. */ 101 uint64_t b2b_off; /* Offset in shared window. */ 102 }; 103 104 #define PLX_NT0_BASE 0x3E000 105 #define PLX_NT1_BASE 0x3C000 106 #define PLX_NTX_BASE(sc) ((sc)->ntx ? PLX_NT1_BASE : PLX_NT0_BASE) 107 #define PLX_NTX_LINK_OFFSET 0x01000 108 109 /* Bases of NTx our/peer interface registers */ 110 #define PLX_NTX_OUR_BASE(sc) \ 111 (PLX_NTX_BASE(sc) + ((sc)->link ? PLX_NTX_LINK_OFFSET : 0)) 112 #define PLX_NTX_PEER_BASE(sc) \ 113 (PLX_NTX_BASE(sc) + ((sc)->link ? 0 : PLX_NTX_LINK_OFFSET)) 114 115 /* Read/write NTx our interface registers */ 116 #define NTX_READ(sc, reg) \ 117 bus_read_4((sc)->conf_res, PLX_NTX_OUR_BASE(sc) + (reg)) 118 #define NTX_WRITE(sc, reg, val) \ 119 bus_write_4((sc)->conf_res, PLX_NTX_OUR_BASE(sc) + (reg), (val)) 120 121 /* Read/write NTx peer interface registers */ 122 #define PNTX_READ(sc, reg) \ 123 bus_read_4((sc)->conf_res, PLX_NTX_PEER_BASE(sc) + (reg)) 124 #define PNTX_WRITE(sc, reg, val) \ 125 bus_write_4((sc)->conf_res, PLX_NTX_PEER_BASE(sc) + (reg), (val)) 126 127 /* Read/write B2B NTx registers */ 128 #define BNTX_READ(sc, reg) \ 129 bus_read_4((sc)->mw_info[(sc)->b2b_mw].mw_res, \ 130 PLX_NTX_BASE(sc) + (reg)) 131 #define BNTX_WRITE(sc, reg, val) \ 132 bus_write_4((sc)->mw_info[(sc)->b2b_mw].mw_res, \ 133 PLX_NTX_BASE(sc) + (reg), (val)) 134 135 #define PLX_PORT_BASE(p) ((p) << 12) 136 #define PLX_STATION_PORT_BASE(sc) PLX_PORT_BASE((sc)->port & ~7) 137 138 #define PLX_PORT_CONTROL(sc) (PLX_STATION_PORT_BASE(sc) + 0x208) 139 140 static int ntb_plx_init(device_t dev); 141 static int ntb_plx_detach(device_t dev); 142 static int ntb_plx_mw_set_trans_internal(device_t dev, unsigned mw_idx); 143 144 static int 145 ntb_plx_probe(device_t dev) 146 { 147 148 switch (pci_get_devid(dev)) { 149 case 0x87a010b5: 150 device_set_desc(dev, "PLX Non-Transparent Bridge NT0 Link"); 151 return (BUS_PROBE_DEFAULT); 152 case 0x87a110b5: 153 device_set_desc(dev, "PLX Non-Transparent Bridge NT1 Link"); 154 return (BUS_PROBE_DEFAULT); 155 case 0x87b010b5: 156 device_set_desc(dev, "PLX Non-Transparent Bridge NT0 Virtual"); 157 return (BUS_PROBE_DEFAULT); 158 case 0x87b110b5: 159 device_set_desc(dev, "PLX Non-Transparent Bridge NT1 Virtual"); 160 return (BUS_PROBE_DEFAULT); 161 } 162 return (ENXIO); 163 } 164 165 static int 166 ntb_plx_init(device_t dev) 167 { 168 struct ntb_plx_softc *sc = device_get_softc(dev); 169 struct ntb_plx_mw_info *mw; 170 uint64_t val64; 171 int i; 172 uint32_t val; 173 174 if (sc->b2b_mw >= 0) { 175 /* Set peer BAR0/1 size and address for B2B NTx access. */ 176 mw = &sc->mw_info[sc->b2b_mw]; 177 if (mw->mw_64bit) { 178 PNTX_WRITE(sc, 0xe4, 0x3); /* 64-bit */ 179 val64 = 0x2000000000000000 * mw->mw_bar | 0x4; 180 PNTX_WRITE(sc, PCIR_BAR(0), val64); 181 PNTX_WRITE(sc, PCIR_BAR(0) + 4, val64 >> 32); 182 } else { 183 PNTX_WRITE(sc, 0xe4, 0x2); /* 32-bit */ 184 val = 0x20000000 * mw->mw_bar; 185 PNTX_WRITE(sc, PCIR_BAR(0), val); 186 } 187 188 /* Set Virtual to Link address translation for B2B. */ 189 for (i = 0; i < sc->mw_count; i++) { 190 mw = &sc->mw_info[i]; 191 if (mw->mw_64bit) { 192 val64 = 0x2000000000000000 * mw->mw_bar; 193 NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, val64); 194 NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4 + 4, val64 >> 32); 195 } else { 196 val = 0x20000000 * mw->mw_bar; 197 NTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, val); 198 } 199 } 200 201 /* Make sure Virtual to Link A-LUT is disabled. */ 202 if (sc->alut) 203 PNTX_WRITE(sc, 0xc94, 0); 204 205 /* Enable Link Interface LUT entries 0/1 for peer 0/1. */ 206 PNTX_WRITE(sc, 0xdb4, 0x00090001); 207 } 208 209 /* 210 * Enable Virtual Interface LUT entry 0 for 0:0.0 and 211 * entry 1 for our Requester ID reported by chip. 212 */ 213 val = (NTX_READ(sc, 0xc90) << 16) | 0x00010001; 214 NTX_WRITE(sc, sc->link ? 0xdb4 : 0xd94, val); 215 216 /* Set Link to Virtual address translation. */ 217 for (i = 0; i < sc->mw_count; i++) { 218 mw = &sc->mw_info[i]; 219 if (mw->mw_xlat_size != 0) 220 ntb_plx_mw_set_trans_internal(dev, i); 221 } 222 223 pci_enable_busmaster(dev); 224 if (sc->b2b_mw >= 0) 225 PNTX_WRITE(sc, PCIR_COMMAND, PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); 226 227 return (0); 228 } 229 230 static void 231 ntb_plx_isr(void *arg) 232 { 233 device_t dev = arg; 234 struct ntb_plx_softc *sc = device_get_softc(dev); 235 uint32_t val; 236 237 ntb_db_event((device_t)arg, 0); 238 239 if (sc->link) /* Link Interface has no Link Error registers. */ 240 return; 241 242 val = NTX_READ(sc, 0xfe0); 243 if (val == 0) 244 return; 245 NTX_WRITE(sc, 0xfe0, val); 246 if (val & 1) 247 device_printf(dev, "Correctable Error\n"); 248 if (val & 2) 249 device_printf(dev, "Uncorrectable Error\n"); 250 if (val & 4) { 251 /* DL_Down resets link side registers, have to reinit. */ 252 ntb_plx_init(dev); 253 ntb_link_event(dev); 254 } 255 if (val & 8) 256 device_printf(dev, "Uncorrectable Error Message Drop\n"); 257 } 258 259 static int 260 ntb_plx_setup_intr(device_t dev) 261 { 262 struct ntb_plx_softc *sc = device_get_softc(dev); 263 int error; 264 265 /* 266 * XXX: This hardware supports MSI, but I found it unusable. 267 * It generates new MSI only when doorbell register goes from 268 * zero, but does not generate it when another bit is set or on 269 * partial clear. It makes operation very racy and unreliable. 270 * The data book mentions some mask juggling magic to workaround 271 * that, but I failed to make it work. 272 */ 273 sc->int_rid = 0; 274 sc->int_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 275 &sc->int_rid, RF_SHAREABLE|RF_ACTIVE); 276 if (sc->int_res == NULL) { 277 device_printf(dev, "bus_alloc_resource failed\n"); 278 return (ENOMEM); 279 } 280 error = bus_setup_intr(dev, sc->int_res, INTR_MPSAFE | INTR_TYPE_MISC, 281 NULL, ntb_plx_isr, dev, &sc->int_tag); 282 if (error != 0) { 283 device_printf(dev, "bus_setup_intr failed: %d\n", error); 284 return (error); 285 } 286 287 if (!sc->link) { /* Link Interface has no Link Error registers. */ 288 NTX_WRITE(sc, 0xfe0, 0xf); /* Clear link interrupts. */ 289 NTX_WRITE(sc, 0xfe4, 0x0); /* Unmask link interrupts. */ 290 } 291 return (0); 292 } 293 294 static void 295 ntb_plx_teardown_intr(device_t dev) 296 { 297 struct ntb_plx_softc *sc = device_get_softc(dev); 298 299 if (!sc->link) /* Link Interface has no Link Error registers. */ 300 NTX_WRITE(sc, 0xfe4, 0xf); /* Mask link interrupts. */ 301 302 if (sc->int_res) { 303 bus_teardown_intr(dev, sc->int_res, sc->int_tag); 304 bus_release_resource(dev, SYS_RES_IRQ, sc->int_rid, 305 sc->int_res); 306 } 307 } 308 309 static int 310 ntb_plx_attach(device_t dev) 311 { 312 struct ntb_plx_softc *sc = device_get_softc(dev); 313 struct ntb_plx_mw_info *mw; 314 int error = 0, i; 315 uint32_t val; 316 char buf[32]; 317 318 /* Identify what we are (what side of what NTx). */ 319 sc->dev = dev; 320 val = pci_read_config(dev, 0xc8c, 4); 321 sc->ntx = (val & 1) != 0; 322 sc->link = (val & 0x80000000) != 0; 323 324 /* Get access to whole 256KB of chip configuration space via BAR0/1. */ 325 sc->conf_rid = PCIR_BAR(0); 326 sc->conf_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 327 &sc->conf_rid, RF_ACTIVE); 328 if (sc->conf_res == NULL) { 329 device_printf(dev, "Can't allocate configuration BAR.\n"); 330 return (ENXIO); 331 } 332 333 /* Identify chip port we are connected to. */ 334 val = bus_read_4(sc->conf_res, 0x360); 335 sc->port = (val >> ((sc->ntx == 0) ? 8 : 16)) & 0x1f; 336 337 /* Detect A-LUT enable and size. */ 338 val >>= 30; 339 sc->alut = (val == 0x3) ? 1 : ((val & (1 << sc->ntx)) ? 2 : 0); 340 if (sc->alut) 341 device_printf(dev, "%u A-LUT entries\n", 128 * sc->alut); 342 343 /* Find configured memory windows at BAR2-5. */ 344 sc->mw_count = 0; 345 for (i = 2; i <= 5; i++) { 346 mw = &sc->mw_info[sc->mw_count]; 347 mw->mw_bar = i; 348 mw->mw_rid = PCIR_BAR(mw->mw_bar); 349 mw->mw_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 350 &mw->mw_rid, RF_ACTIVE); 351 if (mw->mw_res == NULL) 352 continue; 353 mw->mw_pbase = rman_get_start(mw->mw_res); 354 mw->mw_size = rman_get_size(mw->mw_res); 355 mw->mw_vbase = rman_get_virtual(mw->mw_res); 356 mw->mw_map_mode = VM_MEMATTR_UNCACHEABLE; 357 sc->mw_count++; 358 359 /* Skip over adjacent BAR for 64-bit BARs. */ 360 val = pci_read_config(dev, PCIR_BAR(mw->mw_bar), 4); 361 if ((val & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64) { 362 mw->mw_64bit = 1; 363 i++; 364 } 365 } 366 367 /* Try to identify B2B mode. */ 368 i = 1; 369 snprintf(buf, sizeof(buf), "hint.%s.%d.b2b", device_get_name(dev), 370 device_get_unit(dev)); 371 TUNABLE_INT_FETCH(buf, &i); 372 if (sc->link) { 373 device_printf(dev, "NTB-to-Root Port mode (Link Interface)\n"); 374 sc->b2b_mw = -1; 375 } else if (i == 0) { 376 device_printf(dev, "NTB-to-Root Port mode (Virtual Interface)\n"); 377 sc->b2b_mw = -1; 378 } else { 379 device_printf(dev, "NTB-to-NTB (back-to-back) mode\n"); 380 381 /* We need at least one memory window for B2B peer access. */ 382 if (sc->mw_count == 0) { 383 device_printf(dev, "No memory window BARs enabled.\n"); 384 error = ENXIO; 385 goto out; 386 } 387 sc->b2b_mw = sc->mw_count - 1; 388 389 /* Use half of the window for B2B, but no less then 1MB. */ 390 mw = &sc->mw_info[sc->b2b_mw]; 391 if (mw->mw_size >= 2 * 1024 * 1024) 392 sc->b2b_off = mw->mw_size / 2; 393 else 394 sc->b2b_off = 0; 395 } 396 397 /* 398 * Use Physical Layer User Test Pattern as additional scratchpad. 399 * Make sure they are present and enabled by writing to them. 400 * XXX: Its a hack, but standard 8 registers are not enough. 401 */ 402 sc->spad_offp1 = sc->spad_off1 = PLX_NTX_OUR_BASE(sc) + 0xc6c; 403 sc->spad_offp2 = sc->spad_off2 = PLX_PORT_BASE(sc->ntx * 8) + 0x20c; 404 if (sc->b2b_mw >= 0) { 405 /* In NTB-to-NTB mode each side has own scratchpads. */ 406 sc->spad_count1 = PLX_NUM_SPAD; 407 bus_write_4(sc->conf_res, sc->spad_off2, 0x12345678); 408 if (bus_read_4(sc->conf_res, sc->spad_off2) == 0x12345678) 409 sc->spad_count2 = PLX_NUM_SPAD_PATT; 410 } else { 411 /* Otherwise we have share scratchpads with the peer. */ 412 if (sc->link) { 413 sc->spad_off1 += PLX_NUM_SPAD / 2 * 4; 414 sc->spad_off2 += PLX_NUM_SPAD_PATT / 2 * 4; 415 } else { 416 sc->spad_offp1 += PLX_NUM_SPAD / 2 * 4; 417 sc->spad_offp2 += PLX_NUM_SPAD_PATT / 2 * 4; 418 } 419 sc->spad_count1 = PLX_NUM_SPAD / 2; 420 bus_write_4(sc->conf_res, sc->spad_off2, 0x12345678); 421 if (bus_read_4(sc->conf_res, sc->spad_off2) == 0x12345678) 422 sc->spad_count2 = PLX_NUM_SPAD_PATT / 2; 423 } 424 425 /* Apply static part of NTB configuration. */ 426 ntb_plx_init(dev); 427 428 /* Allocate and setup interrupts. */ 429 error = ntb_plx_setup_intr(dev); 430 if (error) 431 goto out; 432 433 /* Attach children to this controller */ 434 error = ntb_register_device(dev); 435 436 out: 437 if (error != 0) 438 ntb_plx_detach(dev); 439 return (error); 440 } 441 442 static int 443 ntb_plx_detach(device_t dev) 444 { 445 struct ntb_plx_softc *sc = device_get_softc(dev); 446 struct ntb_plx_mw_info *mw; 447 int i; 448 449 /* Detach & delete all children */ 450 ntb_unregister_device(dev); 451 452 /* Disable and free interrupts. */ 453 ntb_plx_teardown_intr(dev); 454 455 /* Free memory resources. */ 456 for (i = 0; i < sc->mw_count; i++) { 457 mw = &sc->mw_info[i]; 458 bus_release_resource(dev, SYS_RES_MEMORY, mw->mw_rid, 459 mw->mw_res); 460 } 461 bus_release_resource(dev, SYS_RES_MEMORY, sc->conf_rid, sc->conf_res); 462 return (0); 463 } 464 465 466 static bool 467 ntb_plx_link_is_up(device_t dev, enum ntb_speed *speed, enum ntb_width *width) 468 { 469 uint16_t link; 470 471 link = pcie_read_config(dev, PCIER_LINK_STA, 2); 472 if (speed != NULL) 473 *speed = (link & PCIEM_LINK_STA_SPEED); 474 if (width != NULL) 475 *width = (link & PCIEM_LINK_STA_WIDTH) >> 4; 476 return ((link & PCIEM_LINK_STA_WIDTH) != 0); 477 } 478 479 static int 480 ntb_plx_link_enable(device_t dev, enum ntb_speed speed __unused, 481 enum ntb_width width __unused) 482 { 483 struct ntb_plx_softc *sc = device_get_softc(dev); 484 uint32_t reg, val; 485 486 /* The fact that we see the Link Interface means link is enabled. */ 487 if (sc->link) { 488 ntb_link_event(dev); 489 return (0); 490 } 491 492 reg = PLX_PORT_CONTROL(sc); 493 val = bus_read_4(sc->conf_res, reg); 494 if ((val & (1 << (sc->port & 7))) == 0) { 495 /* If already enabled, generate fake link event and exit. */ 496 ntb_link_event(dev); 497 return (0); 498 } 499 val &= ~(1 << (sc->port & 7)); 500 bus_write_4(sc->conf_res, reg, val); 501 return (0); 502 } 503 504 static int 505 ntb_plx_link_disable(device_t dev) 506 { 507 struct ntb_plx_softc *sc = device_get_softc(dev); 508 uint32_t reg, val; 509 510 /* Link disable for Link Interface would be suicidal. */ 511 if (sc->link) 512 return (0); 513 514 reg = PLX_PORT_CONTROL(sc); 515 val = bus_read_4(sc->conf_res, reg); 516 val |= (1 << (sc->port & 7)); 517 bus_write_4(sc->conf_res, reg, val); 518 return (0); 519 } 520 521 static bool 522 ntb_plx_link_enabled(device_t dev) 523 { 524 struct ntb_plx_softc *sc = device_get_softc(dev); 525 uint32_t reg, val; 526 527 /* The fact that we see the Link Interface means link is enabled. */ 528 if (sc->link) 529 return (TRUE); 530 531 reg = PLX_PORT_CONTROL(sc); 532 val = bus_read_4(sc->conf_res, reg); 533 return ((val & (1 << (sc->port & 7))) == 0); 534 } 535 536 static uint8_t 537 ntb_plx_mw_count(device_t dev) 538 { 539 struct ntb_plx_softc *sc = device_get_softc(dev); 540 541 if (sc->b2b_mw >= 0 && sc->b2b_off == 0) 542 return (sc->mw_count - 1); /* B2B consumed whole window. */ 543 return (sc->mw_count); 544 } 545 546 static int 547 ntb_plx_mw_get_range(device_t dev, unsigned mw_idx, vm_paddr_t *base, 548 caddr_t *vbase, size_t *size, size_t *align, size_t *align_size, 549 bus_addr_t *plimit) 550 { 551 struct ntb_plx_softc *sc = device_get_softc(dev); 552 struct ntb_plx_mw_info *mw; 553 size_t off; 554 555 if (mw_idx >= sc->mw_count) 556 return (EINVAL); 557 off = 0; 558 if (mw_idx == sc->b2b_mw) { 559 KASSERT(sc->b2b_off != 0, 560 ("user shouldn't get non-shared b2b mw")); 561 off = sc->b2b_off; 562 } 563 mw = &sc->mw_info[mw_idx]; 564 565 /* Local to remote memory window parameters. */ 566 if (base != NULL) 567 *base = mw->mw_pbase + off; 568 if (vbase != NULL) 569 *vbase = mw->mw_vbase + off; 570 if (size != NULL) 571 *size = mw->mw_size - off; 572 573 /* 574 * Remote to local memory window translation address alignment. 575 * Translation address has to be aligned to the BAR size, but A-LUT 576 * entries re-map addresses can be aligned to 1/128 or 1/256 of it. 577 * XXX: In B2B mode we can change BAR size (and so alignmet) live, 578 * but there is no way to report it here, so report safe value. 579 */ 580 if (align != NULL) { 581 if (sc->alut && mw->mw_bar == 2) 582 *align = (mw->mw_size - off) / 128 / sc->alut; 583 else 584 *align = mw->mw_size - off; 585 } 586 587 /* 588 * Remote to local memory window size alignment. 589 * The chip has no limit registers, but A-LUT, when available, allows 590 * access control with granularity of 1/128 or 1/256 of the BAR size. 591 * XXX: In B2B case we can change BAR size live, but there is no way 592 * to report it, so report half of the BAR size, that should be safe. 593 * In non-B2B case there is no control at all, so report the BAR size. 594 */ 595 if (align_size != NULL) { 596 if (sc->alut && mw->mw_bar == 2) 597 *align_size = (mw->mw_size - off) / 128 / sc->alut; 598 else if (sc->b2b_mw >= 0) 599 *align_size = (mw->mw_size - off) / 2; 600 else 601 *align_size = mw->mw_size - off; 602 } 603 604 /* Remote to local memory window translation address upper limit. */ 605 if (plimit != NULL) 606 *plimit = mw->mw_64bit ? BUS_SPACE_MAXADDR : 607 BUS_SPACE_MAXADDR_32BIT; 608 return (0); 609 } 610 611 static int 612 ntb_plx_mw_set_trans_internal(device_t dev, unsigned mw_idx) 613 { 614 struct ntb_plx_softc *sc = device_get_softc(dev); 615 struct ntb_plx_mw_info *mw; 616 uint64_t addr, eaddr, off, size, bsize, esize, val64; 617 uint32_t val; 618 int i; 619 620 mw = &sc->mw_info[mw_idx]; 621 addr = mw->mw_xlat_addr; 622 size = mw->mw_xlat_size; 623 off = 0; 624 if (mw_idx == sc->b2b_mw) { 625 off = sc->b2b_off; 626 KASSERT(off != 0, ("user shouldn't get non-shared b2b mw")); 627 628 /* 629 * While generally we can set any BAR size on link side, 630 * for B2B shared window we can't go above preconfigured 631 * size due to BAR address alignment requirements. 632 */ 633 if (size > mw->mw_size - off) 634 return (EINVAL); 635 } 636 637 if (size > 0) { 638 /* Round BAR size to next power of 2 or at least 1MB. */ 639 bsize = size; 640 if (!powerof2(bsize)) 641 bsize = 1LL << flsll(bsize); 642 if (bsize < 1024 * 1024) 643 bsize = 1024 * 1024; 644 645 /* A-LUT has 128 or 256 times better granularity. */ 646 esize = bsize; 647 if (sc->alut && mw->mw_bar == 2) 648 esize /= 128 * sc->alut; 649 650 /* addr should be aligned to BAR or A-LUT element size. */ 651 if ((addr & (esize - 1)) != 0) 652 return (EINVAL); 653 } else 654 esize = bsize = 0; 655 656 if (mw->mw_64bit) { 657 if (sc->b2b_mw >= 0) { 658 /* Set Link Interface BAR size and enable/disable it. */ 659 val64 = 0; 660 if (bsize > 0) 661 val64 = (~(bsize - 1) & ~0xfffff); 662 val64 |= 0xc; 663 PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4, val64); 664 PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4 + 4, val64 >> 32); 665 666 /* Set Link Interface BAR address. */ 667 val64 = 0x2000000000000000 * mw->mw_bar + off; 668 PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar), val64); 669 PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar) + 4, val64 >> 32); 670 } 671 672 /* Set Virtual Interface BARs address translation */ 673 PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, addr); 674 PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4 + 4, addr >> 32); 675 } else { 676 /* Make sure we fit into 32-bit address space. */ 677 if ((addr & UINT32_MAX) != addr) 678 return (ERANGE); 679 if (((addr + bsize) & UINT32_MAX) != (addr + bsize)) 680 return (ERANGE); 681 682 if (sc->b2b_mw >= 0) { 683 /* Set Link Interface BAR size and enable/disable it. */ 684 val = 0; 685 if (bsize > 0) 686 val = (~(bsize - 1) & ~0xfffff); 687 PNTX_WRITE(sc, 0xe8 + (mw->mw_bar - 2) * 4, val); 688 689 /* Set Link Interface BAR address. */ 690 val64 = 0x20000000 * mw->mw_bar + off; 691 PNTX_WRITE(sc, PCIR_BAR(mw->mw_bar), val64); 692 } 693 694 /* Set Virtual Interface BARs address translation */ 695 PNTX_WRITE(sc, 0xc3c + (mw->mw_bar - 2) * 4, addr); 696 } 697 698 /* Configure and enable Link to Virtual A-LUT if we need it. */ 699 if (sc->alut && mw->mw_bar == 2 && 700 ((addr & (bsize - 1)) != 0 || size != bsize)) { 701 eaddr = addr; 702 for (i = 0; i < 128 * sc->alut; i++) { 703 val = sc->link ? 0 : 1; 704 if (sc->alut == 1) 705 val += 2 * sc->ntx; 706 val *= 0x1000 * sc->alut; 707 val += 0x38000 + i * 4 + (i >= 128 ? 0x0e00 : 0); 708 bus_write_4(sc->conf_res, val, eaddr); 709 bus_write_4(sc->conf_res, val + 0x400, eaddr >> 32); 710 bus_write_4(sc->conf_res, val + 0x800, 711 (eaddr < addr + size) ? 0x3 : 0); 712 eaddr += esize; 713 } 714 NTX_WRITE(sc, 0xc94, 0x10000000); 715 } else if (sc->alut && mw->mw_bar == 2) 716 NTX_WRITE(sc, 0xc94, 0); 717 718 return (0); 719 } 720 721 static int 722 ntb_plx_mw_set_trans(device_t dev, unsigned mw_idx, bus_addr_t addr, size_t size) 723 { 724 struct ntb_plx_softc *sc = device_get_softc(dev); 725 struct ntb_plx_mw_info *mw; 726 727 if (mw_idx >= sc->mw_count) 728 return (EINVAL); 729 mw = &sc->mw_info[mw_idx]; 730 mw->mw_xlat_addr = addr; 731 mw->mw_xlat_size = size; 732 return (ntb_plx_mw_set_trans_internal(dev, mw_idx)); 733 } 734 735 static int 736 ntb_plx_mw_clear_trans(device_t dev, unsigned mw_idx) 737 { 738 739 return (ntb_plx_mw_set_trans(dev, mw_idx, 0, 0)); 740 } 741 742 static int 743 ntb_plx_mw_get_wc(device_t dev, unsigned idx, vm_memattr_t *mode) 744 { 745 struct ntb_plx_softc *sc = device_get_softc(dev); 746 struct ntb_plx_mw_info *mw; 747 748 if (idx >= sc->mw_count) 749 return (EINVAL); 750 mw = &sc->mw_info[idx]; 751 *mode = mw->mw_map_mode; 752 return (0); 753 } 754 755 static int 756 ntb_plx_mw_set_wc(device_t dev, unsigned idx, vm_memattr_t mode) 757 { 758 struct ntb_plx_softc *sc = device_get_softc(dev); 759 struct ntb_plx_mw_info *mw; 760 uint64_t off; 761 int rc; 762 763 if (idx >= sc->mw_count) 764 return (EINVAL); 765 mw = &sc->mw_info[idx]; 766 if (mw->mw_map_mode == mode) 767 return (0); 768 769 off = 0; 770 if (idx == sc->b2b_mw) { 771 KASSERT(sc->b2b_off != 0, 772 ("user shouldn't get non-shared b2b mw")); 773 off = sc->b2b_off; 774 } 775 776 rc = pmap_change_attr((vm_offset_t)mw->mw_vbase + off, 777 mw->mw_size - off, mode); 778 if (rc == 0) 779 mw->mw_map_mode = mode; 780 return (rc); 781 } 782 783 static uint8_t 784 ntb_plx_spad_count(device_t dev) 785 { 786 struct ntb_plx_softc *sc = device_get_softc(dev); 787 788 return (sc->spad_count1 + sc->spad_count2); 789 } 790 791 static int 792 ntb_plx_spad_write(device_t dev, unsigned int idx, uint32_t val) 793 { 794 struct ntb_plx_softc *sc = device_get_softc(dev); 795 u_int off; 796 797 if (idx >= sc->spad_count1 + sc->spad_count2) 798 return (EINVAL); 799 800 if (idx < sc->spad_count1) 801 off = sc->spad_off1 + idx * 4; 802 else 803 off = sc->spad_off2 + (idx - sc->spad_count1) * 4; 804 bus_write_4(sc->conf_res, off, val); 805 return (0); 806 } 807 808 static void 809 ntb_plx_spad_clear(device_t dev) 810 { 811 struct ntb_plx_softc *sc = device_get_softc(dev); 812 int i; 813 814 for (i = 0; i < sc->spad_count1 + sc->spad_count2; i++) 815 ntb_plx_spad_write(dev, i, 0); 816 } 817 818 static int 819 ntb_plx_spad_read(device_t dev, unsigned int idx, uint32_t *val) 820 { 821 struct ntb_plx_softc *sc = device_get_softc(dev); 822 u_int off; 823 824 if (idx >= sc->spad_count1 + sc->spad_count2) 825 return (EINVAL); 826 827 if (idx < sc->spad_count1) 828 off = sc->spad_off1 + idx * 4; 829 else 830 off = sc->spad_off2 + (idx - sc->spad_count1) * 4; 831 *val = bus_read_4(sc->conf_res, off); 832 return (0); 833 } 834 835 static int 836 ntb_plx_peer_spad_write(device_t dev, unsigned int idx, uint32_t val) 837 { 838 struct ntb_plx_softc *sc = device_get_softc(dev); 839 u_int off; 840 841 if (idx >= sc->spad_count1 + sc->spad_count2) 842 return (EINVAL); 843 844 if (idx < sc->spad_count1) 845 off = sc->spad_offp1 + idx * 4; 846 else 847 off = sc->spad_offp2 + (idx - sc->spad_count1) * 4; 848 if (sc->b2b_mw >= 0) 849 bus_write_4(sc->mw_info[sc->b2b_mw].mw_res, off, val); 850 else 851 bus_write_4(sc->conf_res, off, val); 852 return (0); 853 } 854 855 static int 856 ntb_plx_peer_spad_read(device_t dev, unsigned int idx, uint32_t *val) 857 { 858 struct ntb_plx_softc *sc = device_get_softc(dev); 859 u_int off; 860 861 if (idx >= sc->spad_count1 + sc->spad_count2) 862 return (EINVAL); 863 864 if (idx < sc->spad_count1) 865 off = sc->spad_offp1 + idx * 4; 866 else 867 off = sc->spad_offp2 + (idx - sc->spad_count1) * 4; 868 if (sc->b2b_mw >= 0) 869 *val = bus_read_4(sc->mw_info[sc->b2b_mw].mw_res, off); 870 else 871 *val = bus_read_4(sc->conf_res, off); 872 return (0); 873 } 874 875 static uint64_t 876 ntb_plx_db_valid_mask(device_t dev) 877 { 878 879 return ((1LL << PLX_NUM_DB) - 1); 880 } 881 882 static int 883 ntb_plx_db_vector_count(device_t dev) 884 { 885 886 return (1); 887 } 888 889 static uint64_t 890 ntb_plx_db_vector_mask(device_t dev, uint32_t vector) 891 { 892 893 if (vector > 0) 894 return (0); 895 return ((1LL << PLX_NUM_DB) - 1); 896 } 897 898 static void 899 ntb_plx_db_clear(device_t dev, uint64_t bits) 900 { 901 struct ntb_plx_softc *sc = device_get_softc(dev); 902 903 NTX_WRITE(sc, sc->link ? 0xc60 : 0xc50, bits); 904 } 905 906 static void 907 ntb_plx_db_clear_mask(device_t dev, uint64_t bits) 908 { 909 struct ntb_plx_softc *sc = device_get_softc(dev); 910 911 NTX_WRITE(sc, sc->link ? 0xc68 : 0xc58, bits); 912 } 913 914 static uint64_t 915 ntb_plx_db_read(device_t dev) 916 { 917 struct ntb_plx_softc *sc = device_get_softc(dev); 918 919 return (NTX_READ(sc, sc->link ? 0xc5c : 0xc4c)); 920 } 921 922 static void 923 ntb_plx_db_set_mask(device_t dev, uint64_t bits) 924 { 925 struct ntb_plx_softc *sc = device_get_softc(dev); 926 927 NTX_WRITE(sc, sc->link ? 0xc64 : 0xc54, bits); 928 } 929 930 static int 931 ntb_plx_peer_db_addr(device_t dev, bus_addr_t *db_addr, vm_size_t *db_size) 932 { 933 struct ntb_plx_softc *sc = device_get_softc(dev); 934 struct ntb_plx_mw_info *mw; 935 936 KASSERT((db_addr != NULL && db_size != NULL), ("must be non-NULL")); 937 938 if (sc->b2b_mw >= 0) { 939 mw = &sc->mw_info[sc->b2b_mw]; 940 *db_addr = (uint64_t)mw->mw_pbase + PLX_NTX_BASE(sc) + 0xc4c; 941 } else { 942 *db_addr = rman_get_start(sc->conf_res) + PLX_NTX_BASE(sc); 943 *db_addr += sc->link ? 0xc4c : 0xc5c; 944 } 945 *db_size = 4; 946 return (0); 947 } 948 949 static void 950 ntb_plx_peer_db_set(device_t dev, uint64_t bit) 951 { 952 struct ntb_plx_softc *sc = device_get_softc(dev); 953 954 if (sc->b2b_mw >= 0) 955 BNTX_WRITE(sc, 0xc4c, bit); 956 else 957 NTX_WRITE(sc, sc->link ? 0xc4c : 0xc5c, bit); 958 } 959 960 static device_method_t ntb_plx_methods[] = { 961 /* Device interface */ 962 DEVMETHOD(device_probe, ntb_plx_probe), 963 DEVMETHOD(device_attach, ntb_plx_attach), 964 DEVMETHOD(device_detach, ntb_plx_detach), 965 /* Bus interface */ 966 DEVMETHOD(bus_child_location_str, ntb_child_location_str), 967 DEVMETHOD(bus_print_child, ntb_print_child), 968 /* NTB interface */ 969 DEVMETHOD(ntb_link_is_up, ntb_plx_link_is_up), 970 DEVMETHOD(ntb_link_enable, ntb_plx_link_enable), 971 DEVMETHOD(ntb_link_disable, ntb_plx_link_disable), 972 DEVMETHOD(ntb_link_enabled, ntb_plx_link_enabled), 973 DEVMETHOD(ntb_mw_count, ntb_plx_mw_count), 974 DEVMETHOD(ntb_mw_get_range, ntb_plx_mw_get_range), 975 DEVMETHOD(ntb_mw_set_trans, ntb_plx_mw_set_trans), 976 DEVMETHOD(ntb_mw_clear_trans, ntb_plx_mw_clear_trans), 977 DEVMETHOD(ntb_mw_get_wc, ntb_plx_mw_get_wc), 978 DEVMETHOD(ntb_mw_set_wc, ntb_plx_mw_set_wc), 979 DEVMETHOD(ntb_spad_count, ntb_plx_spad_count), 980 DEVMETHOD(ntb_spad_clear, ntb_plx_spad_clear), 981 DEVMETHOD(ntb_spad_write, ntb_plx_spad_write), 982 DEVMETHOD(ntb_spad_read, ntb_plx_spad_read), 983 DEVMETHOD(ntb_peer_spad_write, ntb_plx_peer_spad_write), 984 DEVMETHOD(ntb_peer_spad_read, ntb_plx_peer_spad_read), 985 DEVMETHOD(ntb_db_valid_mask, ntb_plx_db_valid_mask), 986 DEVMETHOD(ntb_db_vector_count, ntb_plx_db_vector_count), 987 DEVMETHOD(ntb_db_vector_mask, ntb_plx_db_vector_mask), 988 DEVMETHOD(ntb_db_clear, ntb_plx_db_clear), 989 DEVMETHOD(ntb_db_clear_mask, ntb_plx_db_clear_mask), 990 DEVMETHOD(ntb_db_read, ntb_plx_db_read), 991 DEVMETHOD(ntb_db_set_mask, ntb_plx_db_set_mask), 992 DEVMETHOD(ntb_peer_db_addr, ntb_plx_peer_db_addr), 993 DEVMETHOD(ntb_peer_db_set, ntb_plx_peer_db_set), 994 DEVMETHOD_END 995 }; 996 997 static DEFINE_CLASS_0(ntb_hw, ntb_plx_driver, ntb_plx_methods, 998 sizeof(struct ntb_plx_softc)); 999 DRIVER_MODULE(ntb_hw_plx, pci, ntb_plx_driver, ntb_hw_devclass, NULL, NULL); 1000 MODULE_DEPEND(ntb_hw_plx, ntb, 1, 1, 1); 1001 MODULE_VERSION(ntb_hw_plx, 1); 1002