aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/mthca/mthca_av.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/mthca/mthca_av.c')
-rw-r--r--drivers/infiniband/hw/mthca/mthca_av.c100
1 files changed, 99 insertions, 1 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index bc5bdcbe51b5..b12aa03be251 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -42,6 +42,20 @@
42 42
43#include "mthca_dev.h" 43#include "mthca_dev.h"
44 44
45enum {
46 MTHCA_RATE_TAVOR_FULL = 0,
47 MTHCA_RATE_TAVOR_1X = 1,
48 MTHCA_RATE_TAVOR_4X = 2,
49 MTHCA_RATE_TAVOR_1X_DDR = 3
50};
51
52enum {
53 MTHCA_RATE_MEMFREE_FULL = 0,
54 MTHCA_RATE_MEMFREE_QUARTER = 1,
55 MTHCA_RATE_MEMFREE_EIGHTH = 2,
56 MTHCA_RATE_MEMFREE_HALF = 3
57};
58
45struct mthca_av { 59struct mthca_av {
46 __be32 port_pd; 60 __be32 port_pd;
47 u8 reserved1; 61 u8 reserved1;
@@ -55,6 +69,90 @@ struct mthca_av {
55 __be32 dgid[4]; 69 __be32 dgid[4];
56}; 70};
57 71
72static enum ib_rate memfree_rate_to_ib(u8 mthca_rate, u8 port_rate)
73{
74 switch (mthca_rate) {
75 case MTHCA_RATE_MEMFREE_EIGHTH:
76 return mult_to_ib_rate(port_rate >> 3);
77 case MTHCA_RATE_MEMFREE_QUARTER:
78 return mult_to_ib_rate(port_rate >> 2);
79 case MTHCA_RATE_MEMFREE_HALF:
80 return mult_to_ib_rate(port_rate >> 1);
81 case MTHCA_RATE_MEMFREE_FULL:
82 default:
83 return mult_to_ib_rate(port_rate);
84 }
85}
86
87static enum ib_rate tavor_rate_to_ib(u8 mthca_rate, u8 port_rate)
88{
89 switch (mthca_rate) {
90 case MTHCA_RATE_TAVOR_1X: return IB_RATE_2_5_GBPS;
91 case MTHCA_RATE_TAVOR_1X_DDR: return IB_RATE_5_GBPS;
92 case MTHCA_RATE_TAVOR_4X: return IB_RATE_10_GBPS;
93 default: return port_rate;
94 }
95}
96
97enum ib_rate mthca_rate_to_ib(struct mthca_dev *dev, u8 mthca_rate, u8 port)
98{
99 if (mthca_is_memfree(dev)) {
100 /* Handle old Arbel FW */
101 if (dev->limits.stat_rate_support == 0x3 && mthca_rate)
102 return IB_RATE_2_5_GBPS;
103
104 return memfree_rate_to_ib(mthca_rate, dev->rate[port - 1]);
105 } else
106 return tavor_rate_to_ib(mthca_rate, dev->rate[port - 1]);
107}
108
109static u8 ib_rate_to_memfree(u8 req_rate, u8 cur_rate)
110{
111 if (cur_rate <= req_rate)
112 return 0;
113
114 /*
115 * Inter-packet delay (IPD) to get from rate X down to a rate
116 * no more than Y is (X - 1) / Y.
117 */
118 switch ((cur_rate - 1) / req_rate) {
119 case 0: return MTHCA_RATE_MEMFREE_FULL;
120 case 1: return MTHCA_RATE_MEMFREE_HALF;
121 case 2: /* fall through */
122 case 3: return MTHCA_RATE_MEMFREE_QUARTER;
123 default: return MTHCA_RATE_MEMFREE_EIGHTH;
124 }
125}
126
127static u8 ib_rate_to_tavor(u8 static_rate)
128{
129 switch (static_rate) {
130 case IB_RATE_2_5_GBPS: return MTHCA_RATE_TAVOR_1X;
131 case IB_RATE_5_GBPS: return MTHCA_RATE_TAVOR_1X_DDR;
132 case IB_RATE_10_GBPS: return MTHCA_RATE_TAVOR_4X;
133 default: return MTHCA_RATE_TAVOR_FULL;
134 }
135}
136
137u8 mthca_get_rate(struct mthca_dev *dev, int static_rate, u8 port)
138{
139 u8 rate;
140
141 if (!static_rate || ib_rate_to_mult(static_rate) >= dev->rate[port - 1])
142 return 0;
143
144 if (mthca_is_memfree(dev))
145 rate = ib_rate_to_memfree(ib_rate_to_mult(static_rate),
146 dev->rate[port - 1]);
147 else
148 rate = ib_rate_to_tavor(static_rate);
149
150 if (!(dev->limits.stat_rate_support & (1 << rate)))
151 rate = 1;
152
153 return rate;
154}
155
58int mthca_create_ah(struct mthca_dev *dev, 156int mthca_create_ah(struct mthca_dev *dev,
59 struct mthca_pd *pd, 157 struct mthca_pd *pd,
60 struct ib_ah_attr *ah_attr, 158 struct ib_ah_attr *ah_attr,
@@ -107,7 +205,7 @@ on_hca_fail:
107 av->g_slid = ah_attr->src_path_bits; 205 av->g_slid = ah_attr->src_path_bits;
108 av->dlid = cpu_to_be16(ah_attr->dlid); 206 av->dlid = cpu_to_be16(ah_attr->dlid);
109 av->msg_sr = (3 << 4) | /* 2K message */ 207 av->msg_sr = (3 << 4) | /* 2K message */
110 ah_attr->static_rate; 208 mthca_get_rate(dev, ah_attr->static_rate, ah_attr->port_num);
111 av->sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28); 209 av->sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
112 if (ah_attr->ah_flags & IB_AH_GRH) { 210 if (ah_attr->ah_flags & IB_AH_GRH) {
113 av->g_slid |= 0x80; 211 av->g_slid |= 0x80;