Date: Wed, 14 Oct 2015 23:48:03 +0000 (UTC) From: "Conrad E. Meyer" <cem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r289347 - head/sys/dev/ntb/ntb_hw Message-ID: <201510142348.t9ENm3V0050817@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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); } /**
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201510142348.t9ENm3V0050817>