Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/ntb/ntb_hw/ntb_hw_amd.c
Show First 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | |||||
#include <dev/pci/pcireg.h> | #include <dev/pci/pcireg.h> | ||||
#include <dev/pci/pcivar.h> | #include <dev/pci/pcivar.h> | ||||
#include "ntb_hw_amd.h" | #include "ntb_hw_amd.h" | ||||
#include "dev/ntb/ntb.h" | #include "dev/ntb/ntb.h" | ||||
MALLOC_DEFINE(M_AMD_NTB, "amd_ntb_hw", "amd_ntb_hw driver memory allocations"); | MALLOC_DEFINE(M_AMD_NTB, "amd_ntb_hw", "amd_ntb_hw driver memory allocations"); | ||||
struct pci_device_table amd_ntb_devs[] = { | static const struct amd_ntb_hw_info amd_ntb_hw_info_list[] = { | ||||
{ PCI_DEV(NTB_HW_AMD_VENDOR_ID, NTB_HW_AMD_DEVICE_ID), | |||||
{ .vendor_id = NTB_HW_AMD_VENDOR_ID, | |||||
.device_id = NTB_HW_AMD_DEVICE_ID1, | |||||
.mw_count = 3, | |||||
.bar_start_idx = 1, | |||||
.spad_count = 16, | |||||
.db_count = 16, | |||||
.msix_vector_count = 24, | |||||
.quirks = QUIRK_MW0_32BIT, | |||||
.desc = "AMD Non-Transparent Bridge"}, | |||||
{ .vendor_id = NTB_HW_AMD_VENDOR_ID, | |||||
.device_id = NTB_HW_AMD_DEVICE_ID2, | |||||
.mw_count = 2, | |||||
.bar_start_idx = 2, | |||||
.spad_count = 16, | |||||
.db_count = 16, | |||||
.msix_vector_count = 24, | |||||
.quirks = 0, | |||||
.desc = "AMD Non-Transparent Bridge"}, | |||||
}; | |||||
static const struct pci_device_table amd_ntb_devs[] = { | |||||
{ PCI_DEV(NTB_HW_AMD_VENDOR_ID, NTB_HW_AMD_DEVICE_ID1), | |||||
.driver_data = (uintptr_t)&amd_ntb_hw_info_list[0], | |||||
PCI_DESCR("AMD Non-Transparent Bridge") }, | |||||
{ PCI_DEV(NTB_HW_AMD_VENDOR_ID, NTB_HW_AMD_DEVICE_ID2), | |||||
.driver_data = (uintptr_t)&amd_ntb_hw_info_list[1], | |||||
PCI_DESCR("AMD Non-Transparent Bridge") } | PCI_DESCR("AMD Non-Transparent Bridge") } | ||||
}; | }; | ||||
static unsigned g_amd_ntb_hw_debug_level; | static unsigned g_amd_ntb_hw_debug_level; | ||||
SYSCTL_UINT(_hw_ntb, OID_AUTO, debug_level, CTLFLAG_RWTUN, | SYSCTL_UINT(_hw_ntb, OID_AUTO, debug_level, CTLFLAG_RWTUN, | ||||
&g_amd_ntb_hw_debug_level, 0, "amd_ntb_hw log level -- higher is verbose"); | &g_amd_ntb_hw_debug_level, 0, "amd_ntb_hw log level -- higher is verbose"); | ||||
#define amd_ntb_printf(lvl, ...) do { \ | #define amd_ntb_printf(lvl, ...) do { \ | ||||
▲ Show 20 Lines • Show All 201 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* AMD NTB memory window routines | * AMD NTB memory window routines | ||||
*/ | */ | ||||
static uint8_t | static uint8_t | ||||
amd_ntb_mw_count(device_t dev) | amd_ntb_mw_count(device_t dev) | ||||
{ | { | ||||
struct amd_ntb_softc *ntb = device_get_softc(dev); | struct amd_ntb_softc *ntb = device_get_softc(dev); | ||||
return (ntb->mw_count); | return (ntb->hw_info->mw_count); | ||||
} | } | ||||
static int | static int | ||||
amd_ntb_mw_get_range(device_t dev, unsigned mw_idx, vm_paddr_t *base, | amd_ntb_mw_get_range(device_t dev, unsigned mw_idx, vm_paddr_t *base, | ||||
caddr_t *vbase, size_t *size, size_t *align, size_t *align_size, | caddr_t *vbase, size_t *size, size_t *align, size_t *align_size, | ||||
bus_addr_t *plimit) | bus_addr_t *plimit) | ||||
{ | { | ||||
struct amd_ntb_softc *ntb = device_get_softc(dev); | struct amd_ntb_softc *ntb = device_get_softc(dev); | ||||
struct amd_ntb_pci_bar_info *bar_info; | struct amd_ntb_pci_bar_info *bar_info; | ||||
if (mw_idx < 0 || mw_idx >= ntb->mw_count) | if (mw_idx < 0 || mw_idx >= ntb->hw_info->mw_count) | ||||
return (EINVAL); | return (EINVAL); | ||||
bar_info = &ntb->bar_info[mw_idx+1]; | bar_info = &ntb->bar_info[ntb->hw_info->bar_start_idx + mw_idx]; | ||||
if (base != NULL) | if (base != NULL) | ||||
*base = bar_info->pbase; | *base = bar_info->pbase; | ||||
if (vbase != NULL) | if (vbase != NULL) | ||||
*vbase = bar_info->vbase; | *vbase = bar_info->vbase; | ||||
if (align != NULL) | if (align != NULL) | ||||
*align = bar_info->size; | *align = bar_info->size; | ||||
if (size != NULL) | if (size != NULL) | ||||
*size = bar_info->size; | *size = bar_info->size; | ||||
if (align_size != NULL) | if (align_size != NULL) | ||||
*align_size = 1; | *align_size = 1; | ||||
if (plimit != NULL) { | if (plimit != NULL) { | ||||
if (mw_idx != 0) | /* | ||||
*plimit = BUS_SPACE_MAXADDR; | * For Device ID 0x145B (which has 3 memory windows), | ||||
else | * memory window 0 use a 32-bit bar. The remaining | ||||
* cases all use 64-bit bar. | |||||
*/ | |||||
if ((mw_idx == 0) && (ntb->hw_info->quirks & QUIRK_MW0_32BIT)) | |||||
*plimit = BUS_SPACE_MAXADDR_32BIT; | *plimit = BUS_SPACE_MAXADDR_32BIT; | ||||
else | |||||
*plimit = BUS_SPACE_MAXADDR; | |||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
amd_ntb_mw_set_trans(device_t dev, unsigned mw_idx, bus_addr_t addr, size_t size) | amd_ntb_mw_set_trans(device_t dev, unsigned mw_idx, bus_addr_t addr, size_t size) | ||||
{ | { | ||||
struct amd_ntb_softc *ntb = device_get_softc(dev); | struct amd_ntb_softc *ntb = device_get_softc(dev); | ||||
struct amd_ntb_pci_bar_info *bar_info; | struct amd_ntb_pci_bar_info *bar_info; | ||||
if (mw_idx < 0 || mw_idx >= ntb->mw_count) | if (mw_idx < 0 || mw_idx >= ntb->hw_info->mw_count) | ||||
return (EINVAL); | return (EINVAL); | ||||
bar_info = &ntb->bar_info[mw_idx+1]; | bar_info = &ntb->bar_info[ntb->hw_info->bar_start_idx + mw_idx]; | ||||
/* make sure the range fits in the usable mw size */ | /* Make sure the range fits in the usable mw size. */ | ||||
if (size > bar_info->size) { | if (size > bar_info->size) { | ||||
amd_ntb_printf(0, "%s: size 0x%x greater than mw_size 0x%x\n", | amd_ntb_printf(0, "%s: size 0x%x greater than mw_size 0x%x\n", | ||||
__func__, (uint32_t)size, (uint32_t)bar_info->size); | __func__, (uint32_t)size, (uint32_t)bar_info->size); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
amd_ntb_printf(1, "%s: mw %d mw_size 0x%x size 0x%x base %p\n", | amd_ntb_printf(1, "%s: mw %d mw_size 0x%x size 0x%x base %p\n", | ||||
__func__, mw_idx, (uint32_t)bar_info->size, | __func__, mw_idx, (uint32_t)bar_info->size, | ||||
(uint32_t)size, (void *)bar_info->pci_bus_handle); | (uint32_t)size, (void *)bar_info->pci_bus_handle); | ||||
/* | /* | ||||
* AMD NTB XLAT and Limit registers needs to be written only after | * AMD NTB XLAT and Limit registers needs to be written only after | ||||
* link enable | * link enable. | ||||
* | * | ||||
* set and verify setting the translation address | * Set and verify setting the translation address register. | ||||
*/ | */ | ||||
amd_ntb_peer_reg_write(8, bar_info->xlat_off, (uint64_t)addr); | amd_ntb_peer_reg_write(8, bar_info->xlat_off, (uint64_t)addr); | ||||
amd_ntb_printf(0, "%s: mw %d xlat_off 0x%x cur_val 0x%jx addr %p\n", | amd_ntb_printf(0, "%s: mw %d xlat_off 0x%x cur_val 0x%jx addr %p\n", | ||||
__func__, mw_idx, bar_info->xlat_off, | __func__, mw_idx, bar_info->xlat_off, | ||||
amd_ntb_peer_reg_read(8, bar_info->xlat_off), (void *)addr); | amd_ntb_peer_reg_read(8, bar_info->xlat_off), (void *)addr); | ||||
/* set and verify setting the limit */ | /* | ||||
if (mw_idx != 0) { | * Set and verify setting the limit register. | ||||
amd_ntb_reg_write(8, bar_info->limit_off, (uint64_t)size); | * | ||||
amd_ntb_printf(1, "%s: limit_off 0x%x cur_val 0x%jx limit 0x%x\n", | * For Device ID 0x145B (which has 3 memory windows), | ||||
__func__, bar_info->limit_off, | * memory window 0 use a 32-bit bar. The remaining | ||||
amd_ntb_peer_reg_read(8, bar_info->limit_off), (uint32_t)size); | * cases all use 64-bit bar. | ||||
} else { | */ | ||||
if ((mw_idx == 0) && (ntb->hw_info->quirks & QUIRK_MW0_32BIT)) { | |||||
amd_ntb_reg_write(4, bar_info->limit_off, (uint64_t)size); | amd_ntb_reg_write(4, bar_info->limit_off, (uint64_t)size); | ||||
amd_ntb_printf(1, "%s: limit_off 0x%x cur_val 0x%x limit 0x%x\n", | amd_ntb_printf(1, "%s: limit_off 0x%x cur_val 0x%x limit 0x%x\n", | ||||
__func__, bar_info->limit_off, | __func__, bar_info->limit_off, | ||||
amd_ntb_peer_reg_read(4, bar_info->limit_off), (uint32_t)size); | amd_ntb_peer_reg_read(4, bar_info->limit_off), | ||||
(uint32_t)size); | |||||
} else { | |||||
amd_ntb_reg_write(8, bar_info->limit_off, (uint64_t)size); | |||||
amd_ntb_printf(1, "%s: limit_off 0x%x cur_val 0x%lx limit 0x%x\n", | |||||
__func__, bar_info->limit_off, | |||||
amd_ntb_peer_reg_read(8, bar_info->limit_off), | |||||
(uint32_t)size); | |||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
amd_ntb_mw_clear_trans(device_t dev, unsigned mw_idx) | amd_ntb_mw_clear_trans(device_t dev, unsigned mw_idx) | ||||
{ | { | ||||
struct amd_ntb_softc *ntb = device_get_softc(dev); | struct amd_ntb_softc *ntb = device_get_softc(dev); | ||||
amd_ntb_printf(1, "%s: mw_idx %d\n", __func__, mw_idx); | amd_ntb_printf(1, "%s: mw_idx %d\n", __func__, mw_idx); | ||||
if (mw_idx < 0 || mw_idx >= ntb->mw_count) | if (mw_idx < 0 || mw_idx >= ntb->hw_info->mw_count) | ||||
return (EINVAL); | return (EINVAL); | ||||
return (amd_ntb_mw_set_trans(dev, mw_idx, 0, 0)); | return (amd_ntb_mw_set_trans(dev, mw_idx, 0, 0)); | ||||
} | } | ||||
static int | static int | ||||
amd_ntb_mw_set_wc(device_t dev, unsigned int mw_idx, vm_memattr_t mode) | amd_ntb_mw_set_wc(device_t dev, unsigned int mw_idx, vm_memattr_t mode) | ||||
{ | { | ||||
struct amd_ntb_softc *ntb = device_get_softc(dev); | struct amd_ntb_softc *ntb = device_get_softc(dev); | ||||
struct amd_ntb_pci_bar_info *bar_info; | struct amd_ntb_pci_bar_info *bar_info; | ||||
int rc; | int rc; | ||||
if (mw_idx < 0 || mw_idx >= ntb->mw_count) | if (mw_idx < 0 || mw_idx >= ntb->hw_info->mw_count) | ||||
return (EINVAL); | return (EINVAL); | ||||
bar_info = &ntb->bar_info[mw_idx+1]; | bar_info = &ntb->bar_info[ntb->hw_info->bar_start_idx + mw_idx]; | ||||
if (mode == bar_info->map_mode) | if (mode == bar_info->map_mode) | ||||
return (0); | return (0); | ||||
rc = pmap_change_attr((vm_offset_t)bar_info->vbase, bar_info->size, mode); | rc = pmap_change_attr((vm_offset_t)bar_info->vbase, bar_info->size, mode); | ||||
if (rc == 0) | if (rc == 0) | ||||
bar_info->map_mode = mode; | bar_info->map_mode = mode; | ||||
return (rc); | return (rc); | ||||
} | } | ||||
static int | static int | ||||
amd_ntb_mw_get_wc(device_t dev, unsigned mw_idx, vm_memattr_t *mode) | amd_ntb_mw_get_wc(device_t dev, unsigned mw_idx, vm_memattr_t *mode) | ||||
{ | { | ||||
struct amd_ntb_softc *ntb = device_get_softc(dev); | struct amd_ntb_softc *ntb = device_get_softc(dev); | ||||
struct amd_ntb_pci_bar_info *bar_info; | struct amd_ntb_pci_bar_info *bar_info; | ||||
amd_ntb_printf(1, "%s: mw_idx %d\n", __func__, mw_idx); | amd_ntb_printf(1, "%s: mw_idx %d\n", __func__, mw_idx); | ||||
if (mw_idx < 0 || mw_idx >= ntb->mw_count) | if (mw_idx < 0 || mw_idx >= ntb->hw_info->mw_count) | ||||
return (EINVAL); | return (EINVAL); | ||||
bar_info = &ntb->bar_info[mw_idx+1]; | bar_info = &ntb->bar_info[ntb->hw_info->bar_start_idx + mw_idx]; | ||||
*mode = bar_info->map_mode; | *mode = bar_info->map_mode; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* AMD NTB doorbell routines | * AMD NTB doorbell routines | ||||
*/ | */ | ||||
static int | static int | ||||
amd_ntb_db_vector_count(device_t dev) | amd_ntb_db_vector_count(device_t dev) | ||||
{ | { | ||||
struct amd_ntb_softc *ntb = device_get_softc(dev); | struct amd_ntb_softc *ntb = device_get_softc(dev); | ||||
amd_ntb_printf(1, "%s: db_count 0x%x\n", __func__, ntb->db_count); | amd_ntb_printf(1, "%s: db_count 0x%x\n", __func__, | ||||
ntb->hw_info->db_count); | |||||
return (ntb->db_count); | return (ntb->hw_info->db_count); | ||||
} | } | ||||
static uint64_t | static uint64_t | ||||
amd_ntb_db_valid_mask(device_t dev) | amd_ntb_db_valid_mask(device_t dev) | ||||
{ | { | ||||
struct amd_ntb_softc *ntb = device_get_softc(dev); | struct amd_ntb_softc *ntb = device_get_softc(dev); | ||||
amd_ntb_printf(1, "%s: db_valid_mask 0x%x\n", | amd_ntb_printf(1, "%s: db_valid_mask 0x%x\n", | ||||
__func__, ntb->db_valid_mask); | __func__, ntb->db_valid_mask); | ||||
return (ntb->db_valid_mask); | return (ntb->db_valid_mask); | ||||
} | } | ||||
static uint64_t | static uint64_t | ||||
amd_ntb_db_vector_mask(device_t dev, uint32_t vector) | amd_ntb_db_vector_mask(device_t dev, uint32_t vector) | ||||
{ | { | ||||
struct amd_ntb_softc *ntb = device_get_softc(dev); | struct amd_ntb_softc *ntb = device_get_softc(dev); | ||||
amd_ntb_printf(1, "%s: vector %d db_count 0x%x db_valid_mask 0x%x\n", | amd_ntb_printf(1, "%s: vector %d db_count 0x%x db_valid_mask 0x%x\n", | ||||
__func__, vector, ntb->db_count, ntb->db_valid_mask); | __func__, vector, ntb->hw_info->db_count, ntb->db_valid_mask); | ||||
if (vector < 0 || vector >= ntb->db_count) | if (vector < 0 || vector >= ntb->hw_info->db_count) | ||||
return (0); | return (0); | ||||
return (ntb->db_valid_mask & (1 << vector)); | return (ntb->db_valid_mask & (1 << vector)); | ||||
} | } | ||||
static uint64_t | static uint64_t | ||||
amd_ntb_db_read(device_t dev) | amd_ntb_db_read(device_t dev) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* AMD NTB scratchpad routines | * AMD NTB scratchpad routines | ||||
*/ | */ | ||||
static uint8_t | static uint8_t | ||||
amd_ntb_spad_count(device_t dev) | amd_ntb_spad_count(device_t dev) | ||||
{ | { | ||||
struct amd_ntb_softc *ntb = device_get_softc(dev); | struct amd_ntb_softc *ntb = device_get_softc(dev); | ||||
amd_ntb_printf(1, "%s: spad_count 0x%x\n", __func__, ntb->spad_count); | amd_ntb_printf(1, "%s: spad_count 0x%x\n", __func__, | ||||
ntb->spad_count); | |||||
return (ntb->spad_count); | return (ntb->spad_count); | ||||
} | } | ||||
static int | static int | ||||
amd_ntb_spad_read(device_t dev, unsigned int idx, uint32_t *val) | amd_ntb_spad_read(device_t dev, unsigned int idx, uint32_t *val) | ||||
{ | { | ||||
struct amd_ntb_softc *ntb = device_get_softc(dev); | struct amd_ntb_softc *ntb = device_get_softc(dev); | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | else { | ||||
sbuf_printf(sb, "AMD Link Status: Up\n"); | sbuf_printf(sb, "AMD Link Status: Up\n"); | ||||
sbuf_printf(sb, "AMD Link Speed: PCI-E Gen %u\n", | sbuf_printf(sb, "AMD Link Speed: PCI-E Gen %u\n", | ||||
NTB_LNK_STA_SPEED(ntb->lnk_sta)); | NTB_LNK_STA_SPEED(ntb->lnk_sta)); | ||||
sbuf_printf(sb, "AMD Link Width: PCI-E Width %u\n", | sbuf_printf(sb, "AMD Link Width: PCI-E Width %u\n", | ||||
NTB_LNK_STA_WIDTH(ntb->lnk_sta)); | NTB_LNK_STA_WIDTH(ntb->lnk_sta)); | ||||
} | } | ||||
sbuf_printf(sb, "AMD Memory window count: %d\n", | sbuf_printf(sb, "AMD Memory window count: %d\n", | ||||
ntb->mw_count); | ntb->hw_info->mw_count); | ||||
sbuf_printf(sb, "AMD Spad count: %d\n", | sbuf_printf(sb, "AMD Spad count: %d\n", | ||||
ntb->spad_count); | ntb->spad_count); | ||||
sbuf_printf(sb, "AMD Doorbell count: %d\n", | sbuf_printf(sb, "AMD Doorbell count: %d\n", | ||||
ntb->db_count); | ntb->hw_info->db_count); | ||||
sbuf_printf(sb, "AMD MSI-X vec count: %d\n\n", | sbuf_printf(sb, "AMD MSI-X vec count: %d\n\n", | ||||
ntb->msix_vec_count); | ntb->msix_vec_count); | ||||
sbuf_printf(sb, "AMD Doorbell valid mask: 0x%x\n", | sbuf_printf(sb, "AMD Doorbell valid mask: 0x%x\n", | ||||
ntb->db_valid_mask); | ntb->db_valid_mask); | ||||
sbuf_printf(sb, "AMD Doorbell Mask: 0x%x\n", | sbuf_printf(sb, "AMD Doorbell Mask: 0x%x\n", | ||||
amd_ntb_reg_read(4, AMD_DBMASK_OFFSET)); | amd_ntb_reg_read(4, AMD_DBMASK_OFFSET)); | ||||
sbuf_printf(sb, "AMD Doorbell: 0x%x\n", | sbuf_printf(sb, "AMD Doorbell: 0x%x\n", | ||||
amd_ntb_reg_read(4, AMD_DBSTAT_OFFSET)); | amd_ntb_reg_read(4, AMD_DBSTAT_OFFSET)); | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | if (!amd_link_is_up(ntb)) { | ||||
callout_reset(&ntb->hb_timer, (AMD_LINK_HB_TIMEOUT * 10), | callout_reset(&ntb->hb_timer, (AMD_LINK_HB_TIMEOUT * 10), | ||||
amd_link_hb, ntb); | amd_link_hb, ntb); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
amd_ntb_interrupt(struct amd_ntb_softc *ntb, uint16_t vec) | amd_ntb_interrupt(struct amd_ntb_softc *ntb, uint16_t vec) | ||||
{ | { | ||||
if (vec < AMD_DB_CNT) | if (vec < ntb->hw_info->db_count) | ||||
ntb_db_event(ntb->device, vec); | ntb_db_event(ntb->device, vec); | ||||
else | else | ||||
amd_ntb_printf(0, "Invalid vector %d\n", vec); | amd_ntb_printf(0, "Invalid vector %d\n", vec); | ||||
} | } | ||||
static void | static void | ||||
amd_ntb_vec_isr(void *arg) | amd_ntb_vec_isr(void *arg) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | |||||
amd_ntb_init_isr(struct amd_ntb_softc *ntb) | amd_ntb_init_isr(struct amd_ntb_softc *ntb) | ||||
{ | { | ||||
uint32_t supported_vectors, num_vectors; | uint32_t supported_vectors, num_vectors; | ||||
bool msi = false, intx = false; | bool msi = false, intx = false; | ||||
int rc = 0; | int rc = 0; | ||||
ntb->db_mask = ntb->db_valid_mask; | ntb->db_mask = ntb->db_valid_mask; | ||||
rc = amd_ntb_create_msix_vec(ntb, AMD_MSIX_VECTOR_CNT); | rc = amd_ntb_create_msix_vec(ntb, ntb->hw_info->msix_vector_count); | ||||
if (rc != 0) { | if (rc != 0) { | ||||
amd_ntb_printf(0, "Error creating msix vectors: %d\n", rc); | amd_ntb_printf(0, "Error creating msix vectors: %d\n", rc); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
/* | /* | ||||
* Check the number of MSI-X message supported by the device. | * Check the number of MSI-X message supported by the device. | ||||
* Minimum necessary MSI-X message count should be equal to db_count | * Minimum necessary MSI-X message count should be equal to db_count. | ||||
*/ | */ | ||||
supported_vectors = pci_msix_count(ntb->device); | supported_vectors = pci_msix_count(ntb->device); | ||||
num_vectors = MIN(supported_vectors, ntb->db_count); | num_vectors = MIN(supported_vectors, ntb->hw_info->db_count); | ||||
if (num_vectors < ntb->db_count) { | if (num_vectors < ntb->hw_info->db_count) { | ||||
amd_ntb_printf(0, "No minimum msix: supported %d db %d\n", | amd_ntb_printf(0, "No minimum msix: supported %d db %d\n", | ||||
supported_vectors, ntb->db_count); | supported_vectors, ntb->hw_info->db_count); | ||||
msi = true; | msi = true; | ||||
goto err_msix_enable; | goto err_msix_enable; | ||||
} | } | ||||
/* Allocate the necessary number of MSI-x messages */ | /* Allocate the necessary number of MSI-x messages */ | ||||
rc = pci_alloc_msix(ntb->device, &num_vectors); | rc = pci_alloc_msix(ntb->device, &num_vectors); | ||||
if (rc != 0) { | if (rc != 0) { | ||||
amd_ntb_printf(0, "Error allocating msix vectors: %d\n", rc); | amd_ntb_printf(0, "Error allocating msix vectors: %d\n", rc); | ||||
msi = true; | msi = true; | ||||
goto err_msix_enable; | goto err_msix_enable; | ||||
} | } | ||||
if (num_vectors < ntb->db_count) { | if (num_vectors < ntb->hw_info->db_count) { | ||||
amd_ntb_printf(0, "Allocated only %d MSI-X\n", num_vectors); | amd_ntb_printf(0, "Allocated only %d MSI-X\n", num_vectors); | ||||
msi = true; | msi = true; | ||||
/* | /* | ||||
* Else set ntb->db_count = ntb->msix_vec_count = num_vectors, | * Else set ntb->hw_info->db_count = ntb->msix_vec_count = | ||||
* msi=false and dont release msi | * num_vectors, msi=false and dont release msi. | ||||
*/ | */ | ||||
} | } | ||||
err_msix_enable: | err_msix_enable: | ||||
if (msi) { | if (msi) { | ||||
free(ntb->msix_vec, M_AMD_NTB); | free(ntb->msix_vec, M_AMD_NTB); | ||||
ntb->msix_vec = NULL; | ntb->msix_vec = NULL; | ||||
pci_release_msi(ntb->device); | pci_release_msi(ntb->device); | ||||
num_vectors = 1; | num_vectors = 1; | ||||
rc = pci_alloc_msi(ntb->device, &num_vectors); | rc = pci_alloc_msi(ntb->device, &num_vectors); | ||||
if (rc != 0) { | if (rc != 0) { | ||||
amd_ntb_printf(0, "Error allocating msix vectors: %d\n", rc); | amd_ntb_printf(0, "Error allocating msix vectors: %d\n", rc); | ||||
msi = false; | msi = false; | ||||
intx = true; | intx = true; | ||||
} | } | ||||
} | } | ||||
ntb->db_count = ntb->msix_vec_count = num_vectors; | ntb->hw_info->db_count = ntb->msix_vec_count = num_vectors; | ||||
if (intx) { | if (intx) { | ||||
num_vectors = 1; | num_vectors = 1; | ||||
ntb->db_count = 1; | ntb->hw_info->db_count = 1; | ||||
ntb->msix_vec_count = 0; | ntb->msix_vec_count = 0; | ||||
} | } | ||||
amd_ntb_printf(0, "%s: db %d msix %d msi %d intx %d\n", | amd_ntb_printf(0, "%s: db %d msix %d msi %d intx %d\n", | ||||
__func__, ntb->db_count, ntb->msix_vec_count, (int)msi, (int)intx); | __func__, ntb->hw_info->db_count, ntb->msix_vec_count, (int)msi, (int)intx); | ||||
rc = amd_ntb_setup_isr(ntb, num_vectors, msi, intx); | rc = amd_ntb_setup_isr(ntb, num_vectors, msi, intx); | ||||
if (rc != 0) { | if (rc != 0) { | ||||
amd_ntb_printf(0, "Error setting up isr: %d\n", rc); | amd_ntb_printf(0, "Error setting up isr: %d\n", rc); | ||||
amd_ntb_free_msix_vec(ntb); | amd_ntb_free_msix_vec(ntb); | ||||
} | } | ||||
return (rc); | return (rc); | ||||
Show All 34 Lines | if (info & AMD_SIDE_MASK) | ||||
return (NTB_CONN_SEC); | return (NTB_CONN_SEC); | ||||
return (NTB_CONN_PRI); | return (NTB_CONN_PRI); | ||||
} | } | ||||
static int | static int | ||||
amd_ntb_init_dev(struct amd_ntb_softc *ntb) | amd_ntb_init_dev(struct amd_ntb_softc *ntb) | ||||
{ | { | ||||
ntb->mw_count = AMD_MW_CNT; | ntb->db_valid_mask = (1ull << ntb->hw_info->db_count) - 1; | ||||
ntb->spad_count = AMD_SPADS_CNT; | |||||
ntb->db_count = AMD_DB_CNT; | |||||
ntb->db_valid_mask = (1ull << ntb->db_count) - 1; | |||||
mtx_init(&ntb->db_mask_lock, "amd ntb db bits", NULL, MTX_SPIN); | mtx_init(&ntb->db_mask_lock, "amd ntb db bits", NULL, MTX_SPIN); | ||||
switch (ntb->conn_type) { | switch (ntb->conn_type) { | ||||
case NTB_CONN_PRI: | case NTB_CONN_PRI: | ||||
case NTB_CONN_SEC: | case NTB_CONN_SEC: | ||||
ntb->spad_count >>= 1; | ntb->spad_count >>= 1; | ||||
if (ntb->conn_type == NTB_CONN_PRI) { | if (ntb->conn_type == NTB_CONN_PRI) { | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | amd_ntb_map_pci_bars(struct amd_ntb_softc *ntb) | ||||
int rc = 0; | int rc = 0; | ||||
/* NTB Config/Control registers - BAR 0 */ | /* NTB Config/Control registers - BAR 0 */ | ||||
ntb->bar_info[NTB_CONFIG_BAR].pci_resource_id = PCIR_BAR(0); | ntb->bar_info[NTB_CONFIG_BAR].pci_resource_id = PCIR_BAR(0); | ||||
rc = map_bar(ntb, &ntb->bar_info[NTB_CONFIG_BAR]); | rc = map_bar(ntb, &ntb->bar_info[NTB_CONFIG_BAR]); | ||||
if (rc != 0) | if (rc != 0) | ||||
goto out; | goto out; | ||||
/* Memory Window 0 BAR - BAR 1*/ | /* Memory Window 0 BAR - BAR 1 */ | ||||
ntb->bar_info[NTB_BAR_1].pci_resource_id = PCIR_BAR(1); | ntb->bar_info[NTB_BAR_1].pci_resource_id = PCIR_BAR(1); | ||||
rc = map_bar(ntb, &ntb->bar_info[NTB_BAR_1]); | rc = map_bar(ntb, &ntb->bar_info[NTB_BAR_1]); | ||||
if (rc != 0) | if (rc != 0) | ||||
goto out; | goto out; | ||||
ntb->bar_info[NTB_BAR_1].xlat_off = AMD_BAR1XLAT_OFFSET; | ntb->bar_info[NTB_BAR_1].xlat_off = AMD_BAR1XLAT_OFFSET; | ||||
ntb->bar_info[NTB_BAR_1].limit_off = AMD_BAR1LMT_OFFSET; | ntb->bar_info[NTB_BAR_1].limit_off = AMD_BAR1LMT_OFFSET; | ||||
/* Memory Window 1 BAR - BAR 2&3 */ | /* Memory Window 1 BAR - BAR 2&3 */ | ||||
Show All 31 Lines | if (bar_info->pci_resource != NULL) | ||||
bus_release_resource(ntb->device, SYS_RES_MEMORY, | bus_release_resource(ntb->device, SYS_RES_MEMORY, | ||||
bar_info->pci_resource_id, bar_info->pci_resource); | bar_info->pci_resource_id, bar_info->pci_resource); | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
amd_ntb_probe(device_t device) | amd_ntb_probe(device_t device) | ||||
{ | { | ||||
struct amd_ntb_softc *ntb = device_get_softc(device); | |||||
const struct pci_device_table *tbl; | const struct pci_device_table *tbl; | ||||
tbl = PCI_MATCH(device, amd_ntb_devs); | tbl = PCI_MATCH(device, amd_ntb_devs); | ||||
if (tbl == NULL) | if (tbl == NULL) | ||||
return (ENXIO); | return (ENXIO); | ||||
ntb->hw_info = (struct amd_ntb_hw_info *)tbl->driver_data; | |||||
ntb->spad_count = ntb->hw_info->spad_count; | |||||
device_set_desc(device, tbl->descr); | device_set_desc(device, tbl->descr); | ||||
return (BUS_PROBE_GENERIC); | return (BUS_PROBE_GENERIC); | ||||
} | } | ||||
static int | static int | ||||
amd_ntb_attach(device_t device) | amd_ntb_attach(device_t device) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 94 Lines • Show Last 20 Lines |