1/* 2 * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 * 4 * HCA query functions 5 * 6 * Authors: Heiko J Schick <schickhj@de.ibm.com> 7 * Christoph Raisch <raisch@de.ibm.com> 8 * 9 * Copyright (c) 2005 IBM Corporation 10 * 11 * All rights reserved. 12 * 13 * This source code is distributed under a dual license of GPL v2.0 and OpenIB 14 * BSD. 15 * 16 * OpenIB BSD License 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are met: 20 * 21 * Redistributions of source code must retain the above copyright notice, this 22 * list of conditions and the following disclaimer. 23 * 24 * Redistributions in binary form must reproduce the above copyright notice, 25 * this list of conditions and the following disclaimer in the documentation 26 * and/or other materials 27 * provided with the distribution. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 30 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 33 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 36 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 37 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 * POSSIBILITY OF SUCH DAMAGE. 40 */ 41 42#include "ehca_tools.h" 43#include "ehca_iverbs.h" 44#include "hcp_if.h" 45 46int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) 47{ 48 int ret = 0; 49 struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, 50 ib_device); 51 struct hipz_query_hca *rblock; 52 53 rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); 54 if (!rblock) { 55 ehca_err(&shca->ib_device, "Can't allocate rblock memory."); 56 return -ENOMEM; 57 } 58 59 if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { 60 ehca_err(&shca->ib_device, "Can't query device properties"); 61 ret = -EINVAL; 62 goto query_device1; 63 } 64 65 memset(props, 0, sizeof(struct ib_device_attr)); 66 props->fw_ver = rblock->hw_ver; 67 props->max_mr_size = rblock->max_mr_size; 68 props->vendor_id = rblock->vendor_id >> 8; 69 props->vendor_part_id = rblock->vendor_part_id >> 16; 70 props->hw_ver = rblock->hw_ver; 71 props->max_qp = min_t(int, rblock->max_qp, INT_MAX); 72 props->max_qp_wr = min_t(int, rblock->max_wqes_wq, INT_MAX); 73 props->max_sge = min_t(int, rblock->max_sge, INT_MAX); 74 props->max_sge_rd = min_t(int, rblock->max_sge_rd, INT_MAX); 75 props->max_cq = min_t(int, rblock->max_cq, INT_MAX); 76 props->max_cqe = min_t(int, rblock->max_cqe, INT_MAX); 77 props->max_mr = min_t(int, rblock->max_mr, INT_MAX); 78 props->max_mw = min_t(int, rblock->max_mw, INT_MAX); 79 props->max_pd = min_t(int, rblock->max_pd, INT_MAX); 80 props->max_ah = min_t(int, rblock->max_ah, INT_MAX); 81 props->max_fmr = min_t(int, rblock->max_mr, INT_MAX); 82 props->max_srq = 0; 83 props->max_srq_wr = 0; 84 props->max_srq_sge = 0; 85 props->max_pkeys = 16; 86 props->local_ca_ack_delay 87 = rblock->local_ca_ack_delay; 88 props->max_raw_ipv6_qp 89 = min_t(int, rblock->max_raw_ipv6_qp, INT_MAX); 90 props->max_raw_ethy_qp 91 = min_t(int, rblock->max_raw_ethy_qp, INT_MAX); 92 props->max_mcast_grp 93 = min_t(int, rblock->max_mcast_grp, INT_MAX); 94 props->max_mcast_qp_attach 95 = min_t(int, rblock->max_mcast_qp_attach, INT_MAX); 96 props->max_total_mcast_qp_attach 97 = min_t(int, rblock->max_total_mcast_qp_attach, INT_MAX); 98 99query_device1: 100 ehca_free_fw_ctrlblock(rblock); 101 102 return ret; 103} 104 105int ehca_query_port(struct ib_device *ibdev, 106 u8 port, struct ib_port_attr *props) 107{ 108 int ret = 0; 109 struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, 110 ib_device); 111 struct hipz_query_port *rblock; 112 113 rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); 114 if (!rblock) { 115 ehca_err(&shca->ib_device, "Can't allocate rblock memory."); 116 return -ENOMEM; 117 } 118 119 if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) { 120 ehca_err(&shca->ib_device, "Can't query port properties"); 121 ret = -EINVAL; 122 goto query_port1; 123 } 124 125 memset(props, 0, sizeof(struct ib_port_attr)); 126 props->state = rblock->state; 127 128 switch (rblock->max_mtu) { 129 case 0x1: 130 props->active_mtu = props->max_mtu = IB_MTU_256; 131 break; 132 case 0x2: 133 props->active_mtu = props->max_mtu = IB_MTU_512; 134 break; 135 case 0x3: 136 props->active_mtu = props->max_mtu = IB_MTU_1024; 137 break; 138 case 0x4: 139 props->active_mtu = props->max_mtu = IB_MTU_2048; 140 break; 141 case 0x5: 142 props->active_mtu = props->max_mtu = IB_MTU_4096; 143 break; 144 default: 145 ehca_err(&shca->ib_device, "Unknown MTU size: %x.", 146 rblock->max_mtu); 147 break; 148 } 149 150 props->port_cap_flags = rblock->capability_mask; 151 props->gid_tbl_len = rblock->gid_tbl_len; 152 props->max_msg_sz = rblock->max_msg_sz; 153 props->bad_pkey_cntr = rblock->bad_pkey_cntr; 154 props->qkey_viol_cntr = rblock->qkey_viol_cntr; 155 props->pkey_tbl_len = rblock->pkey_tbl_len; 156 props->lid = rblock->lid; 157 props->sm_lid = rblock->sm_lid; 158 props->lmc = rblock->lmc; 159 props->sm_sl = rblock->sm_sl; 160 props->subnet_timeout = rblock->subnet_timeout; 161 props->init_type_reply = rblock->init_type_reply; 162 163 props->active_width = IB_WIDTH_12X; 164 props->active_speed = 0x1; 165 166 /* at the moment (logical) link state is always LINK_UP */ 167 props->phys_state = 0x5; 168 169query_port1: 170 ehca_free_fw_ctrlblock(rblock); 171 172 return ret; 173} 174 175int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) 176{ 177 int ret = 0; 178 struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, ib_device); 179 struct hipz_query_port *rblock; 180 181 if (index > 16) { 182 ehca_err(&shca->ib_device, "Invalid index: %x.", index); 183 return -EINVAL; 184 } 185 186 rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); 187 if (!rblock) { 188 ehca_err(&shca->ib_device, "Can't allocate rblock memory."); 189 return -ENOMEM; 190 } 191 192 if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) { 193 ehca_err(&shca->ib_device, "Can't query port properties"); 194 ret = -EINVAL; 195 goto query_pkey1; 196 } 197 198 memcpy(pkey, &rblock->pkey_entries + index, sizeof(u16)); 199 200query_pkey1: 201 ehca_free_fw_ctrlblock(rblock); 202 203 return ret; 204} 205 206int ehca_query_gid(struct ib_device *ibdev, u8 port, 207 int index, union ib_gid *gid) 208{ 209 int ret = 0; 210 struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, 211 ib_device); 212 struct hipz_query_port *rblock; 213 214 if (index > 255) { 215 ehca_err(&shca->ib_device, "Invalid index: %x.", index); 216 return -EINVAL; 217 } 218 219 rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); 220 if (!rblock) { 221 ehca_err(&shca->ib_device, "Can't allocate rblock memory."); 222 return -ENOMEM; 223 } 224 225 if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) { 226 ehca_err(&shca->ib_device, "Can't query port properties"); 227 ret = -EINVAL; 228 goto query_gid1; 229 } 230 231 memcpy(&gid->raw[0], &rblock->gid_prefix, sizeof(u64)); 232 memcpy(&gid->raw[8], &rblock->guid_entries[index], sizeof(u64)); 233 234query_gid1: 235 ehca_free_fw_ctrlblock(rblock); 236 237 return ret; 238} 239 240const u32 allowed_port_caps = ( 241 IB_PORT_SM | IB_PORT_LED_INFO_SUP | IB_PORT_CM_SUP | 242 IB_PORT_SNMP_TUNNEL_SUP | IB_PORT_DEVICE_MGMT_SUP | 243 IB_PORT_VENDOR_CLASS_SUP); 244 245int ehca_modify_port(struct ib_device *ibdev, 246 u8 port, int port_modify_mask, 247 struct ib_port_modify *props) 248{ 249 int ret = 0; 250 struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, ib_device); 251 struct hipz_query_port *rblock; 252 u32 cap; 253 u64 hret; 254 255 if ((props->set_port_cap_mask | props->clr_port_cap_mask) 256 & ~allowed_port_caps) { 257 ehca_err(&shca->ib_device, "Non-changeable bits set in masks " 258 "set=%x clr=%x allowed=%x", props->set_port_cap_mask, 259 props->clr_port_cap_mask, allowed_port_caps); 260 return -EINVAL; 261 } 262 263 if (mutex_lock_interruptible(&shca->modify_mutex)) 264 return -ERESTARTSYS; 265 266 rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL); 267 if (!rblock) { 268 ehca_err(&shca->ib_device, "Can't allocate rblock memory."); 269 ret = -ENOMEM; 270 goto modify_port1; 271 } 272 273 if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) { 274 ehca_err(&shca->ib_device, "Can't query port properties"); 275 ret = -EINVAL; 276 goto modify_port2; 277 } 278 279 cap = (rblock->capability_mask | props->set_port_cap_mask) 280 & ~props->clr_port_cap_mask; 281 282 hret = hipz_h_modify_port(shca->ipz_hca_handle, port, 283 cap, props->init_type, port_modify_mask); 284 if (hret != H_SUCCESS) { 285 ehca_err(&shca->ib_device, "Modify port failed hret=%lx", hret); 286 ret = -EINVAL; 287 } 288 289modify_port2: 290 ehca_free_fw_ctrlblock(rblock); 291 292modify_port1: 293 mutex_unlock(&shca->modify_mutex); 294 295 return ret; 296} 297