linux/drivers/infiniband/hw/ehca/ehca_hca.c
Hoang-Nam Nguyen 7e28db5d8f IB/ehca: Assure 4K alignment for firmware control blocks
Assure 4K alignment for firmware control blocks in 64K page mode,
because kzalloc()'s result address might not be 4K aligned if 64K
pages are enabled. Thus, we introduce wrappers called
ehca_{alloc,free}_fw_ctrlblock(), which use a slab cache for objects
with 4K length and 4K alignment in order to alloc/free firmware
control blocks in 64K page mode. In 4K page mode those wrappers just
are defines of get_zeroed_page() and free_page().

Signed-off-by: Hoang-Nam Nguyen <hnguyen@de.ibm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
2006-11-09 12:41:57 -08:00

243 lines
7.2 KiB
C

/*
* IBM eServer eHCA Infiniband device driver for Linux on POWER
*
* HCA query functions
*
* Authors: Heiko J Schick <schickhj@de.ibm.com>
* Christoph Raisch <raisch@de.ibm.com>
*
* Copyright (c) 2005 IBM Corporation
*
* All rights reserved.
*
* This source code is distributed under a dual license of GPL v2.0 and OpenIB
* BSD.
*
* OpenIB BSD License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "ehca_tools.h"
#include "ehca_iverbs.h"
#include "hcp_if.h"
int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
{
int ret = 0;
struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
ib_device);
struct hipz_query_hca *rblock;
rblock = ehca_alloc_fw_ctrlblock();
if (!rblock) {
ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
return -ENOMEM;
}
if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) {
ehca_err(&shca->ib_device, "Can't query device properties");
ret = -EINVAL;
goto query_device1;
}
memset(props, 0, sizeof(struct ib_device_attr));
props->fw_ver = rblock->hw_ver;
props->max_mr_size = rblock->max_mr_size;
props->vendor_id = rblock->vendor_id >> 8;
props->vendor_part_id = rblock->vendor_part_id >> 16;
props->hw_ver = rblock->hw_ver;
props->max_qp = min_t(int, rblock->max_qp, INT_MAX);
props->max_qp_wr = min_t(int, rblock->max_wqes_wq, INT_MAX);
props->max_sge = min_t(int, rblock->max_sge, INT_MAX);
props->max_sge_rd = min_t(int, rblock->max_sge_rd, INT_MAX);
props->max_cq = min_t(int, rblock->max_cq, INT_MAX);
props->max_cqe = min_t(int, rblock->max_cqe, INT_MAX);
props->max_mr = min_t(int, rblock->max_mr, INT_MAX);
props->max_mw = min_t(int, rblock->max_mw, INT_MAX);
props->max_pd = min_t(int, rblock->max_pd, INT_MAX);
props->max_ah = min_t(int, rblock->max_ah, INT_MAX);
props->max_fmr = min_t(int, rblock->max_mr, INT_MAX);
props->max_srq = 0;
props->max_srq_wr = 0;
props->max_srq_sge = 0;
props->max_pkeys = 16;
props->local_ca_ack_delay
= rblock->local_ca_ack_delay;
props->max_raw_ipv6_qp
= min_t(int, rblock->max_raw_ipv6_qp, INT_MAX);
props->max_raw_ethy_qp
= min_t(int, rblock->max_raw_ethy_qp, INT_MAX);
props->max_mcast_grp
= min_t(int, rblock->max_mcast_grp, INT_MAX);
props->max_mcast_qp_attach
= min_t(int, rblock->max_mcast_qp_attach, INT_MAX);
props->max_total_mcast_qp_attach
= min_t(int, rblock->max_total_mcast_qp_attach, INT_MAX);
query_device1:
ehca_free_fw_ctrlblock(rblock);
return ret;
}
int ehca_query_port(struct ib_device *ibdev,
u8 port, struct ib_port_attr *props)
{
int ret = 0;
struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
ib_device);
struct hipz_query_port *rblock;
rblock = ehca_alloc_fw_ctrlblock();
if (!rblock) {
ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
return -ENOMEM;
}
if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
ehca_err(&shca->ib_device, "Can't query port properties");
ret = -EINVAL;
goto query_port1;
}
memset(props, 0, sizeof(struct ib_port_attr));
props->state = rblock->state;
switch (rblock->max_mtu) {
case 0x1:
props->active_mtu = props->max_mtu = IB_MTU_256;
break;
case 0x2:
props->active_mtu = props->max_mtu = IB_MTU_512;
break;
case 0x3:
props->active_mtu = props->max_mtu = IB_MTU_1024;
break;
case 0x4:
props->active_mtu = props->max_mtu = IB_MTU_2048;
break;
case 0x5:
props->active_mtu = props->max_mtu = IB_MTU_4096;
break;
default:
ehca_err(&shca->ib_device, "Unknown MTU size: %x.",
rblock->max_mtu);
break;
}
props->gid_tbl_len = rblock->gid_tbl_len;
props->max_msg_sz = rblock->max_msg_sz;
props->bad_pkey_cntr = rblock->bad_pkey_cntr;
props->qkey_viol_cntr = rblock->qkey_viol_cntr;
props->pkey_tbl_len = rblock->pkey_tbl_len;
props->lid = rblock->lid;
props->sm_lid = rblock->sm_lid;
props->lmc = rblock->lmc;
props->sm_sl = rblock->sm_sl;
props->subnet_timeout = rblock->subnet_timeout;
props->init_type_reply = rblock->init_type_reply;
props->active_width = IB_WIDTH_12X;
props->active_speed = 0x1;
query_port1:
ehca_free_fw_ctrlblock(rblock);
return ret;
}
int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
{
int ret = 0;
struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, ib_device);
struct hipz_query_port *rblock;
if (index > 16) {
ehca_err(&shca->ib_device, "Invalid index: %x.", index);
return -EINVAL;
}
rblock = ehca_alloc_fw_ctrlblock();
if (!rblock) {
ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
return -ENOMEM;
}
if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
ehca_err(&shca->ib_device, "Can't query port properties");
ret = -EINVAL;
goto query_pkey1;
}
memcpy(pkey, &rblock->pkey_entries + index, sizeof(u16));
query_pkey1:
ehca_free_fw_ctrlblock(rblock);
return ret;
}
int ehca_query_gid(struct ib_device *ibdev, u8 port,
int index, union ib_gid *gid)
{
int ret = 0;
struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
ib_device);
struct hipz_query_port *rblock;
if (index > 255) {
ehca_err(&shca->ib_device, "Invalid index: %x.", index);
return -EINVAL;
}
rblock = ehca_alloc_fw_ctrlblock();
if (!rblock) {
ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
return -ENOMEM;
}
if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
ehca_err(&shca->ib_device, "Can't query port properties");
ret = -EINVAL;
goto query_gid1;
}
memcpy(&gid->raw[0], &rblock->gid_prefix, sizeof(u64));
memcpy(&gid->raw[8], &rblock->guid_entries[index], sizeof(u64));
query_gid1:
ehca_free_fw_ctrlblock(rblock);
return ret;
}
int ehca_modify_port(struct ib_device *ibdev,
u8 port, int port_modify_mask,
struct ib_port_modify *props)
{
/* Not implemented yet */
return -EFAULT;
}