From 242b494bf22be4056df1493664b00b5d0b238e53 Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Mon, 9 Oct 2017 13:08:28 -0700 Subject: IB/hfi1: Fix serdes loopback set-up Change serdes mode setting to use MISC_CONFIG_BITS in VERIFY_CAP_LOCAL_LINK_WIDTH register. This method of setting up serdes loopback is universally compatible across all firmware versions. Reviewed-by: Jakub Byczkowski Signed-off-by: Jan Sokolowski Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/chip.c | 42 +++++++++++++-------------------------- drivers/infiniband/hw/hfi1/chip.h | 3 +++ 2 files changed, 17 insertions(+), 28 deletions(-) (limited to 'drivers/infiniband/hw') diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index b2ed4b9cda6e..160ada91e849 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -9156,25 +9156,6 @@ static int do_quick_linkup(struct hfi1_devdata *dd) return 0; /* success */ } -/* - * Set the SerDes to internal loopback mode. - * Returns 0 on success, -errno on error. - */ -static int set_serdes_loopback_mode(struct hfi1_devdata *dd) -{ - int ret; - - ret = set_physical_link_state(dd, PLS_INTERNAL_SERDES_LOOPBACK); - if (ret == HCMD_SUCCESS) - return 0; - dd_dev_err(dd, - "Set physical link state to SerDes Loopback failed with return %d\n", - ret); - if (ret >= 0) - ret = -EINVAL; - return ret; -} - /* * Do all special steps to set up loopback. */ @@ -9200,13 +9181,11 @@ static int init_loopback(struct hfi1_devdata *dd) return 0; } - /* handle serdes loopback */ - if (loopback == LOOPBACK_SERDES) { - /* internal serdes loopack needs quick linkup on RTL */ - if (dd->icode == ICODE_RTL_SILICON) - quick_linkup = 1; - return set_serdes_loopback_mode(dd); - } + /* + * SerDes loopback init sequence is handled in set_local_link_attributes + */ + if (loopback == LOOPBACK_SERDES) + return 0; /* LCB loopback - handled at poll time */ if (loopback == LOOPBACK_LCB) { @@ -9265,7 +9244,7 @@ static int set_local_link_attributes(struct hfi1_pportdata *ppd) u8 tx_polarity_inversion; u8 rx_polarity_inversion; int ret; - + u32 misc_bits = 0; /* reset our fabric serdes to clear any lingering problems */ fabric_serdes_reset(dd); @@ -9311,7 +9290,14 @@ static int set_local_link_attributes(struct hfi1_pportdata *ppd) if (ret != HCMD_SUCCESS) goto set_local_link_attributes_fail; - ret = write_vc_local_link_width(dd, 0, 0, + /* + * SerDes loopback init sequence requires + * setting bit 0 of MISC_CONFIG_BITS + */ + if (loopback == LOOPBACK_SERDES) + misc_bits |= 1 << LOOPBACK_SERDES_CONFIG_BIT_MASK_SHIFT; + + ret = write_vc_local_link_width(dd, misc_bits, 0, opa_to_vc_link_widths( ppd->link_width_enabled)); if (ret != HCMD_SUCCESS) diff --git a/drivers/infiniband/hw/hfi1/chip.h b/drivers/infiniband/hw/hfi1/chip.h index b8345a60a0fb..45b645e892c9 100644 --- a/drivers/infiniband/hw/hfi1/chip.h +++ b/drivers/infiniband/hw/hfi1/chip.h @@ -582,6 +582,9 @@ enum { #define LOOPBACK_LCB 2 #define LOOPBACK_CABLE 3 /* external cable */ +/* set up serdes bit in MISC_CONFIG_BITS */ +#define LOOPBACK_SERDES_CONFIG_BIT_MASK_SHIFT 0 + /* read and write hardware registers */ u64 read_csr(const struct hfi1_devdata *dd, u32 offset); void write_csr(const struct hfi1_devdata *dd, u32 offset, u64 value); -- cgit v1.2.3 From 621515da67f150eea0e7b6b05614bd0b65d9d16c Mon Sep 17 00:00:00 2001 From: Jakub Byczkowski Date: Mon, 9 Oct 2017 12:37:56 -0700 Subject: IB/hfi1: Allow meta version 4 for platform configuration Parsing of platform configuration format 4 will fail on meta version check. Allow meta version 4 during parsing. Reviewed-by: Jan Sokolowski Reviewed-by: Ira Weiny Signed-off-by: Jakub Byczkowski Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/infiniband/hw') diff --git a/drivers/infiniband/hw/hfi1/firmware.c b/drivers/infiniband/hw/hfi1/firmware.c index 5aea8f47e670..001698b744ee 100644 --- a/drivers/infiniband/hw/hfi1/firmware.c +++ b/drivers/infiniband/hw/hfi1/firmware.c @@ -1733,7 +1733,7 @@ static int check_meta_version(struct hfi1_devdata *dd, u32 *system_table) ver_start /= 8; meta_ver = *((u8 *)system_table + ver_start) & ((1 << ver_len) - 1); - if (meta_ver < 5) { + if (meta_ver < 4) { dd_dev_info( dd, "%s:Please update platform config\n", __func__); return -EINVAL; -- cgit v1.2.3 From b65c2045cc5089bd3cfacc9fad63798fded64226 Mon Sep 17 00:00:00 2001 From: Grzegorz Morys Date: Mon, 9 Oct 2017 12:38:04 -0700 Subject: IB/hfi1: Correct unnecessary acquisition of HW mutex Avoid acquiring already acquired hardware mutex and releasing the unacquired one as these are redundant operations. Add printouts for such situations to help detect potential errors within the driver. Reviewed-by: Mike Marciniszyn Signed-off-by: Grzegorz Morys Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/firmware.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers/infiniband/hw') diff --git a/drivers/infiniband/hw/hfi1/firmware.c b/drivers/infiniband/hw/hfi1/firmware.c index 001698b744ee..cea0d4f3248f 100644 --- a/drivers/infiniband/hw/hfi1/firmware.c +++ b/drivers/infiniband/hw/hfi1/firmware.c @@ -1387,7 +1387,14 @@ int acquire_hw_mutex(struct hfi1_devdata *dd) unsigned long timeout; int try = 0; u8 mask = 1 << dd->hfi1_id; - u8 user; + u8 user = (u8)read_csr(dd, ASIC_CFG_MUTEX); + + if (user == mask) { + dd_dev_info(dd, + "Hardware mutex already acquired, mutex mask %u\n", + (u32)mask); + return 0; + } retry: timeout = msecs_to_jiffies(HM_TIMEOUT) + jiffies; @@ -1418,7 +1425,15 @@ retry: void release_hw_mutex(struct hfi1_devdata *dd) { - write_csr(dd, ASIC_CFG_MUTEX, 0); + u8 mask = 1 << dd->hfi1_id; + u8 user = (u8)read_csr(dd, ASIC_CFG_MUTEX); + + if (user != mask) + dd_dev_warn(dd, + "Unable to release hardware mutex, mutex mask %u, my mask %u\n", + (u32)user, (u32)mask); + else + write_csr(dd, ASIC_CFG_MUTEX, 0); } /* return the given resource bit(s) as a mask for the given HFI */ -- cgit v1.2.3 From d0a2f454713a42447ee4007582c0e43c47bcf230 Mon Sep 17 00:00:00 2001 From: Don Hiatt Date: Mon, 9 Oct 2017 12:38:12 -0700 Subject: IB/hfi1: Mask out A bit from psn trace The trace logic prior to the fixes below used to mask the A bit from the psn. It now mistakenly displays the A bit, which is already displayed separately. Fix by adding the appropriate mask to the psn tracing. Fixes: 228d2af1b723 ("IB/hfi1: Separate input/output header tracing") Fixes: 863cf89d472f ("IB/hfi1: Add 16B trace support") Reviewed-by: Mike Marciniszyn Signed-off-by: Don Hiatt Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/trace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/infiniband/hw') diff --git a/drivers/infiniband/hw/hfi1/trace.c b/drivers/infiniband/hw/hfi1/trace.c index 9938bb983ce6..9749ec9dd9f2 100644 --- a/drivers/infiniband/hw/hfi1/trace.c +++ b/drivers/infiniband/hw/hfi1/trace.c @@ -154,7 +154,7 @@ void hfi1_trace_parse_9b_bth(struct ib_other_headers *ohdr, *opcode = ib_bth_get_opcode(ohdr); *tver = ib_bth_get_tver(ohdr); *pkey = ib_bth_get_pkey(ohdr); - *psn = ib_bth_get_psn(ohdr); + *psn = mask_psn(ib_bth_get_psn(ohdr)); *qpn = ib_bth_get_qpn(ohdr); } @@ -169,7 +169,7 @@ void hfi1_trace_parse_16b_bth(struct ib_other_headers *ohdr, *pad = ib_bth_get_pad(ohdr); *se = ib_bth_get_se(ohdr); *tver = ib_bth_get_tver(ohdr); - *psn = ib_bth_get_psn(ohdr); + *psn = mask_psn(ib_bth_get_psn(ohdr)); *qpn = ib_bth_get_qpn(ohdr); } -- cgit v1.2.3 From f8195f3b14a046ae33d9c369ffb59b4192f29e08 Mon Sep 17 00:00:00 2001 From: Don Hiatt Date: Mon, 9 Oct 2017 12:38:19 -0700 Subject: IB/hfi1: Eliminate allocation while atomic The PIO trailing buffer was being dynamically allocated but the kcalloc return value was not being checked. Further, the GFP_KERNEL was being used even though the send engine might be called with interrupts disabled. Since the maximum size of the trailing buffer is only 12 bytes (CRC = 4, LT = 1, Pad = 0 to 7 bytes) just statically allocate the buffer, remove the alloc entirely and share it with the SDMA engine by making it global. Reported-by: Leon Romanovsky Fixes: 566d53a82644 ("IB/hfi1: Enhance PIO/SDMA send for 16B") Reviewed-by: Mike Marciniszyn Signed-off-by: Don Hiatt Signed-off-by: Dennis Dalessandro Reviewed-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/common.h | 1 + drivers/infiniband/hw/hfi1/verbs.c | 22 ++++++++-------------- 2 files changed, 9 insertions(+), 14 deletions(-) (limited to 'drivers/infiniband/hw') diff --git a/drivers/infiniband/hw/hfi1/common.h b/drivers/infiniband/hw/hfi1/common.h index 3e27794ec750..7108d4d92259 100644 --- a/drivers/infiniband/hw/hfi1/common.h +++ b/drivers/infiniband/hw/hfi1/common.h @@ -328,6 +328,7 @@ struct diag_pkt { #define SC15_PACKET 0xF #define SIZE_OF_CRC 1 #define SIZE_OF_LT 1 +#define MAX_16B_PADDING 12 /* CRC = 4, LT = 1, Pad = 0 to 7 bytes */ #define LIM_MGMT_P_KEY 0x7FFF #define FULL_MGMT_P_KEY 0xFFFF diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c index e232f3c608b4..726c064b22d8 100644 --- a/drivers/infiniband/hw/hfi1/verbs.c +++ b/drivers/infiniband/hw/hfi1/verbs.c @@ -146,6 +146,9 @@ static int pio_wait(struct rvt_qp *qp, /* Length of buffer to create verbs txreq cache name */ #define TXREQ_NAME_LEN 24 +/* 16B trailing buffer */ +static const u8 trail_buf[MAX_16B_PADDING]; + static uint wss_threshold; module_param(wss_threshold, uint, S_IRUGO); MODULE_PARM_DESC(wss_threshold, "Percentage (1-100) of LLC to use as a threshold for a cacheless copy"); @@ -814,7 +817,6 @@ static int build_verbs_tx_desc( u16 hdrbytes = tx->hdr_dwords << 2; u32 *hdr; u8 extra_bytes = 0; - static char trail_buf[12]; /* CRC = 4, LT = 1, Pad = 0 to 7 bytes */ if (tx->phdr.hdr.hdr_type) { /* @@ -869,9 +871,9 @@ static int build_verbs_tx_desc( } /* add icrc, lt byte, and padding to flit */ - if (extra_bytes != 0) + if (extra_bytes) ret = sdma_txadd_kvaddr(sde->dd, &tx->txreq, - trail_buf, extra_bytes); + (void *)trail_buf, extra_bytes); bail_txadd: return ret; @@ -1128,18 +1130,10 @@ int hfi1_verbs_send_pio(struct rvt_qp *qp, struct hfi1_pkt_state *ps, len -= slen; } } - /* - * Bypass packet will need to copy additional - * bytes to accommodate for CRC and LT bytes - */ - if (extra_bytes) { - u8 *empty_buf; + /* add icrc, lt byte, and padding to flit */ + if (extra_bytes) + seg_pio_copy_mid(pbuf, trail_buf, extra_bytes); - empty_buf = kcalloc(extra_bytes, sizeof(u8), - GFP_KERNEL); - seg_pio_copy_mid(pbuf, empty_buf, extra_bytes); - kfree(empty_buf); - } seg_pio_copy_end(pbuf); } -- cgit v1.2.3 From a8979cc55c0034fbe129904936cfc4b5bf41e59b Mon Sep 17 00:00:00 2001 From: Kaike Wan Date: Mon, 9 Oct 2017 12:38:26 -0700 Subject: IB/hfi1: Set hdr_type when tx req is allocated Setting the protocol type should be part of initializing the tx request. For UC and RC, the current protocol type is part of the qp priv structure. For ud requests, it needs to be adjusted dynamically, based on the AV posted with the WQE. This patch will simplify the initialization of the tx request. Fixes: 5b6cabb0db77 ("IB/hfi1: Add 16B RC/UC support") Reviewed-by: Don Hiatt Reviewed-by: Mike Marciniszyn Signed-off-by: Kaike Wan Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/hw/hfi1/rc.c | 1 - drivers/infiniband/hw/hfi1/uc.c | 1 - drivers/infiniband/hw/hfi1/verbs_txreq.h | 2 ++ 3 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/infiniband/hw') diff --git a/drivers/infiniband/hw/hfi1/rc.c b/drivers/infiniband/hw/hfi1/rc.c index e1cf0c08ca6f..bfe3e38d4b6c 100644 --- a/drivers/infiniband/hw/hfi1/rc.c +++ b/drivers/infiniband/hw/hfi1/rc.c @@ -276,7 +276,6 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) if (IS_ERR(ps->s_txreq)) goto bail_no_tx; - ps->s_txreq->phdr.hdr.hdr_type = priv->hdr_type; if (priv->hdr_type == HFI1_PKT_TYPE_9B) { /* header size in 32-bit words LRH+BTH = (8+12)/4. */ hwords = 5; diff --git a/drivers/infiniband/hw/hfi1/uc.c b/drivers/infiniband/hw/hfi1/uc.c index 0b646173ca22..fcd81866e332 100644 --- a/drivers/infiniband/hw/hfi1/uc.c +++ b/drivers/infiniband/hw/hfi1/uc.c @@ -93,7 +93,6 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) goto done_free_tx; } - ps->s_txreq->phdr.hdr.hdr_type = priv->hdr_type; if (priv->hdr_type == HFI1_PKT_TYPE_9B) { /* header size in 32-bit words LRH+BTH = (8+12)/4. */ hwords = 5; diff --git a/drivers/infiniband/hw/hfi1/verbs_txreq.h b/drivers/infiniband/hw/hfi1/verbs_txreq.h index 76216f2ef35a..cec7a4b34d16 100644 --- a/drivers/infiniband/hw/hfi1/verbs_txreq.h +++ b/drivers/infiniband/hw/hfi1/verbs_txreq.h @@ -92,6 +92,8 @@ static inline struct verbs_txreq *get_txreq(struct hfi1_ibdev *dev, tx->psc = priv->s_sendcontext; /* so that we can test if the sdma decriptors are there */ tx->txreq.num_desc = 0; + /* Set the header type */ + tx->phdr.hdr.hdr_type = priv->hdr_type; return tx; } -- cgit v1.2.3