提交 767dcd42 编写于 作者: R Roland Dreier

Merge branches 'misc' and 'qib' into for-next

......@@ -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[] = {
......
......@@ -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");
......
......@@ -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,34 +5636,34 @@ 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;
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)
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.
*/
*sdr_dds = &txdds_sdr[ppd->cpspec->no_eep];
*ddr_dds = &txdds_ddr[ppd->cpspec->no_eep];
*qdr_dds = &txdds_qdr[ppd->cpspec->no_eep];
* EEPROM, or no QSFP, or override is set, use the
* module parameter value to index into the attentuation
* table.
*/
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;
single_ent = 1;
} else
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;
/* 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 ==
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,
deemph |= SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
tx_override_deemphasis_select);
deemph |= txdds->amp << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
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_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
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_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
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_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
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)
......
......@@ -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:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册