summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcem <cem@FreeBSD.org>2015-11-25 01:59:08 +0000
committercem <cem@FreeBSD.org>2015-11-25 01:59:08 +0000
commitdc18eb23e2b461aebbacdff96e2349bca5a82de6 (patch)
tree053988cb8c8aeaf621a0944934fe87e612709240
parent23b77bcd73f512b37234c155ef6d9546eb5197a3 (diff)
downloadFreeBSD-src-dc18eb23e2b461aebbacdff96e2349bca5a82de6.zip
FreeBSD-src-dc18eb23e2b461aebbacdff96e2349bca5a82de6.tar.gz
NTB: WC/WB isn't enough; set MMR region as UC
And expose vm_memattr_t of current mapping to consumers (as well as the ability to change it to one of UC, WB, WC). After short discussion with: jhb (but no review) Sponsored by: EMC / Isilon Storage Division
-rw-r--r--sys/dev/ntb/ntb_hw/ntb_hw.c61
-rw-r--r--sys/dev/ntb/ntb_hw/ntb_hw.h4
2 files changed, 37 insertions, 28 deletions
diff --git a/sys/dev/ntb/ntb_hw/ntb_hw.c b/sys/dev/ntb/ntb_hw/ntb_hw.c
index c134acd..f71d9e4 100644
--- a/sys/dev/ntb/ntb_hw/ntb_hw.c
+++ b/sys/dev/ntb/ntb_hw/ntb_hw.c
@@ -114,7 +114,7 @@ struct ntb_pci_bar_info {
vm_paddr_t pbase;
caddr_t vbase;
vm_size_t size;
- bool mapped_wc : 1;
+ vm_memattr_t map_mode;
/* Configuration register offsets */
uint32_t psz_off;
@@ -270,7 +270,8 @@ static inline bool bar_is_64bit(struct ntb_softc *, enum ntb_bar);
static inline void bar_get_xlat_params(struct ntb_softc *, enum ntb_bar,
uint32_t *base, uint32_t *xlat, uint32_t *lmt);
static int ntb_map_pci_bars(struct ntb_softc *ntb);
-static int ntb_mw_set_wc_internal(struct ntb_softc *, unsigned idx, bool wc);
+static int ntb_mw_set_wc_internal(struct ntb_softc *, unsigned idx,
+ vm_memattr_t);
static void print_map_success(struct ntb_softc *, struct ntb_pci_bar_info *,
const char *);
static int map_mmr_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar);
@@ -718,6 +719,7 @@ map_mmr_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar)
return (ENXIO);
save_bar_parameters(bar);
+ bar->map_mode = VM_MEMATTR_UNCACHEABLE;
print_map_success(ntb, bar, "mmr");
return (0);
}
@@ -726,6 +728,7 @@ static int
map_memory_window_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar)
{
int rc;
+ vm_memattr_t mapmode;
uint8_t bar_size_bits = 0;
bar->pci_resource = bus_alloc_resource_any(ntb->device, SYS_RES_MEMORY,
@@ -771,29 +774,34 @@ map_memory_window_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar)
save_bar_parameters(bar);
}
+ bar->map_mode = VM_MEMATTR_UNCACHEABLE;
print_map_success(ntb, bar, "mw");
- if (g_ntb_enable_wc == 0)
- return (0);
/* Mark bar region as write combining to improve performance. */
- rc = pmap_change_attr((vm_offset_t)bar->vbase, bar->size,
- VM_MEMATTR_WRITE_COMBINING);
+ mapmode = VM_MEMATTR_WRITE_COMBINING;
+ if (g_ntb_enable_wc == 0)
+ mapmode = VM_MEMATTR_WRITE_BACK;
+
+ rc = pmap_change_attr((vm_offset_t)bar->vbase, bar->size, mapmode);
if (rc == 0) {
- bar->mapped_wc = true;
+ bar->map_mode = mapmode;
device_printf(ntb->device,
"Marked BAR%d v:[%p-%p] p:[%p-%p] as "
- "WRITE_COMBINING.\n",
+ "%s.\n",
PCI_RID2BAR(bar->pci_resource_id), bar->vbase,
(char *)bar->vbase + bar->size - 1,
- (void *)bar->pbase, (void *)(bar->pbase + bar->size - 1));
+ (void *)bar->pbase, (void *)(bar->pbase + bar->size - 1),
+ (mapmode == VM_MEMATTR_WRITE_COMBINING) ? "WRITE_COMBINING"
+ : "WRITE_BACK");
} else
device_printf(ntb->device,
"Unable to mark BAR%d v:[%p-%p] p:[%p-%p] as "
- "WRITE_COMBINING: %d\n",
+ "%s: %d\n",
PCI_RID2BAR(bar->pci_resource_id), bar->vbase,
(char *)bar->vbase + bar->size - 1,
(void *)bar->pbase, (void *)(bar->pbase + bar->size - 1),
- rc);
+ (mapmode == VM_MEMATTR_WRITE_COMBINING) ? "WRITE_COMBINING"
+ : "WRITE_BACK", rc);
/* Proceed anyway */
return (0);
}
@@ -1272,7 +1280,7 @@ ntb_xeon_init_dev(struct ntb_softc *ntb)
ntb->mw_count;
ntb_printf(2, "Setting up b2b mw idx %d means %u\n",
g_ntb_mw_idx, ntb->b2b_mw_idx);
- rc = ntb_mw_set_wc_internal(ntb, ntb->b2b_mw_idx, false);
+ rc = ntb_mw_set_wc_internal(ntb, ntb->b2b_mw_idx, VM_MEMATTR_UNCACHEABLE);
KASSERT(rc == 0, ("shouldn't fail"));
} else if (HAS_FEATURE(NTB_B2BDOORBELL_BIT14))
/*
@@ -2672,9 +2680,11 @@ ntb_mw_clear_trans(struct ntb_softc *ntb, unsigned mw_idx)
*
* Returns: Zero on success, setting *wc; otherwise an error number (e.g. if
* idx is an invalid memory window).
+ *
+ * Mode is a VM_MEMATTR_* type.
*/
int
-ntb_mw_get_wc(struct ntb_softc *ntb, unsigned idx, bool *wc)
+ntb_mw_get_wc(struct ntb_softc *ntb, unsigned idx, vm_memattr_t *mode)
{
struct ntb_pci_bar_info *bar;
@@ -2683,49 +2693,48 @@ ntb_mw_get_wc(struct ntb_softc *ntb, unsigned idx, bool *wc)
idx = ntb_user_mw_to_idx(ntb, idx);
bar = &ntb->bar_info[ntb_mw_to_bar(ntb, idx)];
- *wc = bar->mapped_wc;
+ *mode = bar->map_mode;
return (0);
}
/*
* ntb_mw_set_wc - Set the write-combine status of a memory window
*
- * If 'wc' matches the current status, this does nothing and succeeds.
+ * If 'mode' matches the current status, this does nothing and succeeds. Mode
+ * is a VM_MEMATTR_* type.
*
* Returns: Zero on success, setting the caching attribute on the virtual
* mapping of the BAR; otherwise an error number (e.g. if idx is an invalid
* memory window, or if changing the caching attribute fails).
*/
int
-ntb_mw_set_wc(struct ntb_softc *ntb, unsigned idx, bool wc)
+ntb_mw_set_wc(struct ntb_softc *ntb, unsigned idx, vm_memattr_t mode)
{
if (idx >= ntb_mw_count(ntb))
return (EINVAL);
idx = ntb_user_mw_to_idx(ntb, idx);
- return (ntb_mw_set_wc_internal(ntb, idx, wc));
+ return (ntb_mw_set_wc_internal(ntb, idx, mode));
}
static int
-ntb_mw_set_wc_internal(struct ntb_softc *ntb, unsigned idx, bool wc)
+ntb_mw_set_wc_internal(struct ntb_softc *ntb, unsigned idx, vm_memattr_t mode)
{
struct ntb_pci_bar_info *bar;
- vm_memattr_t attr;
int rc;
bar = &ntb->bar_info[ntb_mw_to_bar(ntb, idx)];
- if (bar->mapped_wc == wc)
+ if (bar->map_mode == mode)
return (0);
- if (wc)
- attr = VM_MEMATTR_WRITE_COMBINING;
- else
- attr = VM_MEMATTR_DEFAULT;
+ if (mode != VM_MEMATTR_UNCACHEABLE && mode != VM_MEMATTR_DEFAULT &&
+ mode != VM_MEMATTR_WRITE_COMBINING)
+ return (EINVAL);
- rc = pmap_change_attr((vm_offset_t)bar->vbase, bar->size, attr);
+ rc = pmap_change_attr((vm_offset_t)bar->vbase, bar->size, mode);
if (rc == 0)
- bar->mapped_wc = wc;
+ bar->map_mode = mode;
return (rc);
}
diff --git a/sys/dev/ntb/ntb_hw/ntb_hw.h b/sys/dev/ntb/ntb_hw/ntb_hw.h
index e10b94a..c35166c 100644
--- a/sys/dev/ntb/ntb_hw/ntb_hw.h
+++ b/sys/dev/ntb/ntb_hw/ntb_hw.h
@@ -82,8 +82,8 @@ int ntb_mw_get_range(struct ntb_softc *, unsigned mw_idx, vm_paddr_t *base,
int ntb_mw_set_trans(struct ntb_softc *, unsigned mw_idx, bus_addr_t, size_t);
int ntb_mw_clear_trans(struct ntb_softc *, unsigned mw_idx);
-int ntb_mw_get_wc(struct ntb_softc *, unsigned mw_idx, bool *wc);
-int ntb_mw_set_wc(struct ntb_softc *, unsigned mw_idx, bool wc);
+int ntb_mw_get_wc(struct ntb_softc *, unsigned mw_idx, vm_memattr_t *mode);
+int ntb_mw_set_wc(struct ntb_softc *, unsigned mw_idx, vm_memattr_t mode);
uint8_t ntb_get_max_spads(struct ntb_softc *ntb);
int ntb_spad_write(struct ntb_softc *ntb, unsigned int idx, uint32_t val);
OpenPOWER on IntegriCloud