diff options
Diffstat (limited to 'drivers/infiniband')
-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 2c24eab35b54..23fb9efe20a4 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 | ||