From owner-svn-src-all@FreeBSD.ORG Wed Nov 26 20:19:37 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id CBDD1AC5; Wed, 26 Nov 2014 20:19:37 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::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 ACC67C64; Wed, 26 Nov 2014 20:19:37 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id sAQKJbxj043562; Wed, 26 Nov 2014 20:19:37 GMT (envelope-from alfred@FreeBSD.org) Received: (from alfred@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id sAQKJaw4043557; Wed, 26 Nov 2014 20:19:36 GMT (envelope-from alfred@FreeBSD.org) Message-Id: <201411262019.sAQKJaw4043557@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: alfred set sender to alfred@FreeBSD.org using -f From: Alfred Perlstein Date: Wed, 26 Nov 2014 20:19:36 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r275136 - in head/sys: dev/e1000 dev/ixgbe kern sys 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.18-1 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, 26 Nov 2014 20:19:38 -0000 Author: alfred Date: Wed Nov 26 20:19:36 2014 New Revision: 275136 URL: https://svnweb.freebsd.org/changeset/base/275136 Log: Make igb and ixgbe check tunables at probe time. This allows one to make a kernel module to tune the number of queues before the driver loads. This is needed so that a module at SI_SUB_CPU can set tunables for these drivers to take. Otherwise getenv is called too early by the TUNABLE macros. Reviewed by: smh Phabric: https://reviews.freebsd.org/D1149 Modified: head/sys/dev/e1000/if_igb.c head/sys/dev/ixgbe/ixgbe.c head/sys/kern/subr_bus.c head/sys/sys/bus.h Modified: head/sys/dev/e1000/if_igb.c ============================================================================== --- head/sys/dev/e1000/if_igb.c Wed Nov 26 18:03:25 2014 (r275135) +++ head/sys/dev/e1000/if_igb.c Wed Nov 26 20:19:36 2014 (r275136) @@ -188,6 +188,7 @@ static char *igb_strings[] = { /********************************************************************* * Function prototypes *********************************************************************/ +static int igb_per_unit_num_queues(SYSCTL_HANDLER_ARGS); static int igb_probe(device_t); static int igb_attach(device_t); static int igb_detach(device_t); @@ -493,6 +494,11 @@ igb_attach(device_t dev) OID_AUTO, "nvm", CTLTYPE_INT|CTLFLAG_RW, adapter, 0, igb_sysctl_nvm_info, "I", "NVM Information"); + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "num_queues", CTLTYPE_INT | CTLFLAG_RD, + adapter, 0, igb_per_unit_num_queues, "I", "Number of Queues"); + igb_set_sysctl_value(adapter, "enable_aim", "Interrupt Moderation", &adapter->enable_aim, igb_enable_aim); @@ -2831,6 +2837,7 @@ igb_setup_msix(struct adapter *adapter) { device_t dev = adapter->dev; int bar, want, queues, msgs, maxqueues; + int n_queues; /* tuneable override */ if (igb_enable_msix == 0) @@ -2858,8 +2865,18 @@ igb_setup_msix(struct adapter *adapter) goto msi; } - /* Figure out a reasonable auto config value */ - queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus; + n_queues = 0; + /* try more specific tunable, then global, then finally default to boot time tunable if set. */ + if (device_getenv_int(dev, "num_queues", &n_queues) != 0) { + device_printf(dev, "using specific tunable num_queues=%d", n_queues); + } else if (TUNABLE_INT_FETCH("hw.igb.num_queues", &n_queues) != 0) { + if (igb_num_queues != n_queues) { + device_printf(dev, "using global tunable hw.igb.num_queues=%d", n_queues); + igb_num_queues = n_queues; + } + } else { + n_queues = igb_num_queues; + } #ifdef RSS /* If we're doing RSS, clamp at the number of RSS buckets */ @@ -2867,10 +2884,12 @@ igb_setup_msix(struct adapter *adapter) queues = rss_getnumbuckets(); #endif - - /* Manual override */ - if (igb_num_queues != 0) - queues = igb_num_queues; + if (n_queues != 0) { + queues = n_queues; + } else { + /* Figure out a reasonable auto config value */ + queues = (mp_ncpus > (msgs-1)) ? (msgs-1) : mp_ncpus; + } /* Sanity check based on HW */ switch (adapter->hw.mac.type) { @@ -2893,12 +2912,17 @@ igb_setup_msix(struct adapter *adapter) maxqueues = 1; break; } - if (queues > maxqueues) + if (queues > maxqueues) { + device_printf(adapter->dev, "requested %d queues, but max for this adapter is %d\n", + queues, maxqueues); queues = maxqueues; - - /* Manual override */ - if (igb_num_queues != 0) - queues = igb_num_queues; + } else if (queues == 0) { + queues = 1; + } else if (queues < 0) { + device_printf(adapter->dev, "requested %d queues, but min for this adapter is %d\n", + queues, 1); + queues = 1; + } /* ** One vector (RX/TX pair) per queue @@ -6384,3 +6408,14 @@ igb_sysctl_eee(SYSCTL_HANDLER_ARGS) IGB_CORE_UNLOCK(adapter); return (0); } + +static int +igb_per_unit_num_queues(SYSCTL_HANDLER_ARGS) +{ + struct adapter *adapter; + + adapter = (struct adapter *) arg1; + + return sysctl_handle_int(oidp, &adapter->num_queues, 0, req); +} + Modified: head/sys/dev/ixgbe/ixgbe.c ============================================================================== --- head/sys/dev/ixgbe/ixgbe.c Wed Nov 26 18:03:25 2014 (r275135) +++ head/sys/dev/ixgbe/ixgbe.c Wed Nov 26 20:19:36 2014 (r275136) @@ -103,6 +103,7 @@ static char *ixgbe_strings[] = { /********************************************************************* * Function prototypes *********************************************************************/ +static int ixgbe_per_unit_num_queues(SYSCTL_HANDLER_ARGS); static int ixgbe_probe(device_t); static int ixgbe_attach(device_t); static int ixgbe_detach(device_t); @@ -475,6 +476,11 @@ ixgbe_attach(device_t dev) SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "num_queues", CTLTYPE_INT | CTLFLAG_RD, + adapter, 0, ixgbe_per_unit_num_queues, "I", "Number of Queues"); + + SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "ts", CTLTYPE_INT | CTLFLAG_RW, adapter, 0, ixgbe_set_thermal_test, "I", "Thermal Test"); @@ -2516,6 +2522,7 @@ ixgbe_setup_msix(struct adapter *adapter { device_t dev = adapter->dev; int rid, want, queues, msgs; + int n_queues; /* Override by tuneable */ if (ixgbe_enable_msix == 0) @@ -2548,15 +2555,29 @@ ixgbe_setup_msix(struct adapter *adapter queues = rss_getnumbuckets(); #endif - if (ixgbe_num_queues != 0) - queues = ixgbe_num_queues; + /* try more specific tunable, then global, then finally default to boot time tunable if set. */ + if (device_getenv_int(dev, "num_queues", &n_queues) != 0) { + device_printf(dev, "using specific tunable numqueues=%d", n_queues); + } else if (TUNABLE_INT_FETCH("hw.ix.num_queues", &n_queues) != 0) { + if (ixgbe_num_queues != n_queues) { + device_printf(dev, "using global tunable num_queues=%d", n_queues); + ixgbe_num_queues = n_queues; + } + } else { + n_queues = ixgbe_num_queues; + } + + if (n_queues < 0) { + device_printf(dev, "tunable < 0, resetting to default"); + n_queues = 0; + } + + if (n_queues != 0) + queues = n_queues; /* Set max queues to 8 when autoconfiguring */ else if ((ixgbe_num_queues == 0) && (queues > 8)) queues = 8; - /* reflect correct sysctl value */ - ixgbe_num_queues = queues; - /* ** Want one vector (RX/TX pair) per queue ** plus an additional for Link. @@ -5943,6 +5964,16 @@ ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS) return error; } +static int +ixgbe_per_unit_num_queues(SYSCTL_HANDLER_ARGS) +{ + struct adapter *adapter; + + adapter = (struct adapter *) arg1; + + return sysctl_handle_int(oidp, &adapter->num_queues, 0, req); +} + /* ** Control link advertise speed: ** 1 - advertise only 1G Modified: head/sys/kern/subr_bus.c ============================================================================== --- head/sys/kern/subr_bus.c Wed Nov 26 18:03:25 2014 (r275135) +++ head/sys/kern/subr_bus.c Wed Nov 26 20:19:36 2014 (r275136) @@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include #include @@ -5031,3 +5033,18 @@ bus_free_resource(device_t dev, int type return (0); return (bus_release_resource(dev, type, rman_get_rid(r), r)); } + +int +device_getenv_int(device_t dev, const char *knob, int *iptr) +{ + char env[128]; + int sz; + + sz = snprintf(env, sizeof(env), "hw.%s.%d.%s", device_get_name(dev), device_get_unit(dev), knob); + if (sz >= sizeof(env)) { + /* XXX: log? return error? bump sysctl error? */ + log(LOG_ERR, "device_getenv_int: knob too long: '%s'", knob); + return 0; + } + return (getenv_int(env, iptr)); +} Modified: head/sys/sys/bus.h ============================================================================== --- head/sys/sys/bus.h Wed Nov 26 18:03:25 2014 (r275135) +++ head/sys/sys/bus.h Wed Nov 26 20:19:36 2014 (r275136) @@ -449,6 +449,7 @@ const char *device_get_nameunit(device_t void *device_get_softc(device_t dev); device_state_t device_get_state(device_t dev); int device_get_unit(device_t dev); +int device_getenv_int(device_t dev, const char *knob, int *iptr); struct sysctl_ctx_list *device_get_sysctl_ctx(device_t dev); struct sysctl_oid *device_get_sysctl_tree(device_t dev); int device_is_alive(device_t dev); /* did probe succeed? */