diff options
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_iba7322.c | 582 |
1 files changed, 179 insertions, 403 deletions
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 2c24eab35b5..23fb9efe20a 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c | |||
| @@ -114,40 +114,18 @@ static ushort qib_singleport; | |||
| 114 | module_param_named(singleport, qib_singleport, ushort, S_IRUGO); | 114 | module_param_named(singleport, qib_singleport, ushort, S_IRUGO); |
| 115 | MODULE_PARM_DESC(singleport, "Use only IB port 1; more per-port buffer space"); | 115 | MODULE_PARM_DESC(singleport, "Use only IB port 1; more per-port buffer space"); |
| 116 | 116 | ||
| 117 | |||
| 118 | /* | ||
| 119 | * Setup QMH7342 receive and transmit parameters, necessary because | ||
| 120 | * each bay, Mez connector, and IB port need different tuning, beyond | ||
| 121 | * what the switch and HCA can do automatically. | ||
| 122 | * It's expected to be done by cat'ing files to the modules file, | ||
| 123 | * rather than setting up as a module parameter. | ||
| 124 | * It's a "write-only" file, returns 0 when read back. | ||
| 125 | * The unit, port, bay (if given), and values MUST be done as a single write. | ||
| 126 | * The unit, port, and bay must precede the values to be effective. | ||
| 127 | */ | ||
| 128 | static int setup_qmh_params(const char *, struct kernel_param *); | ||
| 129 | static unsigned dummy_qmh_params; | ||
| 130 | module_param_call(qmh_serdes_setup, setup_qmh_params, param_get_uint, | ||
| 131 | &dummy_qmh_params, S_IWUSR | S_IRUGO); | ||
| 132 | |||
| 133 | /* similarly for QME7342, but it's simpler */ | ||
| 134 | static int setup_qme_params(const char *, struct kernel_param *); | ||
| 135 | static unsigned dummy_qme_params; | ||
| 136 | module_param_call(qme_serdes_setup, setup_qme_params, param_get_uint, | ||
| 137 | &dummy_qme_params, S_IWUSR | S_IRUGO); | ||
| 138 | |||
| 139 | #define MAX_ATTEN_LEN 64 /* plenty for any real system */ | 117 | #define MAX_ATTEN_LEN 64 /* plenty for any real system */ |
| 140 | /* for read back, default index is ~5m copper cable */ | 118 | /* for read back, default index is ~5m copper cable */ |
| 141 | static char cable_atten_list[MAX_ATTEN_LEN] = "10"; | 119 | static char txselect_list[MAX_ATTEN_LEN] = "10"; |
| 142 | static struct kparam_string kp_cable_atten = { | 120 | static struct kparam_string kp_txselect = { |
| 143 | .string = cable_atten_list, | 121 | .string = txselect_list, |
| 144 | .maxlen = MAX_ATTEN_LEN | 122 | .maxlen = MAX_ATTEN_LEN |
| 145 | }; | 123 | }; |
| 146 | static int setup_cable_atten(const char *, struct kernel_param *); | 124 | static int setup_txselect(const char *, struct kernel_param *); |
| 147 | module_param_call(cable_atten, setup_cable_atten, param_get_string, | 125 | module_param_call(txselect, setup_txselect, param_get_string, |
| 148 | &kp_cable_atten, S_IWUSR | S_IRUGO); | 126 | &kp_txselect, S_IWUSR | S_IRUGO); |
| 149 | MODULE_PARM_DESC(cable_atten, \ | 127 | MODULE_PARM_DESC(txselect, \ |
| 150 | "cable attenuation indices for cables with invalid EEPROM"); | 128 | "Tx serdes indices (for no QSFP or invalid QSFP data)"); |
| 151 | 129 | ||
| 152 | #define BOARD_QME7342 5 | 130 | #define BOARD_QME7342 5 |
| 153 | #define BOARD_QMH7342 6 | 131 | #define BOARD_QMH7342 6 |
| @@ -574,11 +552,12 @@ struct vendor_txdds_ent { | |||
| 574 | static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *); | 552 | static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *); |
| 575 | 553 | ||
| 576 | #define TXDDS_TABLE_SZ 16 /* number of entries per speed in onchip table */ | 554 | #define TXDDS_TABLE_SZ 16 /* number of entries per speed in onchip table */ |
| 555 | #define TXDDS_EXTRA_SZ 11 /* number of extra tx settings entries */ | ||
| 577 | #define SERDES_CHANS 4 /* yes, it's obvious, but one less magic number */ | 556 | #define SERDES_CHANS 4 /* yes, it's obvious, but one less magic number */ |
| 578 | 557 | ||
| 579 | #define H1_FORCE_VAL 8 | 558 | #define H1_FORCE_VAL 8 |
| 580 | #define H1_FORCE_QME 1 /* may be overridden via setup_qme_params() */ | 559 | #define H1_FORCE_QME 1 /* may be overridden via setup_txselect() */ |
| 581 | #define H1_FORCE_QMH 7 /* may be overridden via setup_qmh_params() */ | 560 | #define H1_FORCE_QMH 7 /* may be overridden via setup_txselect() */ |
| 582 | 561 | ||
| 583 | /* The static and dynamic registers are paired, and the pairs indexed by spd */ | 562 | /* The static and dynamic registers are paired, and the pairs indexed by spd */ |
| 584 | #define krp_static_adapt_dis(spd) (KREG_IBPORT_IDX(ADAPT_DISABLE_STATIC_SDR) \ | 563 | #define krp_static_adapt_dis(spd) (KREG_IBPORT_IDX(ADAPT_DISABLE_STATIC_SDR) \ |
| @@ -590,15 +569,6 @@ static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *); | |||
| 590 | #define QDR_STATIC_ADAPT_INIT 0xffffffffffULL /* up, disable H0,H1-8, LE */ | 569 | #define QDR_STATIC_ADAPT_INIT 0xffffffffffULL /* up, disable H0,H1-8, LE */ |
| 591 | #define QDR_STATIC_ADAPT_INIT_R1 0xf0ffffffffULL /* r1 up, disable H0,H1-8 */ | 570 | #define QDR_STATIC_ADAPT_INIT_R1 0xf0ffffffffULL /* r1 up, disable H0,H1-8 */ |
| 592 | 571 | ||
| 593 | static const struct txdds_ent qmh_sdr_txdds = { 11, 0, 5, 6 }; | ||
| 594 | static const struct txdds_ent qmh_ddr_txdds = { 7, 0, 2, 8 }; | ||
| 595 | static const struct txdds_ent qmh_qdr_txdds = { 0, 1, 3, 10 }; | ||
| 596 | |||
| 597 | /* this is used for unknown mez cards also */ | ||
| 598 | static const struct txdds_ent qme_sdr_txdds = { 11, 0, 4, 4 }; | ||
| 599 | static const struct txdds_ent qme_ddr_txdds = { 7, 0, 2, 7 }; | ||
| 600 | static const struct txdds_ent qme_qdr_txdds = { 0, 1, 12, 11 }; | ||
| 601 | |||
| 602 | struct qib_chippport_specific { | 572 | struct qib_chippport_specific { |
| 603 | u64 __iomem *kpregbase; | 573 | u64 __iomem *kpregbase; |
| 604 | u64 __iomem *cpregbase; | 574 | u64 __iomem *cpregbase; |
| @@ -637,12 +607,8 @@ struct qib_chippport_specific { | |||
| 637 | * Per-bay per-channel rcv QMH H1 values and Tx values for QDR. | 607 | * Per-bay per-channel rcv QMH H1 values and Tx values for QDR. |
| 638 | * entry zero is unused, to simplify indexing | 608 | * entry zero is unused, to simplify indexing |
| 639 | */ | 609 | */ |
| 640 | u16 h1_val; | 610 | u8 h1_val; |
| 641 | u8 amp[SERDES_CHANS]; | 611 | u8 no_eep; /* txselect table index to use if no qsfp info */ |
| 642 | u8 pre[SERDES_CHANS]; | ||
| 643 | u8 mainv[SERDES_CHANS]; | ||
| 644 | u8 post[SERDES_CHANS]; | ||
| 645 | u8 no_eep; /* attenuation index to use if no qsfp info */ | ||
| 646 | u8 ipg_tries; | 612 | u8 ipg_tries; |
| 647 | u8 ibmalfusesnap; | 613 | u8 ibmalfusesnap; |
| 648 | struct qib_qsfp_data qsfp_data; | 614 | struct qib_qsfp_data qsfp_data; |
| @@ -5360,7 +5326,13 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs) | |||
| 5360 | QIBL_IB_AUTONEG_INPROG))) | 5326 | QIBL_IB_AUTONEG_INPROG))) |
| 5361 | set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled); | 5327 | set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled); |
| 5362 | if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) { | 5328 | if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) { |
| 5329 | /* unlock the Tx settings, speed may change */ | ||
| 5330 | qib_write_kreg_port(ppd, krp_tx_deemph_override, | ||
| 5331 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
| 5332 | reset_tx_deemphasis_override)); | ||
| 5363 | qib_cancel_sends(ppd); | 5333 | qib_cancel_sends(ppd); |
| 5334 | /* on link down, ensure sane pcs state */ | ||
| 5335 | qib_7322_mini_pcs_reset(ppd); | ||
| 5364 | spin_lock_irqsave(&ppd->sdma_lock, flags); | 5336 | spin_lock_irqsave(&ppd->sdma_lock, flags); |
| 5365 | if (__qib_sdma_running(ppd)) | 5337 | if (__qib_sdma_running(ppd)) |
| 5366 | __qib_sdma_process_event(ppd, | 5338 | __qib_sdma_process_event(ppd, |
| @@ -5766,26 +5738,28 @@ static void qib_init_7322_qsfp(struct qib_pportdata *ppd) | |||
| 5766 | } | 5738 | } |
| 5767 | 5739 | ||
| 5768 | /* | 5740 | /* |
| 5769 | * called at device initialization time, and also if the cable_atten | 5741 | * called at device initialization time, and also if the txselect |
| 5770 | * module parameter is changed. This is used for cables that don't | 5742 | * module parameter is changed. This is used for cables that don't |
| 5771 | * have valid QSFP EEPROMs (not present, or attenuation is zero). | 5743 | * have valid QSFP EEPROMs (not present, or attenuation is zero). |
| 5772 | * We initialize to the default, then if there is a specific | 5744 | * We initialize to the default, then if there is a specific |
| 5773 | * unit,port match, we use that. | 5745 | * unit,port match, we use that (and set it immediately, for the |
| 5746 | * current speed, if the link is at INIT or better). | ||
| 5774 | * String format is "default# unit#,port#=# ... u,p=#", separators must | 5747 | * String format is "default# unit#,port#=# ... u,p=#", separators must |
| 5775 | * be a SPACE character. A newline terminates. | 5748 | * be a SPACE character. A newline terminates. The u,p=# tuples may |
| 5749 | * optionally have "u,p=#,#", where the final # is the H1 value | ||
| 5776 | * The last specific match is used (actually, all are used, but last | 5750 | * The last specific match is used (actually, all are used, but last |
| 5777 | * one is the one that winds up set); if none at all, fall back on default. | 5751 | * one is the one that winds up set); if none at all, fall back on default. |
| 5778 | */ | 5752 | */ |
| 5779 | static void set_no_qsfp_atten(struct qib_devdata *dd, int change) | 5753 | static void set_no_qsfp_atten(struct qib_devdata *dd, int change) |
| 5780 | { | 5754 | { |
| 5781 | char *nxt, *str; | 5755 | char *nxt, *str; |
| 5782 | int pidx, unit, port, deflt; | 5756 | u32 pidx, unit, port, deflt, h1; |
| 5783 | unsigned long val; | 5757 | unsigned long val; |
| 5784 | int any = 0; | 5758 | int any = 0, seth1; |
| 5785 | 5759 | ||
| 5786 | str = cable_atten_list; | 5760 | str = txselect_list; |
| 5787 | 5761 | ||
| 5788 | /* default number is validated in setup_cable_atten() */ | 5762 | /* default number is validated in setup_txselect() */ |
| 5789 | deflt = simple_strtoul(str, &nxt, 0); | 5763 | deflt = simple_strtoul(str, &nxt, 0); |
| 5790 | for (pidx = 0; pidx < dd->num_pports; ++pidx) | 5764 | for (pidx = 0; pidx < dd->num_pports; ++pidx) |
| 5791 | dd->pport[pidx].cpspec->no_eep = deflt; | 5765 | dd->pport[pidx].cpspec->no_eep = deflt; |
| @@ -5812,16 +5786,28 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change) | |||
| 5812 | ; | 5786 | ; |
| 5813 | continue; | 5787 | continue; |
| 5814 | } | 5788 | } |
| 5815 | if (val >= TXDDS_TABLE_SZ) | 5789 | if (val >= TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ) |
| 5816 | continue; | 5790 | continue; |
| 5791 | seth1 = 0; | ||
| 5792 | h1 = 0; /* gcc thinks it might be used uninitted */ | ||
| 5793 | if (*nxt == ',' && nxt[1]) { | ||
| 5794 | str = ++nxt; | ||
| 5795 | h1 = (u32)simple_strtoul(str, &nxt, 0); | ||
| 5796 | if (nxt == str) | ||
| 5797 | while (*nxt && *nxt++ != ' ') /* skip */ | ||
| 5798 | ; | ||
| 5799 | else | ||
| 5800 | seth1 = 1; | ||
| 5801 | } | ||
| 5817 | for (pidx = 0; dd->unit == unit && pidx < dd->num_pports; | 5802 | for (pidx = 0; dd->unit == unit && pidx < dd->num_pports; |
| 5818 | ++pidx) { | 5803 | ++pidx) { |
| 5819 | if (dd->pport[pidx].port != port || | 5804 | struct qib_pportdata *ppd = &dd->pport[pidx]; |
| 5820 | !dd->pport[pidx].link_speed_supported) | 5805 | |
| 5806 | if (ppd->port != port || !ppd->link_speed_supported) | ||
| 5821 | continue; | 5807 | continue; |
| 5822 | dd->pport[pidx].cpspec->no_eep = val; | 5808 | ppd->cpspec->no_eep = val; |
| 5823 | /* now change the IBC and serdes, overriding generic */ | 5809 | /* now change the IBC and serdes, overriding generic */ |
| 5824 | init_txdds_table(&dd->pport[pidx], 1); | 5810 | init_txdds_table(ppd, 1); |
| 5825 | any++; | 5811 | any++; |
| 5826 | } | 5812 | } |
| 5827 | if (*nxt == '\n') | 5813 | if (*nxt == '\n') |
| @@ -5832,35 +5818,35 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change) | |||
| 5832 | * Change the IBC and serdes, but since it's | 5818 | * Change the IBC and serdes, but since it's |
| 5833 | * general, don't override specific settings. | 5819 | * general, don't override specific settings. |
| 5834 | */ | 5820 | */ |
| 5835 | for (pidx = 0; pidx < dd->num_pports; ++pidx) { | 5821 | for (pidx = 0; pidx < dd->num_pports; ++pidx) |
| 5836 | if (!dd->pport[pidx].link_speed_supported) | 5822 | if (dd->pport[pidx].link_speed_supported) |
| 5837 | continue; | 5823 | init_txdds_table(&dd->pport[pidx], 0); |
| 5838 | init_txdds_table(&dd->pport[pidx], 0); | ||
| 5839 | } | ||
| 5840 | } | 5824 | } |
| 5841 | } | 5825 | } |
| 5842 | 5826 | ||
| 5843 | /* handle the cable_atten parameter changing */ | 5827 | /* handle the txselect parameter changing */ |
| 5844 | static int setup_cable_atten(const char *str, struct kernel_param *kp) | 5828 | static int setup_txselect(const char *str, struct kernel_param *kp) |
| 5845 | { | 5829 | { |
| 5846 | struct qib_devdata *dd; | 5830 | struct qib_devdata *dd; |
| 5847 | unsigned long val; | 5831 | unsigned long val; |
| 5848 | char *n; | 5832 | char *n; |
| 5849 | if (strlen(str) >= MAX_ATTEN_LEN) { | 5833 | if (strlen(str) >= MAX_ATTEN_LEN) { |
| 5850 | printk(KERN_INFO QIB_DRV_NAME " cable_atten_values string " | 5834 | printk(KERN_INFO QIB_DRV_NAME " txselect_values string " |
| 5851 | "too long\n"); | 5835 | "too long\n"); |
| 5852 | return -ENOSPC; | 5836 | return -ENOSPC; |
| 5853 | } | 5837 | } |
| 5854 | val = simple_strtoul(str, &n, 0); | 5838 | val = simple_strtoul(str, &n, 0); |
| 5855 | if (n == str || val >= TXDDS_TABLE_SZ) { | 5839 | if (n == str || val >= (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ)) { |
| 5856 | printk(KERN_INFO QIB_DRV_NAME | 5840 | printk(KERN_INFO QIB_DRV_NAME |
| 5857 | "cable_atten_values must start with a number\n"); | 5841 | "txselect_values must start with a number < %d\n", |
| 5842 | TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ); | ||
| 5858 | return -EINVAL; | 5843 | return -EINVAL; |
| 5859 | } | 5844 | } |
| 5860 | strcpy(cable_atten_list, str); | 5845 | strcpy(txselect_list, str); |
| 5861 | 5846 | ||
| 5862 | list_for_each_entry(dd, &qib_dev_list, list) | 5847 | list_for_each_entry(dd, &qib_dev_list, list) |
| 5863 | set_no_qsfp_atten(dd, 1); | 5848 | if (dd->deviceid == PCI_DEVICE_ID_QLOGIC_IB_7322) |
| 5849 | set_no_qsfp_atten(dd, 1); | ||
| 5864 | return 0; | 5850 | return 0; |
| 5865 | } | 5851 | } |
| 5866 | 5852 | ||
| @@ -6261,28 +6247,17 @@ static int qib_init_7322_variables(struct qib_devdata *dd) | |||
| 6261 | * in adapter-specific routines. | 6247 | * in adapter-specific routines. |
| 6262 | */ | 6248 | */ |
| 6263 | if (!(ppd->dd->flags & QIB_HAS_QSFP)) { | 6249 | if (!(ppd->dd->flags & QIB_HAS_QSFP)) { |
| 6264 | int i; | ||
| 6265 | const struct txdds_ent *txdds; | ||
| 6266 | |||
| 6267 | if (!IS_QMH(ppd->dd) && !IS_QME(ppd->dd)) | 6250 | if (!IS_QMH(ppd->dd) && !IS_QME(ppd->dd)) |
| 6268 | qib_devinfo(ppd->dd->pcidev, "IB%u:%u: " | 6251 | qib_devinfo(ppd->dd->pcidev, "IB%u:%u: " |
| 6269 | "Unknown mezzanine card type\n", | 6252 | "Unknown mezzanine card type\n", |
| 6270 | ppd->dd->unit, ppd->port); | 6253 | dd->unit, ppd->port); |
| 6271 | txdds = IS_QMH(ppd->dd) ? &qmh_qdr_txdds : | 6254 | cp->h1_val = IS_QMH(dd) ? H1_FORCE_QMH : H1_FORCE_QME; |
| 6272 | &qme_qdr_txdds; | ||
| 6273 | |||
| 6274 | /* | 6255 | /* |
| 6275 | * set values in case link comes up | 6256 | * Choose center value as default tx serdes setting |
| 6276 | * before table is written to driver. | 6257 | * until changed through module parameter. |
| 6277 | */ | 6258 | */ |
| 6278 | cp->h1_val = IS_QMH(ppd->dd) ? H1_FORCE_QMH : | 6259 | ppd->cpspec->no_eep = IS_QMH(dd) ? |
| 6279 | H1_FORCE_QME; | 6260 | TXDDS_TABLE_SZ + 2 : TXDDS_TABLE_SZ + 4; |
| 6280 | for (i = 0; i < SERDES_CHANS; i++) { | ||
| 6281 | cp->amp[i] = txdds->amp; | ||
| 6282 | cp->pre[i] = txdds->pre; | ||
| 6283 | cp->mainv[i] = txdds->main; | ||
| 6284 | cp->post[i] = txdds->post; | ||
| 6285 | } | ||
| 6286 | } else | 6261 | } else |
| 6287 | cp->h1_val = H1_FORCE_VAL; | 6262 | cp->h1_val = H1_FORCE_VAL; |
| 6288 | 6263 | ||
| @@ -6299,8 +6274,7 @@ static int qib_init_7322_variables(struct qib_devdata *dd) | |||
| 6299 | 6274 | ||
| 6300 | dd->rcvhdrentsize = QIB_RCVHDR_ENTSIZE; | 6275 | dd->rcvhdrentsize = QIB_RCVHDR_ENTSIZE; |
| 6301 | dd->rcvhdrsize = QIB_DFLT_RCVHDRSIZE; | 6276 | dd->rcvhdrsize = QIB_DFLT_RCVHDRSIZE; |
| 6302 | dd->rhf_offset = | 6277 | dd->rhf_offset = dd->rcvhdrentsize - sizeof(u64) / sizeof(u32); |
| 6303 | dd->rcvhdrentsize - sizeof(u64) / sizeof(u32); | ||
| 6304 | 6278 | ||
| 6305 | /* we always allocate at least 2048 bytes for eager buffers */ | 6279 | /* we always allocate at least 2048 bytes for eager buffers */ |
| 6306 | dd->rcvegrbufsize = max(mtu, 2048); | 6280 | dd->rcvegrbufsize = max(mtu, 2048); |
| @@ -7111,8 +7085,8 @@ static const struct txdds_ent txdds_ddr[TXDDS_TABLE_SZ] = { | |||
| 7111 | static const struct txdds_ent txdds_qdr[TXDDS_TABLE_SZ] = { | 7085 | static const struct txdds_ent txdds_qdr[TXDDS_TABLE_SZ] = { |
| 7112 | /* amp, pre, main, post */ | 7086 | /* amp, pre, main, post */ |
| 7113 | { 2, 2, 15, 6 }, /* Loopback */ | 7087 | { 2, 2, 15, 6 }, /* Loopback */ |
| 7114 | { 0, 1, 0, 7 }, /* 2 dB */ | 7088 | { 0, 1, 0, 7 }, /* 2 dB (also QMH7342) */ |
| 7115 | { 0, 1, 0, 9 }, /* 3 dB */ | 7089 | { 0, 1, 0, 9 }, /* 3 dB (also QMH7342) */ |
| 7116 | { 0, 1, 0, 11 }, /* 4 dB */ | 7090 | { 0, 1, 0, 11 }, /* 4 dB */ |
| 7117 | { 0, 1, 0, 13 }, /* 5 dB */ | 7091 | { 0, 1, 0, 13 }, /* 5 dB */ |
| 7118 | { 0, 1, 0, 15 }, /* 6 dB */ | 7092 | { 0, 1, 0, 15 }, /* 6 dB */ |
| @@ -7128,6 +7102,57 @@ static const struct txdds_ent txdds_qdr[TXDDS_TABLE_SZ] = { | |||
| 7128 | { 0, 2, 9, 15 }, /* 16 dB */ | 7102 | { 0, 2, 9, 15 }, /* 16 dB */ |
| 7129 | }; | 7103 | }; |
| 7130 | 7104 | ||
| 7105 | /* | ||
| 7106 | * extra entries for use with txselect, for indices >= TXDDS_TABLE_SZ. | ||
| 7107 | * These are mostly used for mez cards going through connectors | ||
| 7108 | * and backplane traces, but can be used to add other "unusual" | ||
| 7109 | * table values as well. | ||
| 7110 | */ | ||
| 7111 | static const struct txdds_ent txdds_extra_sdr[TXDDS_EXTRA_SZ] = { | ||
| 7112 | /* amp, pre, main, post */ | ||
| 7113 | { 0, 0, 0, 1 }, /* QMH7342 backplane settings */ | ||
| 7114 | { 0, 0, 0, 1 }, /* QMH7342 backplane settings */ | ||
| 7115 | { 0, 0, 0, 2 }, /* QMH7342 backplane settings */ | ||
| 7116 | { 0, 0, 0, 2 }, /* QMH7342 backplane settings */ | ||
| 7117 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
| 7118 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
| 7119 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
| 7120 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
| 7121 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
| 7122 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
| 7123 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
| 7124 | }; | ||
| 7125 | |||
| 7126 | static const struct txdds_ent txdds_extra_ddr[TXDDS_EXTRA_SZ] = { | ||
| 7127 | /* amp, pre, main, post */ | ||
| 7128 | { 0, 0, 0, 7 }, /* QMH7342 backplane settings */ | ||
| 7129 | { 0, 0, 0, 7 }, /* QMH7342 backplane settings */ | ||
| 7130 | { 0, 0, 0, 8 }, /* QMH7342 backplane settings */ | ||
| 7131 | { 0, 0, 0, 8 }, /* QMH7342 backplane settings */ | ||
| 7132 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
| 7133 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
| 7134 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
| 7135 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
| 7136 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
| 7137 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
| 7138 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
| 7139 | }; | ||
| 7140 | |||
| 7141 | static const struct txdds_ent txdds_extra_qdr[TXDDS_EXTRA_SZ] = { | ||
| 7142 | /* amp, pre, main, post */ | ||
| 7143 | { 0, 1, 0, 4 }, /* QMH7342 backplane settings */ | ||
| 7144 | { 0, 1, 0, 5 }, /* QMH7342 backplane settings */ | ||
| 7145 | { 0, 1, 0, 6 }, /* QMH7342 backplane settings */ | ||
| 7146 | { 0, 1, 0, 8 }, /* QMH7342 backplane settings */ | ||
| 7147 | { 0, 1, 12, 10 }, /* QME7342 backplane setting */ | ||
| 7148 | { 0, 1, 12, 11 }, /* QME7342 backplane setting */ | ||
| 7149 | { 0, 1, 12, 12 }, /* QME7342 backplane setting */ | ||
| 7150 | { 0, 1, 12, 14 }, /* QME7342 backplane setting */ | ||
| 7151 | { 0, 1, 12, 6 }, /* QME7342 backplane setting */ | ||
| 7152 | { 0, 1, 12, 7 }, /* QME7342 backplane setting */ | ||
| 7153 | { 0, 1, 12, 8 }, /* QME7342 backplane setting */ | ||
| 7154 | }; | ||
| 7155 | |||
| 7131 | static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds, | 7156 | static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds, |
| 7132 | unsigned atten) | 7157 | unsigned atten) |
| 7133 | { | 7158 | { |
| @@ -7145,7 +7170,7 @@ static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds, | |||
| 7145 | } | 7170 | } |
| 7146 | 7171 | ||
| 7147 | /* | 7172 | /* |
| 7148 | * if override is set, the module parameter cable_atten has a value | 7173 | * if override is set, the module parameter txselect has a value |
| 7149 | * for this specific port, so use it, rather than our normal mechanism. | 7174 | * for this specific port, so use it, rather than our normal mechanism. |
| 7150 | */ | 7175 | */ |
| 7151 | static void find_best_ent(struct qib_pportdata *ppd, | 7176 | static void find_best_ent(struct qib_pportdata *ppd, |
| @@ -7184,15 +7209,28 @@ static void find_best_ent(struct qib_pportdata *ppd, | |||
| 7184 | *ddr_dds = get_atten_table(txdds_ddr, qd->atten[0]); | 7209 | *ddr_dds = get_atten_table(txdds_ddr, qd->atten[0]); |
| 7185 | *qdr_dds = get_atten_table(txdds_qdr, qd->atten[1]); | 7210 | *qdr_dds = get_atten_table(txdds_qdr, qd->atten[1]); |
| 7186 | return; | 7211 | return; |
| 7187 | } else { | 7212 | } else if (ppd->cpspec->no_eep < TXDDS_TABLE_SZ) { |
| 7188 | /* | 7213 | /* |
| 7189 | * If we have no (or incomplete) data from the cable | 7214 | * If we have no (or incomplete) data from the cable |
| 7190 | * EEPROM, or no QSFP, use the module parameter value | 7215 | * EEPROM, or no QSFP, or override is set, use the |
| 7191 | * to index into the attentuation table. | 7216 | * module parameter value to index into the attentuation |
| 7217 | * table. | ||
| 7192 | */ | 7218 | */ |
| 7193 | *sdr_dds = &txdds_sdr[ppd->cpspec->no_eep]; | 7219 | idx = ppd->cpspec->no_eep; |
| 7194 | *ddr_dds = &txdds_ddr[ppd->cpspec->no_eep]; | 7220 | *sdr_dds = &txdds_sdr[idx]; |
| 7195 | *qdr_dds = &txdds_qdr[ppd->cpspec->no_eep]; | 7221 | *ddr_dds = &txdds_ddr[idx]; |
| 7222 | *qdr_dds = &txdds_qdr[idx]; | ||
| 7223 | } else if (ppd->cpspec->no_eep < (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ)) { | ||
| 7224 | /* similar to above, but index into the "extra" table. */ | ||
| 7225 | idx = ppd->cpspec->no_eep - TXDDS_TABLE_SZ; | ||
| 7226 | *sdr_dds = &txdds_extra_sdr[idx]; | ||
| 7227 | *ddr_dds = &txdds_extra_ddr[idx]; | ||
| 7228 | *qdr_dds = &txdds_extra_qdr[idx]; | ||
| 7229 | } else { | ||
| 7230 | /* this shouldn't happen, it's range checked */ | ||
| 7231 | *sdr_dds = txdds_sdr + qib_long_atten; | ||
| 7232 | *ddr_dds = txdds_ddr + qib_long_atten; | ||
| 7233 | *qdr_dds = txdds_qdr + qib_long_atten; | ||
| 7196 | } | 7234 | } |
| 7197 | } | 7235 | } |
| 7198 | 7236 | ||
| @@ -7203,33 +7241,24 @@ static void init_txdds_table(struct qib_pportdata *ppd, int override) | |||
| 7203 | int idx; | 7241 | int idx; |
| 7204 | int single_ent = 0; | 7242 | int single_ent = 0; |
| 7205 | 7243 | ||
| 7206 | if (IS_QMH(ppd->dd)) { | 7244 | find_best_ent(ppd, &sdr_dds, &ddr_dds, &qdr_dds, override); |
| 7207 | /* normally will be overridden, via setup_qmh() */ | 7245 | |
| 7208 | sdr_dds = &qmh_sdr_txdds; | 7246 | /* for mez cards or override, use the selected value for all entries */ |
| 7209 | ddr_dds = &qmh_ddr_txdds; | 7247 | if (!(ppd->dd->flags & QIB_HAS_QSFP) || override) |
| 7210 | qdr_dds = &qmh_qdr_txdds; | ||
| 7211 | single_ent = 1; | ||
| 7212 | } else if (IS_QME(ppd->dd)) { | ||
| 7213 | sdr_dds = &qme_sdr_txdds; | ||
| 7214 | ddr_dds = &qme_ddr_txdds; | ||
| 7215 | qdr_dds = &qme_qdr_txdds; | ||
| 7216 | single_ent = 1; | 7248 | single_ent = 1; |
| 7217 | } else | ||
| 7218 | find_best_ent(ppd, &sdr_dds, &ddr_dds, &qdr_dds, override); | ||
| 7219 | 7249 | ||
| 7220 | /* Fill in the first entry with the best entry found. */ | 7250 | /* Fill in the first entry with the best entry found. */ |
| 7221 | set_txdds(ppd, 0, sdr_dds); | 7251 | set_txdds(ppd, 0, sdr_dds); |
| 7222 | set_txdds(ppd, TXDDS_TABLE_SZ, ddr_dds); | 7252 | set_txdds(ppd, TXDDS_TABLE_SZ, ddr_dds); |
| 7223 | set_txdds(ppd, 2 * TXDDS_TABLE_SZ, qdr_dds); | 7253 | set_txdds(ppd, 2 * TXDDS_TABLE_SZ, qdr_dds); |
| 7224 | 7254 | if (ppd->lflags & (QIBL_LINKINIT | QIBL_LINKARMED | | |
| 7225 | /* | 7255 | QIBL_LINKACTIVE)) { |
| 7226 | * for our current speed, also write that value into the | 7256 | dds = (struct txdds_ent *)(ppd->link_speed_active == |
| 7227 | * tx serdes registers. | 7257 | QIB_IB_QDR ? qdr_dds : |
| 7228 | */ | 7258 | (ppd->link_speed_active == |
| 7229 | dds = (struct txdds_ent *)(ppd->link_speed_active == QIB_IB_QDR ? | 7259 | QIB_IB_DDR ? ddr_dds : sdr_dds)); |
| 7230 | qdr_dds : (ppd->link_speed_active == | 7260 | write_tx_serdes_param(ppd, dds); |
| 7231 | QIB_IB_DDR ? ddr_dds : sdr_dds)); | 7261 | } |
| 7232 | write_tx_serdes_param(ppd, dds); | ||
| 7233 | 7262 | ||
| 7234 | /* Fill in the remaining entries with the default table values. */ | 7263 | /* Fill in the remaining entries with the default table values. */ |
| 7235 | for (idx = 1; idx < ARRAY_SIZE(txdds_sdr); ++idx) { | 7264 | for (idx = 1; idx < ARRAY_SIZE(txdds_sdr); ++idx) { |
| @@ -7352,6 +7381,11 @@ static int serdes_7322_init(struct qib_pportdata *ppd) | |||
| 7352 | */ | 7381 | */ |
| 7353 | init_txdds_table(ppd, 0); | 7382 | init_txdds_table(ppd, 0); |
| 7354 | 7383 | ||
| 7384 | /* ensure no tx overrides from earlier driver loads */ | ||
| 7385 | qib_write_kreg_port(ppd, krp_tx_deemph_override, | ||
| 7386 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
| 7387 | reset_tx_deemphasis_override)); | ||
| 7388 | |||
| 7355 | /* Patch some SerDes defaults to "Better for IB" */ | 7389 | /* Patch some SerDes defaults to "Better for IB" */ |
| 7356 | /* Timing Loop Bandwidth: cdr_timing[11:9] = 0 */ | 7390 | /* Timing Loop Bandwidth: cdr_timing[11:9] = 0 */ |
| 7357 | ibsd_wr_allchans(ppd, 2, 0, BMASK(11, 9)); | 7391 | ibsd_wr_allchans(ppd, 2, 0, BMASK(11, 9)); |
| @@ -7421,7 +7455,7 @@ static int serdes_7322_init(struct qib_pportdata *ppd) | |||
| 7421 | QDR_STATIC_ADAPT_DOWN_R1 : QDR_STATIC_ADAPT_DOWN); | 7455 | QDR_STATIC_ADAPT_DOWN_R1 : QDR_STATIC_ADAPT_DOWN); |
| 7422 | ppd->cpspec->qdr_dfe_on = 1; | 7456 | ppd->cpspec->qdr_dfe_on = 1; |
| 7423 | 7457 | ||
| 7424 | /* (FLoop LOS gate: PPM filter enabled */ | 7458 | /* FLoop LOS gate: PPM filter enabled */ |
| 7425 | ibsd_wr_allchans(ppd, 38, 0 << 10, 1 << 10); | 7459 | ibsd_wr_allchans(ppd, 38, 0 << 10, 1 << 10); |
| 7426 | 7460 | ||
| 7427 | /* rx offset center enabled */ | 7461 | /* rx offset center enabled */ |
| @@ -7486,68 +7520,39 @@ static void write_tx_serdes_param(struct qib_pportdata *ppd, | |||
| 7486 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txc0_ena) | | 7520 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txc0_ena) | |
| 7487 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcp1_ena) | | 7521 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcp1_ena) | |
| 7488 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcn1_ena)); | 7522 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcn1_ena)); |
| 7489 | deemph |= 1ULL << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | 7523 | |
| 7490 | tx_override_deemphasis_select); | 7524 | deemph |= SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, |
| 7491 | deemph |= txdds->amp << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | 7525 | tx_override_deemphasis_select); |
| 7492 | txampcntl_d2a); | 7526 | deemph |= (txdds->amp & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, |
| 7493 | deemph |= txdds->main << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | 7527 | txampcntl_d2a)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, |
| 7494 | txc0_ena); | 7528 | txampcntl_d2a); |
| 7495 | deemph |= txdds->post << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | 7529 | deemph |= (txdds->main & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, |
| 7496 | txcp1_ena); | 7530 | txc0_ena)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, |
| 7497 | deemph |= txdds->pre << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | 7531 | txc0_ena); |
| 7532 | deemph |= (txdds->post & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
| 7533 | txcp1_ena)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
| 7534 | txcp1_ena); | ||
| 7535 | deemph |= (txdds->pre & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
| 7536 | txcn1_ena)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
| 7498 | txcn1_ena); | 7537 | txcn1_ena); |
| 7499 | qib_write_kreg_port(ppd, krp_tx_deemph_override, deemph); | 7538 | qib_write_kreg_port(ppd, krp_tx_deemph_override, deemph); |
| 7500 | } | 7539 | } |
| 7501 | 7540 | ||
| 7502 | /* | 7541 | /* |
| 7503 | * set per-bay, per channel parameters. For now, we ignore | 7542 | * Set the parameters for mez cards on link bounce, so they are |
| 7504 | * do_tx, and always set tx parameters, and set them with the same value | 7543 | * always exactly what was requested. Similar logic to init_txdds |
| 7505 | * for all channels, using the channel 0 value. We may switch to | 7544 | * but does just the serdes. |
| 7506 | * per-channel settings in the future, and that method only needs | ||
| 7507 | * to be done once. | ||
| 7508 | * Because this also writes the IBC txdds table with a single set | ||
| 7509 | * of values, it should be called only for cases where we want to completely | ||
| 7510 | * force a specific setting, typically only for mez cards. | ||
| 7511 | */ | 7545 | */ |
| 7512 | static void adj_tx_serdes(struct qib_pportdata *ppd) | 7546 | static void adj_tx_serdes(struct qib_pportdata *ppd) |
| 7513 | { | 7547 | { |
| 7514 | struct txdds_ent txdds; | 7548 | const struct txdds_ent *sdr_dds, *ddr_dds, *qdr_dds; |
| 7515 | int i; | 7549 | struct txdds_ent *dds; |
| 7516 | u8 *amp, *pre, *mainv, *post; | ||
| 7517 | |||
| 7518 | /* | ||
| 7519 | * Because we use TX_DEEMPHASIS_OVERRIDE, we need to | ||
| 7520 | * always do tx side, just like H1, since it is cleared | ||
| 7521 | * by link down | ||
| 7522 | */ | ||
| 7523 | amp = ppd->cpspec->amp; | ||
| 7524 | pre = ppd->cpspec->pre; | ||
| 7525 | mainv = ppd->cpspec->mainv; | ||
| 7526 | post = ppd->cpspec->post; | ||
| 7527 | |||
| 7528 | amp[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
| 7529 | txampcntl_d2a); | ||
| 7530 | mainv[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
| 7531 | txc0_ena); | ||
| 7532 | post[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
| 7533 | txcp1_ena); | ||
| 7534 | pre[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
| 7535 | txcn1_ena); | ||
| 7536 | |||
| 7537 | /* | ||
| 7538 | * Use the channel zero values, only, for now, for | ||
| 7539 | * all channels | ||
| 7540 | */ | ||
| 7541 | txdds.amp = amp[0]; | ||
| 7542 | txdds.pre = pre[0]; | ||
| 7543 | txdds.main = mainv[0]; | ||
| 7544 | txdds.post = post[0]; | ||
| 7545 | |||
| 7546 | /* write the QDR table for IBC use, as backup for link down */ | ||
| 7547 | for (i = 0; i < ARRAY_SIZE(txdds_qdr); ++i) | ||
| 7548 | set_txdds(ppd, i + 32, &txdds); | ||
| 7549 | 7550 | ||
| 7550 | write_tx_serdes_param(ppd, &txdds); | 7551 | find_best_ent(ppd, &sdr_dds, &ddr_dds, &qdr_dds, 1); |
| 7552 | dds = (struct txdds_ent *)(ppd->link_speed_active == QIB_IB_QDR ? | ||
| 7553 | qdr_dds : (ppd->link_speed_active == QIB_IB_DDR ? | ||
| 7554 | ddr_dds : sdr_dds)); | ||
| 7555 | write_tx_serdes_param(ppd, dds); | ||
| 7551 | } | 7556 | } |
| 7552 | 7557 | ||
| 7553 | /* set QDR forced value for H1, if needed */ | 7558 | /* set QDR forced value for H1, if needed */ |
| @@ -7567,235 +7572,6 @@ static void force_h1(struct qib_pportdata *ppd) | |||
| 7567 | } | 7572 | } |
| 7568 | } | 7573 | } |
| 7569 | 7574 | ||
| 7570 | /* | ||
| 7571 | * Parse the parameters for the QMH7342, to get rx and tx serdes | ||
| 7572 | * settings for that Bay, for both possible mez connectors (PCIe bus) | ||
| 7573 | * and IB link (one link on mez1, two possible on mez2). | ||
| 7574 | * | ||
| 7575 | * Data is comma or white space separated. | ||
| 7576 | * | ||
| 7577 | * A set of data has 7 groups, rx and tx groups have SERDES_CHANS values, | ||
| 7578 | * one per IB lane (serdes channel). | ||
| 7579 | * The groups are Bay, bus# H1 rcv, and amp, pre, post, main Tx values (QDR). | ||
| 7580 | * The Bay # is used only for debugging currently. | ||
| 7581 | * H1 values are set whenever the link goes down, or is at cfg_test or | ||
| 7582 | * cfg_wait_enh. Tx values are programmed once, when this routine is called | ||
| 7583 | * (and with default values at chip initialization). Values are any base, in | ||
| 7584 | * strtoul style, and values are seperated by comma, or any white space | ||
| 7585 | * (space, tab, newline). | ||
| 7586 | * | ||
| 7587 | * An example set might look like this (white space vs | ||
| 7588 | * comma used for human ease of reading) | ||
| 7589 | * The ordering is a set of Bay# Bus# H1, amp, pre, post, and main for mez1 IB1, | ||
| 7590 | * repeat for mez2 IB1, then mez2 IB2. | ||
| 7591 | * | ||
| 7592 | * B B H1:0 amp:0 pre:0 post: 0 main:0 | ||
| 7593 | * a u H1: 1 amp: 1 pre: 1 post: 1 main: 1 | ||
| 7594 | * y s H1: 2 amp: 2 pre: 2 post: 2 main: 2 | ||
| 7595 | * H1: 4 amp: 3 pre: 3 post: 3 main: 3 | ||
| 7596 | * 1 3 8,6,5,6 0,0,0,0 1,1,1,1 10,10,10,10 3,3,3,3 | ||
| 7597 | * 1 6 7,6,6,7 0,0,0,0 1,1,1,1 10,10,10,10 3,3,3,3 | ||
| 7598 | * 1 6 9,7,7,8 0,0,0,0 1,1,1,1 10,10,10,10 3,3,3,3 | ||
| 7599 | */ | ||
| 7600 | #define N_QMH_FIELDS 22 | ||
| 7601 | static int setup_qmh_params(const char *str, struct kernel_param *kp) | ||
| 7602 | { | ||
| 7603 | char *abuf, *v, *nv, *nvp; | ||
| 7604 | struct qib_devdata *dd; | ||
| 7605 | struct qib_pportdata *ppd; | ||
| 7606 | u32 mez, vlen, nf, port, bay; | ||
| 7607 | int ret = 0, found = 0; | ||
| 7608 | |||
| 7609 | vlen = strlen(str) + 1; | ||
| 7610 | abuf = kmalloc(vlen, GFP_KERNEL); | ||
| 7611 | if (!abuf) { | ||
| 7612 | printk(KERN_INFO QIB_DRV_NAME | ||
| 7613 | " Unable to allocate QMH param buffer; ignoring\n"); | ||
| 7614 | return 0; | ||
| 7615 | } | ||
| 7616 | memcpy(abuf, str, vlen); | ||
| 7617 | v = abuf; | ||
| 7618 | |||
| 7619 | /* these 3 are because gcc can't know they are set before used */ | ||
| 7620 | port = 1; | ||
| 7621 | mez = 1; /* used only for debugging */ | ||
| 7622 | bay = 0; /* used only for debugging */ | ||
| 7623 | ppd = NULL; | ||
| 7624 | for (nf = 0; (nv = strsep(&v, ", \t\n\r")) && | ||
| 7625 | nf < (N_QMH_FIELDS * 3);) { | ||
| 7626 | u32 val; | ||
| 7627 | |||
| 7628 | if (!*nv) | ||
| 7629 | /* allow for multiple separators */ | ||
| 7630 | continue; | ||
| 7631 | |||
| 7632 | val = simple_strtoul(nv, &nvp, 0); | ||
| 7633 | if (nv == nvp) { | ||
| 7634 | printk(KERN_INFO QIB_DRV_NAME | ||
| 7635 | " Bay%u, mez%u IB%u non-numeric value (%s) " | ||
| 7636 | "field #%u, ignoring rest\n", bay, mez, | ||
| 7637 | port, nv, nf % (N_QMH_FIELDS * 3)); | ||
| 7638 | ret = -EINVAL; | ||
| 7639 | goto bail; | ||
| 7640 | } | ||
| 7641 | if (!(nf % N_QMH_FIELDS)) { | ||
| 7642 | ppd = NULL; | ||
| 7643 | bay = val; | ||
| 7644 | if (!bay || bay > 16) { | ||
| 7645 | printk(KERN_INFO QIB_DRV_NAME | ||
| 7646 | " Invalid bay # %u, field %u, " | ||
| 7647 | "ignoring rest\n", bay, nf); | ||
| 7648 | ret = -EINVAL; | ||
| 7649 | goto bail; | ||
| 7650 | } | ||
| 7651 | } else if ((nf % N_QMH_FIELDS) == 1) { | ||
| 7652 | u32 bus = val; | ||
| 7653 | if (nf == 1) { | ||
| 7654 | mez = 1; | ||
| 7655 | port = 1; | ||
| 7656 | } else if (nf == (N_QMH_FIELDS + 1)) { | ||
| 7657 | mez = 2; | ||
| 7658 | port = 1; | ||
| 7659 | } else { | ||
| 7660 | mez = 2; | ||
| 7661 | port = 2; | ||
| 7662 | } | ||
| 7663 | list_for_each_entry(dd, &qib_dev_list, list) { | ||
| 7664 | if (dd->deviceid != PCI_DEVICE_ID_QLOGIC_IB_7322 | ||
| 7665 | || !IS_QMH(dd)) | ||
| 7666 | continue; /* only for QMH cards */ | ||
| 7667 | if (dd->pcidev->bus->number == bus) { | ||
| 7668 | found++; | ||
| 7669 | ppd = &dd->pport[port - 1]; | ||
| 7670 | } | ||
| 7671 | } | ||
| 7672 | } else if (ppd) { | ||
| 7673 | u32 parm = (nf % N_QMH_FIELDS) - 2; | ||
| 7674 | if (parm < SERDES_CHANS && !(parm % SERDES_CHANS)) | ||
| 7675 | ppd->cpspec->h1_val = val; | ||
| 7676 | else if (parm < (2 * SERDES_CHANS)) | ||
| 7677 | ppd->cpspec->amp[parm % SERDES_CHANS] = val; | ||
| 7678 | else if (parm < (3 * SERDES_CHANS)) | ||
| 7679 | ppd->cpspec->pre[parm % SERDES_CHANS] = val; | ||
| 7680 | else if (parm < (4 * SERDES_CHANS)) | ||
| 7681 | ppd->cpspec->post[parm % SERDES_CHANS] = val; | ||
| 7682 | else { | ||
| 7683 | ppd->cpspec->mainv[parm % SERDES_CHANS] = val; | ||
| 7684 | /* At the end of a port, set params */ | ||
| 7685 | if (parm == ((5 * SERDES_CHANS) - 1)) | ||
| 7686 | adj_tx_serdes(ppd); | ||
| 7687 | } | ||
| 7688 | } | ||
| 7689 | nf++; | ||
| 7690 | } | ||
| 7691 | if (!found) { | ||
| 7692 | printk(KERN_ERR QIB_DRV_NAME | ||
| 7693 | ": No match found for qmh_serdes_setup parameter\n"); | ||
| 7694 | ret = -EINVAL; | ||
| 7695 | } | ||
| 7696 | bail: | ||
| 7697 | kfree(abuf); | ||
| 7698 | return ret; | ||
| 7699 | } | ||
| 7700 | |||
| 7701 | /* | ||
| 7702 | * Similarly for QME7342, but the format is simpler, values are the | ||
| 7703 | * same for all mez card positions in a blade (2 or 4 per blade), but | ||
| 7704 | * are different for some blades vs others, and we don't need to | ||
| 7705 | * specify different parameters for different serdes channels or different | ||
| 7706 | * IB ports. | ||
| 7707 | * Format is: h1 amp,pre,post,main | ||
| 7708 | * Alternate format (so ports can be different): Pport# h1 amp,pre,post,main | ||
| 7709 | */ | ||
| 7710 | #define N_QME_FIELDS 5 | ||
| 7711 | static int setup_qme_params(const char *str, struct kernel_param *kp) | ||
| 7712 | { | ||
| 7713 | char *abuf, *v, *nv, *nvp; | ||
| 7714 | struct qib_devdata *dd; | ||
| 7715 | u32 vlen, nf, port = 0; | ||
| 7716 | u8 h1, tx[4]; /* amp, pre, post, main */ | ||
| 7717 | int ret = -EINVAL; | ||
| 7718 | char *seplist; | ||
| 7719 | |||
| 7720 | vlen = strlen(str) + 1; | ||
| 7721 | abuf = kmalloc(vlen, GFP_KERNEL); | ||
| 7722 | if (!abuf) { | ||
| 7723 | printk(KERN_INFO QIB_DRV_NAME | ||
| 7724 | " Unable to allocate QME param buffer; ignoring\n"); | ||
| 7725 | return 0; | ||
| 7726 | } | ||
| 7727 | strncpy(abuf, str, vlen); | ||
| 7728 | |||
| 7729 | v = abuf; | ||
| 7730 | seplist = " \t"; | ||
| 7731 | h1 = H1_FORCE_QME; /* gcc can't figure out always set before used */ | ||
| 7732 | |||
| 7733 | for (nf = 0; (nv = strsep(&v, seplist)); ) { | ||
| 7734 | u32 val; | ||
| 7735 | |||
| 7736 | if (!*nv) | ||
| 7737 | /* allow for multiple separators */ | ||
| 7738 | continue; | ||
| 7739 | |||
| 7740 | if (!nf && *nv == 'P') { | ||
| 7741 | /* alternate format with port */ | ||
| 7742 | val = simple_strtoul(++nv, &nvp, 0); | ||
| 7743 | if (nv == nvp || port >= NUM_IB_PORTS) { | ||
| 7744 | printk(KERN_INFO QIB_DRV_NAME | ||
| 7745 | " %s: non-numeric port value (%s) " | ||
| 7746 | "ignoring rest\n", __func__, nv); | ||
| 7747 | goto done; | ||
| 7748 | } | ||
| 7749 | port = val; | ||
| 7750 | continue; /* without incrementing nf */ | ||
| 7751 | } | ||
| 7752 | val = simple_strtoul(nv, &nvp, 0); | ||
| 7753 | if (nv == nvp) { | ||
| 7754 | printk(KERN_INFO QIB_DRV_NAME | ||
| 7755 | " %s: non-numeric value (%s) " | ||
| 7756 | "field #%u, ignoring rest\n", __func__, | ||
| 7757 | nv, nf); | ||
| 7758 | goto done; | ||
| 7759 | } | ||
| 7760 | if (!nf) { | ||
| 7761 | h1 = val; | ||
| 7762 | seplist = ","; | ||
| 7763 | } else | ||
| 7764 | tx[nf - 1] = val; | ||
| 7765 | if (++nf == N_QME_FIELDS) { | ||
| 7766 | list_for_each_entry(dd, &qib_dev_list, list) { | ||
| 7767 | int pidx, i; | ||
| 7768 | if (dd->deviceid != PCI_DEVICE_ID_QLOGIC_IB_7322 | ||
| 7769 | || !IS_QME(dd)) | ||
| 7770 | continue; /* only for QME cards */ | ||
| 7771 | for (pidx = 0; pidx < dd->num_pports; ++pidx) { | ||
| 7772 | struct qib_pportdata *ppd; | ||
| 7773 | ppd = &dd->pport[pidx]; | ||
| 7774 | if ((port && ppd->port != port) || | ||
| 7775 | !ppd->link_speed_supported) | ||
| 7776 | continue; | ||
| 7777 | ppd->cpspec->h1_val = h1; | ||
| 7778 | for (i = 0; i < SERDES_CHANS; i++) { | ||
| 7779 | ppd->cpspec->amp[i] = tx[0]; | ||
| 7780 | ppd->cpspec->pre[i] = tx[1]; | ||
| 7781 | ppd->cpspec->post[i] = tx[2]; | ||
| 7782 | ppd->cpspec->mainv[i] = tx[3]; | ||
| 7783 | } | ||
| 7784 | adj_tx_serdes(ppd); | ||
| 7785 | } | ||
| 7786 | } | ||
| 7787 | ret = 0; | ||
| 7788 | goto done; | ||
| 7789 | } | ||
| 7790 | } | ||
| 7791 | printk(KERN_INFO QIB_DRV_NAME | ||
| 7792 | " %s: Only %u of %u fields provided, skipping\n", | ||
| 7793 | __func__, nf, N_QME_FIELDS); | ||
| 7794 | done: | ||
| 7795 | kfree(abuf); | ||
| 7796 | return ret; | ||
| 7797 | } | ||
| 7798 | |||
| 7799 | #define SJA_EN SYM_MASK(SPC_JTAG_ACCESS_REG, SPC_JTAG_ACCESS_EN) | 7575 | #define SJA_EN SYM_MASK(SPC_JTAG_ACCESS_REG, SPC_JTAG_ACCESS_EN) |
| 7800 | #define BISTEN_LSB SYM_LSB(SPC_JTAG_ACCESS_REG, bist_en) | 7576 | #define BISTEN_LSB SYM_LSB(SPC_JTAG_ACCESS_REG, bist_en) |
| 7801 | 7577 | ||
