ntb_hw_intel.c revision 255276
1/*- 2 * Copyright (C) 2013 Intel Corporation 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#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sys/dev/ntb/ntb_hw/ntb_hw.c 255276 2013-09-05 23:04:36Z carl $"); 29 30#include <sys/param.h> 31#include <sys/kernel.h> 32#include <sys/systm.h> 33#include <sys/bus.h> 34#include <sys/malloc.h> 35#include <sys/module.h> 36#include <sys/queue.h> 37#include <sys/rman.h> 38#include <vm/vm.h> 39#include <vm/pmap.h> 40#include <machine/bus.h> 41#include <machine/pmap.h> 42#include <machine/resource.h> 43#include <dev/pci/pcireg.h> 44#include <dev/pci/pcivar.h> 45 46#include "ntb_regs.h" 47#include "ntb_hw.h" 48 49/* 50 * The Non-Transparent Bridge (NTB) is a device on some Intel processors that 51 * allows you to connect two systems using a PCI-e link. 52 * 53 * This module contains the hardware abstraction layer for the NTB. It allows 54 * you to send and recieve interrupts, map the memory windows and send and 55 * receive messages in the scratch-pad registers. 56 * 57 * NOTE: Much of the code in this module is shared with Linux. Any patches may 58 * be picked up and redistributed in Linux with a dual GPL/BSD license. 59 */ 60 61#define NTB_CONFIG_BAR 0 62#define NTB_B2B_BAR_1 1 63#define NTB_B2B_BAR_2 2 64#define NTB_MAX_BARS 3 65#define NTB_MW_TO_BAR(mw) ((mw) + 1) 66 67#define MAX_MSIX_INTERRUPTS MAX(XEON_MAX_DB_BITS, SOC_MAX_DB_BITS) 68 69#define NTB_HB_TIMEOUT 1 /* second */ 70#define SOC_LINK_RECOVERY_TIME 500 71 72#define DEVICE2SOFTC(dev) ((struct ntb_softc *) device_get_softc(dev)) 73 74enum ntb_device_type { 75 NTB_XEON, 76 NTB_SOC 77}; 78 79/* Device features and workarounds */ 80#define HAS_FEATURE(feature) \ 81 ((ntb->features & (feature)) != 0) 82 83#define NTB_BAR_SIZE_4K (1 << 0) 84#define NTB_REGS_THRU_MW (1 << 1) 85 86struct ntb_hw_info { 87 uint32_t device_id; 88 const char *desc; 89 enum ntb_device_type type; 90 uint64_t features; 91}; 92 93struct ntb_pci_bar_info { 94 bus_space_tag_t pci_bus_tag; 95 bus_space_handle_t pci_bus_handle; 96 int pci_resource_id; 97 struct resource *pci_resource; 98 vm_paddr_t pbase; 99 void *vbase; 100 u_long size; 101}; 102 103struct ntb_int_info { 104 struct resource *res; 105 int rid; 106 void *tag; 107}; 108 109struct ntb_db_cb { 110 ntb_db_callback callback; 111 unsigned int db_num; 112 void *data; 113 struct ntb_softc *ntb; 114}; 115 116struct ntb_softc { 117 device_t device; 118 enum ntb_device_type type; 119 uint64_t features; 120 121 struct ntb_pci_bar_info bar_info[NTB_MAX_BARS]; 122 struct ntb_int_info int_info[MAX_MSIX_INTERRUPTS]; 123 uint32_t allocated_interrupts; 124 125 struct callout heartbeat_timer; 126 struct callout lr_timer; 127 128 void *ntb_transport; 129 ntb_event_callback event_cb; 130 struct ntb_db_cb *db_cb; 131 132 struct { 133 uint32_t max_spads; 134 uint32_t max_db_bits; 135 uint32_t msix_cnt; 136 } limits; 137 struct { 138 uint32_t pdb; 139 uint32_t pdb_mask; 140 uint32_t sdb; 141 uint32_t sbar2_xlat; 142 uint32_t sbar4_xlat; 143 uint32_t spad_remote; 144 uint32_t spad_local; 145 uint32_t lnk_cntl; 146 uint32_t lnk_stat; 147 uint32_t spci_cmd; 148 } reg_ofs; 149 uint8_t conn_type; 150 uint8_t dev_type; 151 uint8_t bits_per_vector; 152 uint8_t link_status; 153 uint8_t link_width; 154 uint8_t link_speed; 155}; 156 157#define ntb_reg_read(SIZE, offset) \ 158 bus_space_read_ ## SIZE (ntb->bar_info[NTB_CONFIG_BAR].pci_bus_tag, \ 159 ntb->bar_info[NTB_CONFIG_BAR].pci_bus_handle, (offset)) 160#define ntb_reg_write(SIZE, offset, val) \ 161 bus_space_write_ ## SIZE (ntb->bar_info[NTB_CONFIG_BAR].pci_bus_tag, \ 162 ntb->bar_info[NTB_CONFIG_BAR].pci_bus_handle, (offset), (val)) 163 164#define ntb_read_1(offset) ntb_reg_read(1, (offset)) 165#define ntb_read_2(offset) ntb_reg_read(2, (offset)) 166#define ntb_read_4(offset) ntb_reg_read(4, (offset)) 167#define ntb_read_8(offset) ntb_reg_read(8, (offset)) 168#define ntb_write_1(offset, val) ntb_reg_write(1, (offset), (val)) 169#define ntb_write_2(offset, val) ntb_reg_write(2, (offset), (val)) 170#define ntb_write_4(offset, val) ntb_reg_write(4, (offset), (val)) 171#define ntb_write_8(offset, val) ntb_reg_write(8, (offset), (val)) 172 173typedef int (*bar_map_strategy)(struct ntb_softc *ntb, 174 struct ntb_pci_bar_info *bar); 175 176static int ntb_probe(device_t device); 177static int ntb_attach(device_t device); 178static int ntb_detach(device_t device); 179static int ntb_map_pci_bars(struct ntb_softc *ntb); 180static int map_pci_bar(struct ntb_softc *ntb, bar_map_strategy strategy, 181 struct ntb_pci_bar_info *bar); 182static int map_mmr_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar); 183static int map_memory_window_bar(struct ntb_softc *ntb, 184 struct ntb_pci_bar_info *bar); 185static void ntb_unmap_pci_bar(struct ntb_softc *ntb); 186static int ntb_setup_interrupts(struct ntb_softc *ntb); 187static void ntb_teardown_interrupts(struct ntb_softc *ntb); 188static void handle_soc_irq(void *arg); 189static void handle_xeon_irq(void *arg); 190static void handle_xeon_event_irq(void *arg); 191static void ntb_handle_legacy_interrupt(void *arg); 192static int ntb_create_callbacks(struct ntb_softc *ntb, int num_vectors); 193static void ntb_free_callbacks(struct ntb_softc *ntb); 194static struct ntb_hw_info *ntb_get_device_info(uint32_t device_id); 195static int ntb_initialize_hw(struct ntb_softc *ntb); 196static int ntb_setup_xeon(struct ntb_softc *ntb); 197static int ntb_setup_soc(struct ntb_softc *ntb); 198static void ntb_handle_heartbeat(void *arg); 199static void ntb_handle_link_event(struct ntb_softc *ntb, int link_state); 200static void recover_soc_link(void *arg); 201static int ntb_check_link_status(struct ntb_softc *ntb); 202static void save_bar_parameters(struct ntb_pci_bar_info *bar); 203 204static struct ntb_hw_info pci_ids[] = { 205 { 0x3C0D8086, "Xeon E5/Core i7 Non-Transparent Bridge B2B", NTB_XEON, 206 NTB_REGS_THRU_MW }, 207 { 0x0C4E8086, "Atom Processor S1200 NTB Primary B2B", NTB_SOC, 0 }, 208 { 0x0E0D8086, "Xeon E5 V2 Non-Transparent Bridge B2B", NTB_XEON, 209 NTB_REGS_THRU_MW | NTB_BAR_SIZE_4K }, 210 { 0x00000000, NULL, NTB_SOC, 0 } 211}; 212 213/* 214 * OS <-> Driver interface structures 215 */ 216MALLOC_DEFINE(M_NTB, "ntb_hw", "ntb_hw driver memory allocations"); 217 218static device_method_t ntb_pci_methods[] = { 219 /* Device interface */ 220 DEVMETHOD(device_probe, ntb_probe), 221 DEVMETHOD(device_attach, ntb_attach), 222 DEVMETHOD(device_detach, ntb_detach), 223 DEVMETHOD_END 224}; 225 226static driver_t ntb_pci_driver = { 227 "ntb_hw", 228 ntb_pci_methods, 229 sizeof(struct ntb_softc), 230}; 231 232static devclass_t ntb_devclass; 233DRIVER_MODULE(ntb_hw, pci, ntb_pci_driver, ntb_devclass, NULL, NULL); 234MODULE_VERSION(ntb_hw, 1); 235 236/* 237 * OS <-> Driver linkage functions 238 */ 239static int 240ntb_probe(device_t device) 241{ 242 struct ntb_hw_info *p = ntb_get_device_info(pci_get_devid(device)); 243 244 if (p != NULL) { 245 device_set_desc(device, p->desc); 246 return (0); 247 } else 248 return (ENXIO); 249} 250 251#define DETACH_ON_ERROR(func) \ 252 error = func; \ 253 if (error < 0) { \ 254 ntb_detach(device); \ 255 return (error); \ 256 } 257 258static int 259ntb_attach(device_t device) 260{ 261 struct ntb_softc *ntb = DEVICE2SOFTC(device); 262 struct ntb_hw_info *p = ntb_get_device_info(pci_get_devid(device)); 263 int error; 264 265 ntb->device = device; 266 ntb->type = p->type; 267 ntb->features = p->features; 268 269 /* Heartbeat timer for NTB_SOC since there is no link interrupt */ 270 callout_init(&ntb->heartbeat_timer, CALLOUT_MPSAFE); 271 callout_init(&ntb->lr_timer, CALLOUT_MPSAFE); 272 273 DETACH_ON_ERROR(ntb_map_pci_bars(ntb)); 274 DETACH_ON_ERROR(ntb_initialize_hw(ntb)); 275 DETACH_ON_ERROR(ntb_setup_interrupts(ntb)); 276 277 pci_enable_busmaster(ntb->device); 278 279 return (error); 280} 281 282static int 283ntb_detach(device_t device) 284{ 285 struct ntb_softc *ntb = DEVICE2SOFTC(device); 286 287 callout_drain(&ntb->heartbeat_timer); 288 callout_drain(&ntb->lr_timer); 289 ntb_teardown_interrupts(ntb); 290 ntb_unmap_pci_bar(ntb); 291 292 return (0); 293} 294 295static int 296ntb_map_pci_bars(struct ntb_softc *ntb) 297{ 298 int rc; 299 300 ntb->bar_info[NTB_CONFIG_BAR].pci_resource_id = PCIR_BAR(0); 301 rc = map_pci_bar(ntb, map_mmr_bar, &ntb->bar_info[NTB_CONFIG_BAR]); 302 if (rc != 0) 303 return rc; 304 305 ntb->bar_info[NTB_B2B_BAR_1].pci_resource_id = PCIR_BAR(2); 306 rc = map_pci_bar(ntb, map_memory_window_bar, 307 &ntb->bar_info[NTB_B2B_BAR_1]); 308 if (rc != 0) 309 return rc; 310 311 ntb->bar_info[NTB_B2B_BAR_2].pci_resource_id = PCIR_BAR(4); 312 rc = map_pci_bar(ntb, map_memory_window_bar, 313 &ntb->bar_info[NTB_B2B_BAR_2]); 314 if (rc != 0) 315 return rc; 316 317 return (0); 318} 319 320static int 321map_pci_bar(struct ntb_softc *ntb, bar_map_strategy strategy, 322 struct ntb_pci_bar_info *bar) 323{ 324 int rc; 325 326 rc = strategy(ntb, bar); 327 if (rc != 0) { 328 device_printf(ntb->device, 329 "unable to allocate pci resource\n"); 330 } else { 331 device_printf(ntb->device, 332 "Bar size = %lx, v %p, p %p\n", 333 bar->size, bar->vbase, 334 (void *)(bar->pbase)); 335 } 336 return (rc); 337} 338 339static int 340map_mmr_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar) 341{ 342 343 bar->pci_resource = bus_alloc_resource_any(ntb->device, SYS_RES_MEMORY, 344 &bar->pci_resource_id, RF_ACTIVE); 345 346 if (bar->pci_resource == NULL) 347 return (ENXIO); 348 else { 349 save_bar_parameters(bar); 350 return (0); 351 } 352} 353 354static int 355map_memory_window_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar) 356{ 357 int rc; 358 uint8_t bar_size_bits = 0; 359 360 bar->pci_resource = bus_alloc_resource_any(ntb->device, 361 SYS_RES_MEMORY, &bar->pci_resource_id, RF_ACTIVE); 362 363 if (bar->pci_resource == NULL) 364 return (ENXIO); 365 else { 366 save_bar_parameters(bar); 367 /* 368 * Ivytown NTB BAR sizes are misreported by the hardware due to 369 * a hardware issue. To work around this, query the size it 370 * should be configured to by the device and modify the resource 371 * to correspond to this new size. The BIOS on systems with this 372 * problem is required to provide enough address space to allow 373 * the driver to make this change safely. 374 * 375 * Ideally I could have just specified the size when I allocated 376 * the resource like: 377 * bus_alloc_resource(ntb->device, 378 * SYS_RES_MEMORY, &bar->pci_resource_id, 0ul, ~0ul, 379 * 1ul << bar_size_bits, RF_ACTIVE); 380 * but the PCI driver does not honor the size in this call, so 381 * we have to modify it after the fact. 382 */ 383 if (HAS_FEATURE(BAR_SIZE_4K)) { 384 if (bar->pci_resource_id == PCIR_BAR(2)) 385 bar_size_bits = pci_read_config(ntb->device, 386 XEON_PBAR23SZ_OFFSET, 1); 387 else 388 bar_size_bits = pci_read_config(ntb->device, 389 XEON_PBAR45SZ_OFFSET, 1); 390 rc = bus_adjust_resource(ntb->device, SYS_RES_MEMORY, 391 bar->pci_resource, bar->pbase, 392 bar->pbase + (1ul << bar_size_bits) - 1); 393 if (rc != 0 ) { 394 device_printf(ntb->device, 395 "unable to resize bar\n"); 396 return (rc); 397 } else 398 save_bar_parameters(bar); 399 } 400 401 /* Mark bar region as write combining to improve performance. */ 402 rc = pmap_change_attr((vm_offset_t)bar->vbase, bar->size, 403 VM_MEMATTR_WRITE_COMBINING); 404 if (rc != 0) { 405 device_printf(ntb->device, "unable to mark bar as" 406 " WRITE_COMBINING\n"); 407 return (rc); 408 } 409 } 410 return (0); 411} 412 413static void 414ntb_unmap_pci_bar(struct ntb_softc *ntb) 415{ 416 struct ntb_pci_bar_info *current_bar; 417 int i; 418 419 for (i = 0; i< NTB_MAX_BARS; i++) { 420 current_bar = &ntb->bar_info[i]; 421 if (current_bar->pci_resource != NULL) 422 bus_release_resource(ntb->device, SYS_RES_MEMORY, 423 current_bar->pci_resource_id, 424 current_bar->pci_resource); 425 } 426} 427 428static int 429ntb_setup_interrupts(struct ntb_softc *ntb) 430{ 431 void (*interrupt_handler)(void *); 432 void *int_arg; 433 bool use_msix = 0; 434 uint32_t num_vectors; 435 int i; 436 437 ntb->allocated_interrupts = 0; 438 /* 439 * On SOC, disable all interrupts. On XEON, disable all but Link 440 * Interrupt. The rest will be unmasked as callbacks are registered. 441 */ 442 if (ntb->type == NTB_SOC) 443 ntb_write_8(ntb->reg_ofs.pdb_mask, ~0); 444 else 445 ntb_write_2(ntb->reg_ofs.pdb_mask, 446 ~(1 << ntb->limits.max_db_bits)); 447 448 num_vectors = MIN(pci_msix_count(ntb->device), 449 ntb->limits.max_db_bits); 450 if (num_vectors >= 1) { 451 pci_alloc_msix(ntb->device, &num_vectors); 452 if (num_vectors >= 4) 453 use_msix = TRUE; 454 } 455 456 ntb_create_callbacks(ntb, num_vectors); 457 if (use_msix == TRUE) { 458 for (i = 0; i < num_vectors; i++) { 459 ntb->int_info[i].rid = i + 1; 460 ntb->int_info[i].res = bus_alloc_resource_any( 461 ntb->device, SYS_RES_IRQ, &ntb->int_info[i].rid, 462 RF_ACTIVE); 463 if (ntb->int_info[i].res == NULL) { 464 device_printf(ntb->device, 465 "bus_alloc_resource failed\n"); 466 return (-1); 467 } 468 ntb->int_info[i].tag = NULL; 469 ntb->allocated_interrupts++; 470 if (ntb->type == NTB_SOC) { 471 interrupt_handler = handle_soc_irq; 472 int_arg = &ntb->db_cb[i]; 473 } else { 474 if (i == num_vectors - 1) { 475 interrupt_handler = handle_xeon_event_irq; 476 int_arg = ntb; 477 } else { 478 interrupt_handler = 479 handle_xeon_irq; 480 int_arg = &ntb->db_cb[i]; 481 } 482 } 483 if (bus_setup_intr(ntb->device, ntb->int_info[i].res, 484 INTR_MPSAFE | INTR_TYPE_MISC, NULL, 485 interrupt_handler, int_arg, 486 &ntb->int_info[i].tag) != 0) { 487 device_printf(ntb->device, 488 "bus_setup_intr failed\n"); 489 return (ENXIO); 490 } 491 } 492 } 493 else { 494 ntb->int_info[0].rid = 0; 495 ntb->int_info[0].res = bus_alloc_resource_any(ntb->device, SYS_RES_IRQ, 496 &ntb->int_info[0].rid, RF_SHAREABLE|RF_ACTIVE); 497 interrupt_handler = ntb_handle_legacy_interrupt; 498 if (ntb->int_info[0].res == NULL) { 499 device_printf(ntb->device, 500 "bus_alloc_resource failed\n"); 501 return (-1); 502 } 503 ntb->int_info[0].tag = NULL; 504 ntb->allocated_interrupts = 1; 505 506 if (bus_setup_intr(ntb->device, ntb->int_info[0].res, 507 INTR_MPSAFE | INTR_TYPE_MISC, NULL, 508 interrupt_handler, ntb, &ntb->int_info[0].tag) != 0) { 509 510 device_printf(ntb->device, "bus_setup_intr failed\n"); 511 return (ENXIO); 512 } 513 } 514 515 return (0); 516} 517 518static void 519ntb_teardown_interrupts(struct ntb_softc *ntb) 520{ 521 struct ntb_int_info *current_int; 522 int i; 523 524 for (i=0; i<ntb->allocated_interrupts; i++) { 525 current_int = &ntb->int_info[i]; 526 if (current_int->tag != NULL) 527 bus_teardown_intr(ntb->device, current_int->res, 528 current_int->tag); 529 530 if (current_int->res != NULL) 531 bus_release_resource(ntb->device, SYS_RES_IRQ, 532 rman_get_rid(current_int->res), current_int->res); 533 } 534 535 ntb_free_callbacks(ntb); 536 pci_release_msi(ntb->device); 537} 538 539static void 540handle_soc_irq(void *arg) 541{ 542 struct ntb_db_cb *db_cb = arg; 543 struct ntb_softc *ntb = db_cb->ntb; 544 545 ntb_write_8(ntb->reg_ofs.pdb, (uint64_t) 1 << db_cb->db_num); 546 547 if (db_cb->callback != NULL) 548 db_cb->callback(db_cb->data, db_cb->db_num); 549} 550 551static void 552handle_xeon_irq(void *arg) 553{ 554 struct ntb_db_cb *db_cb = arg; 555 struct ntb_softc *ntb = db_cb->ntb; 556 557 /* 558 * On Xeon, there are 16 bits in the interrupt register 559 * but only 4 vectors. So, 5 bits are assigned to the first 3 560 * vectors, with the 4th having a single bit for link 561 * interrupts. 562 */ 563 ntb_write_2(ntb->reg_ofs.pdb, 564 ((1 << ntb->bits_per_vector) - 1) << 565 (db_cb->db_num * ntb->bits_per_vector)); 566 567 if (db_cb->callback != NULL) 568 db_cb->callback(db_cb->data, db_cb->db_num); 569} 570 571/* Since we do not have a HW doorbell in SOC, this is only used in JF/JT */ 572static void 573handle_xeon_event_irq(void *arg) 574{ 575 struct ntb_softc *ntb = arg; 576 int rc; 577 578 rc = ntb_check_link_status(ntb); 579 if (rc != 0) 580 device_printf(ntb->device, "Error determining link status\n"); 581 582 /* bit 15 is always the link bit */ 583 ntb_write_2(ntb->reg_ofs.pdb, 1 << ntb->limits.max_db_bits); 584} 585 586static void 587ntb_handle_legacy_interrupt(void *arg) 588{ 589 struct ntb_softc *ntb = arg; 590 unsigned int i = 0; 591 uint64_t pdb64; 592 uint16_t pdb16; 593 594 if (ntb->type == NTB_SOC) { 595 pdb64 = ntb_read_8(ntb->reg_ofs.pdb); 596 597 while (pdb64) { 598 i = ffs(pdb64); 599 pdb64 &= pdb64 - 1; 600 handle_soc_irq(&ntb->db_cb[i]); 601 } 602 } else { 603 pdb16 = ntb_read_2(ntb->reg_ofs.pdb); 604 605 if ((pdb16 & XEON_DB_HW_LINK) != 0) { 606 handle_xeon_event_irq(ntb); 607 pdb16 &= ~XEON_DB_HW_LINK; 608 } 609 610 while (pdb16 != 0) { 611 i = ffs(pdb16); 612 pdb16 &= pdb16 - 1; 613 handle_xeon_irq(&ntb->db_cb[i]); 614 } 615 } 616 617} 618 619static int 620ntb_create_callbacks(struct ntb_softc *ntb, int num_vectors) 621{ 622 int i; 623 624 ntb->db_cb = malloc(num_vectors * sizeof(struct ntb_db_cb), M_NTB, 625 M_ZERO | M_WAITOK); 626 for (i = 0; i < num_vectors; i++) { 627 ntb->db_cb[i].db_num = i; 628 ntb->db_cb[i].ntb = ntb; 629 } 630 631 return (0); 632} 633 634static void 635ntb_free_callbacks(struct ntb_softc *ntb) 636{ 637 int i; 638 639 for (i = 0; i < ntb->limits.max_db_bits; i++) 640 ntb_unregister_db_callback(ntb, i); 641 642 free(ntb->db_cb, M_NTB); 643} 644 645static struct ntb_hw_info * 646ntb_get_device_info(uint32_t device_id) 647{ 648 struct ntb_hw_info *ep = pci_ids; 649 650 while (ep->device_id) { 651 if (ep->device_id == device_id) 652 return (ep); 653 ++ep; 654 } 655 return (NULL); 656} 657 658static int 659ntb_initialize_hw(struct ntb_softc *ntb) 660{ 661 662 if (ntb->type == NTB_SOC) 663 return (ntb_setup_soc(ntb)); 664 else 665 return (ntb_setup_xeon(ntb)); 666} 667 668static int 669ntb_setup_xeon(struct ntb_softc *ntb) 670{ 671 uint8_t val, connection_type; 672 673 val = pci_read_config(ntb->device, NTB_PPD_OFFSET, 1); 674 675 connection_type = val & XEON_PPD_CONN_TYPE; 676 switch (connection_type) { 677 case NTB_CONN_B2B: 678 ntb->conn_type = NTB_CONN_B2B; 679 break; 680 case NTB_CONN_CLASSIC: 681 case NTB_CONN_RP: 682 default: 683 device_printf(ntb->device, "Connection type %d not supported\n", 684 connection_type); 685 return (ENXIO); 686 } 687 688 if ((val & XEON_PPD_DEV_TYPE) != 0) 689 ntb->dev_type = NTB_DEV_DSD; 690 else 691 ntb->dev_type = NTB_DEV_USD; 692 693 ntb->reg_ofs.pdb = XEON_PDOORBELL_OFFSET; 694 ntb->reg_ofs.pdb_mask = XEON_PDBMSK_OFFSET; 695 ntb->reg_ofs.sbar2_xlat = XEON_SBAR2XLAT_OFFSET; 696 ntb->reg_ofs.sbar4_xlat = XEON_SBAR4XLAT_OFFSET; 697 ntb->reg_ofs.lnk_cntl = XEON_NTBCNTL_OFFSET; 698 ntb->reg_ofs.lnk_stat = XEON_LINK_STATUS_OFFSET; 699 ntb->reg_ofs.spad_local = XEON_SPAD_OFFSET; 700 ntb->reg_ofs.spci_cmd = XEON_PCICMD_OFFSET; 701 702 if (ntb->conn_type == NTB_CONN_B2B) { 703 ntb->reg_ofs.sdb = XEON_B2B_DOORBELL_OFFSET; 704 ntb->reg_ofs.spad_remote = XEON_B2B_SPAD_OFFSET; 705 ntb->limits.max_spads = XEON_MAX_SPADS; 706 } else { 707 ntb->reg_ofs.sdb = XEON_SDOORBELL_OFFSET; 708 ntb->reg_ofs.spad_remote = XEON_SPAD_OFFSET; 709 ntb->limits.max_spads = XEON_MAX_COMPAT_SPADS; 710 } 711 712 ntb->limits.max_db_bits = XEON_MAX_DB_BITS; 713 ntb->limits.msix_cnt = XEON_MSIX_CNT; 714 ntb->bits_per_vector = XEON_DB_BITS_PER_VEC; 715 716 /* Enable Bus Master and Memory Space on the secondary side */ 717 ntb_write_2(ntb->reg_ofs.spci_cmd, 718 PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); 719 720 /* Enable link training */ 721 ntb_write_4(ntb->reg_ofs.lnk_cntl, 722 NTB_CNTL_BAR23_SNOOP | NTB_CNTL_BAR45_SNOOP); 723 724 return (0); 725} 726 727static int 728ntb_setup_soc(struct ntb_softc *ntb) 729{ 730 uint32_t val, connection_type; 731 732 val = pci_read_config(ntb->device, NTB_PPD_OFFSET, 4); 733 734 connection_type = (val & SOC_PPD_CONN_TYPE) >> 8; 735 switch (connection_type) { 736 case NTB_CONN_B2B: 737 ntb->conn_type = NTB_CONN_B2B; 738 break; 739 case NTB_CONN_RP: 740 default: 741 device_printf(ntb->device, "Connection type %d not supported\n", 742 connection_type); 743 return (ENXIO); 744 } 745 746 if ((val & SOC_PPD_DEV_TYPE) != 0) 747 ntb->dev_type = NTB_DEV_DSD; 748 else 749 ntb->dev_type = NTB_DEV_USD; 750 751 /* Initiate PCI-E link training */ 752 pci_write_config(ntb->device, NTB_PPD_OFFSET, val | SOC_PPD_INIT_LINK, 753 4); 754 755 ntb->reg_ofs.pdb = SOC_PDOORBELL_OFFSET; 756 ntb->reg_ofs.pdb_mask = SOC_PDBMSK_OFFSET; 757 ntb->reg_ofs.sbar2_xlat = SOC_SBAR2XLAT_OFFSET; 758 ntb->reg_ofs.sbar4_xlat = SOC_SBAR4XLAT_OFFSET; 759 ntb->reg_ofs.lnk_cntl = SOC_NTBCNTL_OFFSET; 760 ntb->reg_ofs.lnk_stat = SOC_LINK_STATUS_OFFSET; 761 ntb->reg_ofs.spad_local = SOC_SPAD_OFFSET; 762 ntb->reg_ofs.spci_cmd = SOC_PCICMD_OFFSET; 763 764 if (ntb->conn_type == NTB_CONN_B2B) { 765 ntb->reg_ofs.sdb = SOC_B2B_DOORBELL_OFFSET; 766 ntb->reg_ofs.spad_remote = SOC_B2B_SPAD_OFFSET; 767 ntb->limits.max_spads = SOC_MAX_SPADS; 768 } else { 769 ntb->reg_ofs.sdb = SOC_PDOORBELL_OFFSET; 770 ntb->reg_ofs.spad_remote = SOC_SPAD_OFFSET; 771 ntb->limits.max_spads = SOC_MAX_COMPAT_SPADS; 772 } 773 774 ntb->limits.max_db_bits = SOC_MAX_DB_BITS; 775 ntb->limits.msix_cnt = SOC_MSIX_CNT; 776 ntb->bits_per_vector = SOC_DB_BITS_PER_VEC; 777 778 /* 779 * FIXME - MSI-X bug on early SOC HW, remove once internal issue is 780 * resolved. Mask transaction layer internal parity errors. 781 */ 782 pci_write_config(ntb->device, 0xFC, 0x4, 4); 783 784 /* 785 * Some BIOSes aren't filling out the XLAT offsets. 786 * Check and correct the issue. 787 */ 788 if (ntb->dev_type == NTB_DEV_USD) { 789 if (ntb_read_8(SOC_PBAR2XLAT_OFFSET) == 0) 790 ntb_write_8(SOC_PBAR2XLAT_OFFSET, 791 SOC_PBAR2XLAT_USD_ADDR); 792 793 if (ntb_read_8(SOC_PBAR4XLAT_OFFSET) == 0) 794 ntb_write_8(SOC_PBAR4XLAT_OFFSET, 795 SOC_PBAR4XLAT_USD_ADDR); 796 797 if (ntb_read_8(SOC_MBAR23_OFFSET) == 0xC) 798 ntb_write_8(SOC_MBAR23_OFFSET, SOC_MBAR23_USD_ADDR); 799 800 if (ntb_read_8(SOC_MBAR45_OFFSET) == 0xC) 801 ntb_write_8(SOC_MBAR45_OFFSET, SOC_MBAR45_USD_ADDR); 802 } else { 803 if (ntb_read_8(SOC_PBAR2XLAT_OFFSET) == 0) 804 ntb_write_8(SOC_PBAR2XLAT_OFFSET, 805 SOC_PBAR2XLAT_DSD_ADDR); 806 807 if (ntb_read_8(SOC_PBAR4XLAT_OFFSET) == 0) 808 ntb_write_8(SOC_PBAR4XLAT_OFFSET, 809 SOC_PBAR4XLAT_DSD_ADDR); 810 811 if (ntb_read_8(SOC_MBAR23_OFFSET) == 0xC) 812 ntb_write_8(SOC_MBAR23_OFFSET, SOC_MBAR23_DSD_ADDR); 813 814 if (ntb_read_8(SOC_MBAR45_OFFSET) == 0xC) 815 ntb_write_8(SOC_MBAR45_OFFSET, SOC_MBAR45_DSD_ADDR); 816 } 817 818 /* Enable Bus Master and Memory Space on the secondary side */ 819 ntb_write_2(ntb->reg_ofs.spci_cmd, 820 PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); 821 callout_reset(&ntb->heartbeat_timer, 0, ntb_handle_heartbeat, ntb); 822 823 return (0); 824} 825 826/* SOC doesn't have link status interrupt, poll on that platform */ 827static void 828ntb_handle_heartbeat(void *arg) 829{ 830 struct ntb_softc *ntb = arg; 831 uint32_t status32; 832 int rc = ntb_check_link_status(ntb); 833 834 if (rc != 0) 835 device_printf(ntb->device, 836 "Error determining link status\n"); 837 /* Check to see if a link error is the cause of the link down */ 838 if (ntb->link_status == NTB_LINK_DOWN) { 839 status32 = ntb_read_4(SOC_LTSSMSTATEJMP_OFFSET); 840 if ((status32 & SOC_LTSSMSTATEJMP_FORCEDETECT) != 0) { 841 callout_reset(&ntb->lr_timer, 0, recover_soc_link, 842 ntb); 843 return; 844 } 845 } 846 847 callout_reset(&ntb->heartbeat_timer, NTB_HB_TIMEOUT * hz, 848 ntb_handle_heartbeat, ntb); 849} 850 851static void 852soc_perform_link_restart(struct ntb_softc *ntb) 853{ 854 uint32_t status; 855 856 /* Driver resets the NTB ModPhy lanes - magic! */ 857 ntb_write_1(SOC_MODPHY_PCSREG6, 0xe0); 858 ntb_write_1(SOC_MODPHY_PCSREG4, 0x40); 859 ntb_write_1(SOC_MODPHY_PCSREG4, 0x60); 860 ntb_write_1(SOC_MODPHY_PCSREG6, 0x60); 861 862 /* Driver waits 100ms to allow the NTB ModPhy to settle */ 863 pause("ModPhy", hz / 10); 864 865 /* Clear AER Errors, write to clear */ 866 status = ntb_read_4(SOC_ERRCORSTS_OFFSET); 867 status &= PCIM_AER_COR_REPLAY_ROLLOVER; 868 ntb_write_4(SOC_ERRCORSTS_OFFSET, status); 869 870 /* Clear unexpected electrical idle event in LTSSM, write to clear */ 871 status = ntb_read_4(SOC_LTSSMERRSTS0_OFFSET); 872 status |= SOC_LTSSMERRSTS0_UNEXPECTEDEI; 873 ntb_write_4(SOC_LTSSMERRSTS0_OFFSET, status); 874 875 /* Clear DeSkew Buffer error, write to clear */ 876 status = ntb_read_4(SOC_DESKEWSTS_OFFSET); 877 status |= SOC_DESKEWSTS_DBERR; 878 ntb_write_4(SOC_DESKEWSTS_OFFSET, status); 879 880 status = ntb_read_4(SOC_IBSTERRRCRVSTS0_OFFSET); 881 status &= SOC_IBIST_ERR_OFLOW; 882 ntb_write_4(SOC_IBSTERRRCRVSTS0_OFFSET, status); 883 884 /* Releases the NTB state machine to allow the link to retrain */ 885 status = ntb_read_4(SOC_LTSSMSTATEJMP_OFFSET); 886 status &= ~SOC_LTSSMSTATEJMP_FORCEDETECT; 887 ntb_write_4(SOC_LTSSMSTATEJMP_OFFSET, status); 888} 889 890static void 891ntb_handle_link_event(struct ntb_softc *ntb, int link_state) 892{ 893 enum ntb_hw_event event; 894 uint16_t status; 895 896 if (ntb->link_status == link_state) 897 return; 898 899 if (link_state == NTB_LINK_UP) { 900 device_printf(ntb->device, "Link Up\n"); 901 ntb->link_status = NTB_LINK_UP; 902 event = NTB_EVENT_HW_LINK_UP; 903 904 if (ntb->type == NTB_SOC) 905 status = ntb_read_2(ntb->reg_ofs.lnk_stat); 906 else 907 status = pci_read_config(ntb->device, 908 XEON_LINK_STATUS_OFFSET, 2); 909 ntb->link_width = (status & NTB_LINK_WIDTH_MASK) >> 4; 910 ntb->link_speed = (status & NTB_LINK_SPEED_MASK); 911 device_printf(ntb->device, "Link Width %d, Link Speed %d\n", 912 ntb->link_width, ntb->link_speed); 913 callout_reset(&ntb->heartbeat_timer, NTB_HB_TIMEOUT * hz, 914 ntb_handle_heartbeat, ntb); 915 } else { 916 device_printf(ntb->device, "Link Down\n"); 917 ntb->link_status = NTB_LINK_DOWN; 918 event = NTB_EVENT_HW_LINK_DOWN; 919 /* Don't modify link width/speed, we need it in link recovery */ 920 } 921 922 /* notify the upper layer if we have an event change */ 923 if (ntb->event_cb != NULL) 924 ntb->event_cb(ntb->ntb_transport, event); 925} 926 927static void 928recover_soc_link(void *arg) 929{ 930 struct ntb_softc *ntb = arg; 931 uint8_t speed, width; 932 uint32_t status32; 933 uint16_t status16; 934 935 soc_perform_link_restart(ntb); 936 pause("Link", SOC_LINK_RECOVERY_TIME * hz / 1000); 937 938 status32 = ntb_read_4(SOC_LTSSMSTATEJMP_OFFSET); 939 if ((status32 & SOC_LTSSMSTATEJMP_FORCEDETECT) != 0) 940 goto retry; 941 942 status32 = ntb_read_4(SOC_IBSTERRRCRVSTS0_OFFSET); 943 if ((status32 & SOC_IBIST_ERR_OFLOW) != 0) 944 goto retry; 945 946 status16 = ntb_read_2(ntb->reg_ofs.lnk_stat); 947 width = (status16 & NTB_LINK_WIDTH_MASK) >> 4; 948 speed = (status16 & NTB_LINK_SPEED_MASK); 949 if (ntb->link_width != width || ntb->link_speed != speed) 950 goto retry; 951 952 callout_reset(&ntb->heartbeat_timer, NTB_HB_TIMEOUT * hz, 953 ntb_handle_heartbeat, ntb); 954 return; 955 956retry: 957 callout_reset(&ntb->lr_timer, NTB_HB_TIMEOUT * hz, recover_soc_link, 958 ntb); 959} 960 961static int 962ntb_check_link_status(struct ntb_softc *ntb) 963{ 964 int link_state; 965 uint32_t ntb_cntl; 966 uint16_t status; 967 968 if (ntb->type == NTB_SOC) { 969 ntb_cntl = ntb_read_4(ntb->reg_ofs.lnk_cntl); 970 if ((ntb_cntl & SOC_CNTL_LINK_DOWN) != 0) 971 link_state = NTB_LINK_DOWN; 972 else 973 link_state = NTB_LINK_UP; 974 } else { 975 status = pci_read_config(ntb->device, XEON_LINK_STATUS_OFFSET, 976 2); 977 978 if ((status & NTB_LINK_STATUS_ACTIVE) != 0) 979 link_state = NTB_LINK_UP; 980 else 981 link_state = NTB_LINK_DOWN; 982 } 983 984 ntb_handle_link_event(ntb, link_state); 985 986 return (0); 987} 988 989/** 990 * ntb_register_event_callback() - register event callback 991 * @ntb: pointer to ntb_softc instance 992 * @func: callback function to register 993 * 994 * This function registers a callback for any HW driver events such as link 995 * up/down, power management notices and etc. 996 * 997 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 998 */ 999int 1000ntb_register_event_callback(struct ntb_softc *ntb, ntb_event_callback func) 1001{ 1002 1003 if (ntb->event_cb != NULL) 1004 return (EINVAL); 1005 1006 ntb->event_cb = func; 1007 1008 return (0); 1009} 1010 1011/** 1012 * ntb_unregister_event_callback() - unregisters the event callback 1013 * @ntb: pointer to ntb_softc instance 1014 * 1015 * This function unregisters the existing callback from transport 1016 */ 1017void 1018ntb_unregister_event_callback(struct ntb_softc *ntb) 1019{ 1020 1021 ntb->event_cb = NULL; 1022} 1023 1024/** 1025 * ntb_register_db_callback() - register a callback for doorbell interrupt 1026 * @ntb: pointer to ntb_softc instance 1027 * @idx: doorbell index to register callback, zero based 1028 * @func: callback function to register 1029 * 1030 * This function registers a callback function for the doorbell interrupt 1031 * on the primary side. The function will unmask the doorbell as well to 1032 * allow interrupt. 1033 * 1034 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 1035 */ 1036int 1037ntb_register_db_callback(struct ntb_softc *ntb, unsigned int idx, void *data, 1038 ntb_db_callback func) 1039{ 1040 uint16_t mask; 1041 1042 if (idx >= ntb->allocated_interrupts || ntb->db_cb[idx].callback) { 1043 device_printf(ntb->device, "Invalid Index.\n"); 1044 return (EINVAL); 1045 } 1046 1047 ntb->db_cb[idx].callback = func; 1048 ntb->db_cb[idx].data = data; 1049 1050 /* unmask interrupt */ 1051 mask = ntb_read_2(ntb->reg_ofs.pdb_mask); 1052 mask &= ~(1 << (idx * ntb->bits_per_vector)); 1053 ntb_write_2(ntb->reg_ofs.pdb_mask, mask); 1054 1055 return (0); 1056} 1057 1058/** 1059 * ntb_unregister_db_callback() - unregister a callback for doorbell interrupt 1060 * @ntb: pointer to ntb_softc instance 1061 * @idx: doorbell index to register callback, zero based 1062 * 1063 * This function unregisters a callback function for the doorbell interrupt 1064 * on the primary side. The function will also mask the said doorbell. 1065 */ 1066void 1067ntb_unregister_db_callback(struct ntb_softc *ntb, unsigned int idx) 1068{ 1069 unsigned long mask; 1070 1071 if (idx >= ntb->allocated_interrupts || !ntb->db_cb[idx].callback) 1072 return; 1073 1074 mask = ntb_read_2(ntb->reg_ofs.pdb_mask); 1075 mask |= 1 << (idx * ntb->bits_per_vector); 1076 ntb_write_2(ntb->reg_ofs.pdb_mask, mask); 1077 1078 ntb->db_cb[idx].callback = NULL; 1079} 1080 1081/** 1082 * ntb_find_transport() - find the transport pointer 1083 * @transport: pointer to pci device 1084 * 1085 * Given the pci device pointer, return the transport pointer passed in when 1086 * the transport attached when it was inited. 1087 * 1088 * RETURNS: pointer to transport. 1089 */ 1090void * 1091ntb_find_transport(struct ntb_softc *ntb) 1092{ 1093 1094 return (ntb->ntb_transport); 1095} 1096 1097/** 1098 * ntb_register_transport() - Register NTB transport with NTB HW driver 1099 * @transport: transport identifier 1100 * 1101 * This function allows a transport to reserve the hardware driver for 1102 * NTB usage. 1103 * 1104 * RETURNS: pointer to ntb_softc, NULL on error. 1105 */ 1106struct ntb_softc * 1107ntb_register_transport(struct ntb_softc *ntb, void *transport) 1108{ 1109 1110 /* 1111 * TODO: when we have more than one transport, we will need to rewrite 1112 * this to prevent race conditions 1113 */ 1114 if (ntb->ntb_transport != NULL) 1115 return (NULL); 1116 1117 ntb->ntb_transport = transport; 1118 return (ntb); 1119} 1120 1121/** 1122 * ntb_unregister_transport() - Unregister the transport with the NTB HW driver 1123 * @ntb - ntb_softc of the transport to be freed 1124 * 1125 * This function unregisters the transport from the HW driver and performs any 1126 * necessary cleanups. 1127 */ 1128void 1129ntb_unregister_transport(struct ntb_softc *ntb) 1130{ 1131 int i; 1132 1133 if (ntb->ntb_transport == NULL) 1134 return; 1135 1136 for (i = 0; i < ntb->allocated_interrupts; i++) 1137 ntb_unregister_db_callback(ntb, i); 1138 1139 ntb_unregister_event_callback(ntb); 1140 ntb->ntb_transport = NULL; 1141} 1142 1143/** 1144 * ntb_get_max_spads() - get the total scratch regs usable 1145 * @ntb: pointer to ntb_softc instance 1146 * 1147 * This function returns the max 32bit scratchpad registers usable by the 1148 * upper layer. 1149 * 1150 * RETURNS: total number of scratch pad registers available 1151 */ 1152int 1153ntb_get_max_spads(struct ntb_softc *ntb) 1154{ 1155 1156 return (ntb->limits.max_spads); 1157} 1158 1159/** 1160 * ntb_write_local_spad() - write to the secondary scratchpad register 1161 * @ntb: pointer to ntb_softc instance 1162 * @idx: index to the scratchpad register, 0 based 1163 * @val: the data value to put into the register 1164 * 1165 * This function allows writing of a 32bit value to the indexed scratchpad 1166 * register. The register resides on the secondary (external) side. 1167 * 1168 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 1169 */ 1170int 1171ntb_write_local_spad(struct ntb_softc *ntb, unsigned int idx, uint32_t val) 1172{ 1173 1174 if (idx >= ntb->limits.max_spads) 1175 return (EINVAL); 1176 1177 ntb_write_4(ntb->reg_ofs.spad_local + idx * 4, val); 1178 1179 return (0); 1180} 1181 1182/** 1183 * ntb_read_local_spad() - read from the primary scratchpad register 1184 * @ntb: pointer to ntb_softc instance 1185 * @idx: index to scratchpad register, 0 based 1186 * @val: pointer to 32bit integer for storing the register value 1187 * 1188 * This function allows reading of the 32bit scratchpad register on 1189 * the primary (internal) side. 1190 * 1191 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 1192 */ 1193int 1194ntb_read_local_spad(struct ntb_softc *ntb, unsigned int idx, uint32_t *val) 1195{ 1196 1197 if (idx >= ntb->limits.max_spads) 1198 return (EINVAL); 1199 1200 *val = ntb_read_4(ntb->reg_ofs.spad_local + idx * 4); 1201 1202 return (0); 1203} 1204 1205/** 1206 * ntb_write_remote_spad() - write to the secondary scratchpad register 1207 * @ntb: pointer to ntb_softc instance 1208 * @idx: index to the scratchpad register, 0 based 1209 * @val: the data value to put into the register 1210 * 1211 * This function allows writing of a 32bit value to the indexed scratchpad 1212 * register. The register resides on the secondary (external) side. 1213 * 1214 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 1215 */ 1216int 1217ntb_write_remote_spad(struct ntb_softc *ntb, unsigned int idx, uint32_t val) 1218{ 1219 1220 if (idx >= ntb->limits.max_spads) 1221 return (EINVAL); 1222 1223 ntb_write_4(ntb->reg_ofs.spad_remote + idx * 4, val); 1224 1225 return (0); 1226} 1227 1228/** 1229 * ntb_read_remote_spad() - read from the primary scratchpad register 1230 * @ntb: pointer to ntb_softc instance 1231 * @idx: index to scratchpad register, 0 based 1232 * @val: pointer to 32bit integer for storing the register value 1233 * 1234 * This function allows reading of the 32bit scratchpad register on 1235 * the primary (internal) side. 1236 * 1237 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 1238 */ 1239int 1240ntb_read_remote_spad(struct ntb_softc *ntb, unsigned int idx, uint32_t *val) 1241{ 1242 1243 if (idx >= ntb->limits.max_spads) 1244 return (EINVAL); 1245 1246 *val = ntb_read_4(ntb->reg_ofs.spad_remote + idx * 4); 1247 1248 return (0); 1249} 1250 1251/** 1252 * ntb_get_mw_vbase() - get virtual addr for the NTB memory window 1253 * @ntb: pointer to ntb_softc instance 1254 * @mw: memory window number 1255 * 1256 * This function provides the base virtual address of the memory window 1257 * specified. 1258 * 1259 * RETURNS: pointer to virtual address, or NULL on error. 1260 */ 1261void * 1262ntb_get_mw_vbase(struct ntb_softc *ntb, unsigned int mw) 1263{ 1264 1265 if (mw >= NTB_NUM_MW) 1266 return (NULL); 1267 1268 return (ntb->bar_info[NTB_MW_TO_BAR(mw)].vbase); 1269} 1270 1271vm_paddr_t 1272ntb_get_mw_pbase(struct ntb_softc *ntb, unsigned int mw) 1273{ 1274 1275 if (mw >= NTB_NUM_MW) 1276 return (0); 1277 1278 return (ntb->bar_info[NTB_MW_TO_BAR(mw)].pbase); 1279} 1280 1281/** 1282 * ntb_get_mw_size() - return size of NTB memory window 1283 * @ntb: pointer to ntb_softc instance 1284 * @mw: memory window number 1285 * 1286 * This function provides the physical size of the memory window specified 1287 * 1288 * RETURNS: the size of the memory window or zero on error 1289 */ 1290u_long 1291ntb_get_mw_size(struct ntb_softc *ntb, unsigned int mw) 1292{ 1293 1294 if (mw >= NTB_NUM_MW) 1295 return (0); 1296 1297 return (ntb->bar_info[NTB_MW_TO_BAR(mw)].size); 1298} 1299 1300/** 1301 * ntb_set_mw_addr - set the memory window address 1302 * @ntb: pointer to ntb_softc instance 1303 * @mw: memory window number 1304 * @addr: base address for data 1305 * 1306 * This function sets the base physical address of the memory window. This 1307 * memory address is where data from the remote system will be transfered into 1308 * or out of depending on how the transport is configured. 1309 */ 1310void 1311ntb_set_mw_addr(struct ntb_softc *ntb, unsigned int mw, uint64_t addr) 1312{ 1313 1314 if (mw >= NTB_NUM_MW) 1315 return; 1316 1317 switch (NTB_MW_TO_BAR(mw)) { 1318 case NTB_B2B_BAR_1: 1319 ntb_write_8(ntb->reg_ofs.sbar2_xlat, addr); 1320 break; 1321 case NTB_B2B_BAR_2: 1322 ntb_write_8(ntb->reg_ofs.sbar4_xlat, addr); 1323 break; 1324 } 1325} 1326 1327/** 1328 * ntb_ring_sdb() - Set the doorbell on the secondary/external side 1329 * @ntb: pointer to ntb_softc instance 1330 * @db: doorbell to ring 1331 * 1332 * This function allows triggering of a doorbell on the secondary/external 1333 * side that will initiate an interrupt on the remote host 1334 * 1335 * RETURNS: An appropriate -ERRNO error value on error, or zero for success. 1336 */ 1337void 1338ntb_ring_sdb(struct ntb_softc *ntb, unsigned int db) 1339{ 1340 1341 if (ntb->type == NTB_SOC) 1342 ntb_write_8(ntb->reg_ofs.sdb, (uint64_t) 1 << db); 1343 else 1344 ntb_write_2(ntb->reg_ofs.sdb, 1345 ((1 << ntb->bits_per_vector) - 1) << 1346 (db * ntb->bits_per_vector)); 1347} 1348 1349/** 1350 * ntb_query_link_status() - return the hardware link status 1351 * @ndev: pointer to ntb_device instance 1352 * 1353 * Returns true if the hardware is connected to the remote system 1354 * 1355 * RETURNS: true or false based on the hardware link state 1356 */ 1357bool 1358ntb_query_link_status(struct ntb_softc *ntb) 1359{ 1360 1361 return (ntb->link_status == NTB_LINK_UP); 1362} 1363 1364static void 1365save_bar_parameters(struct ntb_pci_bar_info *bar) 1366{ 1367 bar->pci_bus_tag = 1368 rman_get_bustag(bar->pci_resource); 1369 bar->pci_bus_handle = 1370 rman_get_bushandle(bar->pci_resource); 1371 bar->pbase = 1372 rman_get_start(bar->pci_resource); 1373 bar->size = 1374 rman_get_size(bar->pci_resource); 1375 bar->vbase = 1376 rman_get_virtual(bar->pci_resource); 1377 1378} 1379 1380device_t ntb_get_device(struct ntb_softc *ntb) 1381{ 1382 1383 return (ntb->device); 1384} 1385