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