summaryrefslogtreecommitdiff
path: root/drivers/infiniband/hw/ehca/ehca_hca.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-09-22 15:47:06 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-22 15:47:06 -0700
commitdb392219c5f572610645696e3672f6ea38783a65 (patch)
tree240878f6367e528840cc4fe92f6b3a251651572f /drivers/infiniband/hw/ehca/ehca_hca.c
parent3e2ab46df697048e222cdc046a2fa97149ca32ba (diff)
parent9cd330d36b32ed48d49561b165842db20bd153cc (diff)
downloadlinux-db392219c5f572610645696e3672f6ea38783a65.tar.gz
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband: (65 commits) IB: Fix typo in kerneldoc for ib_set_client_data() IPoIB: Add some likely/unlikely annotations in hot path IPoIB: Remove unused include of vmalloc.h IPoIB: Rejoin all multicast groups after a port event IPoIB: Create MCGs with all attributes required by RFC IB/sa: fix ib_sa_selector names IB/iser: INFINIBAND_ISER depends on INET IB/mthca: Simplify calls to mthca_cq_clean() RDMA/cma: Document rdma_accept() error handling IB/mthca: Recover from catastrophic errors RDMA/cma: Document rdma_destroy_id() function IB/cm: Do not track remote QPN in timewait state IB/sa: Require SA registration IPoIB: Refactor completion handling IB/iser: Do not use FMR for a single dma entry sg IB/iser: fix some debug prints IB/iser: make FMR "page size" be 4K and not PAGE_SIZE IB/iser: Limit the max size of a scsi command IB/iser: fix a check of SG alignment for RDMA RDMA/cma: Protect against adding device during destruction ...
Diffstat (limited to 'drivers/infiniband/hw/ehca/ehca_hca.c')
-rw-r--r--drivers/infiniband/hw/ehca/ehca_hca.c241
1 files changed, 241 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
new file mode 100644
index 000000000000..5eae6ac48425
--- /dev/null
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -0,0 +1,241 @@
+/*
+ * 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 "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 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL);
+ 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:
+ kfree(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 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL);
+ 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:
+ kfree(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 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL);
+ 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:
+ kfree(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 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL);
+ 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:
+ kfree(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;
+}