svn commit: r289347 - head/sys/dev/ntb/ntb_hw
Conrad E. Meyer
cem at FreeBSD.org
Wed Oct 14 23:48:05 UTC 2015
Author: cem
Date: Wed Oct 14 23:48:03 2015
New Revision: 289347
URL: https://svnweb.freebsd.org/changeset/base/289347
Log:
NTB: Abstract doorbell register access
The doorbell registers (and associated mask) are 16-bit on Xeon but
64-bit on SoC. Abstract IO access to doorbell registers with
'db_ioread' and 'db_iowrite' (names and idea borrowed from the dual
BSD/GPL Linux driver).
Sponsored by: EMC / Isilon Storage Division
Modified:
head/sys/dev/ntb/ntb_hw/ntb_hw.c
Modified: head/sys/dev/ntb/ntb_hw/ntb_hw.c
==============================================================================
--- head/sys/dev/ntb/ntb_hw/ntb_hw.c Wed Oct 14 23:47:52 2015 (r289346)
+++ head/sys/dev/ntb/ntb_hw/ntb_hw.c Wed Oct 14 23:48:03 2015 (r289347)
@@ -211,6 +211,8 @@ static void handle_xeon_irq(void *arg);
static void handle_xeon_event_irq(void *arg);
static void ntb_handle_legacy_interrupt(void *arg);
static void ntb_irq_work(void *arg);
+static uint64_t db_ioread(struct ntb_softc *, uint32_t regoff);
+static void db_iowrite(struct ntb_softc *, uint32_t regoff, uint64_t val);
static void mask_ldb_interrupt(struct ntb_softc *ntb, unsigned int idx);
static void unmask_ldb_interrupt(struct ntb_softc *ntb, unsigned int idx);
static int ntb_create_callbacks(struct ntb_softc *ntb, uint32_t num_vectors);
@@ -601,18 +603,19 @@ static int
ntb_setup_interrupts(struct ntb_softc *ntb)
{
uint32_t desired_vectors, num_vectors;
+ uint64_t mask;
int rc;
ntb->allocated_interrupts = 0;
+
/*
* On SOC, disable all interrupts. On XEON, disable all but Link
* Interrupt. The rest will be unmasked as callbacks are registered.
*/
- if (ntb->type == NTB_SOC)
- ntb_reg_write(8, ntb->reg_ofs.ldb_mask, ~0);
- else
- ntb_reg_write(2, ntb->reg_ofs.ldb_mask,
- (uint16_t) ~(1 << XEON_LINK_DB));
+ mask = 0;
+ if (ntb->type == NTB_XEON)
+ mask = (1 << XEON_LINK_DB);
+ db_iowrite(ntb, ntb->reg_ofs.ldb_mask, ~mask);
num_vectors = desired_vectors = MIN(pci_msix_count(ntb->device),
ntb->limits.max_db_bits);
@@ -700,24 +703,53 @@ ntb_teardown_interrupts(struct ntb_softc
pci_release_msi(ntb->device);
}
+/*
+ * Doorbell register and mask are 64-bit on SoC, 16-bit on Xeon. Abstract it
+ * out to make code clearer.
+ */
+static uint64_t
+db_ioread(struct ntb_softc *ntb, uint32_t regoff)
+{
+
+ if (ntb->type == NTB_SOC)
+ return (ntb_reg_read(8, regoff));
+
+ KASSERT(ntb->type == NTB_XEON, ("bad ntb type"));
+
+ return (ntb_reg_read(2, regoff));
+}
+
+static void
+db_iowrite(struct ntb_softc *ntb, uint32_t regoff, uint64_t val)
+{
+
+ if (ntb->type == NTB_SOC) {
+ ntb_reg_write(8, regoff, val);
+ return;
+ }
+
+ KASSERT(ntb->type == NTB_XEON, ("bad ntb type"));
+ ntb_reg_write(2, regoff, (uint16_t)val);
+}
+
static void
mask_ldb_interrupt(struct ntb_softc *ntb, unsigned int idx)
{
- unsigned long mask;
+ uint64_t mask;
- mask = ntb_reg_read(2, ntb->reg_ofs.ldb_mask);
+ mask = db_ioread(ntb, ntb->reg_ofs.ldb_mask);
mask |= 1 << (idx * ntb->bits_per_vector);
- ntb_reg_write(2, ntb->reg_ofs.ldb_mask, mask);
+ db_iowrite(ntb, ntb->reg_ofs.ldb_mask, mask);
}
static void
unmask_ldb_interrupt(struct ntb_softc *ntb, unsigned int idx)
{
- unsigned long mask;
+ uint64_t mask;
- mask = ntb_reg_read(2, ntb->reg_ofs.ldb_mask);
+ mask = db_ioread(ntb, ntb->reg_ofs.ldb_mask);
mask &= ~(1 << (idx * ntb->bits_per_vector));
- ntb_reg_write(2, ntb->reg_ofs.ldb_mask, mask);
+ db_iowrite(ntb, ntb->reg_ofs.ldb_mask, mask);
}
static void
@@ -726,7 +758,7 @@ handle_soc_irq(void *arg)
struct ntb_db_cb *db_cb = arg;
struct ntb_softc *ntb = db_cb->ntb;
- ntb_reg_write(8, ntb->reg_ofs.ldb, (uint64_t) 1 << db_cb->db_num);
+ db_iowrite(ntb, ntb->reg_ofs.ldb, (uint64_t) 1 << db_cb->db_num);
if (db_cb->callback != NULL) {
mask_ldb_interrupt(ntb, db_cb->db_num);
@@ -746,7 +778,7 @@ handle_xeon_irq(void *arg)
* vectors, with the 4th having a single bit for link
* interrupts.
*/
- ntb_reg_write(2, ntb->reg_ofs.ldb,
+ db_iowrite(ntb, ntb->reg_ofs.ldb,
((1 << ntb->bits_per_vector) - 1) <<
(db_cb->db_num * ntb->bits_per_vector));
@@ -768,40 +800,31 @@ handle_xeon_event_irq(void *arg)
device_printf(ntb->device, "Error determining link status\n");
/* bit 15 is always the link bit */
- ntb_reg_write(2, ntb->reg_ofs.ldb, 1 << XEON_LINK_DB);
+ db_iowrite(ntb, ntb->reg_ofs.ldb, 1 << XEON_LINK_DB);
}
static void
ntb_handle_legacy_interrupt(void *arg)
{
struct ntb_softc *ntb = arg;
- unsigned int i = 0;
- uint64_t ldb64;
- uint16_t ldb16;
-
- if (ntb->type == NTB_SOC) {
- ldb64 = ntb_reg_read(8, ntb->reg_ofs.ldb);
+ unsigned int i;
+ uint64_t ldb;
- while (ldb64) {
- i = ffs(ldb64);
- ldb64 &= ldb64 - 1;
- handle_soc_irq(&ntb->db_cb[i]);
- }
- } else {
- ldb16 = ntb_reg_read(2, ntb->reg_ofs.ldb);
+ ldb = db_ioread(ntb, ntb->reg_ofs.ldb);
- if ((ldb16 & XEON_DB_HW_LINK) != 0) {
- handle_xeon_event_irq(ntb);
- ldb16 &= ~XEON_DB_HW_LINK;
- }
+ if (ntb->type == NTB_XEON && (ldb & XEON_DB_HW_LINK) != 0) {
+ handle_xeon_event_irq(ntb);
+ ldb &= ~XEON_DB_HW_LINK;
+ }
- while (ldb16 != 0) {
- i = ffs(ldb16);
- ldb16 &= ldb16 - 1;
+ while (ldb != 0) {
+ i = ffs(ldb);
+ ldb &= ldb - 1;
+ if (ntb->type == NTB_SOC)
+ handle_soc_irq(&ntb->db_cb[i]);
+ else
handle_xeon_irq(&ntb->db_cb[i]);
- }
}
-
}
static int
@@ -1669,25 +1692,24 @@ ntb_set_mw_addr(struct ntb_softc *ntb, u
*
* This function allows triggering of a doorbell on the secondary/external
* side that will initiate an interrupt on the remote host
- *
- * RETURNS: An appropriate ERRNO error value on error, or zero for success.
*/
void
ntb_ring_doorbell(struct ntb_softc *ntb, unsigned int db)
{
+ uint64_t bit;
if (ntb->type == NTB_SOC)
- ntb_reg_write(8, ntb->reg_ofs.rdb, (uint64_t) 1 << db);
- else {
- if (HAS_FEATURE(NTB_REGS_THRU_MW))
- ntb_mw_write(2, XEON_SHADOW_PDOORBELL_OFFSET,
- ((1 << ntb->bits_per_vector) - 1) <<
- (db * ntb->bits_per_vector));
- else
- ntb_reg_write(2, ntb->reg_ofs.rdb,
- ((1 << ntb->bits_per_vector) - 1) <<
- (db * ntb->bits_per_vector));
+ bit = 1 << db;
+ else
+ bit = ((1 << ntb->bits_per_vector) - 1) <<
+ (db * ntb->bits_per_vector);
+
+ if (HAS_FEATURE(NTB_REGS_THRU_MW)) {
+ ntb_mw_write(2, XEON_SHADOW_PDOORBELL_OFFSET, bit);
+ return;
}
+
+ db_iowrite(ntb, ntb->reg_ofs.rdb, bit);
}
/**
More information about the svn-src-all
mailing list