Skip to content

Commit d98bb7f

Browse files
Don Hiattdledford
authored andcommitted
IB/hfi1: Determine 9B/16B L2 header type based on Address handle
When address handle attributes are initialized, the LIDs are transformed to be in the 32 bit LID space. When constructing the header, hfi1 driver will look at the LID to determine the packet header to be created. Reviewed-by: Dennis Dalessandro <[email protected]> Signed-off-by: Dasaratharaman Chandramouli <[email protected]> Signed-off-by: Don Hiatt <[email protected]> Signed-off-by: Dennis Dalessandro <[email protected]> Signed-off-by: Doug Ledford <[email protected]>
1 parent 5786adf commit d98bb7f

File tree

8 files changed

+168
-8
lines changed

8 files changed

+168
-8
lines changed

drivers/infiniband/core/sa_query.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include <uapi/rdma/ib_user_sa.h>
5151
#include <rdma/ib_marshall.h>
5252
#include <rdma/ib_addr.h>
53+
#include <rdma/opa_addr.h>
5354
#include "sa.h"
5455
#include "core_priv.h"
5556

@@ -1239,6 +1240,11 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
12391240
ah_attr->type = rdma_ah_find_type(device, port_num);
12401241

12411242
rdma_ah_set_dlid(ah_attr, be32_to_cpu(sa_path_get_dlid(rec)));
1243+
1244+
if ((ah_attr->type == RDMA_AH_ATTR_TYPE_OPA) &&
1245+
(rdma_ah_get_dlid(ah_attr) == be16_to_cpu(IB_LID_PERMISSIVE)))
1246+
rdma_ah_set_make_grd(ah_attr, true);
1247+
12421248
rdma_ah_set_sl(ah_attr, rec->sl);
12431249
rdma_ah_set_path_bits(ah_attr, be32_to_cpu(sa_path_get_slid(rec)) &
12441250
get_src_path_mask(device, port_num));
@@ -2288,12 +2294,15 @@ static void update_sm_ah(struct work_struct *work)
22882294
rdma_ah_set_sl(&ah_attr, port_attr.sm_sl);
22892295
rdma_ah_set_port_num(&ah_attr, port->port_num);
22902296
if (port_attr.grh_required) {
2291-
rdma_ah_set_ah_flags(&ah_attr, IB_AH_GRH);
2292-
2293-
rdma_ah_set_subnet_prefix(&ah_attr,
2294-
cpu_to_be64(port_attr.subnet_prefix));
2295-
rdma_ah_set_interface_id(&ah_attr,
2296-
cpu_to_be64(IB_SA_WELL_KNOWN_GUID));
2297+
if (ah_attr.type == RDMA_AH_ATTR_TYPE_OPA) {
2298+
rdma_ah_set_make_grd(&ah_attr, true);
2299+
} else {
2300+
rdma_ah_set_ah_flags(&ah_attr, IB_AH_GRH);
2301+
rdma_ah_set_subnet_prefix(&ah_attr,
2302+
cpu_to_be64(port_attr.subnet_prefix));
2303+
rdma_ah_set_interface_id(&ah_attr,
2304+
cpu_to_be64(IB_SA_WELL_KNOWN_GUID));
2305+
}
22972306
}
22982307

22992308
new_ah->ah = rdma_create_ah(port->agent->qp->pd, &ah_attr);

drivers/infiniband/core/uverbs_cmd.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,6 +2009,7 @@ static int modify_qp(struct ib_uverbs_file *file,
20092009
rdma_ah_set_static_rate(&attr->ah_attr, cmd->base.dest.static_rate);
20102010
rdma_ah_set_port_num(&attr->ah_attr,
20112011
cmd->base.dest.port_num);
2012+
rdma_ah_set_make_grd(&attr->ah_attr, false);
20122013

20132014
attr->alt_ah_attr.type = rdma_ah_find_type(qp->device,
20142015
cmd->base.dest.port_num);
@@ -2032,6 +2033,7 @@ static int modify_qp(struct ib_uverbs_file *file,
20322033
cmd->base.alt_dest.static_rate);
20332034
rdma_ah_set_port_num(&attr->alt_ah_attr,
20342035
cmd->base.alt_dest.port_num);
2036+
rdma_ah_set_make_grd(&attr->alt_ah_attr, false);
20352037

20362038
ret = ib_modify_qp_with_udata(qp, attr,
20372039
modify_qp_mask(qp->qp_type,
@@ -2584,6 +2586,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
25842586
}
25852587

25862588
attr.type = rdma_ah_find_type(ib_dev, cmd.attr.port_num);
2589+
rdma_ah_set_make_grd(&attr, false);
25872590
rdma_ah_set_dlid(&attr, cmd.attr.dlid);
25882591
rdma_ah_set_sl(&attr, cmd.attr.sl);
25892592
rdma_ah_set_path_bits(&attr, cmd.attr.src_path_bits);

drivers/infiniband/hw/hfi1/hfi.h

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
#include <linux/rhashtable.h>
7171
#include <linux/netdevice.h>
7272
#include <rdma/rdma_vt.h>
73+
#include <rdma/opa_addr.h>
7374

7475
#include "chip_registers.h"
7576
#include "common.h"
@@ -353,6 +354,10 @@ struct hfi1_packet {
353354
bool fecn;
354355
};
355356

357+
/* Packet types */
358+
#define HFI1_PKT_TYPE_9B 0
359+
#define HFI1_PKT_TYPE_16B 1
360+
356361
/*
357362
* OPA 16B Header
358363
*/
@@ -2170,6 +2175,31 @@ int hfi1_tempsense_rd(struct hfi1_devdata *dd, struct hfi1_temp *temp);
21702175
#define DD_DEV_ENTRY(dd) __string(dev, dev_name(&(dd)->pcidev->dev))
21712176
#define DD_DEV_ASSIGN(dd) __assign_str(dev, dev_name(&(dd)->pcidev->dev))
21722177

2178+
static inline void hfi1_update_ah_attr(struct ib_device *ibdev,
2179+
struct rdma_ah_attr *attr)
2180+
{
2181+
struct hfi1_pportdata *ppd;
2182+
struct hfi1_ibport *ibp;
2183+
u32 dlid = rdma_ah_get_dlid(attr);
2184+
2185+
/*
2186+
* Kernel clients may not have setup GRH information
2187+
* Set that here.
2188+
*/
2189+
ibp = to_iport(ibdev, rdma_ah_get_port_num(attr));
2190+
ppd = ppd_from_ibp(ibp);
2191+
if ((((dlid >= be16_to_cpu(IB_MULTICAST_LID_BASE)) ||
2192+
(ppd->lid >= be16_to_cpu(IB_MULTICAST_LID_BASE))) &&
2193+
(dlid != be32_to_cpu(OPA_LID_PERMISSIVE)) &&
2194+
(dlid != be16_to_cpu(IB_LID_PERMISSIVE)) &&
2195+
(!(rdma_ah_get_ah_flags(attr) & IB_AH_GRH))) ||
2196+
(rdma_ah_get_make_grd(attr))) {
2197+
rdma_ah_set_ah_flags(attr, IB_AH_GRH);
2198+
rdma_ah_set_interface_id(attr, OPA_MAKE_ID(dlid));
2199+
rdma_ah_set_subnet_prefix(attr, ibp->rvp.gid_prefix);
2200+
}
2201+
}
2202+
21732203
/*
21742204
* hfi1_check_mcast- Check if the given lid is
21752205
* in the OPA multicast range.
@@ -2223,4 +2253,66 @@ static inline bool hfi1_is_16B_mcast(u32 lid)
22232253
opa_get_lid(opa_get_mcast_base(OPA_MCAST_NR), 16B)) &&
22242254
(lid != opa_get_lid(be32_to_cpu(OPA_LID_PERMISSIVE), 16B)));
22252255
}
2256+
2257+
static inline void hfi1_make_opa_lid(struct rdma_ah_attr *attr)
2258+
{
2259+
const struct ib_global_route *grh = rdma_ah_read_grh(attr);
2260+
u32 dlid = rdma_ah_get_dlid(attr);
2261+
2262+
/* Modify ah_attr.dlid to be in the 32 bit LID space.
2263+
* This is how the address will be laid out:
2264+
* Assuming MCAST_NR to be 4,
2265+
* 32 bit permissive LID = 0xFFFFFFFF
2266+
* Multicast LID range = 0xFFFFFFFE to 0xF0000000
2267+
* Unicast LID range = 0xEFFFFFFF to 1
2268+
* Invalid LID = 0
2269+
*/
2270+
if (ib_is_opa_gid(&grh->dgid))
2271+
dlid = opa_get_lid_from_gid(&grh->dgid);
2272+
else if ((dlid >= be16_to_cpu(IB_MULTICAST_LID_BASE)) &&
2273+
(dlid != be16_to_cpu(IB_LID_PERMISSIVE)) &&
2274+
(dlid != be32_to_cpu(OPA_LID_PERMISSIVE)))
2275+
dlid = dlid - be16_to_cpu(IB_MULTICAST_LID_BASE) +
2276+
opa_get_mcast_base(OPA_MCAST_NR);
2277+
else if (dlid == be16_to_cpu(IB_LID_PERMISSIVE))
2278+
dlid = be32_to_cpu(OPA_LID_PERMISSIVE);
2279+
2280+
rdma_ah_set_dlid(attr, dlid);
2281+
}
2282+
2283+
static inline u8 hfi1_get_packet_type(u32 lid)
2284+
{
2285+
/* 9B if lid > 0xF0000000 */
2286+
if (lid >= opa_get_mcast_base(OPA_MCAST_NR))
2287+
return HFI1_PKT_TYPE_9B;
2288+
2289+
/* 16B if lid > 0xC000 */
2290+
if (lid >= opa_get_lid(opa_get_mcast_base(OPA_MCAST_NR), 9B))
2291+
return HFI1_PKT_TYPE_16B;
2292+
2293+
return HFI1_PKT_TYPE_9B;
2294+
}
2295+
2296+
static inline bool hfi1_get_hdr_type(u32 lid, struct rdma_ah_attr *attr)
2297+
{
2298+
/*
2299+
* If there was an incoming 16B packet with permissive
2300+
* LIDs, OPA GIDs would have been programmed when those
2301+
* packets were received. A 16B packet will have to
2302+
* be sent in response to that packet. Return a 16B
2303+
* header type if that's the case.
2304+
*/
2305+
if (rdma_ah_get_dlid(attr) == be32_to_cpu(OPA_LID_PERMISSIVE))
2306+
return (ib_is_opa_gid(&rdma_ah_read_grh(attr)->dgid)) ?
2307+
HFI1_PKT_TYPE_16B : HFI1_PKT_TYPE_9B;
2308+
2309+
/*
2310+
* Return a 16B header type if either the the destination
2311+
* or source lid is extended.
2312+
*/
2313+
if (hfi1_get_packet_type(rdma_ah_get_dlid(attr)) == HFI1_PKT_TYPE_16B)
2314+
return HFI1_PKT_TYPE_16B;
2315+
2316+
return hfi1_get_packet_type(lid);
2317+
}
22262318
#endif /* _HFI1_KERNEL_H */

drivers/infiniband/hw/hfi1/qp.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,31 @@ int hfi1_check_modify_qp(struct rvt_qp *qp, struct ib_qp_attr *attr,
232232
return 0;
233233
}
234234

235+
/*
236+
* qp_set_16b - Set the hdr_type based on whether the slid or the
237+
* dlid in the connection is extended. Only applicable for RC and UC
238+
* QPs. UD QPs determine this on the fly from the ah in the wqe
239+
*/
240+
static inline void qp_set_16b(struct rvt_qp *qp)
241+
{
242+
struct hfi1_pportdata *ppd;
243+
struct hfi1_ibport *ibp;
244+
struct hfi1_qp_priv *priv = qp->priv;
245+
246+
/* Update ah_attr to account for extended LIDs */
247+
hfi1_update_ah_attr(qp->ibqp.device, &qp->remote_ah_attr);
248+
249+
/* Create 32 bit LIDs */
250+
hfi1_make_opa_lid(&qp->remote_ah_attr);
251+
252+
if (!(rdma_ah_get_ah_flags(&qp->remote_ah_attr) & IB_AH_GRH))
253+
return;
254+
255+
ibp = to_iport(qp->ibqp.device, qp->port_num);
256+
ppd = ppd_from_ibp(ibp);
257+
priv->hdr_type = hfi1_get_hdr_type(ppd->lid, &qp->remote_ah_attr);
258+
}
259+
235260
void hfi1_modify_qp(struct rvt_qp *qp, struct ib_qp_attr *attr,
236261
int attr_mask, struct ib_udata *udata)
237262
{
@@ -242,6 +267,7 @@ void hfi1_modify_qp(struct rvt_qp *qp, struct ib_qp_attr *attr,
242267
priv->s_sc = ah_to_sc(ibqp->device, &qp->remote_ah_attr);
243268
priv->s_sde = qp_to_sdma_engine(qp, priv->s_sc);
244269
priv->s_sendcontext = qp_to_send_context(qp, priv->s_sc);
270+
qp_set_16b(qp);
245271
}
246272

247273
if (attr_mask & IB_QP_PATH_MIG_STATE &&
@@ -251,6 +277,7 @@ void hfi1_modify_qp(struct rvt_qp *qp, struct ib_qp_attr *attr,
251277
priv->s_sc = ah_to_sc(ibqp->device, &qp->remote_ah_attr);
252278
priv->s_sde = qp_to_sdma_engine(qp, priv->s_sc);
253279
priv->s_sendcontext = qp_to_send_context(qp, priv->s_sc);
280+
qp_set_16b(qp);
254281
}
255282
}
256283

@@ -751,6 +778,7 @@ void hfi1_migrate_qp(struct rvt_qp *qp)
751778
qp->s_flags |= RVT_S_AHG_CLEAR;
752779
priv->s_sc = ah_to_sc(qp->ibqp.device, &qp->remote_ah_attr);
753780
priv->s_sde = qp_to_sdma_engine(qp, priv->s_sc);
781+
qp_set_16b(qp);
754782

755783
ev.device = qp->ibqp.device;
756784
ev.element.qp = &qp->ibqp;

drivers/infiniband/hw/hfi1/verbs.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,15 @@ static int query_port(struct rvt_dev_info *rdi, u8 port_num,
14211421
props->active_mtu = !valid_ib_mtu(ppd->ibmtu) ? props->max_mtu :
14221422
mtu_to_enum(ppd->ibmtu, IB_MTU_2048);
14231423

1424+
/*
1425+
* sm_lid of 0xFFFF needs special handling so that it can
1426+
* be differentiated from a permissve LID of 0xFFFF.
1427+
* We set the grh_required flag here so the SA can program
1428+
* the DGID in the address handle appropriately
1429+
*/
1430+
if (props->sm_lid == be16_to_cpu(IB_LID_PERMISSIVE))
1431+
props->grh_required = true;
1432+
14241433
return 0;
14251434
}
14261435

@@ -1528,6 +1537,7 @@ static void hfi1_notify_new_ah(struct ib_device *ibdev,
15281537
struct hfi1_pportdata *ppd;
15291538
struct hfi1_devdata *dd;
15301539
u8 sc5;
1540+
struct rdma_ah_attr *attr = &ah->attr;
15311541

15321542
/*
15331543
* Do not trust reading anything from rvt_ah at this point as it is not
@@ -1537,6 +1547,8 @@ static void hfi1_notify_new_ah(struct ib_device *ibdev,
15371547
ibp = to_iport(ibdev, rdma_ah_get_port_num(ah_attr));
15381548
ppd = ppd_from_ibp(ibp);
15391549
sc5 = ibp->sl_to_sc[rdma_ah_get_sl(&ah->attr)];
1550+
hfi1_update_ah_attr(ibdev, attr);
1551+
hfi1_make_opa_lid(attr);
15401552
dd = dd_from_ppd(ppd);
15411553
ah->vl = sc_to_vlt(dd, sc5);
15421554
if (ah->vl < num_vls || ah->vl == 15)

drivers/infiniband/hw/hfi1/verbs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ struct hfi1_qp_priv {
147147
u8 s_sc; /* SC[0..4] for next packet */
148148
struct iowait s_iowait;
149149
struct rvt_qp *owner;
150+
u8 hdr_type; /* 9B or 16B */
150151
};
151152

152153
/*

include/rdma/ib_verbs.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,7 @@ struct roce_ah_attr {
864864
struct opa_ah_attr {
865865
u32 dlid;
866866
u8 src_path_bits;
867+
bool make_grd;
867868
};
868869

869870
struct rdma_ah_attr {
@@ -3625,6 +3626,20 @@ static inline u8 rdma_ah_get_path_bits(const struct rdma_ah_attr *attr)
36253626
return 0;
36263627
}
36273628

3629+
static inline void rdma_ah_set_make_grd(struct rdma_ah_attr *attr,
3630+
bool make_grd)
3631+
{
3632+
if (attr->type == RDMA_AH_ATTR_TYPE_OPA)
3633+
attr->opa.make_grd = make_grd;
3634+
}
3635+
3636+
static inline bool rdma_ah_get_make_grd(const struct rdma_ah_attr *attr)
3637+
{
3638+
if (attr->type == RDMA_AH_ATTR_TYPE_OPA)
3639+
return attr->opa.make_grd;
3640+
return false;
3641+
}
3642+
36283643
static inline void rdma_ah_set_port_num(struct rdma_ah_attr *attr, u8 port_num)
36293644
{
36303645
attr->port_num = port_num;

include/rdma/opa_addr.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
*
7272
* @gid: The Global identifier
7373
*/
74-
static inline bool ib_is_opa_gid(union ib_gid *gid)
74+
static inline bool ib_is_opa_gid(const union ib_gid *gid)
7575
{
7676
return ((be64_to_cpu(gid->global.interface_id) >> 40) ==
7777
OPA_SPECIAL_OUI);
@@ -84,7 +84,7 @@ static inline bool ib_is_opa_gid(union ib_gid *gid)
8484
*
8585
* @gid: The Global identifier
8686
*/
87-
static inline u32 opa_get_lid_from_gid(union ib_gid *gid)
87+
static inline u32 opa_get_lid_from_gid(const union ib_gid *gid)
8888
{
8989
return be64_to_cpu(gid->global.interface_id) & 0xFFFFFFFF;
9090
}

0 commit comments

Comments
 (0)