From owner-svn-src-all@freebsd.org Wed Oct 14 02:14:47 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 3EEDDA12956; Wed, 14 Oct 2015 02:14:47 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 143BD1174; Wed, 14 Oct 2015 02:14:46 +0000 (UTC) (envelope-from cem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t9E2EklY059364; Wed, 14 Oct 2015 02:14:46 GMT (envelope-from cem@FreeBSD.org) Received: (from cem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t9E2EjPe059361; Wed, 14 Oct 2015 02:14:45 GMT (envelope-from cem@FreeBSD.org) Message-Id: <201510140214.t9E2EjPe059361@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: cem set sender to cem@FreeBSD.org using -f From: "Conrad E. Meyer" Date: Wed, 14 Oct 2015 02:14:45 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r289281 - in head/sys/dev/ntb: if_ntb ntb_hw X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 14 Oct 2015 02:14:47 -0000 Author: cem Date: Wed Oct 14 02:14:45 2015 New Revision: 289281 URL: https://svnweb.freebsd.org/changeset/base/289281 Log: NTB: MFV e8aeb60c: Disable interrupts and poll under high load Authored by: Jon Mason Obtained from: Linux (Dual BSD/GPL driver) Sponsored by: EMC / Isilon Storage Division Modified: head/sys/dev/ntb/if_ntb/if_ntb.c head/sys/dev/ntb/ntb_hw/ntb_hw.c head/sys/dev/ntb/ntb_hw/ntb_hw.h Modified: head/sys/dev/ntb/if_ntb/if_ntb.c ============================================================================== --- head/sys/dev/ntb/if_ntb/if_ntb.c Wed Oct 14 02:14:15 2015 (r289280) +++ head/sys/dev/ntb/if_ntb/if_ntb.c Wed Oct 14 02:14:45 2015 (r289281) @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -249,9 +250,8 @@ static int ntb_process_tx(struct ntb_tra static void ntb_tx_copy_task(struct ntb_transport_qp *qp, struct ntb_queue_entry *entry, void *offset); static void ntb_qp_full(void *arg); -static void ntb_transport_rxc_db(void *data, int db_num); +static int ntb_transport_rxc_db(void *arg, int dummy); static void ntb_rx_pendq_full(void *arg); -static void ntb_transport_rx(struct ntb_transport_qp *qp); static int ntb_process_rxc(struct ntb_transport_qp *qp); static void ntb_rx_copy_task(struct ntb_transport_qp *qp, struct ntb_queue_entry *entry, void *offset); @@ -840,24 +840,17 @@ ntb_qp_full(void *arg) /* Transport Rx */ static void -ntb_transport_rxc_db(void *data, int db_num) -{ - struct ntb_transport_qp *qp = data; - - ntb_transport_rx(qp); -} - -static void ntb_rx_pendq_full(void *arg) { CTR0(KTR_NTB, "RX: ntb_rx_pendq_full callout"); - ntb_transport_rx(arg); + ntb_transport_rxc_db(arg, 0); } -static void -ntb_transport_rx(struct ntb_transport_qp *qp) +static int +ntb_transport_rxc_db(void *arg, int dummy __unused) { + struct ntb_transport_qp *qp = arg; uint64_t i; int rc; @@ -867,7 +860,7 @@ ntb_transport_rx(struct ntb_transport_qp */ mtx_lock(&qp->transport->rx_lock); CTR0(KTR_NTB, "RX: transport_rx"); - for (i = 0; i < qp->rx_max_entry; i++) { + for (i = 0; i < MIN(qp->rx_max_entry, INT_MAX); i++) { rc = ntb_process_rxc(qp); if (rc != 0) { CTR0(KTR_NTB, "RX: process_rxc failed"); @@ -875,6 +868,8 @@ ntb_transport_rx(struct ntb_transport_qp } } mtx_unlock(&qp->transport->rx_lock); + + return ((int)i); } static int Modified: head/sys/dev/ntb/ntb_hw/ntb_hw.c ============================================================================== --- head/sys/dev/ntb/ntb_hw/ntb_hw.c Wed Oct 14 02:14:15 2015 (r289280) +++ head/sys/dev/ntb/ntb_hw/ntb_hw.c Wed Oct 14 02:14:45 2015 (r289281) @@ -109,6 +109,7 @@ struct ntb_db_cb { unsigned int db_num; void *data; struct ntb_softc *ntb; + struct callout irq_work; }; struct ntb_softc { @@ -204,6 +205,9 @@ static void handle_soc_irq(void *arg); 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 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, int num_vectors); static void ntb_free_callbacks(struct ntb_softc *ntb); static struct ntb_hw_info *ntb_get_device_info(uint32_t device_id); @@ -580,6 +584,26 @@ ntb_teardown_interrupts(struct ntb_softc } static void +mask_ldb_interrupt(struct ntb_softc *ntb, unsigned int idx) +{ + unsigned long mask; + + mask = ntb_reg_read(2, ntb->reg_ofs.ldb_mask); + mask |= 1 << (idx * ntb->bits_per_vector); + ntb_reg_write(2, ntb->reg_ofs.ldb_mask, mask); +} + +static void +unmask_ldb_interrupt(struct ntb_softc *ntb, unsigned int idx) +{ + unsigned long mask; + + mask = ntb_reg_read(2, ntb->reg_ofs.ldb_mask); + mask &= ~(1 << (idx * ntb->bits_per_vector)); + ntb_reg_write(2, ntb->reg_ofs.ldb_mask, mask); +} + +static void handle_soc_irq(void *arg) { struct ntb_db_cb *db_cb = arg; @@ -587,8 +611,10 @@ handle_soc_irq(void *arg) ntb_reg_write(8, ntb->reg_ofs.ldb, (uint64_t) 1 << db_cb->db_num); - if (db_cb->callback != NULL) - db_cb->callback(db_cb->data, db_cb->db_num); + if (db_cb->callback != NULL) { + mask_ldb_interrupt(ntb, db_cb->db_num); + callout_reset(&db_cb->irq_work, 0, ntb_irq_work, db_cb); + } } static void @@ -607,8 +633,10 @@ handle_xeon_irq(void *arg) ((1 << ntb->bits_per_vector) - 1) << (db_cb->db_num * ntb->bits_per_vector)); - if (db_cb->callback != NULL) - db_cb->callback(db_cb->data, db_cb->db_num); + if (db_cb->callback != NULL) { + mask_ldb_interrupt(ntb, db_cb->db_num); + callout_reset(&db_cb->irq_work, 0, ntb_irq_work, db_cb); + } } /* Since we do not have a HW doorbell in SOC, this is only used in JF/JT */ @@ -1191,6 +1219,25 @@ ntb_unregister_event_callback(struct ntb ntb->event_cb = NULL; } +static void +ntb_irq_work(void *arg) +{ + struct ntb_db_cb *db_cb = arg; + struct ntb_softc *ntb; + int rc; + + rc = db_cb->callback(db_cb->data, db_cb->db_num); + /* Poll if forward progress was made. */ + if (rc != 0) { + callout_reset(&db_cb->irq_work, 0, ntb_irq_work, db_cb); + return; + } + + /* Unmask interrupt if no progress was made. */ + ntb = db_cb->ntb; + unmask_ldb_interrupt(ntb, db_cb->db_num); +} + /** * ntb_register_db_callback() - register a callback for doorbell interrupt * @ntb: pointer to ntb_softc instance @@ -1208,7 +1255,6 @@ int ntb_register_db_callback(struct ntb_softc *ntb, unsigned int idx, void *data, ntb_db_callback func) { - uint16_t mask; if (idx >= ntb->allocated_interrupts || ntb->db_cb[idx].callback) { device_printf(ntb->device, "Invalid Index.\n"); @@ -1217,11 +1263,9 @@ ntb_register_db_callback(struct ntb_soft ntb->db_cb[idx].callback = func; ntb->db_cb[idx].data = data; + callout_init(&ntb->db_cb[idx].irq_work, 1); - /* unmask interrupt */ - mask = ntb_reg_read(2, ntb->reg_ofs.ldb_mask); - mask &= ~(1 << (idx * ntb->bits_per_vector)); - ntb_reg_write(2, ntb->reg_ofs.ldb_mask, mask); + unmask_ldb_interrupt(ntb, idx); return (0); } @@ -1237,15 +1281,13 @@ ntb_register_db_callback(struct ntb_soft void ntb_unregister_db_callback(struct ntb_softc *ntb, unsigned int idx) { - unsigned long mask; if (idx >= ntb->allocated_interrupts || !ntb->db_cb[idx].callback) return; - mask = ntb_reg_read(2, ntb->reg_ofs.ldb_mask); - mask |= 1 << (idx * ntb->bits_per_vector); - ntb_reg_write(2, ntb->reg_ofs.ldb_mask, mask); + mask_ldb_interrupt(ntb, idx); + callout_drain(&ntb->db_cb[idx].irq_work); ntb->db_cb[idx].callback = NULL; } Modified: head/sys/dev/ntb/ntb_hw/ntb_hw.h ============================================================================== --- head/sys/dev/ntb/ntb_hw/ntb_hw.h Wed Oct 14 02:14:15 2015 (r289280) +++ head/sys/dev/ntb/ntb_hw/ntb_hw.h Wed Oct 14 02:14:45 2015 (r289281) @@ -46,7 +46,7 @@ enum ntb_hw_event { SYSCTL_DECL(_hw_ntb); -typedef void (*ntb_db_callback)(void *data, int db_num); +typedef int (*ntb_db_callback)(void *data, int db_num); typedef void (*ntb_event_callback)(void *data, enum ntb_hw_event event); int ntb_register_event_callback(struct ntb_softc *ntb, ntb_event_callback func);