mthca_av.c revision 2fa5e2ebbe2d81f741ba7bed9e07dc38cc734625
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2004 Topspin Communications.  All rights reserved.
3cd4e8fb49d2326364971a56f5a4b664a976f3712Tom Duffy * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software is available to you under a choice of one of two
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * licenses.  You may choose to be licensed under the terms of the GNU
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * General Public License (GPL) Version 2, available from the file
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * COPYING in the main directory of this source tree, or the
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OpenIB.org BSD license below:
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     Redistribution and use in source and binary forms, with or
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     without modification, are permitted provided that the following
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     conditions are met:
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      - Redistributions of source code must retain the above
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *        copyright notice, this list of conditions and the following
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *        disclaimer.
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      - Redistributions in binary form must reproduce the above
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *        copyright notice, this list of conditions and the following
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *        disclaimer in the documentation and/or other materials
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *        provided with the distribution.
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SOFTWARE.
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * $Id: mthca_av.c 1349 2004-12-16 21:09:43Z roland $
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
374e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/string.h>
384e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/slab.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40a4d61e84804f3b14cc35c5e2af768a07c0f64ef6Roland Dreier#include <rdma/ib_verbs.h>
41a4d61e84804f3b14cc35c5e2af768a07c0f64ef6Roland Dreier#include <rdma/ib_cache.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "mthca_dev.h"
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mthca_av {
4697f52eb438be7caebe026421545619d8a0c1398aSean Hefty	__be32 port_pd;
4797f52eb438be7caebe026421545619d8a0c1398aSean Hefty	u8     reserved1;
4897f52eb438be7caebe026421545619d8a0c1398aSean Hefty	u8     g_slid;
4997f52eb438be7caebe026421545619d8a0c1398aSean Hefty	__be16 dlid;
5097f52eb438be7caebe026421545619d8a0c1398aSean Hefty	u8     reserved2;
5197f52eb438be7caebe026421545619d8a0c1398aSean Hefty	u8     gid_index;
5297f52eb438be7caebe026421545619d8a0c1398aSean Hefty	u8     msg_sr;
5397f52eb438be7caebe026421545619d8a0c1398aSean Hefty	u8     hop_limit;
5497f52eb438be7caebe026421545619d8a0c1398aSean Hefty	__be32 sl_tclass_flowlabel;
5597f52eb438be7caebe026421545619d8a0c1398aSean Hefty	__be32 dgid[4];
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mthca_create_ah(struct mthca_dev *dev,
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    struct mthca_pd *pd,
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    struct ib_ah_attr *ah_attr,
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    struct mthca_ah *ah)
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 index = -1;
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mthca_av *av = NULL;
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ah->type = MTHCA_AH_PCI_POOL;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
68d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier	if (mthca_is_memfree(dev)) {
698df8a34de60f8e51c87e5c145679f1a896133199Roland Dreier		ah->av   = kmalloc(sizeof *ah->av, GFP_ATOMIC);
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!ah->av)
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ENOMEM;
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ah->type = MTHCA_AH_KMALLOC;
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		av       = ah->av;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (!atomic_read(&pd->sqp_count) &&
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 !(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) {
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		index = mthca_alloc(&dev->av_table.alloc);
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* fall back to allocate in host memory */
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (index == -1)
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto on_hca_fail;
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
838df8a34de60f8e51c87e5c145679f1a896133199Roland Dreier		av = kmalloc(sizeof *av, GFP_ATOMIC);
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!av)
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto on_hca_fail;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ah->type = MTHCA_AH_ON_HCA;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ah->avdma  = dev->av_table.ddr_av_base +
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			index * MTHCA_AV_SIZE;
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldson_hca_fail:
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ah->type == MTHCA_AH_PCI_POOL) {
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ah->av = pci_pool_alloc(dev->av_table.pool,
958df8a34de60f8e51c87e5c145679f1a896133199Roland Dreier					SLAB_ATOMIC, &ah->avdma);
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!ah->av)
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ENOMEM;
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		av = ah->av;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ah->key = pd->ntmr.ibmr.lkey;
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(av, 0, MTHCA_AV_SIZE);
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	av->port_pd = cpu_to_be32(pd->pd_num | (ah_attr->port_num << 24));
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	av->g_slid  = ah_attr->src_path_bits;
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	av->dlid    = cpu_to_be16(ah_attr->dlid);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	av->msg_sr  = (3 << 4) | /* 2K message */
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ah_attr->static_rate;
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	av->sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ah_attr->ah_flags & IB_AH_GRH) {
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		av->g_slid |= 0x80;
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		av->gid_index = (ah_attr->port_num - 1) * dev->limits.gid_table_len +
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ah_attr->grh.sgid_index;
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		av->hop_limit = ah_attr->grh.hop_limit;
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		av->sl_tclass_flowlabel |=
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cpu_to_be32((ah_attr->grh.traffic_class << 20) |
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    ah_attr->grh.flow_label);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(av->dgid, ah_attr->grh.dgid.raw, 16);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Arbel workaround -- low byte of GID must be 2 */
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		av->dgid[3] = cpu_to_be32(2);
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (0) {
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int j;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mthca_dbg(dev, "Created UDAV at %p/%08lx:\n",
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  av, (unsigned long) ah->avdma);
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (j = 0; j < 8; ++j)
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_DEBUG "  [%2x] %08x\n",
13397f52eb438be7caebe026421545619d8a0c1398aSean Hefty			       j * 4, be32_to_cpu(((__be32 *) av)[j]));
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ah->type == MTHCA_AH_ON_HCA) {
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy_toio(dev->av_table.av_map + index * MTHCA_AV_SIZE,
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    av, MTHCA_AV_SIZE);
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(av);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah)
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (ah->type) {
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MTHCA_AH_ON_HCA:
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mthca_free(&dev->av_table.alloc,
1502fa5e2ebbe2d81f741ba7bed9e07dc38cc734625Roland Dreier			   (ah->avdma - dev->av_table.ddr_av_base) /
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   MTHCA_AV_SIZE);
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MTHCA_AH_PCI_POOL:
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_pool_free(dev->av_table.pool, ah->av, ah->avdma);
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MTHCA_AH_KMALLOC:
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(ah->av);
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1669eacee2ac624bfa9740d49355dbe6ee88d0cba0aMichael S. Tsirkinint mthca_ah_grh_present(struct mthca_ah *ah)
1679eacee2ac624bfa9740d49355dbe6ee88d0cba0aMichael S. Tsirkin{
1689eacee2ac624bfa9740d49355dbe6ee88d0cba0aMichael S. Tsirkin	return !!(ah->av->g_slid & 0x80);
1699eacee2ac624bfa9740d49355dbe6ee88d0cba0aMichael S. Tsirkin}
1709eacee2ac624bfa9740d49355dbe6ee88d0cba0aMichael S. Tsirkin
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  struct ib_ud_header *header)
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ah->type == MTHCA_AH_ON_HCA)
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	header->lrh.service_level   = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28;
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	header->lrh.destination_lid = ah->av->dlid;
17997f52eb438be7caebe026421545619d8a0c1398aSean Hefty	header->lrh.source_lid      = cpu_to_be16(ah->av->g_slid & 0x7f);
1809eacee2ac624bfa9740d49355dbe6ee88d0cba0aMichael S. Tsirkin	if (mthca_ah_grh_present(ah)) {
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		header->grh.traffic_class =
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		header->grh.flow_label    =
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ah->av->sl_tclass_flowlabel & cpu_to_be32(0xfffff);
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ib_get_cached_gid(&dev->ib_dev,
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  be32_to_cpu(ah->av->port_pd) >> 24,
187f9e61929e5e1dacc2afefbde6abc3e6571ca2887Michael S. Tsirkin				  ah->av->gid_index % dev->limits.gid_table_len,
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  &header->grh.source_gid);
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(header->grh.destination_gid.raw,
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       ah->av->dgid, 16);
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __devinit mthca_init_av_table(struct mthca_dev *dev)
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
200d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier	if (mthca_is_memfree(dev))
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = mthca_alloc_init(&dev->av_table.alloc,
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       dev->av_table.num_ddr_avs,
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       dev->av_table.num_ddr_avs - 1,
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       0);
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->av_table.pool = pci_pool_create("mthca_av", dev->pdev,
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     MTHCA_AV_SIZE,
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     MTHCA_AV_SIZE, 0);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev->av_table.pool)
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_free_alloc;
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) {
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->av_table.av_map = ioremap(pci_resource_start(dev->pdev, 4) +
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       dev->av_table.ddr_av_base -
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       dev->ddr_start,
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       dev->av_table.num_ddr_avs *
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					       MTHCA_AV_SIZE);
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!dev->av_table.av_map)
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out_free_pool;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->av_table.av_map = NULL;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_free_pool:
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_pool_destroy(dev->av_table.pool);
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_free_alloc:
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_alloc_cleanup(&dev->av_table.alloc);
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENOMEM;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __devexit mthca_cleanup_av_table(struct mthca_dev *dev)
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
239d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier	if (mthca_is_memfree(dev))
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->av_table.av_map)
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iounmap(dev->av_table.av_map);
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_pool_destroy(dev->av_table.pool);
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_alloc_cleanup(&dev->av_table.alloc);
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
247