summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-30 09:12:16 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-30 09:12:16 -0700
commit3e9345edd8562dc4f9bbca88a598c91c8779a9c4 (patch)
tree01d91aee420251b164e54f850e24ae12aceccab9 /drivers
parentd28619f1563140526e2f84eae436f39206f40a69 (diff)
parent767dcd42e51c69be88f83683eda7883e522618fa (diff)
downloadlinux-3e9345edd8562dc4f9bbca88a598c91c8779a9c4.tar.gz
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
  IB/qib: Remove DCA support until feature is finished
  IB/qib: Use a single txselect module parameter for serdes tuning
  IB/qib: Don't rely on (undefined) order of function parameter evaluation
  IB/ucm: Use memdup_user()
  IB/qib: Fix undefined symbol error when CONFIG_PCI_MSI=n
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/core/ucm.c11
-rw-r--r--drivers/infiniband/hw/qib/qib_fs.c25
-rw-r--r--drivers/infiniband/hw/qib/qib_iba6120.c12
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7322.c771
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c6
5 files changed, 203 insertions, 622 deletions
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 46474842cfe9..08f948df8fa9 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -706,14 +706,9 @@ static int ib_ucm_alloc_data(const void **dest, u64 src, u32 len)
 	if (!len)
 		return 0;
 
-	data = kmalloc(len, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	if (copy_from_user(data, (void __user *)(unsigned long)src, len)) {
-		kfree(data);
-		return -EFAULT;
-	}
+	data = memdup_user((void __user *)(unsigned long)src, len);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
 
 	*dest = data;
 	return 0;
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c
index 755470440ef1..edef8527eb34 100644
--- a/drivers/infiniband/hw/qib/qib_fs.c
+++ b/drivers/infiniband/hw/qib/qib_fs.c
@@ -144,10 +144,11 @@ static ssize_t dev_counters_read(struct file *file, char __user *buf,
 				 size_t count, loff_t *ppos)
 {
 	u64 *counters;
+	size_t avail;
 	struct qib_devdata *dd = private2dd(file);
 
-	return simple_read_from_buffer(buf, count, ppos, counters,
-		dd->f_read_cntrs(dd, *ppos, NULL, &counters));
+	avail = dd->f_read_cntrs(dd, *ppos, NULL, &counters);
+	return simple_read_from_buffer(buf, count, ppos, counters, avail);
 }
 
 /* read the per-device counters */
@@ -155,10 +156,11 @@ static ssize_t dev_names_read(struct file *file, char __user *buf,
 			      size_t count, loff_t *ppos)
 {
 	char *names;
+	size_t avail;
 	struct qib_devdata *dd = private2dd(file);
 
-	return simple_read_from_buffer(buf, count, ppos, names,
-		dd->f_read_cntrs(dd, *ppos, &names, NULL));
+	avail = dd->f_read_cntrs(dd, *ppos, &names, NULL);
+	return simple_read_from_buffer(buf, count, ppos, names, avail);
 }
 
 static const struct file_operations cntr_ops[] = {
@@ -176,10 +178,11 @@ static ssize_t portnames_read(struct file *file, char __user *buf,
 			      size_t count, loff_t *ppos)
 {
 	char *names;
+	size_t avail;
 	struct qib_devdata *dd = private2dd(file);
 
-	return simple_read_from_buffer(buf, count, ppos, names,
-		dd->f_read_portcntrs(dd, *ppos, 0, &names, NULL));
+	avail = dd->f_read_portcntrs(dd, *ppos, 0, &names, NULL);
+	return simple_read_from_buffer(buf, count, ppos, names, avail);
 }
 
 /* read the per-port counters for port 1 (pidx 0) */
@@ -187,10 +190,11 @@ static ssize_t portcntrs_1_read(struct file *file, char __user *buf,
 				size_t count, loff_t *ppos)
 {
 	u64 *counters;
+	size_t avail;
 	struct qib_devdata *dd = private2dd(file);
 
-	return simple_read_from_buffer(buf, count, ppos, counters,
-		dd->f_read_portcntrs(dd, *ppos, 0, NULL, &counters));
+	avail = dd->f_read_portcntrs(dd, *ppos, 0, NULL, &counters);
+	return simple_read_from_buffer(buf, count, ppos, counters, avail);
 }
 
 /* read the per-port counters for port 2 (pidx 1) */
@@ -198,10 +202,11 @@ static ssize_t portcntrs_2_read(struct file *file, char __user *buf,
 				size_t count, loff_t *ppos)
 {
 	u64 *counters;
+	size_t avail;
 	struct qib_devdata *dd = private2dd(file);
 
-	return simple_read_from_buffer(buf, count, ppos, counters,
-		dd->f_read_portcntrs(dd, *ppos, 1, NULL, &counters));
+	avail = dd->f_read_portcntrs(dd, *ppos, 1, NULL, &counters);
+	return simple_read_from_buffer(buf, count, ppos, counters, avail);
 }
 
 static const struct file_operations portcntr_ops[] = {
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index 7b6549fd429b..1eadadc13da8 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -3475,14 +3475,6 @@ struct qib_devdata *qib_init_iba6120_funcs(struct pci_dev *pdev,
 	struct qib_devdata *dd;
 	int ret;
 
-#ifndef CONFIG_PCI_MSI
-	qib_early_err(&pdev->dev, "QLogic PCIE device 0x%x cannot "
-	      "work if CONFIG_PCI_MSI is not enabled\n",
-	      ent->device);
-	dd = ERR_PTR(-ENODEV);
-	goto bail;
-#endif
-
 	dd = qib_alloc_devdata(pdev, sizeof(struct qib_pportdata) +
 			       sizeof(struct qib_chip_specific));
 	if (IS_ERR(dd))
@@ -3554,10 +3546,6 @@ struct qib_devdata *qib_init_iba6120_funcs(struct pci_dev *pdev,
 	if (qib_mini_init)
 		goto bail;
 
-#ifndef CONFIG_PCI_MSI
-	qib_dev_err(dd, "PCI_MSI not configured, NO interrupts\n");
-#endif
-
 	if (qib_pcie_params(dd, 8, NULL, NULL))
 		qib_dev_err(dd, "Failed to setup PCIe or interrupts; "
 			    "continuing anyway\n");
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index 2c24eab35b54..503992d9c5ce 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -42,9 +42,6 @@
 #include <linux/jiffies.h>
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_smi.h>
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
-#include <linux/dca.h>
-#endif
 
 #include "qib.h"
 #include "qib_7322_regs.h"
@@ -114,40 +111,18 @@ 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");
 
-
-/*
- * Setup QMH7342 receive and transmit parameters, necessary because
- * each bay, Mez connector, and IB port need different tuning, beyond
- * what the switch and HCA can do automatically.
- * It's expected to be done by cat'ing files to the modules file,
- * rather than setting up as a module parameter.
- * It's a "write-only" file, returns 0 when read back.
- * The unit, port, bay (if given), and values MUST be done as a single write.
- * The unit, port, and bay must precede the values to be effective.
- */
-static int setup_qmh_params(const char *, struct kernel_param *);
-static unsigned dummy_qmh_params;
-module_param_call(qmh_serdes_setup, setup_qmh_params, param_get_uint,
-		  &dummy_qmh_params, S_IWUSR | S_IRUGO);
-
-/* similarly for QME7342, but it's simpler */
-static int setup_qme_params(const char *, struct kernel_param *);
-static unsigned dummy_qme_params;
-module_param_call(qme_serdes_setup, setup_qme_params, param_get_uint,
-		  &dummy_qme_params, S_IWUSR | S_IRUGO);
-
 #define MAX_ATTEN_LEN 64 /* plenty for any real system */
 /* for read back, default index is ~5m copper cable */
-static char cable_atten_list[MAX_ATTEN_LEN] = "10";
-static struct kparam_string kp_cable_atten = {
-	.string = cable_atten_list,
+static char txselect_list[MAX_ATTEN_LEN] = "10";
+static struct kparam_string kp_txselect = {
+	.string = txselect_list,
 	.maxlen = MAX_ATTEN_LEN
 };
-static int  setup_cable_atten(const char *, struct kernel_param *);
-module_param_call(cable_atten, setup_cable_atten, param_get_string,
-		  &kp_cable_atten, S_IWUSR | S_IRUGO);
-MODULE_PARM_DESC(cable_atten, \
-		 "cable attenuation indices for cables with invalid EEPROM");
+static int  setup_txselect(const char *, struct kernel_param *);
+module_param_call(txselect, setup_txselect, param_get_string,
+		  &kp_txselect, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(txselect, \
+		 "Tx serdes indices (for no QSFP or invalid QSFP data)");
 
 #define BOARD_QME7342 5
 #define BOARD_QMH7342 6
@@ -540,12 +515,6 @@ struct qib_chip_specific {
 	u32 lastbuf_for_pio;
 	u32 stay_in_freeze;
 	u32 recovery_ports_initted;
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
-	u32 dca_ctrl;
-	int rhdr_cpu[18];
-	int sdma_cpu[2];
-	u64 dca_rcvhdr_ctrl[5]; /* B, C, D, E, F */
-#endif
 	struct msix_entry *msix_entries;
 	void  **msix_arg;
 	unsigned long *sendchkenable;
@@ -574,11 +543,12 @@ struct vendor_txdds_ent {
 static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *);
 
 #define TXDDS_TABLE_SZ 16 /* number of entries per speed in onchip table */
+#define TXDDS_EXTRA_SZ 11 /* number of extra tx settings entries */
 #define SERDES_CHANS 4 /* yes, it's obvious, but one less magic number */
 
 #define H1_FORCE_VAL 8
-#define H1_FORCE_QME 1 /*  may be overridden via setup_qme_params() */
-#define H1_FORCE_QMH 7 /*  may be overridden via setup_qmh_params() */
+#define H1_FORCE_QME 1 /*  may be overridden via setup_txselect() */
+#define H1_FORCE_QMH 7 /*  may be overridden via setup_txselect() */
 
 /* The static and dynamic registers are paired, and the pairs indexed by spd */
 #define krp_static_adapt_dis(spd) (KREG_IBPORT_IDX(ADAPT_DISABLE_STATIC_SDR) \
@@ -590,15 +560,6 @@ static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *);
 #define QDR_STATIC_ADAPT_INIT 0xffffffffffULL /* up, disable H0,H1-8, LE */
 #define QDR_STATIC_ADAPT_INIT_R1 0xf0ffffffffULL /* r1 up, disable H0,H1-8 */
 
-static const struct txdds_ent qmh_sdr_txdds =  { 11, 0,  5,  6 };
-static const struct txdds_ent qmh_ddr_txdds =  {  7, 0,  2,  8 };
-static const struct txdds_ent qmh_qdr_txdds =  {  0, 1,  3, 10 };
-
-/* this is used for unknown mez cards also */
-static const struct txdds_ent qme_sdr_txdds =  { 11, 0,  4,  4 };
-static const struct txdds_ent qme_ddr_txdds =  {  7, 0,  2,  7 };
-static const struct txdds_ent qme_qdr_txdds =  {  0, 1, 12, 11 };
-
 struct qib_chippport_specific {
 	u64 __iomem *kpregbase;
 	u64 __iomem *cpregbase;
@@ -637,12 +598,8 @@ struct qib_chippport_specific {
 	 * Per-bay per-channel rcv QMH H1 values and Tx values for QDR.
 	 * entry zero is unused, to simplify indexing
 	 */
-	u16 h1_val;
-	u8 amp[SERDES_CHANS];
-	u8 pre[SERDES_CHANS];
-	u8 mainv[SERDES_CHANS];
-	u8 post[SERDES_CHANS];
-	u8 no_eep;  /* attenuation index to use if no qsfp info */
+	u8 h1_val;
+	u8 no_eep;  /* txselect table index to use if no qsfp info */
 	u8 ipg_tries;
 	u8 ibmalfusesnap;
 	struct qib_qsfp_data qsfp_data;
@@ -676,52 +633,6 @@ static struct {
 		SYM_LSB(IntStatus, SDmaCleanupDone_1), 2 },
 };
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
-static const struct dca_reg_map {
-	int     shadow_inx;
-	int     lsb;
-	u64     mask;
-	u16     regno;
-} dca_rcvhdr_reg_map[] = {
-	{ 0, SYM_LSB(DCACtrlB, RcvHdrq0DCAOPH),
-	   ~SYM_MASK(DCACtrlB, RcvHdrq0DCAOPH) , KREG_IDX(DCACtrlB) },
-	{ 0, SYM_LSB(DCACtrlB, RcvHdrq1DCAOPH),
-	   ~SYM_MASK(DCACtrlB, RcvHdrq1DCAOPH) , KREG_IDX(DCACtrlB) },
-	{ 0, SYM_LSB(DCACtrlB, RcvHdrq2DCAOPH),
-	   ~SYM_MASK(DCACtrlB, RcvHdrq2DCAOPH) , KREG_IDX(DCACtrlB) },
-	{ 0, SYM_LSB(DCACtrlB, RcvHdrq3DCAOPH),
-	   ~SYM_MASK(DCACtrlB, RcvHdrq3DCAOPH) , KREG_IDX(DCACtrlB) },
-	{ 1, SYM_LSB(DCACtrlC, RcvHdrq4DCAOPH),
-	   ~SYM_MASK(DCACtrlC, RcvHdrq4DCAOPH) , KREG_IDX(DCACtrlC) },
-	{ 1, SYM_LSB(DCACtrlC, RcvHdrq5DCAOPH),
-	   ~SYM_MASK(DCACtrlC, RcvHdrq5DCAOPH) , KREG_IDX(DCACtrlC) },
-	{ 1, SYM_LSB(DCACtrlC, RcvHdrq6DCAOPH),
-	   ~SYM_MASK(DCACtrlC, RcvHdrq6DCAOPH) , KREG_IDX(DCACtrlC) },
-	{ 1, SYM_LSB(DCACtrlC, RcvHdrq7DCAOPH),
-	   ~SYM_MASK(DCACtrlC, RcvHdrq7DCAOPH) , KREG_IDX(DCACtrlC) },
-	{ 2, SYM_LSB(DCACtrlD, RcvHdrq8DCAOPH),
-	   ~SYM_MASK(DCACtrlD, RcvHdrq8DCAOPH) , KREG_IDX(DCACtrlD) },
-	{ 2, SYM_LSB(DCACtrlD, RcvHdrq9DCAOPH),
-	   ~SYM_MASK(DCACtrlD, RcvHdrq9DCAOPH) , KREG_IDX(DCACtrlD) },
-	{ 2, SYM_LSB(DCACtrlD, RcvHdrq10DCAOPH),
-	   ~SYM_MASK(DCACtrlD, RcvHdrq10DCAOPH) , KREG_IDX(DCACtrlD) },
-	{ 2, SYM_LSB(DCACtrlD, RcvHdrq11DCAOPH),
-	   ~SYM_MASK(DCACtrlD, RcvHdrq11DCAOPH) , KREG_IDX(DCACtrlD) },
-	{ 3, SYM_LSB(DCACtrlE, RcvHdrq12DCAOPH),
-	   ~SYM_MASK(DCACtrlE, RcvHdrq12DCAOPH) , KREG_IDX(DCACtrlE) },
-	{ 3, SYM_LSB(DCACtrlE, RcvHdrq13DCAOPH),
-	   ~SYM_MASK(DCACtrlE, RcvHdrq13DCAOPH) , KREG_IDX(DCACtrlE) },
-	{ 3, SYM_LSB(DCACtrlE, RcvHdrq14DCAOPH),
-	   ~SYM_MASK(DCACtrlE, RcvHdrq14DCAOPH) , KREG_IDX(DCACtrlE) },
-	{ 3, SYM_LSB(DCACtrlE, RcvHdrq15DCAOPH),
-	   ~SYM_MASK(DCACtrlE, RcvHdrq15DCAOPH) , KREG_IDX(DCACtrlE) },
-	{ 4, SYM_LSB(DCACtrlF, RcvHdrq16DCAOPH),
-	   ~SYM_MASK(DCACtrlF, RcvHdrq16DCAOPH) , KREG_IDX(DCACtrlF) },
-	{ 4, SYM_LSB(DCACtrlF, RcvHdrq17DCAOPH),
-	   ~SYM_MASK(DCACtrlF, RcvHdrq17DCAOPH) , KREG_IDX(DCACtrlF) },
-};
-#endif
-
 /* ibcctrl bits */
 #define QLOGIC_IB_IBCC_LINKINITCMD_DISABLE 1
 /* cycle through TS1/TS2 till OK */
@@ -2572,95 +2483,6 @@ static void qib_setup_7322_setextled(struct qib_pportdata *ppd, u32 on)
 		qib_write_kreg_port(ppd, krp_rcvpktledcnt, ledblink);
 }
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
-static void qib_update_rhdrq_dca(struct qib_ctxtdata *rcd)
-{
-	struct qib_devdata *dd = rcd->dd;
-	struct qib_chip_specific *cspec = dd->cspec;
-	int cpu = get_cpu();
-
-	if (cspec->rhdr_cpu[rcd->ctxt] != cpu) {
-		const struct dca_reg_map *rmp;
-
-		cspec->rhdr_cpu[rcd->ctxt] = cpu;
-		rmp = &dca_rcvhdr_reg_map[rcd->ctxt];
-		cspec->dca_rcvhdr_ctrl[rmp->shadow_inx] &= rmp->mask;
-		cspec->dca_rcvhdr_ctrl[rmp->shadow_inx] |=
-			(u64) dca3_get_tag(&dd->pcidev->dev, cpu) << rmp->lsb;
-		qib_write_kreg(dd, rmp->regno,
-			       cspec->dca_rcvhdr_ctrl[rmp->shadow_inx]);
-		cspec->dca_ctrl |= SYM_MASK(DCACtrlA, RcvHdrqDCAEnable);
-		qib_write_kreg(dd, KREG_IDX(DCACtrlA), cspec->dca_ctrl);
-	}
-	put_cpu();
-}
-
-static void qib_update_sdma_dca(struct qib_pportdata *ppd)
-{
-	struct qib_devdata *dd = ppd->dd;
-	struct qib_chip_specific *cspec = dd->cspec;
-	int cpu = get_cpu();
-	unsigned pidx = ppd->port - 1;
-
-	if (cspec->sdma_cpu[pidx] != cpu) {
-		cspec->sdma_cpu[pidx] = cpu;
-		cspec->dca_rcvhdr_ctrl[4] &= ~(ppd->hw_pidx ?
-			SYM_MASK(DCACtrlF, SendDma1DCAOPH) :
-			SYM_MASK(DCACtrlF, SendDma0DCAOPH));
-		cspec->dca_rcvhdr_ctrl[4] |=
-			(u64) dca3_get_tag(&dd->pcidev->dev, cpu) <<
-				(ppd->hw_pidx ?
-					SYM_LSB(DCACtrlF, SendDma1DCAOPH) :
-					SYM_LSB(DCACtrlF, SendDma0DCAOPH));
-		qib_write_kreg(dd, KREG_IDX(DCACtrlF),
-			       cspec->dca_rcvhdr_ctrl[4]);
-		cspec->dca_ctrl |= ppd->hw_pidx ?
-			SYM_MASK(DCACtrlA, SendDMAHead1DCAEnable) :
-			SYM_MASK(DCACtrlA, SendDMAHead0DCAEnable);
-		qib_write_kreg(dd, KREG_IDX(DCACtrlA), cspec->dca_ctrl);
-	}
-	put_cpu();
-}
-
-static void qib_setup_dca(struct qib_devdata *dd)
-{
-	struct qib_chip_specific *cspec = dd->cspec;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(cspec->rhdr_cpu); i++)
-		cspec->rhdr_cpu[i] = -1;
-	for (i = 0; i < ARRAY_SIZE(cspec->sdma_cpu); i++)
-		cspec->sdma_cpu[i] = -1;
-	cspec->dca_rcvhdr_ctrl[0] =
-		(1ULL << SYM_LSB(DCACtrlB, RcvHdrq0DCAXfrCnt)) |
-		(1ULL << SYM_LSB(DCACtrlB, RcvHdrq1DCAXfrCnt)) |
-		(1ULL << SYM_LSB(DCACtrlB, RcvHdrq2DCAXfrCnt)) |
-		(1ULL << SYM_LSB(DCACtrlB, RcvHdrq3DCAXfrCnt));
-	cspec->dca_rcvhdr_ctrl[1] =
-		(1ULL << SYM_LSB(DCACtrlC, RcvHdrq4DCAXfrCnt)) |
-		(1ULL << SYM_LSB(DCACtrlC, RcvHdrq5DCAXfrCnt)) |
-		(1ULL << SYM_LSB(DCACtrlC, RcvHdrq6DCAXfrCnt)) |
-		(1ULL << SYM_LSB(DCACtrlC, RcvHdrq7DCAXfrCnt));
-	cspec->dca_rcvhdr_ctrl[2] =
-		(1ULL << SYM_LSB(DCACtrlD, RcvHdrq8DCAXfrCnt)) |
-		(1ULL << SYM_LSB(DCACtrlD, RcvHdrq9DCAXfrCnt)) |
-		(1ULL << SYM_LSB(DCACtrlD, RcvHdrq10DCAXfrCnt)) |
-		(1ULL << SYM_LSB(DCACtrlD, RcvHdrq11DCAXfrCnt));
-	cspec->dca_rcvhdr_ctrl[3] =
-		(1ULL << SYM_LSB(DCACtrlE, RcvHdrq12DCAXfrCnt)) |
-		(1ULL << SYM_LSB(DCACtrlE, RcvHdrq13DCAXfrCnt)) |
-		(1ULL << SYM_LSB(DCACtrlE, RcvHdrq14DCAXfrCnt)) |
-		(1ULL << SYM_LSB(DCACtrlE, RcvHdrq15DCAXfrCnt));
-	cspec->dca_rcvhdr_ctrl[4] =
-		(1ULL << SYM_LSB(DCACtrlF, RcvHdrq16DCAXfrCnt)) |
-		(1ULL << SYM_LSB(DCACtrlF, RcvHdrq17DCAXfrCnt));
-	for (i = 0; i < ARRAY_SIZE(cspec->sdma_cpu); i++)
-		qib_write_kreg(dd, KREG_IDX(DCACtrlB) + i,
-			       cspec->dca_rcvhdr_ctrl[i]);
-}
-
-#endif
-
 /*
  * Disable MSIx interrupt if enabled, call generic MSIx code
  * to cleanup, and clear pending MSIx interrupts.
@@ -2701,15 +2523,6 @@ static void qib_setup_7322_cleanup(struct qib_devdata *dd)
 {
 	int i;
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
-	if (dd->flags & QIB_DCA_ENABLED) {
-		dca_remove_requester(&dd->pcidev->dev);
-		dd->flags &= ~QIB_DCA_ENABLED;
-		dd->cspec->dca_ctrl = 0;
-		qib_write_kreg(dd, KREG_IDX(DCACtrlA), dd->cspec->dca_ctrl);
-	}
-#endif
-
 	qib_7322_free_irq(dd);
 	kfree(dd->cspec->cntrs);
 	kfree(dd->cspec->sendchkenable);
@@ -3017,11 +2830,6 @@ static irqreturn_t qib_7322pintr(int irq, void *data)
 	if (dd->int_counter != (u32) -1)
 		dd->int_counter++;
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
-	if (dd->flags & QIB_DCA_ENABLED)
-		qib_update_rhdrq_dca(rcd);
-#endif
-
 	/* Clear the interrupt bit we expect to be set. */
 	qib_write_kreg(dd, kr_intclear, ((1ULL << QIB_I_RCVAVAIL_LSB) |
 		       (1ULL << QIB_I_RCVURG_LSB)) << rcd->ctxt);
@@ -3085,11 +2893,6 @@ static irqreturn_t sdma_intr(int irq, void *data)
 	if (dd->int_counter != (u32) -1)
 		dd->int_counter++;
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
-	if (dd->flags & QIB_DCA_ENABLED)
-		qib_update_sdma_dca(ppd);
-#endif
-
 	/* Clear the interrupt bit we expect to be set. */
 	qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
 		       INT_MASK_P(SDma, 1) : INT_MASK_P(SDma, 0));
@@ -3119,11 +2922,6 @@ static irqreturn_t sdma_idle_intr(int irq, void *data)
 	if (dd->int_counter != (u32) -1)
 		dd->int_counter++;
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
-	if (dd->flags & QIB_DCA_ENABLED)
-		qib_update_sdma_dca(ppd);
-#endif
-
 	/* Clear the interrupt bit we expect to be set. */
 	qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
 		       INT_MASK_P(SDmaIdle, 1) : INT_MASK_P(SDmaIdle, 0));
@@ -3153,11 +2951,6 @@ static irqreturn_t sdma_progress_intr(int irq, void *data)
 	if (dd->int_counter != (u32) -1)
 		dd->int_counter++;
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
-	if (dd->flags & QIB_DCA_ENABLED)
-		qib_update_sdma_dca(ppd);
-#endif
-
 	/* Clear the interrupt bit we expect to be set. */
 	qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
 		       INT_MASK_P(SDmaProgress, 1) :
@@ -3188,11 +2981,6 @@ static irqreturn_t sdma_cleanup_intr(int irq, void *data)
 	if (dd->int_counter != (u32) -1)
 		dd->int_counter++;
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
-	if (dd->flags & QIB_DCA_ENABLED)
-		qib_update_sdma_dca(ppd);
-#endif
-
 	/* Clear the interrupt bit we expect to be set. */
 	qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ?
 		       INT_MASK_PM(SDmaCleanupDone, 1) :
@@ -4299,10 +4087,6 @@ static void rcvctrl_7322_mod(struct qib_pportdata *ppd, unsigned int op,
 		qib_write_kreg_ctxt(dd, krc_rcvhdraddr, ctxt,
 				    rcd->rcvhdrq_phys);
 		rcd->seq_cnt = 1;
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
-		if (dd->flags & QIB_DCA_ENABLED)
-			qib_update_rhdrq_dca(rcd);
-#endif
 	}
 	if (op & QIB_RCVCTRL_CTXT_DIS)
 		ppd->p_rcvctrl &=
@@ -5360,7 +5144,13 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
 				     QIBL_IB_AUTONEG_INPROG)))
 			set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled);
 		if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) {
+			/* unlock the Tx settings, speed may change */
+			qib_write_kreg_port(ppd, krp_tx_deemph_override,
+				SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+				reset_tx_deemphasis_override));
 			qib_cancel_sends(ppd);
+			/* on link down, ensure sane pcs state */
+			qib_7322_mini_pcs_reset(ppd);
 			spin_lock_irqsave(&ppd->sdma_lock, flags);
 			if (__qib_sdma_running(ppd))
 				__qib_sdma_process_event(ppd,
@@ -5766,26 +5556,28 @@ static void qib_init_7322_qsfp(struct qib_pportdata *ppd)
 }
 
 /*
- * called at device initialization time, and also if the cable_atten
+ * called at device initialization time, and also if the txselect
  * module parameter is changed.  This is used for cables that don't
  * have valid QSFP EEPROMs (not present, or attenuation is zero).
  * We initialize to the default, then if there is a specific
- * unit,port match, we use that.
+ * unit,port match, we use that (and set it immediately, for the
+ * current speed, if the link is at INIT or better).
  * String format is "default# unit#,port#=# ... u,p=#", separators must
- * be a SPACE character.  A newline terminates.
+ * be a SPACE character.  A newline terminates.  The u,p=# tuples may
+ * optionally have "u,p=#,#", where the final # is the H1 value
  * The last specific match is used (actually, all are used, but last
  * one is the one that winds up set); if none at all, fall back on default.
  */
 static void set_no_qsfp_atten(struct qib_devdata *dd, int change)
 {
 	char *nxt, *str;
-	int pidx, unit, port, deflt;
+	u32 pidx, unit, port, deflt, h1;
 	unsigned long val;
-	int any = 0;
+	int any = 0, seth1;
 
-	str = cable_atten_list;
+	str = txselect_list;
 
-	/* default number is validated in setup_cable_atten() */
+	/* default number is validated in setup_txselect() */
 	deflt = simple_strtoul(str, &nxt, 0);
 	for (pidx = 0; pidx < dd->num_pports; ++pidx)
 		dd->pport[pidx].cpspec->no_eep = deflt;
@@ -5812,16 +5604,28 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change)
 				;
 			continue;
 		}
-		if (val >= TXDDS_TABLE_SZ)
+		if (val >= TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ)
 			continue;
+		seth1 = 0;
+		h1 = 0; /* gcc thinks it might be used uninitted */
+		if (*nxt == ',' && nxt[1]) {
+			str = ++nxt;
+			h1 = (u32)simple_strtoul(str, &nxt, 0);
+			if (nxt == str)
+				while (*nxt && *nxt++ != ' ') /* skip */
+					;
+			else
+				seth1 = 1;
+		}
 		for (pidx = 0; dd->unit == unit && pidx < dd->num_pports;
 		     ++pidx) {
-			if (dd->pport[pidx].port != port ||
-				!dd->pport[pidx].link_speed_supported)
+			struct qib_pportdata *ppd = &dd->pport[pidx];
+
+			if (ppd->port != port || !ppd->link_speed_supported)
 				continue;
-			dd->pport[pidx].cpspec->no_eep = val;
+			ppd->cpspec->no_eep = val;
 			/* now change the IBC and serdes, overriding generic */
-			init_txdds_table(&dd->pport[pidx], 1);
+			init_txdds_table(ppd, 1);
 			any++;
 		}
 		if (*nxt == '\n')
@@ -5832,35 +5636,35 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change)
 		 * Change the IBC and serdes, but since it's
 		 * general, don't override specific settings.
 		 */
-		for (pidx = 0; pidx < dd->num_pports; ++pidx) {
-			if (!dd->pport[pidx].link_speed_supported)
-				continue;
-			init_txdds_table(&dd->pport[pidx], 0);
-		}
+		for (pidx = 0; pidx < dd->num_pports; ++pidx)
+			if (dd->pport[pidx].link_speed_supported)
+				init_txdds_table(&dd->pport[pidx], 0);
 	}
 }
 
-/* handle the cable_atten parameter changing */
-static int setup_cable_atten(const char *str, struct kernel_param *kp)
+/* handle the txselect parameter changing */
+static int setup_txselect(const char *str, struct kernel_param *kp)
 {
 	struct qib_devdata *dd;
 	unsigned long val;
 	char *n;
 	if (strlen(str) >= MAX_ATTEN_LEN) {
-		printk(KERN_INFO QIB_DRV_NAME " cable_atten_values string "
+		printk(KERN_INFO QIB_DRV_NAME " txselect_values string "
 		       "too long\n");
 		return -ENOSPC;
 	}
 	val = simple_strtoul(str, &n, 0);
-	if (n == str || val >= TXDDS_TABLE_SZ) {
+	if (n == str || val >= (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ)) {
 		printk(KERN_INFO QIB_DRV_NAME
-		       "cable_atten_values must start with a number\n");
+		       "txselect_values must start with a number < %d\n",
+			TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ);
 		return -EINVAL;
 	}
-	strcpy(cable_atten_list, str);
+	strcpy(txselect_list, str);
 
 	list_for_each_entry(dd, &qib_dev_list, list)
-		set_no_qsfp_atten(dd, 1);
+		if (dd->deviceid == PCI_DEVICE_ID_QLOGIC_IB_7322)
+			set_no_qsfp_atten(dd, 1);
 	return 0;
 }
 
@@ -6261,28 +6065,17 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
 		 * in adapter-specific routines.
 		 */
 		if (!(ppd->dd->flags & QIB_HAS_QSFP)) {
-			int i;
-			const struct txdds_ent *txdds;
-
 			if (!IS_QMH(ppd->dd) && !IS_QME(ppd->dd))
 				qib_devinfo(ppd->dd->pcidev, "IB%u:%u: "
 					    "Unknown mezzanine card type\n",
-					    ppd->dd->unit, ppd->port);
-			txdds = IS_QMH(ppd->dd) ? &qmh_qdr_txdds :
-				&qme_qdr_txdds;
-
+					    dd->unit, ppd->port);
+			cp->h1_val = IS_QMH(dd) ? H1_FORCE_QMH : H1_FORCE_QME;
 			/*
-			 * set values in case link comes up
-			 * before table is written to driver.
+			 * Choose center value as default tx serdes setting
+			 * until changed through module parameter.
 			 */
-			cp->h1_val = IS_QMH(ppd->dd) ? H1_FORCE_QMH :
-				H1_FORCE_QME;
-			for (i = 0; i < SERDES_CHANS; i++) {
-				cp->amp[i] = txdds->amp;
-				cp->pre[i] = txdds->pre;
-				cp->mainv[i] = txdds->main;
-				cp->post[i] = txdds->post;
-			}
+			ppd->cpspec->no_eep = IS_QMH(dd) ?
+				TXDDS_TABLE_SZ + 2 : TXDDS_TABLE_SZ + 4;
 		} else
 			cp->h1_val = H1_FORCE_VAL;
 
@@ -6299,8 +6092,7 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
 
 	dd->rcvhdrentsize = QIB_RCVHDR_ENTSIZE;
 	dd->rcvhdrsize = QIB_DFLT_RCVHDRSIZE;
-	dd->rhf_offset =
-		dd->rcvhdrentsize - sizeof(u64) / sizeof(u32);
+	dd->rhf_offset = dd->rcvhdrentsize - sizeof(u64) / sizeof(u32);
 
 	/* we always allocate at least 2048 bytes for eager buffers */
 	dd->rcvegrbufsize = max(mtu, 2048);
@@ -6919,13 +6711,6 @@ struct qib_devdata *qib_init_iba7322_funcs(struct pci_dev *pdev,
 	/* clear diagctrl register, in case diags were running and crashed */
 	qib_write_kreg(dd, kr_hwdiagctrl, 0);
 
-#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE)
-	ret = dca_add_requester(&pdev->dev);
-	if (!ret) {
-		dd->flags |= QIB_DCA_ENABLED;
-		qib_setup_dca(dd);
-	}
-#endif
 	goto bail;
 
 bail_cleanup:
@@ -7111,8 +6896,8 @@ static const struct txdds_ent txdds_ddr[TXDDS_TABLE_SZ] = {
 static const struct txdds_ent txdds_qdr[TXDDS_TABLE_SZ] = {
 	/* amp, pre, main, post */
 	{  2, 2, 15,  6 },	/* Loopback */
-	{  0, 1,  0,  7 },	/*  2 dB */
-	{  0, 1,  0,  9 },	/*  3 dB */
+	{  0, 1,  0,  7 },	/*  2 dB (also QMH7342) */
+	{  0, 1,  0,  9 },	/*  3 dB (also QMH7342) */
 	{  0, 1,  0, 11 },	/*  4 dB */
 	{  0, 1,  0, 13 },	/*  5 dB */
 	{  0, 1,  0, 15 },	/*  6 dB */
@@ -7128,6 +6913,57 @@ static const struct txdds_ent txdds_qdr[TXDDS_TABLE_SZ] = {
 	{  0, 2,  9, 15 },	/* 16 dB */
 };
 
+/*
+ * extra entries for use with txselect, for indices >= TXDDS_TABLE_SZ.
+ * These are mostly used for mez cards going through connectors
+ * and backplane traces, but can be used to add other "unusual"
+ * table values as well.
+ */
+static const struct txdds_ent txdds_extra_sdr[TXDDS_EXTRA_SZ] = {
+	/* amp, pre, main, post */
+	{  0, 0, 0,  1 },	/* QMH7342 backplane settings */
+	{  0, 0, 0,  1 },	/* QMH7342 backplane settings */
+	{  0, 0, 0,  2 },	/* QMH7342 backplane settings */
+	{  0, 0, 0,  2 },	/* QMH7342 backplane settings */
+	{  0, 0, 0, 11 },	/* QME7342 backplane settings */
+	{  0, 0, 0, 11 },	/* QME7342 backplane settings */
+	{  0, 0, 0, 11 },	/* QME7342 backplane settings */
+	{  0, 0, 0, 11 },	/* QME7342 backplane settings */
+	{  0, 0, 0, 11 },	/* QME7342 backplane settings */
+	{  0, 0, 0, 11 },	/* QME7342 backplane settings */
+	{  0, 0, 0, 11 },	/* QME7342 backplane settings */
+};
+
+static const struct txdds_ent txdds_extra_ddr[TXDDS_EXTRA_SZ] = {
+	/* amp, pre, main, post */
+	{  0, 0, 0,  7 },	/* QMH7342 backplane settings */
+	{  0, 0, 0,  7 },	/* QMH7342 backplane settings */
+	{  0, 0, 0,  8 },	/* QMH7342 backplane settings */
+	{  0, 0, 0,  8 },	/* QMH7342 backplane settings */
+	{  0, 0, 0, 13 },	/* QME7342 backplane settings */
+	{  0, 0, 0, 13 },	/* QME7342 backplane settings */
+	{  0, 0, 0, 13 },	/* QME7342 backplane settings */
+	{  0, 0, 0, 13 },	/* QME7342 backplane settings */
+	{  0, 0, 0, 13 },	/* QME7342 backplane settings */
+	{  0, 0, 0, 13 },	/* QME7342 backplane settings */
+	{  0, 0, 0, 13 },	/* QME7342 backplane settings */
+};
+
+static const struct txdds_ent txdds_extra_qdr[TXDDS_EXTRA_SZ] = {
+	/* amp, pre, main, post */
+	{  0, 1,  0,  4 },	/* QMH7342 backplane settings */
+	{  0, 1,  0,  5 },	/* QMH7342 backplane settings */
+	{  0, 1,  0,  6 },	/* QMH7342 backplane settings */
+	{  0, 1,  0,  8 },	/* QMH7342 backplane settings */
+	{  0, 1, 12, 10 },	/* QME7342 backplane setting */
+	{  0, 1, 12, 11 },	/* QME7342 backplane setting */
+	{  0, 1, 12, 12 },	/* QME7342 backplane setting */
+	{  0, 1, 12, 14 },	/* QME7342 backplane setting */
+	{  0, 1, 12,  6 },	/* QME7342 backplane setting */
+	{  0, 1, 12,  7 },	/* QME7342 backplane setting */
+	{  0, 1, 12,  8 },	/* QME7342 backplane setting */
+};
+
 static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds,
 					       unsigned atten)
 {
@@ -7145,7 +6981,7 @@ static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds,
 }
 
 /*
- * if override is set, the module parameter cable_atten has a value
+ * if override is set, the module parameter txselect has a value
  * for this specific port, so use it, rather than our normal mechanism.
  */
 static void find_best_ent(struct qib_pportdata *ppd,
@@ -7184,15 +7020,28 @@ static void find_best_ent(struct qib_pportdata *ppd,
 		*ddr_dds = get_atten_table(txdds_ddr, qd->atten[0]);
 		*qdr_dds = get_atten_table(txdds_qdr, qd->atten[1]);
 		return;
-	} else {
+	} else if (ppd->cpspec->no_eep < TXDDS_TABLE_SZ) {
 		/*
 		 * If we have no (or incomplete) data from the cable
-		 * EEPROM, or no QSFP, use the module parameter value
-		 * to index into the attentuation table.
+		 * EEPROM, or no QSFP, or override is set, use the
+		 * module parameter value to index into the attentuation
+		 * table.
 		 */
-		*sdr_dds = &txdds_sdr[ppd->cpspec->no_eep];
-		*ddr_dds = &txdds_ddr[ppd->cpspec->no_eep];
-		*qdr_dds = &txdds_qdr[ppd->cpspec->no_eep];
+		idx = ppd->cpspec->no_eep;
+		*sdr_dds = &txdds_sdr[idx];
+		*ddr_dds = &txdds_ddr[idx];
+		*qdr_dds = &txdds_qdr[idx];
+	} else if (ppd->cpspec->no_eep < (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ)) {
+		/* similar to above, but index into the "extra" table. */
+		idx = ppd->cpspec->no_eep - TXDDS_TABLE_SZ;
+		*sdr_dds = &txdds_extra_sdr[idx];
+		*ddr_dds = &txdds_extra_ddr[idx];
+		*qdr_dds = &txdds_extra_qdr[idx];
+	} else {
+		/* this shouldn't happen, it's range checked */
+		*sdr_dds = txdds_sdr + qib_long_atten;
+		*ddr_dds = txdds_ddr + qib_long_atten;
+		*qdr_dds = txdds_qdr + qib_long_atten;
 	}
 }
 
@@ -7203,33 +7052,24 @@ static void init_txdds_table(struct qib_pportdata *ppd, int override)
 	int idx;
 	int single_ent = 0;
 
-	if (IS_QMH(ppd->dd)) {
-		/* normally will be overridden, via setup_qmh() */
-		sdr_dds = &qmh_sdr_txdds;
-		ddr_dds = &qmh_ddr_txdds;
-		qdr_dds = &qmh_qdr_txdds;
-		single_ent = 1;
-	} else if (IS_QME(ppd->dd)) {
-		sdr_dds = &qme_sdr_txdds;
-		ddr_dds = &qme_ddr_txdds;
-		qdr_dds = &qme_qdr_txdds;
+	find_best_ent(ppd, &sdr_dds, &ddr_dds, &qdr_dds, override);
+
+	/* for mez cards or override, use the selected value for all entries */
+	if (!(ppd->dd->flags & QIB_HAS_QSFP) || override)
 		single_ent = 1;
-	} else
-		find_best_ent(ppd, &sdr_dds, &ddr_dds, &qdr_dds, override);
 
 	/* Fill in the first entry with the best entry found. */
 	set_txdds(ppd, 0, sdr_dds);
 	set_txdds(ppd, TXDDS_TABLE_SZ, ddr_dds);
 	set_txdds(ppd, 2 * TXDDS_TABLE_SZ, qdr_dds);
-
-	/*
-	 * for our current speed, also write that value into the
-	 * tx serdes registers.
-	 */
-	dds = (struct txdds_ent *)(ppd->link_speed_active == QIB_IB_QDR ?
-				   qdr_dds : (ppd->link_speed_active ==
-					      QIB_IB_DDR ? ddr_dds : sdr_dds));
-	write_tx_serdes_param(ppd, dds);
+	if (ppd->lflags & (QIBL_LINKINIT | QIBL_LINKARMED |
+		QIBL_LINKACTIVE)) {
+		dds = (struct txdds_ent *)(ppd->link_speed_active ==
+					   QIB_IB_QDR ?  qdr_dds :
+					   (ppd->link_speed_active ==
+					    QIB_IB_DDR ? ddr_dds : sdr_dds));
+		write_tx_serdes_param(ppd, dds);
+	}
 
 	/* Fill in the remaining entries with the default table values. */
 	for (idx = 1; idx < ARRAY_SIZE(txdds_sdr); ++idx) {
@@ -7352,6 +7192,11 @@ static int serdes_7322_init(struct qib_pportdata *ppd)
 	 */
 	init_txdds_table(ppd, 0);
 
+	/* ensure no tx overrides from earlier driver loads */
+	qib_write_kreg_port(ppd, krp_tx_deemph_override,
+		SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+		reset_tx_deemphasis_override));
+
 	/* Patch some SerDes defaults to "Better for IB" */
 	/* Timing Loop Bandwidth: cdr_timing[11:9] = 0 */
 	ibsd_wr_allchans(ppd, 2, 0, BMASK(11, 9));
@@ -7421,7 +7266,7 @@ static int serdes_7322_init(struct qib_pportdata *ppd)
 			    QDR_STATIC_ADAPT_DOWN_R1 : QDR_STATIC_ADAPT_DOWN);
 	ppd->cpspec->qdr_dfe_on = 1;
 
-	/* (FLoop LOS gate: PPM filter  enabled */
+	/* FLoop LOS gate: PPM filter  enabled */
 	ibsd_wr_allchans(ppd, 38, 0 << 10, 1 << 10);
 
 	/* rx offset center enabled */
@@ -7486,68 +7331,39 @@ static void write_tx_serdes_param(struct qib_pportdata *ppd,
 		    SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txc0_ena) |
 		    SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcp1_ena) |
 		    SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcn1_ena));
-	deemph |= 1ULL << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
-				  tx_override_deemphasis_select);
-	deemph |= txdds->amp << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
-				    txampcntl_d2a);
-	deemph |= txdds->main << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
-				      txc0_ena);
-	deemph |= txdds->post << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
-				     txcp1_ena);
-	deemph |= txdds->pre << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+
+	deemph |= SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+			   tx_override_deemphasis_select);
+	deemph |= (txdds->amp & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+		    txampcntl_d2a)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+				       txampcntl_d2a);
+	deemph |= (txdds->main & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+		     txc0_ena)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+				   txc0_ena);
+	deemph |= (txdds->post & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+		     txcp1_ena)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+				    txcp1_ena);
+	deemph |= (txdds->pre & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
+		     txcn1_ena)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
 				    txcn1_ena);
 	qib_write_kreg_port(ppd, krp_tx_deemph_override, deemph);
 }
 
 /*
- * set per-bay, per channel parameters.  For now, we ignore
- * do_tx, and always set tx parameters, and set them with the same value
- * for all channels, using the channel 0 value.   We may switch to
- * per-channel settings in the future, and that method only needs
- * to be done once.
- * Because this also writes the IBC txdds table with a single set
- * of values, it should be called only for cases where we want to completely
- * force a specific setting, typically only for mez cards.
+ * Set the parameters for mez cards on link bounce, so they are
+ * always exactly what was requested.  Similar logic to init_txdds
+ * but does just the serdes.
  */
 static void adj_tx_serdes(struct qib_pportdata *ppd)
 {
-	struct txdds_ent txdds;
-	int i;
-	u8 *amp, *pre, *mainv, *post;
-
-	/*
-	 * Because we use TX_DEEMPHASIS_OVERRIDE, we need to
-	 * always do tx side, just like H1, since it is cleared
-	 * by link down
-	 */
-	amp = ppd->cpspec->amp;
-	pre = ppd->cpspec->pre;
-	mainv = ppd->cpspec->mainv;
-	post = ppd->cpspec->post;
-
-	amp[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
-			    txampcntl_d2a);
-	mainv[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
-			      txc0_ena);
-	post[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
-			     txcp1_ena);
-	pre[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
-			    txcn1_ena);
-
-	/*
-	 * Use the channel zero values, only, for now, for
-	 * all channels
-	*/
-	txdds.amp = amp[0];
-	txdds.pre = pre[0];
-	txdds.main = mainv[0];
-	txdds.post = post[0];
-
-	/* write the QDR table for IBC use, as backup for link down */
-	for (i = 0; i < ARRAY_SIZE(txdds_qdr); ++i)
-		set_txdds(ppd, i + 32, &txdds);
+	const struct txdds_ent *sdr_dds, *ddr_dds, *qdr_dds;
+	struct txdds_ent *dds;
 
-	write_tx_serdes_param(ppd, &txdds);
+	find_best_ent(ppd, &sdr_dds, &ddr_dds, &qdr_dds, 1);
+	dds = (struct txdds_ent *)(ppd->link_speed_active == QIB_IB_QDR ?
+		qdr_dds : (ppd->link_speed_active == QIB_IB_DDR ?
+				ddr_dds : sdr_dds));
+	write_tx_serdes_param(ppd, dds);
 }
 
 /* set QDR forced value for H1, if needed */
@@ -7567,235 +7383,6 @@ static void force_h1(struct qib_pportdata *ppd)
 	}
 }
 
-/*
- * Parse the parameters for the QMH7342, to get rx and tx serdes
- * settings for that Bay, for both possible mez connectors (PCIe bus)
- * and IB link (one link on mez1, two possible on mez2).
- *
- * Data is comma or white space separated.
- *
- * A set of data has 7 groups, rx and tx groups have SERDES_CHANS values,
- * one per IB lane (serdes channel).
- * The groups are Bay, bus# H1 rcv, and amp, pre, post, main Tx values (QDR).
- * The Bay # is used only for debugging currently.
- * H1 values are set whenever the link goes down, or is at cfg_test or
- * cfg_wait_enh.  Tx values are programmed once, when this routine is called
- * (and with default values at chip initialization).  Values are any base, in
- * strtoul style, and values are seperated by comma, or any white space
- * (space, tab, newline).
- *
- * An example set might look like this (white space vs
- * comma used for human ease of reading)
- * The ordering is a set of Bay# Bus# H1, amp, pre, post, and main for mez1 IB1,
- * repeat for mez2 IB1, then mez2 IB2.
- *
- * B B H1:0       amp:0       pre:0        post: 0        main:0
- * a u H1:  1     amp:  1     pre:  1      post:   1      main:  1
- * y s H1:    2   amp:    2   pre:    2    post:      2   main:    2
- *     H1:      4 amp:      3 pre:      3  post:        3 main:      3
- * 1 3    8,6,5,6     0,0,0,0     1,1,1,1       10,10,10,10    3,3,3,3
- * 1 6    7,6,6,7     0,0,0,0     1,1,1,1       10,10,10,10    3,3,3,3
- * 1 6    9,7,7,8     0,0,0,0     1,1,1,1       10,10,10,10    3,3,3,3
- */
-#define N_QMH_FIELDS 22
-static int setup_qmh_params(const char *str, struct kernel_param *kp)
-{
-	char *abuf, *v, *nv, *nvp;
-	struct qib_devdata *dd;
-	struct qib_pportdata *ppd;
-	u32 mez, vlen, nf, port, bay;
-	int ret = 0, found = 0;
-
-	vlen = strlen(str) + 1;
-	abuf = kmalloc(vlen, GFP_KERNEL);
-	if (!abuf) {
-		printk(KERN_INFO QIB_DRV_NAME
-		       " Unable to allocate QMH param buffer; ignoring\n");
-		return 0;
-	}
-	memcpy(abuf, str, vlen);
-	v = abuf;
-
-	/* these 3 are because gcc can't know they are set before used */
-	port = 1;
-	mez = 1; /* used only for debugging */
-	bay = 0; /* used only for debugging */
-	ppd = NULL;
-	for (nf = 0; (nv = strsep(&v, ", \t\n\r")) &&
-	     nf < (N_QMH_FIELDS * 3);) {
-		u32 val;
-
-		if (!*nv)
-			/* allow for multiple separators */
-			continue;
-
-		val = simple_strtoul(nv, &nvp, 0);
-		if (nv == nvp) {
-			printk(KERN_INFO QIB_DRV_NAME
-			       " Bay%u, mez%u IB%u non-numeric value (%s) "
-			       "field #%u, ignoring rest\n", bay, mez,
-			       port, nv, nf % (N_QMH_FIELDS * 3));
-			ret = -EINVAL;
-			goto bail;
-		}
-		if (!(nf % N_QMH_FIELDS)) {
-			ppd = NULL;
-			bay = val;
-			if (!bay || bay > 16) {
-				printk(KERN_INFO QIB_DRV_NAME
-				       " Invalid bay # %u, field %u, "
-				       "ignoring rest\n", bay, nf);
-				ret = -EINVAL;
-				goto bail;
-			}
-		} else if ((nf % N_QMH_FIELDS) == 1) {
-			u32 bus = val;
-			if (nf == 1) {
-				mez = 1;
-				port = 1;
-			} else if (nf == (N_QMH_FIELDS + 1)) {
-				mez = 2;
-				port = 1;
-			} else {
-				mez = 2;
-				port = 2;
-			}
-			list_for_each_entry(dd, &qib_dev_list, list) {
-				if (dd->deviceid != PCI_DEVICE_ID_QLOGIC_IB_7322
-				    || !IS_QMH(dd))
-					continue; /* only for QMH cards */
-				if (dd->pcidev->bus->number == bus) {
-					found++;
-					ppd = &dd->pport[port - 1];
-				}
-			}
-		} else if (ppd) {
-			u32 parm = (nf % N_QMH_FIELDS) - 2;
-			if (parm < SERDES_CHANS && !(parm % SERDES_CHANS))
-				ppd->cpspec->h1_val = val;
-			else if (parm < (2 * SERDES_CHANS))
-				ppd->cpspec->amp[parm % SERDES_CHANS] = val;
-			else if (parm < (3 * SERDES_CHANS))
-				ppd->cpspec->pre[parm % SERDES_CHANS] = val;
-			else if (parm < (4 * SERDES_CHANS))
-				ppd->cpspec->post[parm % SERDES_CHANS] = val;
-			else {
-				ppd->cpspec->mainv[parm % SERDES_CHANS] = val;
-				/* At the end of a port, set params */
-				if (parm == ((5 * SERDES_CHANS) - 1))
-					adj_tx_serdes(ppd);
-			}
-		}
-		nf++;
-	}
-	if (!found) {
-		printk(KERN_ERR QIB_DRV_NAME
-		       ": No match found for qmh_serdes_setup parameter\n");
-		ret = -EINVAL;
-	}
-bail:
-	kfree(abuf);
-	return ret;
-}
-
-/*
- * Similarly for QME7342, but the format is simpler, values are the
- * same for all mez card positions in a blade (2 or 4 per blade), but
- * are different for some blades vs others, and we don't need to
- * specify different parameters for different serdes channels or different
- * IB ports.
- * Format is: h1 amp,pre,post,main
- * Alternate format (so ports can be different): Pport# h1 amp,pre,post,main
- */
-#define N_QME_FIELDS 5
-static int setup_qme_params(const char *str, struct kernel_param *kp)
-{
-	char *abuf, *v, *nv, *nvp;
-	struct qib_devdata *dd;
-	u32 vlen, nf, port = 0;
-	u8 h1, tx[4]; /* amp, pre, post, main */
-	int ret =  -EINVAL;
-	char *seplist;
-
-	vlen = strlen(str) + 1;
-	abuf = kmalloc(vlen, GFP_KERNEL);
-	if (!abuf) {
-		printk(KERN_INFO QIB_DRV_NAME
-		       " Unable to allocate QME param buffer; ignoring\n");
-		return 0;
-	}
-	strncpy(abuf, str, vlen);
-
-	v = abuf;
-	seplist = " \t";
-	h1 = H1_FORCE_QME; /* gcc can't figure out always set before used */
-
-	for (nf = 0; (nv = strsep(&v, seplist)); ) {
-		u32 val;
-
-		if (!*nv)
-			/* allow for multiple separators */
-			continue;
-
-		if (!nf && *nv == 'P') {
-			/* alternate format with port */
-			val = simple_strtoul(++nv, &nvp, 0);
-			if (nv == nvp || port >= NUM_IB_PORTS) {
-				printk(KERN_INFO QIB_DRV_NAME
-				       " %s: non-numeric port value (%s) "
-				       "ignoring rest\n", __func__, nv);
-				goto done;
-			}
-			port = val;
-			continue; /* without incrementing nf */
-		}
-		val = simple_strtoul(nv, &nvp, 0);
-		if (nv == nvp) {
-			printk(KERN_INFO QIB_DRV_NAME
-			       " %s: non-numeric value (%s) "
-			       "field #%u, ignoring rest\n", __func__,
-			       nv, nf);
-			goto done;
-		}
-		if (!nf) {
-			h1 = val;
-			seplist = ",";
-		} else
-			tx[nf - 1] = val;
-		if (++nf == N_QME_FIELDS) {
-			list_for_each_entry(dd, &qib_dev_list, list) {
-				int pidx, i;
-				if (dd->deviceid != PCI_DEVICE_ID_QLOGIC_IB_7322
-				    || !IS_QME(dd))
-					continue; /* only for QME cards */
-				for (pidx = 0; pidx < dd->num_pports; ++pidx) {
-					struct qib_pportdata *ppd;
-					ppd = &dd->pport[pidx];
-					if ((port && ppd->port != port) ||
-						!ppd->link_speed_supported)
-						continue;
-					ppd->cpspec->h1_val = h1;
-					for (i = 0; i < SERDES_CHANS; i++) {
-						ppd->cpspec->amp[i] = tx[0];
-						ppd->cpspec->pre[i] = tx[1];
-						ppd->cpspec->post[i] = tx[2];
-						ppd->cpspec->mainv[i] = tx[3];
-					}
-					adj_tx_serdes(ppd);
-				}
-			}
-			ret = 0;
-			goto done;
-		}
-	}
-	printk(KERN_INFO QIB_DRV_NAME
-	       " %s: Only %u of %u fields provided, skipping\n",
-	       __func__, nf, N_QME_FIELDS);
-done:
-	kfree(abuf);
-	return ret;
-}
-
 #define SJA_EN SYM_MASK(SPC_JTAG_ACCESS_REG, SPC_JTAG_ACCESS_EN)
 #define BISTEN_LSB SYM_LSB(SPC_JTAG_ACCESS_REG, bist_en)
 
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index c0139c07e97e..9b40f345ac3f 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -1237,7 +1237,13 @@ static int __devinit qib_init_one(struct pci_dev *pdev,
 	 */
 	switch (ent->device) {
 	case PCI_DEVICE_ID_QLOGIC_IB_6120:
+#ifdef CONFIG_PCI_MSI
 		dd = qib_init_iba6120_funcs(pdev, ent);
+#else
+		qib_early_err(&pdev->dev, "QLogic PCIE device 0x%x cannot "
+		      "work if CONFIG_PCI_MSI is not enabled\n",
+		      ent->device);
+#endif
 		break;
 
 	case PCI_DEVICE_ID_QLOGIC_IB_7220: