@@ -51,6 +51,7 @@
#include <linux/completion.h>
#include <linux/kref.h>
#include <linux/sched.h>
+#include <linux/moduleparam.h>
#include "qib_common.h"
#include "qib_verbs.h"
@@ -721,7 +722,7 @@ struct qib_devdata {
u64 __iomem *kregend;
/* physical address of chip for io_remap, etc. */
resource_size_t physaddr;
- /* qib_cfgctxts pointers */
+ /* cfgctxts pointers */
struct qib_ctxtdata **rcd; /* Receive Context Data */
/* qib_pportdata, points to array of (physical) port-specific
@@ -1077,6 +1078,114 @@ struct qib_devdata {
struct tasklet_struct error_tasklet;
};
+enum qib_mod_param_t {
+ qib_mod_param_drv,
+ qib_mod_param_unit,
+ qib_mod_param_port
+};
+
+typedef int (*param_set_func_t)(struct qib_devdata *, u8, u64);
+
+struct qib_mod_param {
+ const char *name;
+ enum qib_mod_param_t type;
+ param_set_func_t func;
+ ulong dflt;
+ struct list_head list;
+ struct list_head pport;
+};
+
+extern int qib_set_mod_param(const char *, struct kernel_param *);
+extern int qib_get_mod_param(char *, struct kernel_param *);
+extern u64 qib_read_mod_param(struct qib_mod_param *, u16, u8);
+extern void qib_clean_mod_param(void);
+
+#define MAX_QIB_PARAM_LEN 128
+/**
+ * QIB_MODPARAM_GLOBAL - define a global module parameter
+ * @N: name of the module parameter
+ *
+ * Define a global module parameter for use in multiple files.
+ */
+#define QIB_MODPARAM_GLOBAL(N) \
+extern struct qib_mod_param qmp_##N
+/**
+ * QIB_MODPARAM_DRV - define a driver-scope module parameter
+ * @N: name of the module parameter
+ * @D: default value
+ * @P: visibility in sysfs
+ * @S: description
+ *
+ * Define a driver-scope (global to the driver instance) module
+ * parameter.
+ */
+#define QIB_MODPARAM_DRV(N, D, P, S) \
+ struct qib_mod_param qmp_##N = { \
+ .name = __stringify(N), \
+ .type = qib_mod_param_drv, \
+ .dflt = (ulong)D, \
+ .pport = { NULL, NULL } \
+ }; \
+ module_param_named(N, qmp_##N.dflt, ulong, P); \
+ MODULE_PARM_DESC(N, S " (dflt: " __stringify(D) ")")
+/**
+ * QIB_MODPARAM_UNIT - define a unit-scope module parameter
+ * @N: name of the module parameter
+ * @F: callback function for dynamic value settings
+ * @D: default value
+ * @P: visibility in sysfs
+ * @D: description
+ *
+ * Define a unit-scope module parameter. Unit-scope module
+ * parameters allows specifying individual values for each of the
+ * QIB units.
+ */
+#define QIB_MODPARAM_UNIT(N, F, D, P, S) \
+ struct qib_mod_param qmp_##N = { \
+ .name = __stringify(N), \
+ .func = ((P) & S_IWUGO ? F : NULL), \
+ .type = qib_mod_param_unit, \
+ .dflt = (ulong)D, \
+ .pport = { NULL, NULL } \
+ }; \
+ module_param_call(N, qib_set_mod_param, qib_get_mod_param, \
+ &qmp_##N, (P)); \
+ MODULE_PARM_DESC(N, S " (dflt: " __stringify(D) ")")
+/**
+ * QIB_MODPARAM_PORT - define a port-scope module parameter
+ * @N: name of the module parameter
+ * @F: callback function for dynamic value settings
+ * @D: default value
+ * @P: visibility in sysfs
+ * @D: description
+ *
+ * Define a port-scope module parameter. Port-scope module
+ * parameters allow specifying individual values foe each of the
+ * ports on any of the QIB units.
+ */
+#define QIB_MODPARAM_PORT(N, F, D, P, S) \
+ struct qib_mod_param qmp_##N = { \
+ .name = __stringify(N), \
+ .func = ((P) & S_IWUGO ? F : NULL), \
+ .type = qib_mod_param_port, \
+ .dflt = (ulong)D, \
+ .pport = { NULL, NULL } \
+ }; \
+ module_param_call(N, qib_set_mod_param, qib_get_mod_param, \
+ &qmp_##N, (P)); \
+ MODULE_PARM_DESC(N, S " (dflt: " __stringify(D) ")")
+/**
+ * QIB_MODPARAM_GET - retrieve a module parameter value
+ * @N: name of the module parameter
+ * @U: unit number
+ * @P: port number
+ *
+ * Get the value for the specific unit/port. The macro will return
+ * the correct value regardless of a specific value for the
+ * specified unit/port is present or the default should be used.
+ */
+#define QIB_MODPARAM_GET(N, U, P) qib_read_mod_param(&qmp_##N, U, P)
+
/* hol_state values */
#define QIB_HOL_UP 0
#define QIB_HOL_INIT 1
@@ -1106,6 +1215,7 @@ struct qib_filedata {
};
extern struct list_head qib_dev_list;
+extern struct list_head qib_mod_param_list;
extern spinlock_t qib_devs_lock;
extern struct qib_devdata *qib_lookup(int unit);
extern u32 qib_cpulist_count;
@@ -1437,11 +1547,10 @@ const char *qib_get_unit_name(int unit);
#endif
/* global module parameter variables */
-extern unsigned qib_ibmtu;
-extern ushort qib_cfgctxts;
-extern ushort qib_num_cfg_vls;
+QIB_MODPARAM_GLOBAL(ibmtu);
+QIB_MODPARAM_GLOBAL(cfgctxts);
+QIB_MODPARAM_GLOBAL(krcvqs);
extern ushort qib_mini_init; /* If set, do few (ideally 0) writes to chip */
-extern unsigned qib_n_krcv_queues;
extern unsigned qib_sdma_fetch_arb;
extern unsigned qib_compat_ddr_negotiate;
extern int qib_special_trigger;
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2012 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -42,6 +43,9 @@
#include "qib.h"
+#undef pr_fmt
+#define pr_fmt(fmt) QIB_DRV_NAME " " fmt
+
/*
* The size has to be longer than this string, so we can append
* board/chip information to it in the init code.
@@ -50,11 +54,21 @@ const char ib_qib_version[] = QIB_IDSTR "\n";
DEFINE_SPINLOCK(qib_devs_lock);
LIST_HEAD(qib_dev_list);
+LIST_HEAD(qib_mod_param_list);
DEFINE_MUTEX(qib_mutex); /* general driver use */
-unsigned qib_ibmtu;
-module_param_named(ibmtu, qib_ibmtu, uint, S_IRUGO);
-MODULE_PARM_DESC(ibmtu, "Set max IB MTU (0=2KB, 1=256, 2=512, ... 5=4096");
+/* Per-unit/port module parameter value structure
+ * linked to the qib_mod_param structure - one per
+ * unit/port */
+struct qib_mod_param_pport {
+ struct list_head list;
+ u16 unit;
+ u8 port;
+ u64 value;
+};
+
+QIB_MODPARAM_PORT(ibmtu, NULL, 5, S_IRUGO,
+ "Set max IB MTU (0=2KB, 1=256, 2=512, ... 5=4096");
unsigned qib_compat_ddr_negotiate = 1;
module_param_named(compat_ddr_negotiate, qib_compat_ddr_negotiate, uint,
@@ -88,6 +102,178 @@ const char *qib_get_unit_name(int unit)
return iname;
}
+int qib_set_mod_param(const char *str, struct kernel_param *kp)
+{
+ char *next = (char *)str, *tmp;
+ unsigned long val = 0, dft;
+ u32 unit = 0, port = 0;
+ struct qib_mod_param *param =
+ (struct qib_mod_param *)kp->arg;
+ struct qib_mod_param_pport *pport, *p;
+ int ret = 0;
+
+ if (strlen(str) >= MAX_QIB_PARAM_LEN) {
+ pr_warn("parameter value too long\n");
+ ret = -ENOSPC;
+ goto done;
+ }
+
+ /* qib_dev_list will be empty only when the driver is initially
+ * loading. */
+ if (list_empty(&qib_dev_list) || !param->pport.next)
+ INIT_LIST_HEAD(¶m->pport);
+ tmp = next;
+ dft = simple_strtoul(tmp, &next, 0);
+ if (next == tmp) {
+ pr_warn("invalid parameter value\n");
+ ret = -EINVAL;
+ goto done;
+ }
+ /* clear any previously added port entries */
+ list_for_each_entry_safe(pport, p, ¶m->pport, list) {
+ list_del(&pport->list);
+ kfree(pport);
+ }
+ if (!*next || *next == '\n' || *next == ',')
+ param->dflt = dft;
+ else if (*next && *next == ':')
+ /* no default, rewind the string */
+ next = tmp;
+ else
+ pr_warn("invalid parameter value\n");
+ while (*next && next[1]) {
+ if (*next == ',')
+ tmp = ++next;
+ unit = simple_strtoul(tmp, &next, 0);
+ if (param->type == qib_mod_param_port) {
+ if (next == tmp || !*next || *next != ':') {
+ pr_warn("Invalid unit:port argument at \"%s\".\n",
+ tmp);
+ while (*next && *next++ != ',')
+ ;
+ tmp = next;
+ continue;
+ }
+ tmp = ++next;
+ port = simple_strtoul(tmp, &next, 0);
+ if (!port) {
+ /* port numbers start at 1, 0 is invalid */
+ pr_warn("Invalid argument at \"%s\". Port numbers start at 1.\n",
+ tmp);
+ while (*next && *next++ != ',')
+ ;
+ tmp = next;
+ continue;
+ }
+ }
+ if (next == tmp || *next != '=') {
+ pr_warn("Invalid %s argument at \"%s\".\n",
+ (param->type == qib_mod_param_port ?
+ "port" : "unit"), tmp);
+ while (*next && *next++ != ',')
+ ;
+ tmp = next;
+ continue;
+ }
+ tmp = ++next;
+ val = simple_strtoul(tmp, &next, 0);
+ if (next == tmp) {
+ pr_warn("Invalid value string at \"%s\"\n", tmp);
+ while (*next && *next++ != ',')
+ ;
+ tmp = next;
+ continue;
+ }
+ pport = kzalloc(sizeof(struct qib_mod_param_pport),
+ GFP_KERNEL);
+ if (!pport) {
+ pr_err("no memory for module parameter.\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+ pport->unit = unit;
+ pport->port = port;
+ pport->value = val;
+ list_add_tail(&pport->list, ¶m->pport);
+ if (!*next || *next == '\n')
+ break;
+ tmp = ++next;
+ }
+ /* add parameter to list so it can be cleaned up */
+ if (!param->list.next)
+ list_add(¶m->list, &qib_mod_param_list);
+
+ if (param->func && qib_count_units(NULL, NULL)) {
+ struct qib_devdata *dd;
+ list_for_each_entry(pport, ¶m->pport, list) {
+ param_set_func_t setfunc = param->func;
+ list_for_each_entry(dd, &qib_dev_list, list)
+ if (dd->unit == pport->unit)
+ break;
+ if (!setfunc(dd, pport->port, pport->value))
+ pr_err("Error setting module parameter %s for IB%u:%u",
+ param->name,
+ pport->unit,
+ pport->port);
+ }
+ }
+done:
+ return ret;
+}
+
+int qib_get_mod_param(char *buffer, struct kernel_param *kp)
+{
+ struct qib_mod_param *param =
+ (struct qib_mod_param *)kp->arg;
+ struct qib_mod_param_pport *pport;
+ char *p = buffer;
+ int s = 0;
+
+ s = scnprintf(p, PAGE_SIZE, "%lu", param->dflt);
+ p += s;
+
+ if (param->pport.next)
+ list_for_each_entry(pport, ¶m->pport, list) {
+ *p++ = ',';
+ if (param->type == qib_mod_param_unit)
+ s = scnprintf(p, PAGE_SIZE, "%u=%llu",
+ pport->unit, pport->value);
+ else if (param->type == qib_mod_param_port)
+ s = scnprintf(p, PAGE_SIZE, "%u:%u=%llu",
+ pport->unit, pport->port,
+ pport->value);
+ p += s;
+ }
+ return strlen(buffer);
+}
+
+u64 qib_read_mod_param(struct qib_mod_param *param, u16 unit, u8 port)
+{
+ struct qib_mod_param_pport *pport;
+ u64 ret = param->dflt;
+
+ if (param->type != qib_mod_param_drv)
+ if (param->pport.next && !list_empty(¶m->pport))
+ list_for_each_entry(pport, ¶m->pport, list)
+ if (pport->unit == unit &&
+ pport->port == port)
+ ret = pport->value;
+ return ret;
+}
+
+void qib_clean_mod_param(void)
+{
+ struct qib_mod_param *p;
+ struct qib_mod_param_pport *pp, *pps;
+
+ list_for_each_entry(p, &qib_mod_param_list, list) {
+ list_for_each_entry_safe(pp, pps, &p->pport, list) {
+ list_del(&pp->list);
+ kfree(pp);
+ }
+ }
+}
+
/*
* Return count of units with at least one port ACTIVE.
*/
@@ -618,7 +804,8 @@ int qib_set_mtu(struct qib_pportdata *ppd, u16 arg)
ret = -EINVAL;
goto bail;
}
- chk = ib_mtu_enum_to_int(qib_ibmtu);
+ chk = ib_mtu_enum_to_int(
+ QIB_MODPARAM_GET(ibmtu, ppd->dd->unit, ppd->port));
if (chk > 0 && arg > chk) {
ret = -EINVAL;
goto bail;
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation.
- * All rights reserved.
+ * Copyright (c) 2012 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -2062,9 +2062,10 @@ qib_6120_get_msgheader(struct qib_devdata *dd, __le32 *rhf_addr)
static void qib_6120_config_ctxts(struct qib_devdata *dd)
{
+ u32 nkrcvqs = QIB_MODPARAM_GET(krcvqs, dd->unit, 0);
dd->ctxtcnt = qib_read_kreg32(dd, kr_portcnt);
- if (qib_n_krcv_queues > 1) {
- dd->first_user_ctxt = qib_n_krcv_queues * dd->num_pports;
+ if (nkrcvqs > 1) {
+ dd->first_user_ctxt = nkrcvqs * dd->num_pports;
if (dd->first_user_ctxt > dd->ctxtcnt)
dd->first_user_ctxt = dd->ctxtcnt;
dd->qpn_mask = dd->first_user_ctxt <= 2 ? 2 : 6;
@@ -3124,7 +3125,7 @@ static void get_6120_chip_params(struct qib_devdata *dd)
dd->piosize2k = val & ~0U;
dd->piosize4k = val >> 32;
- mtu = ib_mtu_enum_to_int(qib_ibmtu);
+ mtu = ib_mtu_enum_to_int(QIB_MODPARAM_GET(ibmtu, dd->unit, 1));
if (mtu == -1)
mtu = QIB_DEFAULT_MTU;
dd->pport->ibmtu = (u32)mtu;
@@ -3274,7 +3275,7 @@ static int init_6120_variables(struct qib_devdata *dd)
dd->rhf_offset = 0;
/* we always allocate at least 2048 bytes for eager buffers */
- ret = ib_mtu_enum_to_int(qib_ibmtu);
+ ret = ib_mtu_enum_to_int(QIB_MODPARAM_GET(ibmtu, dd->unit, 1));
dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
@@ -3314,7 +3315,6 @@ static int init_6120_variables(struct qib_devdata *dd)
if (qib_mini_init)
goto bail;
- qib_num_cfg_vls = 1; /* if any 6120's, only one VL */
ret = qib_create_ctxts(dd);
init_6120_cntrnames(dd);
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation.
- * All rights reserved.
+ * Copyright (c) 2012 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -2293,19 +2293,21 @@ static void qib_7220_config_ctxts(struct qib_devdata *dd)
{
unsigned long flags;
u32 nchipctxts;
+ u32 cfgctxts = QIB_MODPARAM_GET(cfgctxts, dd->unit, 0);
+ u32 nkrcvqs = QIB_MODPARAM_GET(krcvqs, dd->unit, 0);
nchipctxts = qib_read_kreg32(dd, kr_portcnt);
dd->cspec->numctxts = nchipctxts;
- if (qib_n_krcv_queues > 1) {
+ if (nkrcvqs > 1) {
dd->qpn_mask = 0x3e;
- dd->first_user_ctxt = qib_n_krcv_queues * dd->num_pports;
+ dd->first_user_ctxt = nkrcvqs * dd->num_pports;
if (dd->first_user_ctxt > nchipctxts)
dd->first_user_ctxt = nchipctxts;
} else
dd->first_user_ctxt = dd->num_pports;
dd->n_krcv_queues = dd->first_user_ctxt;
- if (!qib_cfgctxts) {
+ if (!cfgctxts) {
int nctxts = dd->first_user_ctxt + num_online_cpus();
if (nctxts <= 5)
@@ -2314,8 +2316,8 @@ static void qib_7220_config_ctxts(struct qib_devdata *dd)
dd->ctxtcnt = 9;
else if (nctxts <= nchipctxts)
dd->ctxtcnt = nchipctxts;
- } else if (qib_cfgctxts <= nchipctxts)
- dd->ctxtcnt = qib_cfgctxts;
+ } else if (cfgctxts <= nchipctxts)
+ dd->ctxtcnt = cfgctxts;
if (!dd->ctxtcnt) /* none of the above, set to max */
dd->ctxtcnt = nchipctxts;
@@ -3839,7 +3841,7 @@ static void get_7220_chip_params(struct qib_devdata *dd)
dd->piosize2k = val & ~0U;
dd->piosize4k = val >> 32;
- mtu = ib_mtu_enum_to_int(qib_ibmtu);
+ mtu = ib_mtu_enum_to_int(QIB_MODPARAM_GET(ibmtu, dd->unit, 1));
if (mtu == -1)
mtu = QIB_DEFAULT_MTU;
dd->pport->ibmtu = (u32)mtu;
@@ -4078,15 +4080,13 @@ static int qib_init_7220_variables(struct qib_devdata *dd)
ppd->cpspec->chase_timer.function = reenable_7220_chase;
ppd->cpspec->chase_timer.data = (unsigned long)ppd;
- qib_num_cfg_vls = 1; /* if any 7220's, only one VL */
-
dd->rcvhdrentsize = QIB_RCVHDR_ENTSIZE;
dd->rcvhdrsize = QIB_DFLT_RCVHDRSIZE;
dd->rhf_offset =
dd->rcvhdrentsize - sizeof(u64) / sizeof(u32);
/* we always allocate at least 2048 bytes for eager buffers */
- ret = ib_mtu_enum_to_int(qib_ibmtu);
+ ret = ib_mtu_enum_to_int(QIB_MODPARAM_GET(ibmtu, dd->unit, 1));
dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
@@ -100,9 +100,8 @@ static const unsigned sdma_idle_cnt = 64;
* Number of VLs we are configured to use (to allow for more
* credits per vl, etc.)
*/
-ushort qib_num_cfg_vls = 2;
-module_param_named(num_vls, qib_num_cfg_vls, ushort, S_IRUGO);
-MODULE_PARM_DESC(num_vls, "Set number of Virtual Lanes to use (1-8)");
+static QIB_MODPARAM_PORT(num_vls, NULL, 2, S_IRUGO,
+ "Set number of Virtual Lanes to use (1-8)");
static ushort qib_chase = 1;
module_param_named(chase, qib_chase, ushort, S_IRUGO);
@@ -113,9 +112,8 @@ module_param_named(long_attenuation, qib_long_atten, ushort, S_IRUGO);
MODULE_PARM_DESC(long_attenuation, \
"attenuation cutoff (dB) for long copper cable setup");
-static ushort qib_singleport;
-module_param_named(singleport, qib_singleport, ushort, S_IRUGO);
-MODULE_PARM_DESC(singleport, "Use only IB port 1; more per-port buffer space");
+static QIB_MODPARAM_UNIT(singleport, NULL, 0, S_IRUGO,
+ "Use only IB port 1; more per-port buffer space");
static ushort qib_krcvq01_no_msi;
module_param_named(krcvq01_no_msi, qib_krcvq01_no_msi, ushort, S_IRUGO);
@@ -3306,7 +3304,8 @@ static unsigned qib_7322_boardname(struct qib_devdata *dd)
dd->majrev, dd->minrev,
(unsigned)SYM_FIELD(dd->revision, Revision_R, SW));
- if (qib_singleport && (features >> PORT_SPD_CAP_SHIFT) & PORT_SPD_CAP) {
+ if (QIB_MODPARAM_GET(singleport, dd->unit, 0) &&
+ (features >> PORT_SPD_CAP_SHIFT) & PORT_SPD_CAP) {
qib_devinfo(dd->pcidev, "IB%u: Forced to single port mode"
" by module parameter\n", dd->unit);
features &= PORT_SPD_CAP;
@@ -3595,12 +3594,14 @@ static void qib_7322_config_ctxts(struct qib_devdata *dd)
{
unsigned long flags;
u32 nchipctxts;
+ u32 cfgctxts = QIB_MODPARAM_GET(cfgctxts, dd->unit, 0);
+ u32 nkrcvqs = QIB_MODPARAM_GET(krcvqs, dd->unit, 0);
nchipctxts = qib_read_kreg32(dd, kr_contextcnt);
dd->cspec->numctxts = nchipctxts;
- if (qib_n_krcv_queues > 1 && dd->num_pports) {
+ if (nkrcvqs > 1 && dd->num_pports) {
dd->first_user_ctxt = NUM_IB_PORTS +
- (qib_n_krcv_queues - 1) * dd->num_pports;
+ (nkrcvqs - 1) * dd->num_pports;
if (dd->first_user_ctxt > nchipctxts)
dd->first_user_ctxt = nchipctxts;
dd->n_krcv_queues = dd->first_user_ctxt / dd->num_pports;
@@ -3609,7 +3610,7 @@ static void qib_7322_config_ctxts(struct qib_devdata *dd)
dd->n_krcv_queues = 1;
}
- if (!qib_cfgctxts) {
+ if (!cfgctxts) {
int nctxts = dd->first_user_ctxt + num_online_cpus();
if (nctxts <= 6)
@@ -3618,10 +3619,10 @@ static void qib_7322_config_ctxts(struct qib_devdata *dd)
dd->ctxtcnt = 10;
else if (nctxts <= nchipctxts)
dd->ctxtcnt = nchipctxts;
- } else if (qib_cfgctxts < dd->num_pports)
+ } else if (cfgctxts < dd->num_pports)
dd->ctxtcnt = dd->num_pports;
- else if (qib_cfgctxts <= nchipctxts)
- dd->ctxtcnt = qib_cfgctxts;
+ else if (cfgctxts <= nchipctxts)
+ dd->ctxtcnt = cfgctxts;
if (!dd->ctxtcnt) /* none of the above, set to max */
dd->ctxtcnt = nchipctxts;
@@ -5451,7 +5452,6 @@ static void get_7322_chip_params(struct qib_devdata *dd)
{
u64 val;
u32 piobufs;
- int mtu;
dd->palign = qib_read_kreg32(dd, kr_pagealign);
@@ -5470,11 +5470,10 @@ static void get_7322_chip_params(struct qib_devdata *dd)
dd->piosize2k = val & ~0U;
dd->piosize4k = val >> 32;
- mtu = ib_mtu_enum_to_int(qib_ibmtu);
- if (mtu == -1)
- mtu = QIB_DEFAULT_MTU;
- dd->pport[0].ibmtu = (u32)mtu;
- dd->pport[1].ibmtu = (u32)mtu;
+ dd->pport[0].ibmtu = ib_mtu_enum_to_int(
+ QIB_MODPARAM_GET(ibmtu, dd->unit, 1));
+ dd->pport[1].ibmtu = ib_mtu_enum_to_int(
+ QIB_MODPARAM_GET(ibmtu, dd->unit, 2));
/* these may be adjusted in init_chip_wc_pat() */
dd->pio2kbase = (u32 __iomem *)
@@ -6073,7 +6072,7 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
{
struct qib_pportdata *ppd;
unsigned features, pidx, sbufcnt;
- int ret, mtu;
+ int ret, maxmtu = 0;
u32 sbufs, updthresh;
/* pport structs are contiguous, allocated after devdata */
@@ -6150,10 +6149,6 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
*/
qib_7322_set_baseaddrs(dd);
- mtu = ib_mtu_enum_to_int(qib_ibmtu);
- if (mtu == -1)
- mtu = QIB_DEFAULT_MTU;
-
dd->cspec->int_enable_mask = QIB_I_BITSEXTANT;
/* all hwerrors become interrupts, unless special purposed */
dd->cspec->hwerrmask = ~0ULL;
@@ -6163,9 +6158,14 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
~(SYM_MASK(HwErrMask, IBSerdesPClkNotDetectMask_0) |
SYM_MASK(HwErrMask, IBSerdesPClkNotDetectMask_1) |
HWE_MASK(LATriggered));
-
for (pidx = 0; pidx < NUM_IB_PORTS; ++pidx) {
struct qib_chippport_specific *cp = ppd->cpspec;
+ int mtu = ib_mtu_enum_to_int(
+ QIB_MODPARAM_GET(ibmtu, dd->unit, pidx+1));
+ u8 vls = QIB_MODPARAM_GET(num_vls, dd->unit, pidx+1);
+ if (mtu == -1)
+ mtu = QIB_DEFAULT_MTU;
+ maxmtu = max(maxmtu, mtu);
ppd->link_speed_supported = features & PORT_SPD_CAP;
features >>= PORT_SPD_CAP_SHIFT;
if (!ppd->link_speed_supported) {
@@ -6219,7 +6219,7 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
ppd->link_width_active = IB_WIDTH_4X;
ppd->link_speed_active = QIB_IB_SDR;
ppd->delay_mult = ib_rate_to_delay[IB_RATE_10_GBPS];
- switch (qib_num_cfg_vls) {
+ switch (vls) {
case 1:
ppd->vls_supported = IB_VL_VL0;
break;
@@ -6229,8 +6229,7 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
default:
qib_devinfo(dd->pcidev,
"Invalid num_vls %u, using 4 VLs\n",
- qib_num_cfg_vls);
- qib_num_cfg_vls = 4;
+ vls);
/* fall through */
case 4:
ppd->vls_supported = IB_VL_VL0_3;
@@ -6242,9 +6241,8 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
qib_devinfo(dd->pcidev,
"Invalid num_vls %u for MTU %d "
", using 4 VLs\n",
- qib_num_cfg_vls, mtu);
+ vls, mtu);
ppd->vls_supported = IB_VL_VL0_3;
- qib_num_cfg_vls = 4;
}
break;
}
@@ -6294,7 +6292,7 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
dd->rhf_offset = dd->rcvhdrentsize - sizeof(u64) / sizeof(u32);
/* we always allocate at least 2048 bytes for eager buffers */
- dd->rcvegrbufsize = max(mtu, 2048);
+ dd->rcvegrbufsize = max(maxmtu, 2048);
BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
@@ -56,9 +56,8 @@
* Number of ctxts we are configured to use (to allow for more pio
* buffers per ctxt, etc.) Zero means use chip value.
*/
-ushort qib_cfgctxts;
-module_param_named(cfgctxts, qib_cfgctxts, ushort, S_IRUGO);
-MODULE_PARM_DESC(cfgctxts, "Set max number of contexts to use");
+QIB_MODPARAM_UNIT(cfgctxts, NULL, 0, S_IRUGO,
+ "Set max number of contexts to use");
/*
* If set, do not write to any regs if avoidable, hack to allow
@@ -68,9 +67,8 @@ ushort qib_mini_init;
module_param_named(mini_init, qib_mini_init, ushort, S_IRUGO);
MODULE_PARM_DESC(mini_init, "If set, do minimal diag init");
-unsigned qib_n_krcv_queues;
-module_param_named(krcvqs, qib_n_krcv_queues, uint, S_IRUGO);
-MODULE_PARM_DESC(krcvqs, "number of kernel receive queues per IB port");
+QIB_MODPARAM_PORT(krcvqs, NULL, 0, S_IRUGO,
+ "number of kernel receive queues per IB port");
unsigned qib_cc_table_size;
module_param_named(cc_table_size, qib_cc_table_size, uint, S_IRUGO);
@@ -96,14 +94,15 @@ unsigned long *qib_cpulist;
/* set number of contexts we'll actually use */
void qib_set_ctxtcnt(struct qib_devdata *dd)
{
- if (!qib_cfgctxts) {
+ u64 val = QIB_MODPARAM_GET(cfgctxts, dd->unit, 0);
+ if (!val) {
dd->cfgctxts = dd->first_user_ctxt + num_online_cpus();
if (dd->cfgctxts > dd->ctxtcnt)
dd->cfgctxts = dd->ctxtcnt;
- } else if (qib_cfgctxts < dd->num_pports)
+ } else if (val < dd->num_pports)
dd->cfgctxts = dd->ctxtcnt;
- else if (qib_cfgctxts <= dd->ctxtcnt)
- dd->cfgctxts = qib_cfgctxts;
+ else if (val <= dd->ctxtcnt)
+ dd->cfgctxts = val;
else
dd->cfgctxts = dd->ctxtcnt;
dd->freectxts = (dd->first_user_ctxt > dd->cfgctxts) ? 0 :
@@ -676,10 +675,10 @@ int qib_init(struct qib_devdata *dd, int reinit)
if (lastfail)
ret = lastfail;
ppd = dd->pport + pidx;
- mtu = ib_mtu_enum_to_int(qib_ibmtu);
+ mtu = ib_mtu_enum_to_int(
+ QIB_MODPARAM_GET(ibmtu, dd->unit, ppd->port));
if (mtu == -1) {
mtu = QIB_DEFAULT_MTU;
- qib_ibmtu = 0; /* don't leave invalid value */
}
/* set max we can ever have for this driver load */
ppd->init_ibmaxlen = min(mtu > 2048 ?
@@ -1231,6 +1230,7 @@ static void __exit qlogic_ib_cleanup(void)
idr_destroy(&qib_unit_table);
qib_dev_cleanup();
+ qib_clean_mod_param();
}
module_exit(qlogic_ib_cleanup);
@@ -535,7 +535,8 @@ static int subn_get_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
pip->vl_arb_low_cap =
dd->f_get_ib_cfg(ppd, QIB_IB_CFG_VL_LOW_CAP);
/* InitTypeReply = 0 */
- pip->inittypereply_mtucap = qib_ibmtu ? qib_ibmtu : IB_MTU_4096;
+ pip->inittypereply_mtucap =
+ QIB_MODPARAM_GET(ibmtu, dd->unit, ppd->port);
/* HCAs ignore VLStallCount and HOQLife */
/* pip->vlstallcnt_hoqlife; */
pip->operationalvl_pei_peo_fpi_fpo =
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2008, 2009 QLogic Corporation. All rights reserved.
+ * Copyright (c) 2012 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008 - 2012 QLogic Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -500,9 +501,8 @@ static int val2fld(int wd, int mask)
return wd;
}
-static int qib_pcie_coalesce;
-module_param_named(pcie_coalesce, qib_pcie_coalesce, int, S_IRUGO);
-MODULE_PARM_DESC(pcie_coalesce, "tune PCIe colescing on some Intel chipsets");
+static QIB_MODPARAM_UNIT(pcie_coalesce, NULL, 0, S_IRUGO,
+ "tune PCIe colescing on some Intel chipsets");
/*
* Enable PCIe completion and data coalescing, on Intel 5x00 and 7300
@@ -518,7 +518,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)
u16 devid;
u32 mask, bits, val;
- if (!qib_pcie_coalesce)
+ if (!QIB_MODPARAM_GET(pcie_coalesce, dd->unit, 0))
return 0;
/* Find out supported and configured values for parent (root) */
@@ -577,9 +577,8 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)
* BIOS may not set PCIe bus-utilization parameters for best performance.
* Check and optionally adjust them to maximize our throughput.
*/
-static int qib_pcie_caps;
-module_param_named(pcie_caps, qib_pcie_caps, int, S_IRUGO);
-MODULE_PARM_DESC(pcie_caps, "Max PCIe tuning: Payload (0..3), ReadReq (4..7)");
+static QIB_MODPARAM_UNIT(pcie_caps, NULL, 0, S_IRUGO,
+ "Max PCIe tuning: Payload (4lsb), ReadReq (D4..7)");
static int qib_tune_pcie_caps(struct qib_devdata *dd)
{
@@ -589,6 +588,7 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
u16 pcaps, pctl, ecaps, ectl;
int rc_sup, ep_sup;
int rc_cur, ep_cur;
+ int caps = QIB_MODPARAM_GET(pcie_caps, dd->unit, 0);
/* Find out supported and configured values for parent (root) */
parent = dd->pcidev->bus->self;
@@ -620,8 +620,8 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
ep_cur = fld2val(ectl, PCI_EXP_DEVCTL_PAYLOAD);
/* If Supported greater than limit in module param, limit it */
- if (rc_sup > (qib_pcie_caps & 7))
- rc_sup = qib_pcie_caps & 7;
+ if (rc_sup > (caps & 7))
+ rc_sup = caps & 7;
/* If less than (allowed, supported), bump root payload */
if (rc_sup > rc_cur) {
rc_cur = rc_sup;
@@ -643,8 +643,8 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
* which is code '5' (log2(4096) - 7)
*/
rc_sup = 5;
- if (rc_sup > ((qib_pcie_caps >> 4) & 7))
- rc_sup = (qib_pcie_caps >> 4) & 7;
+ if (rc_sup > ((caps >> 4) & 7))
+ rc_sup = (caps >> 4) & 7;
rc_cur = fld2val(pctl, PCI_EXP_DEVCTL_READRQ);
ep_cur = fld2val(ectl, PCI_EXP_DEVCTL_READRQ);
@@ -1621,7 +1621,8 @@ static int qib_query_port(struct ib_device *ibdev, u8 port,
props->max_vl_num = qib_num_vls(ppd->vls_supported);
props->init_type_reply = 0;
- props->max_mtu = qib_ibmtu ? qib_ibmtu : IB_MTU_4096;
+ props->max_mtu = QIB_MODPARAM_GET(ibmtu, dd->unit, ppd->port) ?
+ QIB_MODPARAM_GET(ibmtu, dd->unit, ppd->port) : IB_MTU_4096;
switch (ppd->ibmtu) {
case 4096:
mtu = IB_MTU_4096;