Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf6a9e31 authored by Jack Morgenstein's avatar Jack Morgenstein Committed by Roland Dreier
Browse files

IB: simplify static rate encoding



Push translation of static rate to HCA format into low-level drivers,
where it belongs.  For static rate encoding, use encoding of rate
field from IB standard PathRecord, with addition of value 0, for
backwards compatibility with current usage.  The changes are:

 - Add enum ib_rate to midlayer includes.
 - Get rid of static rate translation in IPoIB; just use static rate
   directly from Path and MulticastGroup records.
 - Update mthca driver to translate absolute static rate into the
   format used by hardware.  This also fixes mthca's static rate
   handling for HCAs that are capable of 4X DDR.

Signed-off-by: default avatarJack Morgenstein <jackm@mellanox.co.il>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent d2e0655e
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -45,6 +45,40 @@
#include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h>

int ib_rate_to_mult(enum ib_rate rate)
{
	switch (rate) {
	case IB_RATE_2_5_GBPS: return  1;
	case IB_RATE_5_GBPS:   return  2;
	case IB_RATE_10_GBPS:  return  4;
	case IB_RATE_20_GBPS:  return  8;
	case IB_RATE_30_GBPS:  return 12;
	case IB_RATE_40_GBPS:  return 16;
	case IB_RATE_60_GBPS:  return 24;
	case IB_RATE_80_GBPS:  return 32;
	case IB_RATE_120_GBPS: return 48;
	default:	       return -1;
	}
}
EXPORT_SYMBOL(ib_rate_to_mult);

enum ib_rate mult_to_ib_rate(int mult)
{
	switch (mult) {
	case 1:  return IB_RATE_2_5_GBPS;
	case 2:  return IB_RATE_5_GBPS;
	case 4:  return IB_RATE_10_GBPS;
	case 8:  return IB_RATE_20_GBPS;
	case 12: return IB_RATE_30_GBPS;
	case 16: return IB_RATE_40_GBPS;
	case 24: return IB_RATE_60_GBPS;
	case 32: return IB_RATE_80_GBPS;
	case 48: return IB_RATE_120_GBPS;
	default: return IB_RATE_PORT_CURRENT;
	}
}
EXPORT_SYMBOL(mult_to_ib_rate);

/* Protection domains */

struct ib_pd *ib_alloc_pd(struct ib_device *device)
+99 −1
Original line number Diff line number Diff line
@@ -42,6 +42,20 @@

#include "mthca_dev.h"

enum {
      MTHCA_RATE_TAVOR_FULL   = 0,
      MTHCA_RATE_TAVOR_1X     = 1,
      MTHCA_RATE_TAVOR_4X     = 2,
      MTHCA_RATE_TAVOR_1X_DDR = 3
};

enum {
      MTHCA_RATE_MEMFREE_FULL    = 0,
      MTHCA_RATE_MEMFREE_QUARTER = 1,
      MTHCA_RATE_MEMFREE_EIGHTH  = 2,
      MTHCA_RATE_MEMFREE_HALF    = 3
};

struct mthca_av {
	__be32 port_pd;
	u8     reserved1;
@@ -55,6 +69,90 @@ struct mthca_av {
	__be32 dgid[4];
};

static enum ib_rate memfree_rate_to_ib(u8 mthca_rate, u8 port_rate)
{
	switch (mthca_rate) {
	case MTHCA_RATE_MEMFREE_EIGHTH:
		return mult_to_ib_rate(port_rate >> 3);
	case MTHCA_RATE_MEMFREE_QUARTER:
		return mult_to_ib_rate(port_rate >> 2);
	case MTHCA_RATE_MEMFREE_HALF:
		return mult_to_ib_rate(port_rate >> 1);
	case MTHCA_RATE_MEMFREE_FULL:
	default:
		return mult_to_ib_rate(port_rate);
	}
}

static enum ib_rate tavor_rate_to_ib(u8 mthca_rate, u8 port_rate)
{
	switch (mthca_rate) {
	case MTHCA_RATE_TAVOR_1X:     return IB_RATE_2_5_GBPS;
	case MTHCA_RATE_TAVOR_1X_DDR: return IB_RATE_5_GBPS;
	case MTHCA_RATE_TAVOR_4X:     return IB_RATE_10_GBPS;
	default:		      return port_rate;
	}
}

enum ib_rate mthca_rate_to_ib(struct mthca_dev *dev, u8 mthca_rate, u8 port)
{
	if (mthca_is_memfree(dev)) {
		/* Handle old Arbel FW */
		if (dev->limits.stat_rate_support == 0x3 && mthca_rate)
			return IB_RATE_2_5_GBPS;

		return memfree_rate_to_ib(mthca_rate, dev->rate[port - 1]);
	} else
		return tavor_rate_to_ib(mthca_rate, dev->rate[port - 1]);
}

static u8 ib_rate_to_memfree(u8 req_rate, u8 cur_rate)
{
	if (cur_rate <= req_rate)
		return 0;

	/*
	 * Inter-packet delay (IPD) to get from rate X down to a rate
	 * no more than Y is (X - 1) / Y.
	 */
	switch ((cur_rate - 1) / req_rate) {
	case 0:	 return MTHCA_RATE_MEMFREE_FULL;
	case 1:	 return MTHCA_RATE_MEMFREE_HALF;
	case 2:	 /* fall through */
	case 3:	 return MTHCA_RATE_MEMFREE_QUARTER;
	default: return MTHCA_RATE_MEMFREE_EIGHTH;
	}
}

static u8 ib_rate_to_tavor(u8 static_rate)
{
	switch (static_rate) {
	case IB_RATE_2_5_GBPS: return MTHCA_RATE_TAVOR_1X;
	case IB_RATE_5_GBPS:   return MTHCA_RATE_TAVOR_1X_DDR;
	case IB_RATE_10_GBPS:  return MTHCA_RATE_TAVOR_4X;
	default:	       return MTHCA_RATE_TAVOR_FULL;
	}
}

u8 mthca_get_rate(struct mthca_dev *dev, int static_rate, u8 port)
{
	u8 rate;

	if (!static_rate || ib_rate_to_mult(static_rate) >= dev->rate[port - 1])
		return 0;

	if (mthca_is_memfree(dev))
		rate = ib_rate_to_memfree(ib_rate_to_mult(static_rate),
					  dev->rate[port - 1]);
	else
		rate = ib_rate_to_tavor(static_rate);

	if (!(dev->limits.stat_rate_support & (1 << rate)))
		rate = 1;

	return rate;
}

int mthca_create_ah(struct mthca_dev *dev,
		    struct mthca_pd *pd,
		    struct ib_ah_attr *ah_attr,
@@ -107,7 +205,7 @@ on_hca_fail:
	av->g_slid  = ah_attr->src_path_bits;
	av->dlid    = cpu_to_be16(ah_attr->dlid);
	av->msg_sr  = (3 << 4) | /* 2K message */
		ah_attr->static_rate;
		mthca_get_rate(dev, ah_attr->static_rate, ah_attr->port_num);
	av->sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
	if (ah_attr->ah_flags & IB_AH_GRH) {
		av->g_slid |= 0x80;
+4 −0
Original line number Diff line number Diff line
@@ -965,6 +965,7 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
	u32 *outbox;
	u8 field;
	u16 size;
	u16 stat_rate;
	int err;

#define QUERY_DEV_LIM_OUT_SIZE             0x100
@@ -995,6 +996,7 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
#define QUERY_DEV_LIM_MTU_WIDTH_OFFSET      0x36
#define QUERY_DEV_LIM_VL_PORT_OFFSET        0x37
#define QUERY_DEV_LIM_MAX_GID_OFFSET        0x3b
#define QUERY_DEV_LIM_RATE_SUPPORT_OFFSET   0x3c
#define QUERY_DEV_LIM_MAX_PKEY_OFFSET       0x3f
#define QUERY_DEV_LIM_FLAGS_OFFSET          0x44
#define QUERY_DEV_LIM_RSVD_UAR_OFFSET       0x48
@@ -1086,6 +1088,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
	dev_lim->num_ports = field & 0xf;
	MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_GID_OFFSET);
	dev_lim->max_gids = 1 << (field & 0xf);
	MTHCA_GET(stat_rate, outbox, QUERY_DEV_LIM_RATE_SUPPORT_OFFSET);
	dev_lim->stat_rate_support = stat_rate;
	MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_PKEY_OFFSET);
	dev_lim->max_pkeys = 1 << (field & 0xf);
	MTHCA_GET(dev_lim->flags, outbox, QUERY_DEV_LIM_FLAGS_OFFSET);
+1 −0
Original line number Diff line number Diff line
@@ -146,6 +146,7 @@ struct mthca_dev_lim {
	int max_vl;
	int num_ports;
	int max_gids;
	u16 stat_rate_support;
	int max_pkeys;
	u32 flags;
	int reserved_uars;
+4 −0
Original line number Diff line number Diff line
@@ -172,6 +172,7 @@ struct mthca_limits {
	int      reserved_pds;
	u32      page_size_cap;
	u32      flags;
	u16      stat_rate_support;
	u8       port_width_cap;
};

@@ -353,6 +354,7 @@ struct mthca_dev {
	struct ib_mad_agent  *send_agent[MTHCA_MAX_PORTS][2];
	struct ib_ah         *sm_ah[MTHCA_MAX_PORTS];
	spinlock_t            sm_lock;
	u8                    rate[MTHCA_MAX_PORTS];
};

#ifdef CONFIG_INFINIBAND_MTHCA_DEBUG
@@ -555,6 +557,8 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
		  struct ib_ud_header *header);
int mthca_ah_query(struct ib_ah *ibah, struct ib_ah_attr *attr);
int mthca_ah_grh_present(struct mthca_ah *ah);
u8 mthca_get_rate(struct mthca_dev *dev, int static_rate, u8 port);
enum ib_rate mthca_rate_to_ib(struct mthca_dev *dev, u8 mthca_rate, u8 port);

int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
Loading