2 * Copyright (c) 2004 Topspin Communications. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * $Id: mthca_av.c 1349 2004-12-16 21:09:43Z roland $
35 #include <linux/init.h>
40 #include "mthca_dev.h"
51 u32 sl_tclass_flowlabel
;
55 int mthca_create_ah(struct mthca_dev
*dev
,
57 struct ib_ah_attr
*ah_attr
,
61 struct mthca_av
*av
= NULL
;
63 ah
->type
= MTHCA_AH_PCI_POOL
;
65 if (mthca_is_memfree(dev
)) {
66 ah
->av
= kmalloc(sizeof *ah
->av
, GFP_ATOMIC
);
70 ah
->type
= MTHCA_AH_KMALLOC
;
72 } else if (!atomic_read(&pd
->sqp_count
) &&
73 !(dev
->mthca_flags
& MTHCA_FLAG_DDR_HIDDEN
)) {
74 index
= mthca_alloc(&dev
->av_table
.alloc
);
76 /* fall back to allocate in host memory */
80 av
= kmalloc(sizeof *av
, GFP_ATOMIC
);
84 ah
->type
= MTHCA_AH_ON_HCA
;
85 ah
->avdma
= dev
->av_table
.ddr_av_base
+
86 index
* MTHCA_AV_SIZE
;
90 if (ah
->type
== MTHCA_AH_PCI_POOL
) {
91 ah
->av
= pci_pool_alloc(dev
->av_table
.pool
,
92 SLAB_ATOMIC
, &ah
->avdma
);
99 ah
->key
= pd
->ntmr
.ibmr
.lkey
;
101 memset(av
, 0, MTHCA_AV_SIZE
);
103 av
->port_pd
= cpu_to_be32(pd
->pd_num
| (ah_attr
->port_num
<< 24));
104 av
->g_slid
= ah_attr
->src_path_bits
;
105 av
->dlid
= cpu_to_be16(ah_attr
->dlid
);
106 av
->msg_sr
= (3 << 4) | /* 2K message */
107 ah_attr
->static_rate
;
108 av
->sl_tclass_flowlabel
= cpu_to_be32(ah_attr
->sl
<< 28);
109 if (ah_attr
->ah_flags
& IB_AH_GRH
) {
111 av
->gid_index
= (ah_attr
->port_num
- 1) * dev
->limits
.gid_table_len
+
112 ah_attr
->grh
.sgid_index
;
113 av
->hop_limit
= ah_attr
->grh
.hop_limit
;
114 av
->sl_tclass_flowlabel
|=
115 cpu_to_be32((ah_attr
->grh
.traffic_class
<< 20) |
116 ah_attr
->grh
.flow_label
);
117 memcpy(av
->dgid
, ah_attr
->grh
.dgid
.raw
, 16);
119 /* Arbel workaround -- low byte of GID must be 2 */
120 av
->dgid
[3] = cpu_to_be32(2);
126 mthca_dbg(dev
, "Created UDAV at %p/%08lx:\n",
127 av
, (unsigned long) ah
->avdma
);
128 for (j
= 0; j
< 8; ++j
)
129 printk(KERN_DEBUG
" [%2x] %08x\n",
130 j
* 4, be32_to_cpu(((u32
*) av
)[j
]));
133 if (ah
->type
== MTHCA_AH_ON_HCA
) {
134 memcpy_toio(dev
->av_table
.av_map
+ index
* MTHCA_AV_SIZE
,
142 int mthca_destroy_ah(struct mthca_dev
*dev
, struct mthca_ah
*ah
)
145 case MTHCA_AH_ON_HCA
:
146 mthca_free(&dev
->av_table
.alloc
,
147 (ah
->avdma
- dev
->av_table
.ddr_av_base
) /
151 case MTHCA_AH_PCI_POOL
:
152 pci_pool_free(dev
->av_table
.pool
, ah
->av
, ah
->avdma
);
155 case MTHCA_AH_KMALLOC
:
163 int mthca_read_ah(struct mthca_dev
*dev
, struct mthca_ah
*ah
,
164 struct ib_ud_header
*header
)
166 if (ah
->type
== MTHCA_AH_ON_HCA
)
169 header
->lrh
.service_level
= be32_to_cpu(ah
->av
->sl_tclass_flowlabel
) >> 28;
170 header
->lrh
.destination_lid
= ah
->av
->dlid
;
171 header
->lrh
.source_lid
= ah
->av
->g_slid
& 0x7f;
172 if (ah
->av
->g_slid
& 0x80) {
173 header
->grh_present
= 1;
174 header
->grh
.traffic_class
=
175 (be32_to_cpu(ah
->av
->sl_tclass_flowlabel
) >> 20) & 0xff;
176 header
->grh
.flow_label
=
177 ah
->av
->sl_tclass_flowlabel
& cpu_to_be32(0xfffff);
178 ib_get_cached_gid(&dev
->ib_dev
,
179 be32_to_cpu(ah
->av
->port_pd
) >> 24,
181 &header
->grh
.source_gid
);
182 memcpy(header
->grh
.destination_gid
.raw
,
185 header
->grh_present
= 0;
191 int __devinit
mthca_init_av_table(struct mthca_dev
*dev
)
195 if (mthca_is_memfree(dev
))
198 err
= mthca_alloc_init(&dev
->av_table
.alloc
,
199 dev
->av_table
.num_ddr_avs
,
200 dev
->av_table
.num_ddr_avs
- 1,
205 dev
->av_table
.pool
= pci_pool_create("mthca_av", dev
->pdev
,
208 if (!dev
->av_table
.pool
)
211 if (!(dev
->mthca_flags
& MTHCA_FLAG_DDR_HIDDEN
)) {
212 dev
->av_table
.av_map
= ioremap(pci_resource_start(dev
->pdev
, 4) +
213 dev
->av_table
.ddr_av_base
-
215 dev
->av_table
.num_ddr_avs
*
217 if (!dev
->av_table
.av_map
)
220 dev
->av_table
.av_map
= NULL
;
225 pci_pool_destroy(dev
->av_table
.pool
);
228 mthca_alloc_cleanup(&dev
->av_table
.alloc
);
232 void __devexit
mthca_cleanup_av_table(struct mthca_dev
*dev
)
234 if (mthca_is_memfree(dev
))
237 if (dev
->av_table
.av_map
)
238 iounmap(dev
->av_table
.av_map
);
239 pci_pool_destroy(dev
->av_table
.pool
);
240 mthca_alloc_cleanup(&dev
->av_table
.alloc
);