diff options
author | Byczkowski, Jakub <jakub.byczkowski@intel.com> | 2017-05-12 12:01:37 -0400 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2017-06-01 17:04:20 -0400 |
commit | b3e6b4bdbb609762d8401ac4a959d590b4e4e3b8 (patch) | |
tree | 87997267ddfad332c0773f2adf807eea6e9803a4 | |
parent | e4785b0633574a607daaa04bf2fe43550055194f (diff) |
RDMA/hfi1: Defer setting VL15 credits to link-up interrupt
Keep VL15 credits at 0 during LNI, before link-up. Store
VL15 credits value during verify cap interrupt and set
in after link-up. This addresses an issue where VL15 MAD
packets could be sent by one side of the link before
the other side is ready to receive them.
Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Reviewed-by: Dean Luick <dean.luick@intel.com>
Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Jakub Byczkowski <jakub.byczkowski@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r-- | drivers/infiniband/hw/hfi1/chip.c | 67 | ||||
-rw-r--r-- | drivers/infiniband/hw/hfi1/chip_registers.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/hfi1/hfi.h | 11 | ||||
-rw-r--r-- | drivers/infiniband/hw/hfi1/intr.c | 3 |
4 files changed, 64 insertions, 19 deletions
diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index 5d6b1eeaa9a0..2ba00b89df6a 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c | |||
@@ -6312,25 +6312,38 @@ static void handle_8051_request(struct hfi1_pportdata *ppd) | |||
6312 | } | 6312 | } |
6313 | } | 6313 | } |
6314 | 6314 | ||
6315 | static void write_global_credit(struct hfi1_devdata *dd, | 6315 | /* |
6316 | u8 vau, u16 total, u16 shared) | 6316 | * Set up allocation unit vaulue. |
6317 | */ | ||
6318 | void set_up_vau(struct hfi1_devdata *dd, u8 vau) | ||
6317 | { | 6319 | { |
6318 | write_csr(dd, SEND_CM_GLOBAL_CREDIT, | 6320 | u64 reg = read_csr(dd, SEND_CM_GLOBAL_CREDIT); |
6319 | ((u64)total << | 6321 | |
6320 | SEND_CM_GLOBAL_CREDIT_TOTAL_CREDIT_LIMIT_SHIFT) | | 6322 | /* do not modify other values in the register */ |
6321 | ((u64)shared << | 6323 | reg &= ~SEND_CM_GLOBAL_CREDIT_AU_SMASK; |
6322 | SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SHIFT) | | 6324 | reg |= (u64)vau << SEND_CM_GLOBAL_CREDIT_AU_SHIFT; |
6323 | ((u64)vau << SEND_CM_GLOBAL_CREDIT_AU_SHIFT)); | 6325 | write_csr(dd, SEND_CM_GLOBAL_CREDIT, reg); |
6324 | } | 6326 | } |
6325 | 6327 | ||
6326 | /* | 6328 | /* |
6327 | * Set up initial VL15 credits of the remote. Assumes the rest of | 6329 | * Set up initial VL15 credits of the remote. Assumes the rest of |
6328 | * the CM credit registers are zero from a previous global or credit reset . | 6330 | * the CM credit registers are zero from a previous global or credit reset. |
6331 | * Shared limit for VL15 will always be 0. | ||
6329 | */ | 6332 | */ |
6330 | void set_up_vl15(struct hfi1_devdata *dd, u8 vau, u16 vl15buf) | 6333 | void set_up_vl15(struct hfi1_devdata *dd, u16 vl15buf) |
6331 | { | 6334 | { |
6332 | /* leave shared count at zero for both global and VL15 */ | 6335 | u64 reg = read_csr(dd, SEND_CM_GLOBAL_CREDIT); |
6333 | write_global_credit(dd, vau, vl15buf, 0); | 6336 | |
6337 | /* set initial values for total and shared credit limit */ | ||
6338 | reg &= ~(SEND_CM_GLOBAL_CREDIT_TOTAL_CREDIT_LIMIT_SMASK | | ||
6339 | SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SMASK); | ||
6340 | |||
6341 | /* | ||
6342 | * Set total limit to be equal to VL15 credits. | ||
6343 | * Leave shared limit at 0. | ||
6344 | */ | ||
6345 | reg |= (u64)vl15buf << SEND_CM_GLOBAL_CREDIT_TOTAL_CREDIT_LIMIT_SHIFT; | ||
6346 | write_csr(dd, SEND_CM_GLOBAL_CREDIT, reg); | ||
6334 | 6347 | ||
6335 | write_csr(dd, SEND_CM_CREDIT_VL15, (u64)vl15buf | 6348 | write_csr(dd, SEND_CM_CREDIT_VL15, (u64)vl15buf |
6336 | << SEND_CM_CREDIT_VL15_DEDICATED_LIMIT_VL_SHIFT); | 6349 | << SEND_CM_CREDIT_VL15_DEDICATED_LIMIT_VL_SHIFT); |
@@ -6348,9 +6361,11 @@ void reset_link_credits(struct hfi1_devdata *dd) | |||
6348 | for (i = 0; i < TXE_NUM_DATA_VL; i++) | 6361 | for (i = 0; i < TXE_NUM_DATA_VL; i++) |
6349 | write_csr(dd, SEND_CM_CREDIT_VL + (8 * i), 0); | 6362 | write_csr(dd, SEND_CM_CREDIT_VL + (8 * i), 0); |
6350 | write_csr(dd, SEND_CM_CREDIT_VL15, 0); | 6363 | write_csr(dd, SEND_CM_CREDIT_VL15, 0); |
6351 | write_global_credit(dd, 0, 0, 0); | 6364 | write_csr(dd, SEND_CM_GLOBAL_CREDIT, 0); |
6352 | /* reset the CM block */ | 6365 | /* reset the CM block */ |
6353 | pio_send_control(dd, PSC_CM_RESET); | 6366 | pio_send_control(dd, PSC_CM_RESET); |
6367 | /* reset cached value */ | ||
6368 | dd->vl15buf_cached = 0; | ||
6354 | } | 6369 | } |
6355 | 6370 | ||
6356 | /* convert a vCU to a CU */ | 6371 | /* convert a vCU to a CU */ |
@@ -6839,24 +6854,35 @@ void handle_link_up(struct work_struct *work) | |||
6839 | { | 6854 | { |
6840 | struct hfi1_pportdata *ppd = container_of(work, struct hfi1_pportdata, | 6855 | struct hfi1_pportdata *ppd = container_of(work, struct hfi1_pportdata, |
6841 | link_up_work); | 6856 | link_up_work); |
6857 | struct hfi1_devdata *dd = ppd->dd; | ||
6858 | |||
6842 | set_link_state(ppd, HLS_UP_INIT); | 6859 | set_link_state(ppd, HLS_UP_INIT); |
6843 | 6860 | ||
6844 | /* cache the read of DC_LCB_STS_ROUND_TRIP_LTP_CNT */ | 6861 | /* cache the read of DC_LCB_STS_ROUND_TRIP_LTP_CNT */ |
6845 | read_ltp_rtt(ppd->dd); | 6862 | read_ltp_rtt(dd); |
6846 | /* | 6863 | /* |
6847 | * OPA specifies that certain counters are cleared on a transition | 6864 | * OPA specifies that certain counters are cleared on a transition |
6848 | * to link up, so do that. | 6865 | * to link up, so do that. |
6849 | */ | 6866 | */ |
6850 | clear_linkup_counters(ppd->dd); | 6867 | clear_linkup_counters(dd); |
6851 | /* | 6868 | /* |
6852 | * And (re)set link up default values. | 6869 | * And (re)set link up default values. |
6853 | */ | 6870 | */ |
6854 | set_linkup_defaults(ppd); | 6871 | set_linkup_defaults(ppd); |
6855 | 6872 | ||
6873 | /* | ||
6874 | * Set VL15 credits. Use cached value from verify cap interrupt. | ||
6875 | * In case of quick linkup or simulator, vl15 value will be set by | ||
6876 | * handle_linkup_change. VerifyCap interrupt handler will not be | ||
6877 | * called in those scenarios. | ||
6878 | */ | ||
6879 | if (!(quick_linkup || dd->icode == ICODE_FUNCTIONAL_SIMULATOR)) | ||
6880 | set_up_vl15(dd, dd->vl15buf_cached); | ||
6881 | |||
6856 | /* enforce link speed enabled */ | 6882 | /* enforce link speed enabled */ |
6857 | if ((ppd->link_speed_active & ppd->link_speed_enabled) == 0) { | 6883 | if ((ppd->link_speed_active & ppd->link_speed_enabled) == 0) { |
6858 | /* oops - current speed is not enabled, bounce */ | 6884 | /* oops - current speed is not enabled, bounce */ |
6859 | dd_dev_err(ppd->dd, | 6885 | dd_dev_err(dd, |
6860 | "Link speed active 0x%x is outside enabled 0x%x, downing link\n", | 6886 | "Link speed active 0x%x is outside enabled 0x%x, downing link\n", |
6861 | ppd->link_speed_active, ppd->link_speed_enabled); | 6887 | ppd->link_speed_active, ppd->link_speed_enabled); |
6862 | set_link_down_reason(ppd, OPA_LINKDOWN_REASON_SPEED_POLICY, 0, | 6888 | set_link_down_reason(ppd, OPA_LINKDOWN_REASON_SPEED_POLICY, 0, |
@@ -7357,7 +7383,14 @@ void handle_verify_cap(struct work_struct *work) | |||
7357 | */ | 7383 | */ |
7358 | if (vau == 0) | 7384 | if (vau == 0) |
7359 | vau = 1; | 7385 | vau = 1; |
7360 | set_up_vl15(dd, vau, vl15buf); | 7386 | set_up_vau(dd, vau); |
7387 | |||
7388 | /* | ||
7389 | * Set VL15 credits to 0 in global credit register. Cache remote VL15 | ||
7390 | * credits value and wait for link-up interrupt ot set it. | ||
7391 | */ | ||
7392 | set_up_vl15(dd, 0); | ||
7393 | dd->vl15buf_cached = vl15buf; | ||
7361 | 7394 | ||
7362 | /* set up the LCB CRC mode */ | 7395 | /* set up the LCB CRC mode */ |
7363 | crc_mask = ppd->port_crc_mode_enabled & partner_supported_crc; | 7396 | crc_mask = ppd->port_crc_mode_enabled & partner_supported_crc; |
diff --git a/drivers/infiniband/hw/hfi1/chip_registers.h b/drivers/infiniband/hw/hfi1/chip_registers.h index 5bfa839d1c48..793514f1d15f 100644 --- a/drivers/infiniband/hw/hfi1/chip_registers.h +++ b/drivers/infiniband/hw/hfi1/chip_registers.h | |||
@@ -839,7 +839,9 @@ | |||
839 | #define SEND_CM_CTRL_FORCE_CREDIT_MODE_SMASK 0x8ull | 839 | #define SEND_CM_CTRL_FORCE_CREDIT_MODE_SMASK 0x8ull |
840 | #define SEND_CM_CTRL_RESETCSR 0x0000000000000020ull | 840 | #define SEND_CM_CTRL_RESETCSR 0x0000000000000020ull |
841 | #define SEND_CM_GLOBAL_CREDIT (TXE + 0x000000000508) | 841 | #define SEND_CM_GLOBAL_CREDIT (TXE + 0x000000000508) |
842 | #define SEND_CM_GLOBAL_CREDIT_AU_MASK 0x7ull | ||
842 | #define SEND_CM_GLOBAL_CREDIT_AU_SHIFT 16 | 843 | #define SEND_CM_GLOBAL_CREDIT_AU_SHIFT 16 |
844 | #define SEND_CM_GLOBAL_CREDIT_AU_SMASK 0x70000ull | ||
843 | #define SEND_CM_GLOBAL_CREDIT_RESETCSR 0x0000094000030000ull | 845 | #define SEND_CM_GLOBAL_CREDIT_RESETCSR 0x0000094000030000ull |
844 | #define SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_MASK 0xFFFFull | 846 | #define SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_MASK 0xFFFFull |
845 | #define SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SHIFT 0 | 847 | #define SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SHIFT 0 |
diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h index da322e6668cc..414a04a481c2 100644 --- a/drivers/infiniband/hw/hfi1/hfi.h +++ b/drivers/infiniband/hw/hfi1/hfi.h | |||
@@ -1045,6 +1045,14 @@ struct hfi1_devdata { | |||
1045 | /* initial vl15 credits to use */ | 1045 | /* initial vl15 credits to use */ |
1046 | u16 vl15_init; | 1046 | u16 vl15_init; |
1047 | 1047 | ||
1048 | /* | ||
1049 | * Cached value for vl15buf, read during verify cap interrupt. VL15 | ||
1050 | * credits are to be kept at 0 and set when handling the link-up | ||
1051 | * interrupt. This removes the possibility of receiving VL15 MAD | ||
1052 | * packets before this HFI is ready. | ||
1053 | */ | ||
1054 | u16 vl15buf_cached; | ||
1055 | |||
1048 | /* Misc small ints */ | 1056 | /* Misc small ints */ |
1049 | u8 n_krcv_queues; | 1057 | u8 n_krcv_queues; |
1050 | u8 qos_shift; | 1058 | u8 qos_shift; |
@@ -1598,7 +1606,8 @@ int hfi1_rcvbuf_validate(u32 size, u8 type, u16 *encode); | |||
1598 | int fm_get_table(struct hfi1_pportdata *ppd, int which, void *t); | 1606 | int fm_get_table(struct hfi1_pportdata *ppd, int which, void *t); |
1599 | int fm_set_table(struct hfi1_pportdata *ppd, int which, void *t); | 1607 | int fm_set_table(struct hfi1_pportdata *ppd, int which, void *t); |
1600 | 1608 | ||
1601 | void set_up_vl15(struct hfi1_devdata *dd, u8 vau, u16 vl15buf); | 1609 | void set_up_vau(struct hfi1_devdata *dd, u8 vau); |
1610 | void set_up_vl15(struct hfi1_devdata *dd, u16 vl15buf); | ||
1602 | void reset_link_credits(struct hfi1_devdata *dd); | 1611 | void reset_link_credits(struct hfi1_devdata *dd); |
1603 | void assign_remote_cm_au_table(struct hfi1_devdata *dd, u8 vcu); | 1612 | void assign_remote_cm_au_table(struct hfi1_devdata *dd, u8 vcu); |
1604 | 1613 | ||
diff --git a/drivers/infiniband/hw/hfi1/intr.c b/drivers/infiniband/hw/hfi1/intr.c index ba265d0ae93b..04a5082d5ac5 100644 --- a/drivers/infiniband/hw/hfi1/intr.c +++ b/drivers/infiniband/hw/hfi1/intr.c | |||
@@ -130,7 +130,8 @@ void handle_linkup_change(struct hfi1_devdata *dd, u32 linkup) | |||
130 | * the remote values. Both sides must be using the values. | 130 | * the remote values. Both sides must be using the values. |
131 | */ | 131 | */ |
132 | if (quick_linkup || dd->icode == ICODE_FUNCTIONAL_SIMULATOR) { | 132 | if (quick_linkup || dd->icode == ICODE_FUNCTIONAL_SIMULATOR) { |
133 | set_up_vl15(dd, dd->vau, dd->vl15_init); | 133 | set_up_vau(dd, dd->vau); |
134 | set_up_vl15(dd, dd->vl15_init); | ||
134 | assign_remote_cm_au_table(dd, dd->vcu); | 135 | assign_remote_cm_au_table(dd, dd->vcu); |
135 | } | 136 | } |
136 | 137 | ||