2 * Copyright (c) 2004 Topspin Communications. All rights reserved.
3 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34 #include <linux/string.h>
35 #include <linux/slab.h>
37 #include <rdma/ib_verbs.h>
38 #include <rdma/ib_cache.h>
40 #include "mthca_dev.h"
43 MTHCA_RATE_TAVOR_FULL
= 0,
44 MTHCA_RATE_TAVOR_1X
= 1,
45 MTHCA_RATE_TAVOR_4X
= 2,
46 MTHCA_RATE_TAVOR_1X_DDR
= 3
50 MTHCA_RATE_MEMFREE_FULL
= 0,
51 MTHCA_RATE_MEMFREE_QUARTER
= 1,
52 MTHCA_RATE_MEMFREE_EIGHTH
= 2,
53 MTHCA_RATE_MEMFREE_HALF
= 3
65 __be32 sl_tclass_flowlabel
;
69 static enum ib_rate
memfree_rate_to_ib(u8 mthca_rate
, u8 port_rate
)
72 case MTHCA_RATE_MEMFREE_EIGHTH
:
73 return mult_to_ib_rate(port_rate
>> 3);
74 case MTHCA_RATE_MEMFREE_QUARTER
:
75 return mult_to_ib_rate(port_rate
>> 2);
76 case MTHCA_RATE_MEMFREE_HALF
:
77 return mult_to_ib_rate(port_rate
>> 1);
78 case MTHCA_RATE_MEMFREE_FULL
:
80 return mult_to_ib_rate(port_rate
);
84 static enum ib_rate
tavor_rate_to_ib(u8 mthca_rate
, u8 port_rate
)
87 case MTHCA_RATE_TAVOR_1X
: return IB_RATE_2_5_GBPS
;
88 case MTHCA_RATE_TAVOR_1X_DDR
: return IB_RATE_5_GBPS
;
89 case MTHCA_RATE_TAVOR_4X
: return IB_RATE_10_GBPS
;
90 default: return mult_to_ib_rate(port_rate
);
94 enum ib_rate
mthca_rate_to_ib(struct mthca_dev
*dev
, u8 mthca_rate
, u8 port
)
96 if (mthca_is_memfree(dev
)) {
97 /* Handle old Arbel FW */
98 if (dev
->limits
.stat_rate_support
== 0x3 && mthca_rate
)
99 return IB_RATE_2_5_GBPS
;
101 return memfree_rate_to_ib(mthca_rate
, dev
->rate
[port
- 1]);
103 return tavor_rate_to_ib(mthca_rate
, dev
->rate
[port
- 1]);
106 static u8
ib_rate_to_memfree(u8 req_rate
, u8 cur_rate
)
108 if (cur_rate
<= req_rate
)
112 * Inter-packet delay (IPD) to get from rate X down to a rate
113 * no more than Y is (X - 1) / Y.
115 switch ((cur_rate
- 1) / req_rate
) {
116 case 0: return MTHCA_RATE_MEMFREE_FULL
;
117 case 1: return MTHCA_RATE_MEMFREE_HALF
;
118 case 2: /* fall through */
119 case 3: return MTHCA_RATE_MEMFREE_QUARTER
;
120 default: return MTHCA_RATE_MEMFREE_EIGHTH
;
124 static u8
ib_rate_to_tavor(u8 static_rate
)
126 switch (static_rate
) {
127 case IB_RATE_2_5_GBPS
: return MTHCA_RATE_TAVOR_1X
;
128 case IB_RATE_5_GBPS
: return MTHCA_RATE_TAVOR_1X_DDR
;
129 case IB_RATE_10_GBPS
: return MTHCA_RATE_TAVOR_4X
;
130 default: return MTHCA_RATE_TAVOR_FULL
;
134 u8
mthca_get_rate(struct mthca_dev
*dev
, int static_rate
, u8 port
)
138 if (!static_rate
|| ib_rate_to_mult(static_rate
) >= dev
->rate
[port
- 1])
141 if (mthca_is_memfree(dev
))
142 rate
= ib_rate_to_memfree(ib_rate_to_mult(static_rate
),
143 dev
->rate
[port
- 1]);
145 rate
= ib_rate_to_tavor(static_rate
);
147 if (!(dev
->limits
.stat_rate_support
& (1 << rate
)))
153 int mthca_create_ah(struct mthca_dev
*dev
,
155 struct ib_ah_attr
*ah_attr
,
159 struct mthca_av
*av
= NULL
;
161 ah
->type
= MTHCA_AH_PCI_POOL
;
163 if (mthca_is_memfree(dev
)) {
164 ah
->av
= kmalloc(sizeof *ah
->av
, GFP_ATOMIC
);
168 ah
->type
= MTHCA_AH_KMALLOC
;
170 } else if (!atomic_read(&pd
->sqp_count
) &&
171 !(dev
->mthca_flags
& MTHCA_FLAG_DDR_HIDDEN
)) {
172 index
= mthca_alloc(&dev
->av_table
.alloc
);
174 /* fall back to allocate in host memory */
178 av
= kmalloc(sizeof *av
, GFP_ATOMIC
);
182 ah
->type
= MTHCA_AH_ON_HCA
;
183 ah
->avdma
= dev
->av_table
.ddr_av_base
+
184 index
* MTHCA_AV_SIZE
;
188 if (ah
->type
== MTHCA_AH_PCI_POOL
) {
189 ah
->av
= pci_pool_alloc(dev
->av_table
.pool
,
190 GFP_ATOMIC
, &ah
->avdma
);
197 ah
->key
= pd
->ntmr
.ibmr
.lkey
;
199 memset(av
, 0, MTHCA_AV_SIZE
);
201 av
->port_pd
= cpu_to_be32(pd
->pd_num
| (ah_attr
->port_num
<< 24));
202 av
->g_slid
= ah_attr
->src_path_bits
;
203 av
->dlid
= cpu_to_be16(ah_attr
->dlid
);
204 av
->msg_sr
= (3 << 4) | /* 2K message */
205 mthca_get_rate(dev
, ah_attr
->static_rate
, ah_attr
->port_num
);
206 av
->sl_tclass_flowlabel
= cpu_to_be32(ah_attr
->sl
<< 28);
207 if (ah_attr
->ah_flags
& IB_AH_GRH
) {
209 av
->gid_index
= (ah_attr
->port_num
- 1) * dev
->limits
.gid_table_len
+
210 ah_attr
->grh
.sgid_index
;
211 av
->hop_limit
= ah_attr
->grh
.hop_limit
;
212 av
->sl_tclass_flowlabel
|=
213 cpu_to_be32((ah_attr
->grh
.traffic_class
<< 20) |
214 ah_attr
->grh
.flow_label
);
215 memcpy(av
->dgid
, ah_attr
->grh
.dgid
.raw
, 16);
217 /* Arbel workaround -- low byte of GID must be 2 */
218 av
->dgid
[3] = cpu_to_be32(2);
224 mthca_dbg(dev
, "Created UDAV at %p/%08lx:\n",
225 av
, (unsigned long) ah
->avdma
);
226 for (j
= 0; j
< 8; ++j
)
227 printk(KERN_DEBUG
" [%2x] %08x\n",
228 j
* 4, be32_to_cpu(((__be32
*) av
)[j
]));
231 if (ah
->type
== MTHCA_AH_ON_HCA
) {
232 memcpy_toio(dev
->av_table
.av_map
+ index
* MTHCA_AV_SIZE
,
240 int mthca_destroy_ah(struct mthca_dev
*dev
, struct mthca_ah
*ah
)
243 case MTHCA_AH_ON_HCA
:
244 mthca_free(&dev
->av_table
.alloc
,
245 (ah
->avdma
- dev
->av_table
.ddr_av_base
) /
249 case MTHCA_AH_PCI_POOL
:
250 pci_pool_free(dev
->av_table
.pool
, ah
->av
, ah
->avdma
);
253 case MTHCA_AH_KMALLOC
:
261 int mthca_ah_grh_present(struct mthca_ah
*ah
)
263 return !!(ah
->av
->g_slid
& 0x80);
266 int mthca_read_ah(struct mthca_dev
*dev
, struct mthca_ah
*ah
,
267 struct ib_ud_header
*header
)
269 if (ah
->type
== MTHCA_AH_ON_HCA
)
272 header
->lrh
.service_level
= be32_to_cpu(ah
->av
->sl_tclass_flowlabel
) >> 28;
273 header
->lrh
.destination_lid
= ah
->av
->dlid
;
274 header
->lrh
.source_lid
= cpu_to_be16(ah
->av
->g_slid
& 0x7f);
275 if (mthca_ah_grh_present(ah
)) {
276 header
->grh
.traffic_class
=
277 (be32_to_cpu(ah
->av
->sl_tclass_flowlabel
) >> 20) & 0xff;
278 header
->grh
.flow_label
=
279 ah
->av
->sl_tclass_flowlabel
& cpu_to_be32(0xfffff);
280 header
->grh
.hop_limit
= ah
->av
->hop_limit
;
281 ib_get_cached_gid(&dev
->ib_dev
,
282 be32_to_cpu(ah
->av
->port_pd
) >> 24,
283 ah
->av
->gid_index
% dev
->limits
.gid_table_len
,
284 &header
->grh
.source_gid
);
285 memcpy(header
->grh
.destination_gid
.raw
,
292 int mthca_ah_query(struct ib_ah
*ibah
, struct ib_ah_attr
*attr
)
294 struct mthca_ah
*ah
= to_mah(ibah
);
295 struct mthca_dev
*dev
= to_mdev(ibah
->device
);
297 /* Only implement for MAD and memfree ah for now. */
298 if (ah
->type
== MTHCA_AH_ON_HCA
)
301 memset(attr
, 0, sizeof *attr
);
302 attr
->dlid
= be16_to_cpu(ah
->av
->dlid
);
303 attr
->sl
= be32_to_cpu(ah
->av
->sl_tclass_flowlabel
) >> 28;
304 attr
->port_num
= be32_to_cpu(ah
->av
->port_pd
) >> 24;
305 attr
->static_rate
= mthca_rate_to_ib(dev
, ah
->av
->msg_sr
& 0x7,
307 attr
->src_path_bits
= ah
->av
->g_slid
& 0x7F;
308 attr
->ah_flags
= mthca_ah_grh_present(ah
) ? IB_AH_GRH
: 0;
310 if (attr
->ah_flags
) {
311 attr
->grh
.traffic_class
=
312 be32_to_cpu(ah
->av
->sl_tclass_flowlabel
) >> 20;
313 attr
->grh
.flow_label
=
314 be32_to_cpu(ah
->av
->sl_tclass_flowlabel
) & 0xfffff;
315 attr
->grh
.hop_limit
= ah
->av
->hop_limit
;
316 attr
->grh
.sgid_index
= ah
->av
->gid_index
&
317 (dev
->limits
.gid_table_len
- 1);
318 memcpy(attr
->grh
.dgid
.raw
, ah
->av
->dgid
, 16);
324 int mthca_init_av_table(struct mthca_dev
*dev
)
328 if (mthca_is_memfree(dev
))
331 err
= mthca_alloc_init(&dev
->av_table
.alloc
,
332 dev
->av_table
.num_ddr_avs
,
333 dev
->av_table
.num_ddr_avs
- 1,
338 dev
->av_table
.pool
= pci_pool_create("mthca_av", dev
->pdev
,
341 if (!dev
->av_table
.pool
)
344 if (!(dev
->mthca_flags
& MTHCA_FLAG_DDR_HIDDEN
)) {
345 dev
->av_table
.av_map
= ioremap(pci_resource_start(dev
->pdev
, 4) +
346 dev
->av_table
.ddr_av_base
-
348 dev
->av_table
.num_ddr_avs
*
350 if (!dev
->av_table
.av_map
)
353 dev
->av_table
.av_map
= NULL
;
358 pci_pool_destroy(dev
->av_table
.pool
);
361 mthca_alloc_cleanup(&dev
->av_table
.alloc
);
365 void mthca_cleanup_av_table(struct mthca_dev
*dev
)
367 if (mthca_is_memfree(dev
))
370 if (dev
->av_table
.av_map
)
371 iounmap(dev
->av_table
.av_map
);
372 pci_pool_destroy(dev
->av_table
.pool
);
373 mthca_alloc_cleanup(&dev
->av_table
.alloc
);