diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index a61ec7e33613..6fd1018a6c1b 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -2314,7 +2314,7 @@ static void update_sm_ah(struct work_struct *work)
 	rdma_ah_set_dlid(&ah_attr, port_attr.sm_lid);
 	rdma_ah_set_sl(&ah_attr, port_attr.sm_sl);
 	rdma_ah_set_port_num(&ah_attr, port->port_num);
-	if (port_attr.grh_required) {
+	if (port_attr.port_cap_flags & IB_PORT_GRH_REQUIRED) {
 		if (ah_attr.type == RDMA_AH_ATTR_TYPE_OPA) {
 			rdma_ah_set_make_grd(&ah_attr, true);
 		} else {
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 126d3efb976f..868f7549182d 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1979,14 +1979,20 @@ static int modify_qp(struct ib_uverbs_file *file,
 	}
 
 	if ((cmd->base.attr_mask & IB_QP_AV) &&
-	    !rdma_is_port_valid(qp->device, cmd->base.dest.port_num)) {
+	    !(rdma_is_port_valid(qp->device, cmd->base.dest.port_num) &&
+	      rdma_validate_av(qp->device, cmd->base.dest.port_num,
+			       cmd->base.dest.is_global))) {
 		ret = -EINVAL;
 		goto release_qp;
 	}
 
 	if ((cmd->base.attr_mask & IB_QP_ALT_PATH) &&
-	    (!rdma_is_port_valid(qp->device, cmd->base.alt_port_num) ||
-	    !rdma_is_port_valid(qp->device, cmd->base.alt_dest.port_num))) {
+	    !(rdma_is_port_valid(qp->device, cmd->base.alt_port_num) &&
+	      rdma_validate_av(qp->device, cmd->base.alt_port_num,
+			       cmd->base.alt_dest.is_global) &&
+	      rdma_is_port_valid(qp->device, cmd->base.alt_dest.port_num) &&
+	      rdma_validate_av(qp->device, cmd->base.alt_dest.port_num,
+			       cmd->base.alt_dest.is_global))) {
 		ret = -EINVAL;
 		goto release_qp;
 	}
@@ -2559,6 +2565,9 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
 	if (!rdma_is_port_valid(ib_dev, cmd.attr.port_num))
 		return -EINVAL;
 
+	if (!rdma_validate_av(ib_dev, cmd.attr.port_num, cmd.attr.is_global))
+		return -EINVAL;
+
 	ib_uverbs_init_udata(&udata, buf + sizeof(cmd),
 		   u64_to_user_ptr(cmd.response) + sizeof(resp),
 		   in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c
index c8cf4d4984d3..f00eeb636c7e 100644
--- a/drivers/infiniband/hw/hfi1/verbs.c
+++ b/drivers/infiniband/hw/hfi1/verbs.c
@@ -1491,11 +1491,11 @@ static int query_port(struct rvt_dev_info *rdi, u8 port_num,
 	/*
 	 * sm_lid of 0xFFFF needs special handling so that it can
 	 * be differentiated from a permissve LID of 0xFFFF.
-	 * We set the grh_required flag here so the SA can program
+	 * We set the IB_PORT_GRH_REQUIRED flag here so the SA can program
 	 * the DGID in the address handle appropriately
 	 */
 	if (props->sm_lid == be16_to_cpu(IB_LID_PERMISSIVE))
-		props->grh_required = true;
+		props->port_cap_flags |= IB_PORT_GRH_REQUIRED;
 
 	return 0;
 }
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 5b70744f414a..385f28a16bc2 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -85,6 +85,34 @@ static enum rdma_link_layer mlx4_ib_port_link_layer(struct ib_device *device,
 
 static struct workqueue_struct *wq;
 
+enum {
+	MLX4_SUPPORTED_IB_SPEC_PORT_CAP_FLAGS =
+		IB_PORT_SM			  |
+		IB_PORT_NOTICE_SUP		  |
+		IB_PORT_TRAP_SUP		  |
+		IB_PORT_OPT_IPD_SUP		  |
+		IB_PORT_AUTO_MIGR_SUP		  |
+		IB_PORT_SL_MAP_SUP		  |
+		IB_PORT_MKEY_NVRAM		  |
+		IB_PORT_PKEY_NVRAM		  |
+		IB_PORT_LED_INFO_SUP		  |
+		IB_PORT_SM_DISABLED		  |
+		IB_PORT_SYS_IMAGE_GUID_SUP	  |
+		IB_PORT_PKEY_SW_EXT_PORT_TRAP_SUP |
+		IB_PORT_EXTENDED_SPEEDS_SUP	  |
+		IB_PORT_CM_SUP			  |
+		IB_PORT_SNMP_TUNNEL_SUP		  |
+		IB_PORT_REINIT_SUP		  |
+		IB_PORT_DEVICE_MGMT_SUP		  |
+		IB_PORT_VENDOR_CLASS_SUP	  |
+		IB_PORT_DR_NOTICE_SUP		  |
+		IB_PORT_CAP_MASK_NOTICE_SUP	  |
+		IB_PORT_BOOT_MGMT_SUP		  |
+		IB_PORT_LINK_LATENCY_SUP	  |
+		IB_PORT_CLIENT_REG_SUP
+};
+
+
 static void init_query_mad(struct ib_smp *mad)
 {
 	mad->base_version  = 1;
@@ -694,6 +722,7 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port,
 	props->subnet_timeout	= out_mad->data[51] & 0x1f;
 	props->max_vl_num	= out_mad->data[37] >> 4;
 	props->init_type_reply	= out_mad->data[41] >> 4;
+	props->port_cap_flags  &= MLX4_SUPPORTED_IB_SPEC_PORT_CAP_FLAGS;
 
 	/* Check if extended speeds (EDR/FDR/...) are supported */
 	if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) {
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 169f32a0726b..a4817049b06b 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -93,6 +93,33 @@ enum {
 	MLX5_ATOMIC_SIZE_QP_8BYTES = 1 << 3,
 };
 
+enum {
+	MLX5_SUPPORTED_IB_SPEC_PORT_CAP_FLAGS =
+		IB_PORT_SM			  |
+		IB_PORT_NOTICE_SUP		  |
+		IB_PORT_TRAP_SUP		  |
+		IB_PORT_OPT_IPD_SUP		  |
+		IB_PORT_AUTO_MIGR_SUP		  |
+		IB_PORT_SL_MAP_SUP		  |
+		IB_PORT_MKEY_NVRAM		  |
+		IB_PORT_PKEY_NVRAM		  |
+		IB_PORT_LED_INFO_SUP		  |
+		IB_PORT_SM_DISABLED		  |
+		IB_PORT_SYS_IMAGE_GUID_SUP	  |
+		IB_PORT_PKEY_SW_EXT_PORT_TRAP_SUP |
+		IB_PORT_EXTENDED_SPEEDS_SUP	  |
+		IB_PORT_CM_SUP			  |
+		IB_PORT_SNMP_TUNNEL_SUP		  |
+		IB_PORT_REINIT_SUP		  |
+		IB_PORT_DEVICE_MGMT_SUP		  |
+		IB_PORT_VENDOR_CLASS_SUP	  |
+		IB_PORT_DR_NOTICE_SUP		  |
+		IB_PORT_CAP_MASK_NOTICE_SUP	  |
+		IB_PORT_BOOT_MGMT_SUP		  |
+		IB_PORT_LINK_LATENCY_SUP	  |
+		IB_PORT_CLIENT_REG_SUP
+};
+
 static struct workqueue_struct *mlx5_ib_event_wq;
 static LIST_HEAD(mlx5_ib_unaffiliated_port_list);
 static LIST_HEAD(mlx5_ib_dev_list);
@@ -1239,7 +1266,9 @@ static int mlx5_query_hca_port(struct ib_device *ibdev, u8 port,
 	props->qkey_viol_cntr	= rep->qkey_violation_counter;
 	props->subnet_timeout	= rep->subnet_timeout;
 	props->init_type_reply	= rep->init_type_reply;
-	props->grh_required	= rep->grh_required;
+	props->port_cap_flags  &= MLX5_SUPPORTED_IB_SPEC_PORT_CAP_FLAGS;
+	if (rep->grh_required)
+		props->port_cap_flags  |= IB_PORT_GRH_REQUIRED;
 
 	err = mlx5_query_port_link_width_oper(mdev, &ib_link_width_oper, port);
 	if (err)
@@ -4302,7 +4331,8 @@ static void destroy_dev_resources(struct mlx5_ib_resources *devr)
 		cancel_work_sync(&devr->ports[port].pkey_change_work);
 }
 
-static u32 get_core_cap_flags(struct ib_device *ibdev)
+static u32 get_core_cap_flags(struct ib_device *ibdev,
+			      struct ib_port_attr *port_attr)
 {
 	struct mlx5_ib_dev *dev = to_mdev(ibdev);
 	enum rdma_link_layer ll = mlx5_ib_port_link_layer(ibdev, 1);
@@ -4311,8 +4341,14 @@ static u32 get_core_cap_flags(struct ib_device *ibdev)
 	bool raw_support = !mlx5_core_mp_enabled(dev->mdev);
 	u32 ret = 0;
 
-	if (ll == IB_LINK_LAYER_INFINIBAND)
-		return RDMA_CORE_PORT_IBA_IB;
+	if (ll == IB_LINK_LAYER_INFINIBAND) {
+		ret = RDMA_CORE_PORT_IBA_IB;
+
+		if (port_attr->port_cap_flags & IB_PORT_GRH_REQUIRED)
+			ret |= RDMA_CORE_CAP_IB_GRH_REQUIRED;
+
+		return ret;
+	}
 
 	if (raw_support)
 		ret = RDMA_CORE_PORT_RAW_PACKET;
@@ -4340,15 +4376,13 @@ static int mlx5_port_immutable(struct ib_device *ibdev, u8 port_num,
 	enum rdma_link_layer ll = mlx5_ib_port_link_layer(ibdev, port_num);
 	int err;
 
-	immutable->core_cap_flags = get_core_cap_flags(ibdev);
-
 	err = ib_query_port(ibdev, port_num, &attr);
 	if (err)
 		return err;
 
 	immutable->pkey_tbl_len = attr.pkey_tbl_len;
 	immutable->gid_tbl_len = attr.gid_tbl_len;
-	immutable->core_cap_flags = get_core_cap_flags(ibdev);
+	immutable->core_cap_flags = get_core_cap_flags(ibdev, &attr);
 	if ((ll == IB_LINK_LAYER_INFINIBAND) || MLX5_CAP_GEN(dev->mdev, roce))
 		immutable->max_mad_size = IB_MGMT_MAD_SIZE;
 
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 541f237965c7..8917a29ff194 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -49,6 +49,34 @@
 #include <rdma/mthca-abi.h>
 #include "mthca_memfree.h"
 
+
+enum {
+	MTHCA_SUPPORTED_IB_SPEC_PORT_CAP_FLAGS =
+		IB_PORT_SM			  |
+		IB_PORT_NOTICE_SUP		  |
+		IB_PORT_TRAP_SUP		  |
+		IB_PORT_OPT_IPD_SUP		  |
+		IB_PORT_AUTO_MIGR_SUP		  |
+		IB_PORT_SL_MAP_SUP		  |
+		IB_PORT_MKEY_NVRAM		  |
+		IB_PORT_PKEY_NVRAM		  |
+		IB_PORT_LED_INFO_SUP		  |
+		IB_PORT_SM_DISABLED		  |
+		IB_PORT_SYS_IMAGE_GUID_SUP	  |
+		IB_PORT_PKEY_SW_EXT_PORT_TRAP_SUP |
+		IB_PORT_EXTENDED_SPEEDS_SUP	  |
+		IB_PORT_CM_SUP			  |
+		IB_PORT_SNMP_TUNNEL_SUP		  |
+		IB_PORT_REINIT_SUP		  |
+		IB_PORT_DEVICE_MGMT_SUP		  |
+		IB_PORT_VENDOR_CLASS_SUP	  |
+		IB_PORT_DR_NOTICE_SUP		  |
+		IB_PORT_CAP_MASK_NOTICE_SUP	  |
+		IB_PORT_BOOT_MGMT_SUP		  |
+		IB_PORT_LINK_LATENCY_SUP	  |
+		IB_PORT_CLIENT_REG_SUP
+};
+
 static void init_query_mad(struct ib_smp *mad)
 {
 	mad->base_version  = 1;
@@ -176,6 +204,7 @@ static int mthca_query_port(struct ib_device *ibdev,
 	props->subnet_timeout    = out_mad->data[51] & 0x1f;
 	props->max_vl_num        = out_mad->data[37] >> 4;
 	props->init_type_reply   = out_mad->data[41] >> 4;
+	props->port_cap_flags   &= MTHCA_SUPPORTED_IB_SPEC_PORT_CAP_FLAGS;
 
  out:
 	kfree(in_mad);
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h b/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
index 44cb1cfba417..aa15af435362 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
@@ -72,6 +72,33 @@
 #define PVRDMA_NUM_RING_PAGES		4
 #define PVRDMA_QP_NUM_HEADER_PAGES	1
 
+enum {
+	PVRDMA_SUPPORTED_IB_SPEC_PORT_CAP_FLAGS =
+		IB_PORT_SM			  |
+		IB_PORT_NOTICE_SUP		  |
+		IB_PORT_TRAP_SUP		  |
+		IB_PORT_OPT_IPD_SUP		  |
+		IB_PORT_AUTO_MIGR_SUP		  |
+		IB_PORT_SL_MAP_SUP		  |
+		IB_PORT_MKEY_NVRAM		  |
+		IB_PORT_PKEY_NVRAM		  |
+		IB_PORT_LED_INFO_SUP		  |
+		IB_PORT_SM_DISABLED		  |
+		IB_PORT_SYS_IMAGE_GUID_SUP	  |
+		IB_PORT_PKEY_SW_EXT_PORT_TRAP_SUP |
+		IB_PORT_EXTENDED_SPEEDS_SUP	  |
+		IB_PORT_CM_SUP			  |
+		IB_PORT_SNMP_TUNNEL_SUP		  |
+		IB_PORT_REINIT_SUP		  |
+		IB_PORT_DEVICE_MGMT_SUP		  |
+		IB_PORT_VENDOR_CLASS_SUP	  |
+		IB_PORT_DR_NOTICE_SUP		  |
+		IB_PORT_CAP_MASK_NOTICE_SUP	  |
+		IB_PORT_BOOT_MGMT_SUP		  |
+		IB_PORT_LINK_LATENCY_SUP	  |
+		IB_PORT_CLIENT_REG_SUP
+};
+
 struct pvrdma_dev;
 
 struct pvrdma_page_dir {
@@ -351,7 +378,7 @@ static inline int ib_port_cap_flags_to_pvrdma(int flags)
 
 static inline int pvrdma_port_cap_flags_to_ib(int flags)
 {
-	return flags;
+	return flags & PVRDMA_SUPPORTED_IB_SPEC_PORT_CAP_FLAGS;
 }
 
 static inline enum pvrdma_port_width ib_port_width_to_pvrdma(
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index d84e6b6a8a56..2323a5624161 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -455,6 +455,7 @@ enum ib_port_cap_flags {
 	IB_PORT_LINK_LATENCY_SUP		= 1 << 24,
 	IB_PORT_CLIENT_REG_SUP			= 1 << 25,
 	IB_PORT_IP_BASED_GIDS			= 1 << 26,
+	IB_PORT_GRH_REQUIRED			= 1 << 27,
 };
 
 enum ib_port_width {
@@ -554,6 +555,7 @@ static inline struct rdma_hw_stats *rdma_alloc_hw_stats_struct(
 #define RDMA_CORE_CAP_AF_IB             0x00001000
 #define RDMA_CORE_CAP_ETH_AH            0x00002000
 #define RDMA_CORE_CAP_OPA_AH            0x00004000
+#define RDMA_CORE_CAP_IB_GRH_REQUIRED   0x00008000
 
 /* Protocol                             0xFFF00000 */
 #define RDMA_CORE_CAP_PROT_IB           0x00100000
@@ -610,7 +612,6 @@ struct ib_port_attr {
 	u8			active_width;
 	u8			active_speed;
 	u8                      phys_state;
-	bool			grh_required;
 };
 
 enum ib_device_modify_flags {
@@ -2706,6 +2707,13 @@ static inline int rdma_is_port_valid(const struct ib_device *device,
 		port <= rdma_end_port(device));
 }
 
+static inline bool rdma_validate_av(const struct ib_device *device,
+				    u8 port_num, u8 is_global)
+{
+	return is_global || !(device->port_immutable[port_num].core_cap_flags &
+		RDMA_CORE_CAP_IB_GRH_REQUIRED);
+}
+
 static inline bool rdma_protocol_ib(const struct ib_device *device, u8 port_num)
 {
 	return device->port_immutable[port_num].core_cap_flags & RDMA_CORE_CAP_PROT_IB;
