Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/ehca: Add driver for IBM eHCA InfiniBand adapters

Add a driver for IBM GX bus InfiniBand adapters, which are usable with
some pSeries/System p systems.

Signed-off-by: Heiko J Schick <schickhj.ibm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>

authored by

Heiko J Schick and committed by
Roland Dreier
fab97220 ded7f1a1

+11582
+8
MAINTAINERS
··· 991 991 W: http://aeschi.ch.eu.org/efs/ 992 992 S: Orphan 993 993 994 + EHCA (IBM GX bus InfiniBand adapter) DRIVER: 995 + P: Hoang-Nam Nguyen 996 + M: hnguyen@de.ibm.com 997 + P: Christoph Raisch 998 + M: raisch@de.ibm.com 999 + L: openib-general@openib.org 1000 + S: Supported 1001 + 994 1002 EMU10K1 SOUND DRIVER 995 1003 P: James Courtier-Dutton 996 1004 M: James@superbug.demon.co.uk
+1
drivers/infiniband/Kconfig
··· 36 36 37 37 source "drivers/infiniband/hw/mthca/Kconfig" 38 38 source "drivers/infiniband/hw/ipath/Kconfig" 39 + source "drivers/infiniband/hw/ehca/Kconfig" 39 40 40 41 source "drivers/infiniband/ulp/ipoib/Kconfig" 41 42
+1
drivers/infiniband/Makefile
··· 1 1 obj-$(CONFIG_INFINIBAND) += core/ 2 2 obj-$(CONFIG_INFINIBAND_MTHCA) += hw/mthca/ 3 3 obj-$(CONFIG_IPATH_CORE) += hw/ipath/ 4 + obj-$(CONFIG_INFINIBAND_EHCA) += hw/ehca/ 4 5 obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/ 5 6 obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/ 6 7 obj-$(CONFIG_INFINIBAND_ISER) += ulp/iser/
+16
drivers/infiniband/hw/ehca/Kconfig
··· 1 + config INFINIBAND_EHCA 2 + tristate "eHCA support" 3 + depends on IBMEBUS && INFINIBAND 4 + ---help--- 5 + This driver supports the IBM pSeries eHCA InfiniBand adapter. 6 + 7 + To compile the driver as a module, choose M here. The module 8 + will be called ib_ehca. 9 + 10 + config INFINIBAND_EHCA_SCALING 11 + bool "Scaling support (EXPERIMENTAL)" 12 + depends on IBMEBUS && INFINIBAND_EHCA && HOTPLUG_CPU && EXPERIMENTAL 13 + ---help--- 14 + eHCA scaling support schedules the CQ callbacks to different CPUs. 15 + 16 + To enable this feature choose Y here.
+16
drivers/infiniband/hw/ehca/Makefile
··· 1 + # Authors: Heiko J Schick <schickhj@de.ibm.com> 2 + # Christoph Raisch <raisch@de.ibm.com> 3 + # Joachim Fenkes <fenkes@de.ibm.com> 4 + # 5 + # Copyright (c) 2005 IBM Corporation 6 + # 7 + # All rights reserved. 8 + # 9 + # This source code is distributed under a dual license of GPL v2.0 and OpenIB BSD. 10 + 11 + obj-$(CONFIG_INFINIBAND_EHCA) += ib_ehca.o 12 + 13 + ib_ehca-objs = ehca_main.o ehca_hca.o ehca_mcast.o ehca_pd.o ehca_av.o ehca_eq.o \ 14 + ehca_cq.o ehca_qp.o ehca_sqp.o ehca_mrmw.o ehca_reqs.o ehca_irq.o \ 15 + ehca_uverbs.o ipz_pt_fn.o hcp_if.o hcp_phyp.o 16 +
+271
drivers/infiniband/hw/ehca/ehca_av.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * adress vector functions 5 + * 6 + * Authors: Hoang-Nam Nguyen <hnguyen@de.ibm.com> 7 + * Khadija Souissi <souissik@de.ibm.com> 8 + * Reinhard Ernst <rernst@de.ibm.com> 9 + * Christoph Raisch <raisch@de.ibm.com> 10 + * 11 + * Copyright (c) 2005 IBM Corporation 12 + * 13 + * All rights reserved. 14 + * 15 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 16 + * BSD. 17 + * 18 + * OpenIB BSD License 19 + * 20 + * Redistribution and use in source and binary forms, with or without 21 + * modification, are permitted provided that the following conditions are met: 22 + * 23 + * Redistributions of source code must retain the above copyright notice, this 24 + * list of conditions and the following disclaimer. 25 + * 26 + * Redistributions in binary form must reproduce the above copyright notice, 27 + * this list of conditions and the following disclaimer in the documentation 28 + * and/or other materials 29 + * provided with the distribution. 30 + * 31 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 32 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 35 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 36 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 38 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 39 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 + * POSSIBILITY OF SUCH DAMAGE. 42 + */ 43 + 44 + 45 + #include <asm/current.h> 46 + 47 + #include "ehca_tools.h" 48 + #include "ehca_iverbs.h" 49 + #include "hcp_if.h" 50 + 51 + static struct kmem_cache *av_cache; 52 + 53 + struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) 54 + { 55 + int ret; 56 + struct ehca_av *av; 57 + struct ehca_shca *shca = container_of(pd->device, struct ehca_shca, 58 + ib_device); 59 + 60 + av = kmem_cache_alloc(av_cache, SLAB_KERNEL); 61 + if (!av) { 62 + ehca_err(pd->device, "Out of memory pd=%p ah_attr=%p", 63 + pd, ah_attr); 64 + return ERR_PTR(-ENOMEM); 65 + } 66 + 67 + av->av.sl = ah_attr->sl; 68 + av->av.dlid = ah_attr->dlid; 69 + av->av.slid_path_bits = ah_attr->src_path_bits; 70 + 71 + if (ehca_static_rate < 0) { 72 + int ah_mult = ib_rate_to_mult(ah_attr->static_rate); 73 + int ehca_mult = 74 + ib_rate_to_mult(shca->sport[ah_attr->port_num].rate ); 75 + 76 + if (ah_mult >= ehca_mult) 77 + av->av.ipd = 0; 78 + else 79 + av->av.ipd = (ah_mult > 0) ? 80 + ((ehca_mult - 1) / ah_mult) : 0; 81 + } else 82 + av->av.ipd = ehca_static_rate; 83 + 84 + av->av.lnh = ah_attr->ah_flags; 85 + av->av.grh.word_0 = EHCA_BMASK_SET(GRH_IPVERSION_MASK, 6); 86 + av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_TCLASS_MASK, 87 + ah_attr->grh.traffic_class); 88 + av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_FLOWLABEL_MASK, 89 + ah_attr->grh.flow_label); 90 + av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_HOPLIMIT_MASK, 91 + ah_attr->grh.hop_limit); 92 + av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_NEXTHEADER_MASK, 0x1B); 93 + /* set sgid in grh.word_1 */ 94 + if (ah_attr->ah_flags & IB_AH_GRH) { 95 + int rc; 96 + struct ib_port_attr port_attr; 97 + union ib_gid gid; 98 + memset(&port_attr, 0, sizeof(port_attr)); 99 + rc = ehca_query_port(pd->device, ah_attr->port_num, 100 + &port_attr); 101 + if (rc) { /* invalid port number */ 102 + ret = -EINVAL; 103 + ehca_err(pd->device, "Invalid port number " 104 + "ehca_query_port() returned %x " 105 + "pd=%p ah_attr=%p", rc, pd, ah_attr); 106 + goto create_ah_exit1; 107 + } 108 + memset(&gid, 0, sizeof(gid)); 109 + rc = ehca_query_gid(pd->device, 110 + ah_attr->port_num, 111 + ah_attr->grh.sgid_index, &gid); 112 + if (rc) { 113 + ret = -EINVAL; 114 + ehca_err(pd->device, "Failed to retrieve sgid " 115 + "ehca_query_gid() returned %x " 116 + "pd=%p ah_attr=%p", rc, pd, ah_attr); 117 + goto create_ah_exit1; 118 + } 119 + memcpy(&av->av.grh.word_1, &gid, sizeof(gid)); 120 + } 121 + /* for the time being we use a hard coded PMTU of 2048 Bytes */ 122 + av->av.pmtu = 4; 123 + 124 + /* dgid comes in grh.word_3 */ 125 + memcpy(&av->av.grh.word_3, &ah_attr->grh.dgid, 126 + sizeof(ah_attr->grh.dgid)); 127 + 128 + return &av->ib_ah; 129 + 130 + create_ah_exit1: 131 + kmem_cache_free(av_cache, av); 132 + 133 + return ERR_PTR(ret); 134 + } 135 + 136 + int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 137 + { 138 + struct ehca_av *av; 139 + struct ehca_ud_av new_ehca_av; 140 + struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd); 141 + u32 cur_pid = current->tgid; 142 + 143 + if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && 144 + my_pd->ownpid != cur_pid) { 145 + ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x", 146 + cur_pid, my_pd->ownpid); 147 + return -EINVAL; 148 + } 149 + 150 + memset(&new_ehca_av, 0, sizeof(new_ehca_av)); 151 + new_ehca_av.sl = ah_attr->sl; 152 + new_ehca_av.dlid = ah_attr->dlid; 153 + new_ehca_av.slid_path_bits = ah_attr->src_path_bits; 154 + new_ehca_av.ipd = ah_attr->static_rate; 155 + new_ehca_av.lnh = EHCA_BMASK_SET(GRH_FLAG_MASK, 156 + (ah_attr->ah_flags & IB_AH_GRH) > 0); 157 + new_ehca_av.grh.word_0 = EHCA_BMASK_SET(GRH_TCLASS_MASK, 158 + ah_attr->grh.traffic_class); 159 + new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_FLOWLABEL_MASK, 160 + ah_attr->grh.flow_label); 161 + new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_HOPLIMIT_MASK, 162 + ah_attr->grh.hop_limit); 163 + new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_NEXTHEADER_MASK, 0x1b); 164 + 165 + /* set sgid in grh.word_1 */ 166 + if (ah_attr->ah_flags & IB_AH_GRH) { 167 + int rc; 168 + struct ib_port_attr port_attr; 169 + union ib_gid gid; 170 + memset(&port_attr, 0, sizeof(port_attr)); 171 + rc = ehca_query_port(ah->device, ah_attr->port_num, 172 + &port_attr); 173 + if (rc) { /* invalid port number */ 174 + ehca_err(ah->device, "Invalid port number " 175 + "ehca_query_port() returned %x " 176 + "ah=%p ah_attr=%p port_num=%x", 177 + rc, ah, ah_attr, ah_attr->port_num); 178 + return -EINVAL; 179 + } 180 + memset(&gid, 0, sizeof(gid)); 181 + rc = ehca_query_gid(ah->device, 182 + ah_attr->port_num, 183 + ah_attr->grh.sgid_index, &gid); 184 + if (rc) { 185 + ehca_err(ah->device, "Failed to retrieve sgid " 186 + "ehca_query_gid() returned %x " 187 + "ah=%p ah_attr=%p port_num=%x " 188 + "sgid_index=%x", 189 + rc, ah, ah_attr, ah_attr->port_num, 190 + ah_attr->grh.sgid_index); 191 + return -EINVAL; 192 + } 193 + memcpy(&new_ehca_av.grh.word_1, &gid, sizeof(gid)); 194 + } 195 + 196 + new_ehca_av.pmtu = 4; /* see also comment in create_ah() */ 197 + 198 + memcpy(&new_ehca_av.grh.word_3, &ah_attr->grh.dgid, 199 + sizeof(ah_attr->grh.dgid)); 200 + 201 + av = container_of(ah, struct ehca_av, ib_ah); 202 + av->av = new_ehca_av; 203 + 204 + return 0; 205 + } 206 + 207 + int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) 208 + { 209 + struct ehca_av *av = container_of(ah, struct ehca_av, ib_ah); 210 + struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd); 211 + u32 cur_pid = current->tgid; 212 + 213 + if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && 214 + my_pd->ownpid != cur_pid) { 215 + ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x", 216 + cur_pid, my_pd->ownpid); 217 + return -EINVAL; 218 + } 219 + 220 + memcpy(&ah_attr->grh.dgid, &av->av.grh.word_3, 221 + sizeof(ah_attr->grh.dgid)); 222 + ah_attr->sl = av->av.sl; 223 + 224 + ah_attr->dlid = av->av.dlid; 225 + 226 + ah_attr->src_path_bits = av->av.slid_path_bits; 227 + ah_attr->static_rate = av->av.ipd; 228 + ah_attr->ah_flags = EHCA_BMASK_GET(GRH_FLAG_MASK, av->av.lnh); 229 + ah_attr->grh.traffic_class = EHCA_BMASK_GET(GRH_TCLASS_MASK, 230 + av->av.grh.word_0); 231 + ah_attr->grh.hop_limit = EHCA_BMASK_GET(GRH_HOPLIMIT_MASK, 232 + av->av.grh.word_0); 233 + ah_attr->grh.flow_label = EHCA_BMASK_GET(GRH_FLOWLABEL_MASK, 234 + av->av.grh.word_0); 235 + 236 + return 0; 237 + } 238 + 239 + int ehca_destroy_ah(struct ib_ah *ah) 240 + { 241 + struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd); 242 + u32 cur_pid = current->tgid; 243 + 244 + if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && 245 + my_pd->ownpid != cur_pid) { 246 + ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x", 247 + cur_pid, my_pd->ownpid); 248 + return -EINVAL; 249 + } 250 + 251 + kmem_cache_free(av_cache, container_of(ah, struct ehca_av, ib_ah)); 252 + 253 + return 0; 254 + } 255 + 256 + int ehca_init_av_cache(void) 257 + { 258 + av_cache = kmem_cache_create("ehca_cache_av", 259 + sizeof(struct ehca_av), 0, 260 + SLAB_HWCACHE_ALIGN, 261 + NULL, NULL); 262 + if (!av_cache) 263 + return -ENOMEM; 264 + return 0; 265 + } 266 + 267 + void ehca_cleanup_av_cache(void) 268 + { 269 + if (av_cache) 270 + kmem_cache_destroy(av_cache); 271 + }
+346
drivers/infiniband/hw/ehca/ehca_classes.h
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * Struct definition for eHCA internal structures 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 + #ifndef __EHCA_CLASSES_H__ 43 + #define __EHCA_CLASSES_H__ 44 + 45 + #include "ehca_classes.h" 46 + #include "ipz_pt_fn.h" 47 + 48 + struct ehca_module; 49 + struct ehca_qp; 50 + struct ehca_cq; 51 + struct ehca_eq; 52 + struct ehca_mr; 53 + struct ehca_mw; 54 + struct ehca_pd; 55 + struct ehca_av; 56 + 57 + #ifdef CONFIG_PPC64 58 + #include "ehca_classes_pSeries.h" 59 + #endif 60 + 61 + #include <rdma/ib_verbs.h> 62 + #include <rdma/ib_user_verbs.h> 63 + 64 + #include "ehca_irq.h" 65 + 66 + struct ehca_eq { 67 + u32 length; 68 + struct ipz_queue ipz_queue; 69 + struct ipz_eq_handle ipz_eq_handle; 70 + struct work_struct work; 71 + struct h_galpas galpas; 72 + int is_initialized; 73 + struct ehca_pfeq pf; 74 + spinlock_t spinlock; 75 + struct tasklet_struct interrupt_task; 76 + u32 ist; 77 + }; 78 + 79 + struct ehca_sport { 80 + struct ib_cq *ibcq_aqp1; 81 + struct ib_qp *ibqp_aqp1; 82 + enum ib_rate rate; 83 + enum ib_port_state port_state; 84 + }; 85 + 86 + struct ehca_shca { 87 + struct ib_device ib_device; 88 + struct ibmebus_dev *ibmebus_dev; 89 + u8 num_ports; 90 + int hw_level; 91 + struct list_head shca_list; 92 + struct ipz_adapter_handle ipz_hca_handle; 93 + struct ehca_sport sport[2]; 94 + struct ehca_eq eq; 95 + struct ehca_eq neq; 96 + struct ehca_mr *maxmr; 97 + struct ehca_pd *pd; 98 + struct h_galpas galpas; 99 + }; 100 + 101 + struct ehca_pd { 102 + struct ib_pd ib_pd; 103 + struct ipz_pd fw_pd; 104 + u32 ownpid; 105 + }; 106 + 107 + struct ehca_qp { 108 + struct ib_qp ib_qp; 109 + u32 qp_type; 110 + struct ipz_queue ipz_squeue; 111 + struct ipz_queue ipz_rqueue; 112 + struct h_galpas galpas; 113 + u32 qkey; 114 + u32 real_qp_num; 115 + u32 token; 116 + spinlock_t spinlock_s; 117 + spinlock_t spinlock_r; 118 + u32 sq_max_inline_data_size; 119 + struct ipz_qp_handle ipz_qp_handle; 120 + struct ehca_pfqp pf; 121 + struct ib_qp_init_attr init_attr; 122 + u64 uspace_squeue; 123 + u64 uspace_rqueue; 124 + u64 uspace_fwh; 125 + struct ehca_cq *send_cq; 126 + struct ehca_cq *recv_cq; 127 + unsigned int sqerr_purgeflag; 128 + struct hlist_node list_entries; 129 + }; 130 + 131 + /* must be power of 2 */ 132 + #define QP_HASHTAB_LEN 8 133 + 134 + struct ehca_cq { 135 + struct ib_cq ib_cq; 136 + struct ipz_queue ipz_queue; 137 + struct h_galpas galpas; 138 + spinlock_t spinlock; 139 + u32 cq_number; 140 + u32 token; 141 + u32 nr_of_entries; 142 + struct ipz_cq_handle ipz_cq_handle; 143 + struct ehca_pfcq pf; 144 + spinlock_t cb_lock; 145 + u64 uspace_queue; 146 + u64 uspace_fwh; 147 + struct hlist_head qp_hashtab[QP_HASHTAB_LEN]; 148 + struct list_head entry; 149 + u32 nr_callbacks; 150 + spinlock_t task_lock; 151 + u32 ownpid; 152 + }; 153 + 154 + enum ehca_mr_flag { 155 + EHCA_MR_FLAG_FMR = 0x80000000, /* FMR, created with ehca_alloc_fmr */ 156 + EHCA_MR_FLAG_MAXMR = 0x40000000, /* max-MR */ 157 + }; 158 + 159 + struct ehca_mr { 160 + union { 161 + struct ib_mr ib_mr; /* must always be first in ehca_mr */ 162 + struct ib_fmr ib_fmr; /* must always be first in ehca_mr */ 163 + } ib; 164 + spinlock_t mrlock; 165 + 166 + enum ehca_mr_flag flags; 167 + u32 num_pages; /* number of MR pages */ 168 + u32 num_4k; /* number of 4k "page" portions to form MR */ 169 + int acl; /* ACL (stored here for usage in reregister) */ 170 + u64 *start; /* virtual start address (stored here for */ 171 + /* usage in reregister) */ 172 + u64 size; /* size (stored here for usage in reregister) */ 173 + u32 fmr_page_size; /* page size for FMR */ 174 + u32 fmr_max_pages; /* max pages for FMR */ 175 + u32 fmr_max_maps; /* max outstanding maps for FMR */ 176 + u32 fmr_map_cnt; /* map counter for FMR */ 177 + /* fw specific data */ 178 + struct ipz_mrmw_handle ipz_mr_handle; /* MR handle for h-calls */ 179 + struct h_galpas galpas; 180 + /* data for userspace bridge */ 181 + u32 nr_of_pages; 182 + void *pagearray; 183 + }; 184 + 185 + struct ehca_mw { 186 + struct ib_mw ib_mw; /* gen2 mw, must always be first in ehca_mw */ 187 + spinlock_t mwlock; 188 + 189 + u8 never_bound; /* indication MW was never bound */ 190 + struct ipz_mrmw_handle ipz_mw_handle; /* MW handle for h-calls */ 191 + struct h_galpas galpas; 192 + }; 193 + 194 + enum ehca_mr_pgi_type { 195 + EHCA_MR_PGI_PHYS = 1, /* type of ehca_reg_phys_mr, 196 + * ehca_rereg_phys_mr, 197 + * ehca_reg_internal_maxmr */ 198 + EHCA_MR_PGI_USER = 2, /* type of ehca_reg_user_mr */ 199 + EHCA_MR_PGI_FMR = 3 /* type of ehca_map_phys_fmr */ 200 + }; 201 + 202 + struct ehca_mr_pginfo { 203 + enum ehca_mr_pgi_type type; 204 + u64 num_pages; 205 + u64 page_cnt; 206 + u64 num_4k; /* number of 4k "page" portions */ 207 + u64 page_4k_cnt; /* counter for 4k "page" portions */ 208 + u64 next_4k; /* next 4k "page" portion in buffer/chunk/listelem */ 209 + 210 + /* type EHCA_MR_PGI_PHYS section */ 211 + int num_phys_buf; 212 + struct ib_phys_buf *phys_buf_array; 213 + u64 next_buf; 214 + 215 + /* type EHCA_MR_PGI_USER section */ 216 + struct ib_umem *region; 217 + struct ib_umem_chunk *next_chunk; 218 + u64 next_nmap; 219 + 220 + /* type EHCA_MR_PGI_FMR section */ 221 + u64 *page_list; 222 + u64 next_listelem; 223 + /* next_4k also used within EHCA_MR_PGI_FMR */ 224 + }; 225 + 226 + /* output parameters for MR/FMR hipz calls */ 227 + struct ehca_mr_hipzout_parms { 228 + struct ipz_mrmw_handle handle; 229 + u32 lkey; 230 + u32 rkey; 231 + u64 len; 232 + u64 vaddr; 233 + u32 acl; 234 + }; 235 + 236 + /* output parameters for MW hipz calls */ 237 + struct ehca_mw_hipzout_parms { 238 + struct ipz_mrmw_handle handle; 239 + u32 rkey; 240 + }; 241 + 242 + struct ehca_av { 243 + struct ib_ah ib_ah; 244 + struct ehca_ud_av av; 245 + }; 246 + 247 + struct ehca_ucontext { 248 + struct ib_ucontext ib_ucontext; 249 + }; 250 + 251 + struct ehca_module *ehca_module_new(void); 252 + 253 + int ehca_module_delete(struct ehca_module *me); 254 + 255 + int ehca_eq_ctor(struct ehca_eq *eq); 256 + 257 + int ehca_eq_dtor(struct ehca_eq *eq); 258 + 259 + struct ehca_shca *ehca_shca_new(void); 260 + 261 + int ehca_shca_delete(struct ehca_shca *me); 262 + 263 + struct ehca_sport *ehca_sport_new(struct ehca_shca *anchor); 264 + 265 + int ehca_init_pd_cache(void); 266 + void ehca_cleanup_pd_cache(void); 267 + int ehca_init_cq_cache(void); 268 + void ehca_cleanup_cq_cache(void); 269 + int ehca_init_qp_cache(void); 270 + void ehca_cleanup_qp_cache(void); 271 + int ehca_init_av_cache(void); 272 + void ehca_cleanup_av_cache(void); 273 + int ehca_init_mrmw_cache(void); 274 + void ehca_cleanup_mrmw_cache(void); 275 + 276 + extern spinlock_t ehca_qp_idr_lock; 277 + extern spinlock_t ehca_cq_idr_lock; 278 + extern struct idr ehca_qp_idr; 279 + extern struct idr ehca_cq_idr; 280 + 281 + extern int ehca_static_rate; 282 + extern int ehca_port_act_time; 283 + extern int ehca_use_hp_mr; 284 + 285 + struct ipzu_queue_resp { 286 + u64 queue; /* points to first queue entry */ 287 + u32 qe_size; /* queue entry size */ 288 + u32 act_nr_of_sg; 289 + u32 queue_length; /* queue length allocated in bytes */ 290 + u32 pagesize; 291 + u32 toggle_state; 292 + u32 dummy; /* padding for 8 byte alignment */ 293 + }; 294 + 295 + struct ehca_create_cq_resp { 296 + u32 cq_number; 297 + u32 token; 298 + struct ipzu_queue_resp ipz_queue; 299 + struct h_galpas galpas; 300 + }; 301 + 302 + struct ehca_create_qp_resp { 303 + u32 qp_num; 304 + u32 token; 305 + u32 qp_type; 306 + u32 qkey; 307 + /* qp_num assigned by ehca: sqp0/1 may have got different numbers */ 308 + u32 real_qp_num; 309 + u32 dummy; /* padding for 8 byte alignment */ 310 + struct ipzu_queue_resp ipz_squeue; 311 + struct ipzu_queue_resp ipz_rqueue; 312 + struct h_galpas galpas; 313 + }; 314 + 315 + struct ehca_alloc_cq_parms { 316 + u32 nr_cqe; 317 + u32 act_nr_of_entries; 318 + u32 act_pages; 319 + struct ipz_eq_handle eq_handle; 320 + }; 321 + 322 + struct ehca_alloc_qp_parms { 323 + int servicetype; 324 + int sigtype; 325 + int daqp_ctrl; 326 + int max_send_sge; 327 + int max_recv_sge; 328 + int ud_av_l_key_ctl; 329 + 330 + u16 act_nr_send_wqes; 331 + u16 act_nr_recv_wqes; 332 + u8 act_nr_recv_sges; 333 + u8 act_nr_send_sges; 334 + 335 + u32 nr_rq_pages; 336 + u32 nr_sq_pages; 337 + 338 + struct ipz_eq_handle ipz_eq_handle; 339 + struct ipz_pd pd; 340 + }; 341 + 342 + int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp); 343 + int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int qp_num); 344 + struct ehca_qp* ehca_cq_get_qp(struct ehca_cq *cq, int qp_num); 345 + 346 + #endif
+236
drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * pSeries interface definitions 5 + * 6 + * Authors: Waleri Fomin <fomin@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 + #ifndef __EHCA_CLASSES_PSERIES_H__ 43 + #define __EHCA_CLASSES_PSERIES_H__ 44 + 45 + #include "hcp_phyp.h" 46 + #include "ipz_pt_fn.h" 47 + 48 + 49 + struct ehca_pfqp { 50 + struct ipz_qpt sqpt; 51 + struct ipz_qpt rqpt; 52 + }; 53 + 54 + struct ehca_pfcq { 55 + struct ipz_qpt qpt; 56 + u32 cqnr; 57 + }; 58 + 59 + struct ehca_pfeq { 60 + struct ipz_qpt qpt; 61 + struct h_galpa galpa; 62 + u32 eqnr; 63 + }; 64 + 65 + struct ipz_adapter_handle { 66 + u64 handle; 67 + }; 68 + 69 + struct ipz_cq_handle { 70 + u64 handle; 71 + }; 72 + 73 + struct ipz_eq_handle { 74 + u64 handle; 75 + }; 76 + 77 + struct ipz_qp_handle { 78 + u64 handle; 79 + }; 80 + struct ipz_mrmw_handle { 81 + u64 handle; 82 + }; 83 + 84 + struct ipz_pd { 85 + u32 value; 86 + }; 87 + 88 + struct hcp_modify_qp_control_block { 89 + u32 qkey; /* 00 */ 90 + u32 rdd; /* reliable datagram domain */ 91 + u32 send_psn; /* 02 */ 92 + u32 receive_psn; /* 03 */ 93 + u32 prim_phys_port; /* 04 */ 94 + u32 alt_phys_port; /* 05 */ 95 + u32 prim_p_key_idx; /* 06 */ 96 + u32 alt_p_key_idx; /* 07 */ 97 + u32 rdma_atomic_ctrl; /* 08 */ 98 + u32 qp_state; /* 09 */ 99 + u32 reserved_10; /* 10 */ 100 + u32 rdma_nr_atomic_resp_res; /* 11 */ 101 + u32 path_migration_state; /* 12 */ 102 + u32 rdma_atomic_outst_dest_qp; /* 13 */ 103 + u32 dest_qp_nr; /* 14 */ 104 + u32 min_rnr_nak_timer_field; /* 15 */ 105 + u32 service_level; /* 16 */ 106 + u32 send_grh_flag; /* 17 */ 107 + u32 retry_count; /* 18 */ 108 + u32 timeout; /* 19 */ 109 + u32 path_mtu; /* 20 */ 110 + u32 max_static_rate; /* 21 */ 111 + u32 dlid; /* 22 */ 112 + u32 rnr_retry_count; /* 23 */ 113 + u32 source_path_bits; /* 24 */ 114 + u32 traffic_class; /* 25 */ 115 + u32 hop_limit; /* 26 */ 116 + u32 source_gid_idx; /* 27 */ 117 + u32 flow_label; /* 28 */ 118 + u32 reserved_29; /* 29 */ 119 + union { /* 30 */ 120 + u64 dw[2]; 121 + u8 byte[16]; 122 + } dest_gid; 123 + u32 service_level_al; /* 34 */ 124 + u32 send_grh_flag_al; /* 35 */ 125 + u32 retry_count_al; /* 36 */ 126 + u32 timeout_al; /* 37 */ 127 + u32 max_static_rate_al; /* 38 */ 128 + u32 dlid_al; /* 39 */ 129 + u32 rnr_retry_count_al; /* 40 */ 130 + u32 source_path_bits_al; /* 41 */ 131 + u32 traffic_class_al; /* 42 */ 132 + u32 hop_limit_al; /* 43 */ 133 + u32 source_gid_idx_al; /* 44 */ 134 + u32 flow_label_al; /* 45 */ 135 + u32 reserved_46; /* 46 */ 136 + u32 reserved_47; /* 47 */ 137 + union { /* 48 */ 138 + u64 dw[2]; 139 + u8 byte[16]; 140 + } dest_gid_al; 141 + u32 max_nr_outst_send_wr; /* 52 */ 142 + u32 max_nr_outst_recv_wr; /* 53 */ 143 + u32 disable_ete_credit_check; /* 54 */ 144 + u32 qp_number; /* 55 */ 145 + u64 send_queue_handle; /* 56 */ 146 + u64 recv_queue_handle; /* 58 */ 147 + u32 actual_nr_sges_in_sq_wqe; /* 60 */ 148 + u32 actual_nr_sges_in_rq_wqe; /* 61 */ 149 + u32 qp_enable; /* 62 */ 150 + u32 curr_srq_limit; /* 63 */ 151 + u64 qp_aff_asyn_ev_log_reg; /* 64 */ 152 + u64 shared_rq_hndl; /* 66 */ 153 + u64 trigg_doorbell_qp_hndl; /* 68 */ 154 + u32 reserved_70_127[58]; /* 70 */ 155 + }; 156 + 157 + #define MQPCB_MASK_QKEY EHCA_BMASK_IBM(0,0) 158 + #define MQPCB_MASK_SEND_PSN EHCA_BMASK_IBM(2,2) 159 + #define MQPCB_MASK_RECEIVE_PSN EHCA_BMASK_IBM(3,3) 160 + #define MQPCB_MASK_PRIM_PHYS_PORT EHCA_BMASK_IBM(4,4) 161 + #define MQPCB_PRIM_PHYS_PORT EHCA_BMASK_IBM(24,31) 162 + #define MQPCB_MASK_ALT_PHYS_PORT EHCA_BMASK_IBM(5,5) 163 + #define MQPCB_MASK_PRIM_P_KEY_IDX EHCA_BMASK_IBM(6,6) 164 + #define MQPCB_PRIM_P_KEY_IDX EHCA_BMASK_IBM(24,31) 165 + #define MQPCB_MASK_ALT_P_KEY_IDX EHCA_BMASK_IBM(7,7) 166 + #define MQPCB_MASK_RDMA_ATOMIC_CTRL EHCA_BMASK_IBM(8,8) 167 + #define MQPCB_MASK_QP_STATE EHCA_BMASK_IBM(9,9) 168 + #define MQPCB_QP_STATE EHCA_BMASK_IBM(24,31) 169 + #define MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES EHCA_BMASK_IBM(11,11) 170 + #define MQPCB_MASK_PATH_MIGRATION_STATE EHCA_BMASK_IBM(12,12) 171 + #define MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP EHCA_BMASK_IBM(13,13) 172 + #define MQPCB_MASK_DEST_QP_NR EHCA_BMASK_IBM(14,14) 173 + #define MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD EHCA_BMASK_IBM(15,15) 174 + #define MQPCB_MASK_SERVICE_LEVEL EHCA_BMASK_IBM(16,16) 175 + #define MQPCB_MASK_SEND_GRH_FLAG EHCA_BMASK_IBM(17,17) 176 + #define MQPCB_MASK_RETRY_COUNT EHCA_BMASK_IBM(18,18) 177 + #define MQPCB_MASK_TIMEOUT EHCA_BMASK_IBM(19,19) 178 + #define MQPCB_MASK_PATH_MTU EHCA_BMASK_IBM(20,20) 179 + #define MQPCB_PATH_MTU EHCA_BMASK_IBM(24,31) 180 + #define MQPCB_MASK_MAX_STATIC_RATE EHCA_BMASK_IBM(21,21) 181 + #define MQPCB_MAX_STATIC_RATE EHCA_BMASK_IBM(24,31) 182 + #define MQPCB_MASK_DLID EHCA_BMASK_IBM(22,22) 183 + #define MQPCB_DLID EHCA_BMASK_IBM(16,31) 184 + #define MQPCB_MASK_RNR_RETRY_COUNT EHCA_BMASK_IBM(23,23) 185 + #define MQPCB_RNR_RETRY_COUNT EHCA_BMASK_IBM(29,31) 186 + #define MQPCB_MASK_SOURCE_PATH_BITS EHCA_BMASK_IBM(24,24) 187 + #define MQPCB_SOURCE_PATH_BITS EHCA_BMASK_IBM(25,31) 188 + #define MQPCB_MASK_TRAFFIC_CLASS EHCA_BMASK_IBM(25,25) 189 + #define MQPCB_TRAFFIC_CLASS EHCA_BMASK_IBM(24,31) 190 + #define MQPCB_MASK_HOP_LIMIT EHCA_BMASK_IBM(26,26) 191 + #define MQPCB_HOP_LIMIT EHCA_BMASK_IBM(24,31) 192 + #define MQPCB_MASK_SOURCE_GID_IDX EHCA_BMASK_IBM(27,27) 193 + #define MQPCB_SOURCE_GID_IDX EHCA_BMASK_IBM(24,31) 194 + #define MQPCB_MASK_FLOW_LABEL EHCA_BMASK_IBM(28,28) 195 + #define MQPCB_FLOW_LABEL EHCA_BMASK_IBM(12,31) 196 + #define MQPCB_MASK_DEST_GID EHCA_BMASK_IBM(30,30) 197 + #define MQPCB_MASK_SERVICE_LEVEL_AL EHCA_BMASK_IBM(31,31) 198 + #define MQPCB_SERVICE_LEVEL_AL EHCA_BMASK_IBM(28,31) 199 + #define MQPCB_MASK_SEND_GRH_FLAG_AL EHCA_BMASK_IBM(32,32) 200 + #define MQPCB_SEND_GRH_FLAG_AL EHCA_BMASK_IBM(31,31) 201 + #define MQPCB_MASK_RETRY_COUNT_AL EHCA_BMASK_IBM(33,33) 202 + #define MQPCB_RETRY_COUNT_AL EHCA_BMASK_IBM(29,31) 203 + #define MQPCB_MASK_TIMEOUT_AL EHCA_BMASK_IBM(34,34) 204 + #define MQPCB_TIMEOUT_AL EHCA_BMASK_IBM(27,31) 205 + #define MQPCB_MASK_MAX_STATIC_RATE_AL EHCA_BMASK_IBM(35,35) 206 + #define MQPCB_MAX_STATIC_RATE_AL EHCA_BMASK_IBM(24,31) 207 + #define MQPCB_MASK_DLID_AL EHCA_BMASK_IBM(36,36) 208 + #define MQPCB_DLID_AL EHCA_BMASK_IBM(16,31) 209 + #define MQPCB_MASK_RNR_RETRY_COUNT_AL EHCA_BMASK_IBM(37,37) 210 + #define MQPCB_RNR_RETRY_COUNT_AL EHCA_BMASK_IBM(29,31) 211 + #define MQPCB_MASK_SOURCE_PATH_BITS_AL EHCA_BMASK_IBM(38,38) 212 + #define MQPCB_SOURCE_PATH_BITS_AL EHCA_BMASK_IBM(25,31) 213 + #define MQPCB_MASK_TRAFFIC_CLASS_AL EHCA_BMASK_IBM(39,39) 214 + #define MQPCB_TRAFFIC_CLASS_AL EHCA_BMASK_IBM(24,31) 215 + #define MQPCB_MASK_HOP_LIMIT_AL EHCA_BMASK_IBM(40,40) 216 + #define MQPCB_HOP_LIMIT_AL EHCA_BMASK_IBM(24,31) 217 + #define MQPCB_MASK_SOURCE_GID_IDX_AL EHCA_BMASK_IBM(41,41) 218 + #define MQPCB_SOURCE_GID_IDX_AL EHCA_BMASK_IBM(24,31) 219 + #define MQPCB_MASK_FLOW_LABEL_AL EHCA_BMASK_IBM(42,42) 220 + #define MQPCB_FLOW_LABEL_AL EHCA_BMASK_IBM(12,31) 221 + #define MQPCB_MASK_DEST_GID_AL EHCA_BMASK_IBM(44,44) 222 + #define MQPCB_MASK_MAX_NR_OUTST_SEND_WR EHCA_BMASK_IBM(45,45) 223 + #define MQPCB_MAX_NR_OUTST_SEND_WR EHCA_BMASK_IBM(16,31) 224 + #define MQPCB_MASK_MAX_NR_OUTST_RECV_WR EHCA_BMASK_IBM(46,46) 225 + #define MQPCB_MAX_NR_OUTST_RECV_WR EHCA_BMASK_IBM(16,31) 226 + #define MQPCB_MASK_DISABLE_ETE_CREDIT_CHECK EHCA_BMASK_IBM(47,47) 227 + #define MQPCB_DISABLE_ETE_CREDIT_CHECK EHCA_BMASK_IBM(31,31) 228 + #define MQPCB_QP_NUMBER EHCA_BMASK_IBM(8,31) 229 + #define MQPCB_MASK_QP_ENABLE EHCA_BMASK_IBM(48,48) 230 + #define MQPCB_QP_ENABLE EHCA_BMASK_IBM(31,31) 231 + #define MQPCB_MASK_CURR_SQR_LIMIT EHCA_BMASK_IBM(49,49) 232 + #define MQPCB_CURR_SQR_LIMIT EHCA_BMASK_IBM(15,31) 233 + #define MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG EHCA_BMASK_IBM(50,50) 234 + #define MQPCB_MASK_SHARED_RQ_HNDL EHCA_BMASK_IBM(51,51) 235 + 236 + #endif /* __EHCA_CLASSES_PSERIES_H__ */
+427
drivers/infiniband/hw/ehca/ehca_cq.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * Completion queue handling 5 + * 6 + * Authors: Waleri Fomin <fomin@de.ibm.com> 7 + * Khadija Souissi <souissi@de.ibm.com> 8 + * Reinhard Ernst <rernst@de.ibm.com> 9 + * Heiko J Schick <schickhj@de.ibm.com> 10 + * Hoang-Nam Nguyen <hnguyen@de.ibm.com> 11 + * 12 + * 13 + * Copyright (c) 2005 IBM Corporation 14 + * 15 + * All rights reserved. 16 + * 17 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 18 + * BSD. 19 + * 20 + * OpenIB BSD License 21 + * 22 + * Redistribution and use in source and binary forms, with or without 23 + * modification, are permitted provided that the following conditions are met: 24 + * 25 + * Redistributions of source code must retain the above copyright notice, this 26 + * list of conditions and the following disclaimer. 27 + * 28 + * Redistributions in binary form must reproduce the above copyright notice, 29 + * this list of conditions and the following disclaimer in the documentation 30 + * and/or other materials 31 + * provided with the distribution. 32 + * 33 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 34 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 36 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 37 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 38 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 39 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 40 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 41 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 42 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 43 + * POSSIBILITY OF SUCH DAMAGE. 44 + */ 45 + 46 + #include <asm/current.h> 47 + 48 + #include "ehca_iverbs.h" 49 + #include "ehca_classes.h" 50 + #include "ehca_irq.h" 51 + #include "hcp_if.h" 52 + 53 + static struct kmem_cache *cq_cache; 54 + 55 + int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp) 56 + { 57 + unsigned int qp_num = qp->real_qp_num; 58 + unsigned int key = qp_num & (QP_HASHTAB_LEN-1); 59 + unsigned long spl_flags; 60 + 61 + spin_lock_irqsave(&cq->spinlock, spl_flags); 62 + hlist_add_head(&qp->list_entries, &cq->qp_hashtab[key]); 63 + spin_unlock_irqrestore(&cq->spinlock, spl_flags); 64 + 65 + ehca_dbg(cq->ib_cq.device, "cq_num=%x real_qp_num=%x", 66 + cq->cq_number, qp_num); 67 + 68 + return 0; 69 + } 70 + 71 + int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num) 72 + { 73 + int ret = -EINVAL; 74 + unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1); 75 + struct hlist_node *iter; 76 + struct ehca_qp *qp; 77 + unsigned long spl_flags; 78 + 79 + spin_lock_irqsave(&cq->spinlock, spl_flags); 80 + hlist_for_each(iter, &cq->qp_hashtab[key]) { 81 + qp = hlist_entry(iter, struct ehca_qp, list_entries); 82 + if (qp->real_qp_num == real_qp_num) { 83 + hlist_del(iter); 84 + ehca_dbg(cq->ib_cq.device, 85 + "removed qp from cq .cq_num=%x real_qp_num=%x", 86 + cq->cq_number, real_qp_num); 87 + ret = 0; 88 + break; 89 + } 90 + } 91 + spin_unlock_irqrestore(&cq->spinlock, spl_flags); 92 + if (ret) 93 + ehca_err(cq->ib_cq.device, 94 + "qp not found cq_num=%x real_qp_num=%x", 95 + cq->cq_number, real_qp_num); 96 + 97 + return ret; 98 + } 99 + 100 + struct ehca_qp* ehca_cq_get_qp(struct ehca_cq *cq, int real_qp_num) 101 + { 102 + struct ehca_qp *ret = NULL; 103 + unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1); 104 + struct hlist_node *iter; 105 + struct ehca_qp *qp; 106 + hlist_for_each(iter, &cq->qp_hashtab[key]) { 107 + qp = hlist_entry(iter, struct ehca_qp, list_entries); 108 + if (qp->real_qp_num == real_qp_num) { 109 + ret = qp; 110 + break; 111 + } 112 + } 113 + return ret; 114 + } 115 + 116 + struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, 117 + struct ib_ucontext *context, 118 + struct ib_udata *udata) 119 + { 120 + static const u32 additional_cqe = 20; 121 + struct ib_cq *cq; 122 + struct ehca_cq *my_cq; 123 + struct ehca_shca *shca = 124 + container_of(device, struct ehca_shca, ib_device); 125 + struct ipz_adapter_handle adapter_handle; 126 + struct ehca_alloc_cq_parms param; /* h_call's out parameters */ 127 + struct h_galpa gal; 128 + void *vpage; 129 + u32 counter; 130 + u64 rpage, cqx_fec, h_ret; 131 + int ipz_rc, ret, i; 132 + unsigned long flags; 133 + 134 + if (cqe >= 0xFFFFFFFF - 64 - additional_cqe) 135 + return ERR_PTR(-EINVAL); 136 + 137 + my_cq = kmem_cache_alloc(cq_cache, SLAB_KERNEL); 138 + if (!my_cq) { 139 + ehca_err(device, "Out of memory for ehca_cq struct device=%p", 140 + device); 141 + return ERR_PTR(-ENOMEM); 142 + } 143 + 144 + memset(my_cq, 0, sizeof(struct ehca_cq)); 145 + memset(&param, 0, sizeof(struct ehca_alloc_cq_parms)); 146 + 147 + spin_lock_init(&my_cq->spinlock); 148 + spin_lock_init(&my_cq->cb_lock); 149 + spin_lock_init(&my_cq->task_lock); 150 + my_cq->ownpid = current->tgid; 151 + 152 + cq = &my_cq->ib_cq; 153 + 154 + adapter_handle = shca->ipz_hca_handle; 155 + param.eq_handle = shca->eq.ipz_eq_handle; 156 + 157 + do { 158 + if (!idr_pre_get(&ehca_cq_idr, GFP_KERNEL)) { 159 + cq = ERR_PTR(-ENOMEM); 160 + ehca_err(device, "Can't reserve idr nr. device=%p", 161 + device); 162 + goto create_cq_exit1; 163 + } 164 + 165 + spin_lock_irqsave(&ehca_cq_idr_lock, flags); 166 + ret = idr_get_new(&ehca_cq_idr, my_cq, &my_cq->token); 167 + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); 168 + 169 + } while (ret == -EAGAIN); 170 + 171 + if (ret) { 172 + cq = ERR_PTR(-ENOMEM); 173 + ehca_err(device, "Can't allocate new idr entry. device=%p", 174 + device); 175 + goto create_cq_exit1; 176 + } 177 + 178 + /* 179 + * CQs maximum depth is 4GB-64, but we need additional 20 as buffer 180 + * for receiving errors CQEs. 181 + */ 182 + param.nr_cqe = cqe + additional_cqe; 183 + h_ret = hipz_h_alloc_resource_cq(adapter_handle, my_cq, &param); 184 + 185 + if (h_ret != H_SUCCESS) { 186 + ehca_err(device, "hipz_h_alloc_resource_cq() failed " 187 + "h_ret=%lx device=%p", h_ret, device); 188 + cq = ERR_PTR(ehca2ib_return_code(h_ret)); 189 + goto create_cq_exit2; 190 + } 191 + 192 + ipz_rc = ipz_queue_ctor(&my_cq->ipz_queue, param.act_pages, 193 + EHCA_PAGESIZE, sizeof(struct ehca_cqe), 0); 194 + if (!ipz_rc) { 195 + ehca_err(device, "ipz_queue_ctor() failed ipz_rc=%x device=%p", 196 + ipz_rc, device); 197 + cq = ERR_PTR(-EINVAL); 198 + goto create_cq_exit3; 199 + } 200 + 201 + for (counter = 0; counter < param.act_pages; counter++) { 202 + vpage = ipz_qpageit_get_inc(&my_cq->ipz_queue); 203 + if (!vpage) { 204 + ehca_err(device, "ipz_qpageit_get_inc() " 205 + "returns NULL device=%p", device); 206 + cq = ERR_PTR(-EAGAIN); 207 + goto create_cq_exit4; 208 + } 209 + rpage = virt_to_abs(vpage); 210 + 211 + h_ret = hipz_h_register_rpage_cq(adapter_handle, 212 + my_cq->ipz_cq_handle, 213 + &my_cq->pf, 214 + 0, 215 + 0, 216 + rpage, 217 + 1, 218 + my_cq->galpas. 219 + kernel); 220 + 221 + if (h_ret < H_SUCCESS) { 222 + ehca_err(device, "hipz_h_register_rpage_cq() failed " 223 + "ehca_cq=%p cq_num=%x h_ret=%lx counter=%i " 224 + "act_pages=%i", my_cq, my_cq->cq_number, 225 + h_ret, counter, param.act_pages); 226 + cq = ERR_PTR(-EINVAL); 227 + goto create_cq_exit4; 228 + } 229 + 230 + if (counter == (param.act_pages - 1)) { 231 + vpage = ipz_qpageit_get_inc(&my_cq->ipz_queue); 232 + if ((h_ret != H_SUCCESS) || vpage) { 233 + ehca_err(device, "Registration of pages not " 234 + "complete ehca_cq=%p cq_num=%x " 235 + "h_ret=%lx", my_cq, my_cq->cq_number, 236 + h_ret); 237 + cq = ERR_PTR(-EAGAIN); 238 + goto create_cq_exit4; 239 + } 240 + } else { 241 + if (h_ret != H_PAGE_REGISTERED) { 242 + ehca_err(device, "Registration of page failed " 243 + "ehca_cq=%p cq_num=%x h_ret=%lx" 244 + "counter=%i act_pages=%i", 245 + my_cq, my_cq->cq_number, 246 + h_ret, counter, param.act_pages); 247 + cq = ERR_PTR(-ENOMEM); 248 + goto create_cq_exit4; 249 + } 250 + } 251 + } 252 + 253 + ipz_qeit_reset(&my_cq->ipz_queue); 254 + 255 + gal = my_cq->galpas.kernel; 256 + cqx_fec = hipz_galpa_load(gal, CQTEMM_OFFSET(cqx_fec)); 257 + ehca_dbg(device, "ehca_cq=%p cq_num=%x CQX_FEC=%lx", 258 + my_cq, my_cq->cq_number, cqx_fec); 259 + 260 + my_cq->ib_cq.cqe = my_cq->nr_of_entries = 261 + param.act_nr_of_entries - additional_cqe; 262 + my_cq->cq_number = (my_cq->ipz_cq_handle.handle) & 0xffff; 263 + 264 + for (i = 0; i < QP_HASHTAB_LEN; i++) 265 + INIT_HLIST_HEAD(&my_cq->qp_hashtab[i]); 266 + 267 + if (context) { 268 + struct ipz_queue *ipz_queue = &my_cq->ipz_queue; 269 + struct ehca_create_cq_resp resp; 270 + struct vm_area_struct *vma; 271 + memset(&resp, 0, sizeof(resp)); 272 + resp.cq_number = my_cq->cq_number; 273 + resp.token = my_cq->token; 274 + resp.ipz_queue.qe_size = ipz_queue->qe_size; 275 + resp.ipz_queue.act_nr_of_sg = ipz_queue->act_nr_of_sg; 276 + resp.ipz_queue.queue_length = ipz_queue->queue_length; 277 + resp.ipz_queue.pagesize = ipz_queue->pagesize; 278 + resp.ipz_queue.toggle_state = ipz_queue->toggle_state; 279 + ret = ehca_mmap_nopage(((u64)(my_cq->token) << 32) | 0x12000000, 280 + ipz_queue->queue_length, 281 + (void**)&resp.ipz_queue.queue, 282 + &vma); 283 + if (ret) { 284 + ehca_err(device, "Could not mmap queue pages"); 285 + cq = ERR_PTR(ret); 286 + goto create_cq_exit4; 287 + } 288 + my_cq->uspace_queue = resp.ipz_queue.queue; 289 + resp.galpas = my_cq->galpas; 290 + ret = ehca_mmap_register(my_cq->galpas.user.fw_handle, 291 + (void**)&resp.galpas.kernel.fw_handle, 292 + &vma); 293 + if (ret) { 294 + ehca_err(device, "Could not mmap fw_handle"); 295 + cq = ERR_PTR(ret); 296 + goto create_cq_exit5; 297 + } 298 + my_cq->uspace_fwh = (u64)resp.galpas.kernel.fw_handle; 299 + if (ib_copy_to_udata(udata, &resp, sizeof(resp))) { 300 + ehca_err(device, "Copy to udata failed."); 301 + goto create_cq_exit6; 302 + } 303 + } 304 + 305 + return cq; 306 + 307 + create_cq_exit6: 308 + ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE); 309 + 310 + create_cq_exit5: 311 + ehca_munmap(my_cq->uspace_queue, my_cq->ipz_queue.queue_length); 312 + 313 + create_cq_exit4: 314 + ipz_queue_dtor(&my_cq->ipz_queue); 315 + 316 + create_cq_exit3: 317 + h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 1); 318 + if (h_ret != H_SUCCESS) 319 + ehca_err(device, "hipz_h_destroy_cq() failed ehca_cq=%p " 320 + "cq_num=%x h_ret=%lx", my_cq, my_cq->cq_number, h_ret); 321 + 322 + create_cq_exit2: 323 + spin_lock_irqsave(&ehca_cq_idr_lock, flags); 324 + idr_remove(&ehca_cq_idr, my_cq->token); 325 + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); 326 + 327 + create_cq_exit1: 328 + kmem_cache_free(cq_cache, my_cq); 329 + 330 + return cq; 331 + } 332 + 333 + int ehca_destroy_cq(struct ib_cq *cq) 334 + { 335 + u64 h_ret; 336 + int ret; 337 + struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); 338 + int cq_num = my_cq->cq_number; 339 + struct ib_device *device = cq->device; 340 + struct ehca_shca *shca = container_of(device, struct ehca_shca, 341 + ib_device); 342 + struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle; 343 + u32 cur_pid = current->tgid; 344 + unsigned long flags; 345 + 346 + spin_lock_irqsave(&ehca_cq_idr_lock, flags); 347 + while (my_cq->nr_callbacks) 348 + yield(); 349 + 350 + idr_remove(&ehca_cq_idr, my_cq->token); 351 + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); 352 + 353 + if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) { 354 + ehca_err(device, "Invalid caller pid=%x ownpid=%x", 355 + cur_pid, my_cq->ownpid); 356 + return -EINVAL; 357 + } 358 + 359 + /* un-mmap if vma alloc */ 360 + if (my_cq->uspace_queue ) { 361 + ret = ehca_munmap(my_cq->uspace_queue, 362 + my_cq->ipz_queue.queue_length); 363 + if (ret) 364 + ehca_err(device, "Could not munmap queue ehca_cq=%p " 365 + "cq_num=%x", my_cq, cq_num); 366 + ret = ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE); 367 + if (ret) 368 + ehca_err(device, "Could not munmap fwh ehca_cq=%p " 369 + "cq_num=%x", my_cq, cq_num); 370 + } 371 + 372 + h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0); 373 + if (h_ret == H_R_STATE) { 374 + /* cq in err: read err data and destroy it forcibly */ 375 + ehca_dbg(device, "ehca_cq=%p cq_num=%x ressource=%lx in err " 376 + "state. Try to delete it forcibly.", 377 + my_cq, cq_num, my_cq->ipz_cq_handle.handle); 378 + ehca_error_data(shca, my_cq, my_cq->ipz_cq_handle.handle); 379 + h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 1); 380 + if (h_ret == H_SUCCESS) 381 + ehca_dbg(device, "cq_num=%x deleted successfully.", 382 + cq_num); 383 + } 384 + if (h_ret != H_SUCCESS) { 385 + ehca_err(device, "hipz_h_destroy_cq() failed h_ret=%lx " 386 + "ehca_cq=%p cq_num=%x", h_ret, my_cq, cq_num); 387 + return ehca2ib_return_code(h_ret); 388 + } 389 + ipz_queue_dtor(&my_cq->ipz_queue); 390 + kmem_cache_free(cq_cache, my_cq); 391 + 392 + return 0; 393 + } 394 + 395 + int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata) 396 + { 397 + struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); 398 + u32 cur_pid = current->tgid; 399 + 400 + if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) { 401 + ehca_err(cq->device, "Invalid caller pid=%x ownpid=%x", 402 + cur_pid, my_cq->ownpid); 403 + return -EINVAL; 404 + } 405 + 406 + /* TODO: proper resize needs to be done */ 407 + ehca_err(cq->device, "not implemented yet"); 408 + 409 + return -EFAULT; 410 + } 411 + 412 + int ehca_init_cq_cache(void) 413 + { 414 + cq_cache = kmem_cache_create("ehca_cache_cq", 415 + sizeof(struct ehca_cq), 0, 416 + SLAB_HWCACHE_ALIGN, 417 + NULL, NULL); 418 + if (!cq_cache) 419 + return -ENOMEM; 420 + return 0; 421 + } 422 + 423 + void ehca_cleanup_cq_cache(void) 424 + { 425 + if (cq_cache) 426 + kmem_cache_destroy(cq_cache); 427 + }
+185
drivers/infiniband/hw/ehca/ehca_eq.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * Event queue handling 5 + * 6 + * Authors: Waleri Fomin <fomin@de.ibm.com> 7 + * Khadija Souissi <souissi@de.ibm.com> 8 + * Reinhard Ernst <rernst@de.ibm.com> 9 + * Heiko J Schick <schickhj@de.ibm.com> 10 + * Hoang-Nam Nguyen <hnguyen@de.ibm.com> 11 + * 12 + * 13 + * Copyright (c) 2005 IBM Corporation 14 + * 15 + * All rights reserved. 16 + * 17 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 18 + * BSD. 19 + * 20 + * OpenIB BSD License 21 + * 22 + * Redistribution and use in source and binary forms, with or without 23 + * modification, are permitted provided that the following conditions are met: 24 + * 25 + * Redistributions of source code must retain the above copyright notice, this 26 + * list of conditions and the following disclaimer. 27 + * 28 + * Redistributions in binary form must reproduce the above copyright notice, 29 + * this list of conditions and the following disclaimer in the documentation 30 + * and/or other materials 31 + * provided with the distribution. 32 + * 33 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 34 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 36 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 37 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 38 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 39 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 40 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 41 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 42 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 43 + * POSSIBILITY OF SUCH DAMAGE. 44 + */ 45 + 46 + #include "ehca_classes.h" 47 + #include "ehca_irq.h" 48 + #include "ehca_iverbs.h" 49 + #include "ehca_qes.h" 50 + #include "hcp_if.h" 51 + #include "ipz_pt_fn.h" 52 + 53 + int ehca_create_eq(struct ehca_shca *shca, 54 + struct ehca_eq *eq, 55 + const enum ehca_eq_type type, const u32 length) 56 + { 57 + u64 ret; 58 + u32 nr_pages; 59 + u32 i; 60 + void *vpage; 61 + struct ib_device *ib_dev = &shca->ib_device; 62 + 63 + spin_lock_init(&eq->spinlock); 64 + eq->is_initialized = 0; 65 + 66 + if (type != EHCA_EQ && type != EHCA_NEQ) { 67 + ehca_err(ib_dev, "Invalid EQ type %x. eq=%p", type, eq); 68 + return -EINVAL; 69 + } 70 + if (!length) { 71 + ehca_err(ib_dev, "EQ length must not be zero. eq=%p", eq); 72 + return -EINVAL; 73 + } 74 + 75 + ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle, 76 + &eq->pf, 77 + type, 78 + length, 79 + &eq->ipz_eq_handle, 80 + &eq->length, 81 + &nr_pages, &eq->ist); 82 + 83 + if (ret != H_SUCCESS) { 84 + ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p", eq); 85 + return -EINVAL; 86 + } 87 + 88 + ret = ipz_queue_ctor(&eq->ipz_queue, nr_pages, 89 + EHCA_PAGESIZE, sizeof(struct ehca_eqe), 0); 90 + if (!ret) { 91 + ehca_err(ib_dev, "Can't allocate EQ pages eq=%p", eq); 92 + goto create_eq_exit1; 93 + } 94 + 95 + for (i = 0; i < nr_pages; i++) { 96 + u64 rpage; 97 + 98 + if (!(vpage = ipz_qpageit_get_inc(&eq->ipz_queue))) { 99 + ret = H_RESOURCE; 100 + goto create_eq_exit2; 101 + } 102 + 103 + rpage = virt_to_abs(vpage); 104 + ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle, 105 + eq->ipz_eq_handle, 106 + &eq->pf, 107 + 0, 0, rpage, 1); 108 + 109 + if (i == (nr_pages - 1)) { 110 + /* last page */ 111 + vpage = ipz_qpageit_get_inc(&eq->ipz_queue); 112 + if (ret != H_SUCCESS || vpage) 113 + goto create_eq_exit2; 114 + } else { 115 + if (ret != H_PAGE_REGISTERED || !vpage) 116 + goto create_eq_exit2; 117 + } 118 + } 119 + 120 + ipz_qeit_reset(&eq->ipz_queue); 121 + 122 + /* register interrupt handlers and initialize work queues */ 123 + if (type == EHCA_EQ) { 124 + ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_eq, 125 + SA_INTERRUPT, "ehca_eq", 126 + (void *)shca); 127 + if (ret < 0) 128 + ehca_err(ib_dev, "Can't map interrupt handler."); 129 + 130 + tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca); 131 + } else if (type == EHCA_NEQ) { 132 + ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_neq, 133 + SA_INTERRUPT, "ehca_neq", 134 + (void *)shca); 135 + if (ret < 0) 136 + ehca_err(ib_dev, "Can't map interrupt handler."); 137 + 138 + tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca); 139 + } 140 + 141 + eq->is_initialized = 1; 142 + 143 + return 0; 144 + 145 + create_eq_exit2: 146 + ipz_queue_dtor(&eq->ipz_queue); 147 + 148 + create_eq_exit1: 149 + hipz_h_destroy_eq(shca->ipz_hca_handle, eq); 150 + 151 + return -EINVAL; 152 + } 153 + 154 + void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq) 155 + { 156 + unsigned long flags; 157 + void *eqe; 158 + 159 + spin_lock_irqsave(&eq->spinlock, flags); 160 + eqe = ipz_eqit_eq_get_inc_valid(&eq->ipz_queue); 161 + spin_unlock_irqrestore(&eq->spinlock, flags); 162 + 163 + return eqe; 164 + } 165 + 166 + int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq) 167 + { 168 + unsigned long flags; 169 + u64 h_ret; 170 + 171 + spin_lock_irqsave(&eq->spinlock, flags); 172 + ibmebus_free_irq(NULL, eq->ist, (void *)shca); 173 + 174 + h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq); 175 + 176 + spin_unlock_irqrestore(&eq->spinlock, flags); 177 + 178 + if (h_ret != H_SUCCESS) { 179 + ehca_err(&shca->ib_device, "Can't free EQ resources."); 180 + return -EINVAL; 181 + } 182 + ipz_queue_dtor(&eq->ipz_queue); 183 + 184 + return 0; 185 + }
+241
drivers/infiniband/hw/ehca/ehca_hca.c
··· 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 "hcp_if.h" 44 + 45 + int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) 46 + { 47 + int ret = 0; 48 + struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, 49 + ib_device); 50 + struct hipz_query_hca *rblock; 51 + 52 + rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); 53 + if (!rblock) { 54 + ehca_err(&shca->ib_device, "Can't allocate rblock memory."); 55 + return -ENOMEM; 56 + } 57 + 58 + if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { 59 + ehca_err(&shca->ib_device, "Can't query device properties"); 60 + ret = -EINVAL; 61 + goto query_device1; 62 + } 63 + 64 + memset(props, 0, sizeof(struct ib_device_attr)); 65 + props->fw_ver = rblock->hw_ver; 66 + props->max_mr_size = rblock->max_mr_size; 67 + props->vendor_id = rblock->vendor_id >> 8; 68 + props->vendor_part_id = rblock->vendor_part_id >> 16; 69 + props->hw_ver = rblock->hw_ver; 70 + props->max_qp = min_t(int, rblock->max_qp, INT_MAX); 71 + props->max_qp_wr = min_t(int, rblock->max_wqes_wq, INT_MAX); 72 + props->max_sge = min_t(int, rblock->max_sge, INT_MAX); 73 + props->max_sge_rd = min_t(int, rblock->max_sge_rd, INT_MAX); 74 + props->max_cq = min_t(int, rblock->max_cq, INT_MAX); 75 + props->max_cqe = min_t(int, rblock->max_cqe, INT_MAX); 76 + props->max_mr = min_t(int, rblock->max_mr, INT_MAX); 77 + props->max_mw = min_t(int, rblock->max_mw, INT_MAX); 78 + props->max_pd = min_t(int, rblock->max_pd, INT_MAX); 79 + props->max_ah = min_t(int, rblock->max_ah, INT_MAX); 80 + props->max_fmr = min_t(int, rblock->max_mr, INT_MAX); 81 + props->max_srq = 0; 82 + props->max_srq_wr = 0; 83 + props->max_srq_sge = 0; 84 + props->max_pkeys = 16; 85 + props->local_ca_ack_delay 86 + = rblock->local_ca_ack_delay; 87 + props->max_raw_ipv6_qp 88 + = min_t(int, rblock->max_raw_ipv6_qp, INT_MAX); 89 + props->max_raw_ethy_qp 90 + = min_t(int, rblock->max_raw_ethy_qp, INT_MAX); 91 + props->max_mcast_grp 92 + = min_t(int, rblock->max_mcast_grp, INT_MAX); 93 + props->max_mcast_qp_attach 94 + = min_t(int, rblock->max_mcast_qp_attach, INT_MAX); 95 + props->max_total_mcast_qp_attach 96 + = min_t(int, rblock->max_total_mcast_qp_attach, INT_MAX); 97 + 98 + query_device1: 99 + kfree(rblock); 100 + 101 + return ret; 102 + } 103 + 104 + int ehca_query_port(struct ib_device *ibdev, 105 + u8 port, struct ib_port_attr *props) 106 + { 107 + int ret = 0; 108 + struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, 109 + ib_device); 110 + struct hipz_query_port *rblock; 111 + 112 + rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); 113 + if (!rblock) { 114 + ehca_err(&shca->ib_device, "Can't allocate rblock memory."); 115 + return -ENOMEM; 116 + } 117 + 118 + if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) { 119 + ehca_err(&shca->ib_device, "Can't query port properties"); 120 + ret = -EINVAL; 121 + goto query_port1; 122 + } 123 + 124 + memset(props, 0, sizeof(struct ib_port_attr)); 125 + props->state = rblock->state; 126 + 127 + switch (rblock->max_mtu) { 128 + case 0x1: 129 + props->active_mtu = props->max_mtu = IB_MTU_256; 130 + break; 131 + case 0x2: 132 + props->active_mtu = props->max_mtu = IB_MTU_512; 133 + break; 134 + case 0x3: 135 + props->active_mtu = props->max_mtu = IB_MTU_1024; 136 + break; 137 + case 0x4: 138 + props->active_mtu = props->max_mtu = IB_MTU_2048; 139 + break; 140 + case 0x5: 141 + props->active_mtu = props->max_mtu = IB_MTU_4096; 142 + break; 143 + default: 144 + ehca_err(&shca->ib_device, "Unknown MTU size: %x.", 145 + rblock->max_mtu); 146 + break; 147 + } 148 + 149 + props->gid_tbl_len = rblock->gid_tbl_len; 150 + props->max_msg_sz = rblock->max_msg_sz; 151 + props->bad_pkey_cntr = rblock->bad_pkey_cntr; 152 + props->qkey_viol_cntr = rblock->qkey_viol_cntr; 153 + props->pkey_tbl_len = rblock->pkey_tbl_len; 154 + props->lid = rblock->lid; 155 + props->sm_lid = rblock->sm_lid; 156 + props->lmc = rblock->lmc; 157 + props->sm_sl = rblock->sm_sl; 158 + props->subnet_timeout = rblock->subnet_timeout; 159 + props->init_type_reply = rblock->init_type_reply; 160 + 161 + props->active_width = IB_WIDTH_12X; 162 + props->active_speed = 0x1; 163 + 164 + query_port1: 165 + kfree(rblock); 166 + 167 + return ret; 168 + } 169 + 170 + int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) 171 + { 172 + int ret = 0; 173 + struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, ib_device); 174 + struct hipz_query_port *rblock; 175 + 176 + if (index > 16) { 177 + ehca_err(&shca->ib_device, "Invalid index: %x.", index); 178 + return -EINVAL; 179 + } 180 + 181 + rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); 182 + if (!rblock) { 183 + ehca_err(&shca->ib_device, "Can't allocate rblock memory."); 184 + return -ENOMEM; 185 + } 186 + 187 + if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) { 188 + ehca_err(&shca->ib_device, "Can't query port properties"); 189 + ret = -EINVAL; 190 + goto query_pkey1; 191 + } 192 + 193 + memcpy(pkey, &rblock->pkey_entries + index, sizeof(u16)); 194 + 195 + query_pkey1: 196 + kfree(rblock); 197 + 198 + return ret; 199 + } 200 + 201 + int ehca_query_gid(struct ib_device *ibdev, u8 port, 202 + int index, union ib_gid *gid) 203 + { 204 + int ret = 0; 205 + struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, 206 + ib_device); 207 + struct hipz_query_port *rblock; 208 + 209 + if (index > 255) { 210 + ehca_err(&shca->ib_device, "Invalid index: %x.", index); 211 + return -EINVAL; 212 + } 213 + 214 + rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); 215 + if (!rblock) { 216 + ehca_err(&shca->ib_device, "Can't allocate rblock memory."); 217 + return -ENOMEM; 218 + } 219 + 220 + if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) { 221 + ehca_err(&shca->ib_device, "Can't query port properties"); 222 + ret = -EINVAL; 223 + goto query_gid1; 224 + } 225 + 226 + memcpy(&gid->raw[0], &rblock->gid_prefix, sizeof(u64)); 227 + memcpy(&gid->raw[8], &rblock->guid_entries[index], sizeof(u64)); 228 + 229 + query_gid1: 230 + kfree(rblock); 231 + 232 + return ret; 233 + } 234 + 235 + int ehca_modify_port(struct ib_device *ibdev, 236 + u8 port, int port_modify_mask, 237 + struct ib_port_modify *props) 238 + { 239 + /* Not implemented yet */ 240 + return -EFAULT; 241 + }
+762
drivers/infiniband/hw/ehca/ehca_irq.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * Functions for EQs, NEQs and interrupts 5 + * 6 + * Authors: Heiko J Schick <schickhj@de.ibm.com> 7 + * Khadija Souissi <souissi@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_classes.h" 43 + #include "ehca_irq.h" 44 + #include "ehca_iverbs.h" 45 + #include "ehca_tools.h" 46 + #include "hcp_if.h" 47 + #include "hipz_fns.h" 48 + 49 + #define EQE_COMPLETION_EVENT EHCA_BMASK_IBM(1,1) 50 + #define EQE_CQ_QP_NUMBER EHCA_BMASK_IBM(8,31) 51 + #define EQE_EE_IDENTIFIER EHCA_BMASK_IBM(2,7) 52 + #define EQE_CQ_NUMBER EHCA_BMASK_IBM(8,31) 53 + #define EQE_QP_NUMBER EHCA_BMASK_IBM(8,31) 54 + #define EQE_QP_TOKEN EHCA_BMASK_IBM(32,63) 55 + #define EQE_CQ_TOKEN EHCA_BMASK_IBM(32,63) 56 + 57 + #define NEQE_COMPLETION_EVENT EHCA_BMASK_IBM(1,1) 58 + #define NEQE_EVENT_CODE EHCA_BMASK_IBM(2,7) 59 + #define NEQE_PORT_NUMBER EHCA_BMASK_IBM(8,15) 60 + #define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16,16) 61 + 62 + #define ERROR_DATA_LENGTH EHCA_BMASK_IBM(52,63) 63 + #define ERROR_DATA_TYPE EHCA_BMASK_IBM(0,7) 64 + 65 + #ifdef CONFIG_INFINIBAND_EHCA_SCALING 66 + 67 + static void queue_comp_task(struct ehca_cq *__cq); 68 + 69 + static struct ehca_comp_pool* pool; 70 + static struct notifier_block comp_pool_callback_nb; 71 + 72 + #endif 73 + 74 + static inline void comp_event_callback(struct ehca_cq *cq) 75 + { 76 + if (!cq->ib_cq.comp_handler) 77 + return; 78 + 79 + spin_lock(&cq->cb_lock); 80 + cq->ib_cq.comp_handler(&cq->ib_cq, cq->ib_cq.cq_context); 81 + spin_unlock(&cq->cb_lock); 82 + 83 + return; 84 + } 85 + 86 + static void print_error_data(struct ehca_shca * shca, void* data, 87 + u64* rblock, int length) 88 + { 89 + u64 type = EHCA_BMASK_GET(ERROR_DATA_TYPE, rblock[2]); 90 + u64 resource = rblock[1]; 91 + 92 + switch (type) { 93 + case 0x1: /* Queue Pair */ 94 + { 95 + struct ehca_qp *qp = (struct ehca_qp*)data; 96 + 97 + /* only print error data if AER is set */ 98 + if (rblock[6] == 0) 99 + return; 100 + 101 + ehca_err(&shca->ib_device, 102 + "QP 0x%x (resource=%lx) has errors.", 103 + qp->ib_qp.qp_num, resource); 104 + break; 105 + } 106 + case 0x4: /* Completion Queue */ 107 + { 108 + struct ehca_cq *cq = (struct ehca_cq*)data; 109 + 110 + ehca_err(&shca->ib_device, 111 + "CQ 0x%x (resource=%lx) has errors.", 112 + cq->cq_number, resource); 113 + break; 114 + } 115 + default: 116 + ehca_err(&shca->ib_device, 117 + "Unknown errror type: %lx on %s.", 118 + type, shca->ib_device.name); 119 + break; 120 + } 121 + 122 + ehca_err(&shca->ib_device, "Error data is available: %lx.", resource); 123 + ehca_err(&shca->ib_device, "EHCA ----- error data begin " 124 + "---------------------------------------------------"); 125 + ehca_dmp(rblock, length, "resource=%lx", resource); 126 + ehca_err(&shca->ib_device, "EHCA ----- error data end " 127 + "----------------------------------------------------"); 128 + 129 + return; 130 + } 131 + 132 + int ehca_error_data(struct ehca_shca *shca, void *data, 133 + u64 resource) 134 + { 135 + 136 + unsigned long ret; 137 + u64 *rblock; 138 + unsigned long block_count; 139 + 140 + rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); 141 + if (!rblock) { 142 + ehca_err(&shca->ib_device, "Cannot allocate rblock memory."); 143 + ret = -ENOMEM; 144 + goto error_data1; 145 + } 146 + 147 + ret = hipz_h_error_data(shca->ipz_hca_handle, 148 + resource, 149 + rblock, 150 + &block_count); 151 + 152 + if (ret == H_R_STATE) { 153 + ehca_err(&shca->ib_device, 154 + "No error data is available: %lx.", resource); 155 + } 156 + else if (ret == H_SUCCESS) { 157 + int length; 158 + 159 + length = EHCA_BMASK_GET(ERROR_DATA_LENGTH, rblock[0]); 160 + 161 + if (length > PAGE_SIZE) 162 + length = PAGE_SIZE; 163 + 164 + print_error_data(shca, data, rblock, length); 165 + } 166 + else { 167 + ehca_err(&shca->ib_device, 168 + "Error data could not be fetched: %lx", resource); 169 + } 170 + 171 + kfree(rblock); 172 + 173 + error_data1: 174 + return ret; 175 + 176 + } 177 + 178 + static void qp_event_callback(struct ehca_shca *shca, 179 + u64 eqe, 180 + enum ib_event_type event_type) 181 + { 182 + struct ib_event event; 183 + struct ehca_qp *qp; 184 + unsigned long flags; 185 + u32 token = EHCA_BMASK_GET(EQE_QP_TOKEN, eqe); 186 + 187 + spin_lock_irqsave(&ehca_qp_idr_lock, flags); 188 + qp = idr_find(&ehca_qp_idr, token); 189 + spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); 190 + 191 + 192 + if (!qp) 193 + return; 194 + 195 + ehca_error_data(shca, qp, qp->ipz_qp_handle.handle); 196 + 197 + if (!qp->ib_qp.event_handler) 198 + return; 199 + 200 + event.device = &shca->ib_device; 201 + event.event = event_type; 202 + event.element.qp = &qp->ib_qp; 203 + 204 + qp->ib_qp.event_handler(&event, qp->ib_qp.qp_context); 205 + 206 + return; 207 + } 208 + 209 + static void cq_event_callback(struct ehca_shca *shca, 210 + u64 eqe) 211 + { 212 + struct ehca_cq *cq; 213 + unsigned long flags; 214 + u32 token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe); 215 + 216 + spin_lock_irqsave(&ehca_cq_idr_lock, flags); 217 + cq = idr_find(&ehca_cq_idr, token); 218 + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); 219 + 220 + if (!cq) 221 + return; 222 + 223 + ehca_error_data(shca, cq, cq->ipz_cq_handle.handle); 224 + 225 + return; 226 + } 227 + 228 + static void parse_identifier(struct ehca_shca *shca, u64 eqe) 229 + { 230 + u8 identifier = EHCA_BMASK_GET(EQE_EE_IDENTIFIER, eqe); 231 + 232 + switch (identifier) { 233 + case 0x02: /* path migrated */ 234 + qp_event_callback(shca, eqe, IB_EVENT_PATH_MIG); 235 + break; 236 + case 0x03: /* communication established */ 237 + qp_event_callback(shca, eqe, IB_EVENT_COMM_EST); 238 + break; 239 + case 0x04: /* send queue drained */ 240 + qp_event_callback(shca, eqe, IB_EVENT_SQ_DRAINED); 241 + break; 242 + case 0x05: /* QP error */ 243 + case 0x06: /* QP error */ 244 + qp_event_callback(shca, eqe, IB_EVENT_QP_FATAL); 245 + break; 246 + case 0x07: /* CQ error */ 247 + case 0x08: /* CQ error */ 248 + cq_event_callback(shca, eqe); 249 + break; 250 + case 0x09: /* MRMWPTE error */ 251 + ehca_err(&shca->ib_device, "MRMWPTE error."); 252 + break; 253 + case 0x0A: /* port event */ 254 + ehca_err(&shca->ib_device, "Port event."); 255 + break; 256 + case 0x0B: /* MR access error */ 257 + ehca_err(&shca->ib_device, "MR access error."); 258 + break; 259 + case 0x0C: /* EQ error */ 260 + ehca_err(&shca->ib_device, "EQ error."); 261 + break; 262 + case 0x0D: /* P/Q_Key mismatch */ 263 + ehca_err(&shca->ib_device, "P/Q_Key mismatch."); 264 + break; 265 + case 0x10: /* sampling complete */ 266 + ehca_err(&shca->ib_device, "Sampling complete."); 267 + break; 268 + case 0x11: /* unaffiliated access error */ 269 + ehca_err(&shca->ib_device, "Unaffiliated access error."); 270 + break; 271 + case 0x12: /* path migrating error */ 272 + ehca_err(&shca->ib_device, "Path migration error."); 273 + break; 274 + case 0x13: /* interface trace stopped */ 275 + ehca_err(&shca->ib_device, "Interface trace stopped."); 276 + break; 277 + case 0x14: /* first error capture info available */ 278 + default: 279 + ehca_err(&shca->ib_device, "Unknown identifier: %x on %s.", 280 + identifier, shca->ib_device.name); 281 + break; 282 + } 283 + 284 + return; 285 + } 286 + 287 + static void parse_ec(struct ehca_shca *shca, u64 eqe) 288 + { 289 + struct ib_event event; 290 + u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); 291 + u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); 292 + 293 + switch (ec) { 294 + case 0x30: /* port availability change */ 295 + if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { 296 + ehca_info(&shca->ib_device, 297 + "port %x is active.", port); 298 + event.device = &shca->ib_device; 299 + event.event = IB_EVENT_PORT_ACTIVE; 300 + event.element.port_num = port; 301 + shca->sport[port - 1].port_state = IB_PORT_ACTIVE; 302 + ib_dispatch_event(&event); 303 + } else { 304 + ehca_info(&shca->ib_device, 305 + "port %x is inactive.", port); 306 + event.device = &shca->ib_device; 307 + event.event = IB_EVENT_PORT_ERR; 308 + event.element.port_num = port; 309 + shca->sport[port - 1].port_state = IB_PORT_DOWN; 310 + ib_dispatch_event(&event); 311 + } 312 + break; 313 + case 0x31: 314 + /* port configuration change 315 + * disruptive change is caused by 316 + * LID, PKEY or SM change 317 + */ 318 + ehca_warn(&shca->ib_device, 319 + "disruptive port %x configuration change", port); 320 + 321 + ehca_info(&shca->ib_device, 322 + "port %x is inactive.", port); 323 + event.device = &shca->ib_device; 324 + event.event = IB_EVENT_PORT_ERR; 325 + event.element.port_num = port; 326 + shca->sport[port - 1].port_state = IB_PORT_DOWN; 327 + ib_dispatch_event(&event); 328 + 329 + ehca_info(&shca->ib_device, 330 + "port %x is active.", port); 331 + event.device = &shca->ib_device; 332 + event.event = IB_EVENT_PORT_ACTIVE; 333 + event.element.port_num = port; 334 + shca->sport[port - 1].port_state = IB_PORT_ACTIVE; 335 + ib_dispatch_event(&event); 336 + break; 337 + case 0x32: /* adapter malfunction */ 338 + ehca_err(&shca->ib_device, "Adapter malfunction."); 339 + break; 340 + case 0x33: /* trace stopped */ 341 + ehca_err(&shca->ib_device, "Traced stopped."); 342 + break; 343 + default: 344 + ehca_err(&shca->ib_device, "Unknown event code: %x on %s.", 345 + ec, shca->ib_device.name); 346 + break; 347 + } 348 + 349 + return; 350 + } 351 + 352 + static inline void reset_eq_pending(struct ehca_cq *cq) 353 + { 354 + u64 CQx_EP; 355 + struct h_galpa gal = cq->galpas.kernel; 356 + 357 + hipz_galpa_store_cq(gal, cqx_ep, 0x0); 358 + CQx_EP = hipz_galpa_load(gal, CQTEMM_OFFSET(cqx_ep)); 359 + 360 + return; 361 + } 362 + 363 + irqreturn_t ehca_interrupt_neq(int irq, void *dev_id, struct pt_regs *regs) 364 + { 365 + struct ehca_shca *shca = (struct ehca_shca*)dev_id; 366 + 367 + tasklet_hi_schedule(&shca->neq.interrupt_task); 368 + 369 + return IRQ_HANDLED; 370 + } 371 + 372 + void ehca_tasklet_neq(unsigned long data) 373 + { 374 + struct ehca_shca *shca = (struct ehca_shca*)data; 375 + struct ehca_eqe *eqe; 376 + u64 ret; 377 + 378 + eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->neq); 379 + 380 + while (eqe) { 381 + if (!EHCA_BMASK_GET(NEQE_COMPLETION_EVENT, eqe->entry)) 382 + parse_ec(shca, eqe->entry); 383 + 384 + eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->neq); 385 + } 386 + 387 + ret = hipz_h_reset_event(shca->ipz_hca_handle, 388 + shca->neq.ipz_eq_handle, 0xFFFFFFFFFFFFFFFFL); 389 + 390 + if (ret != H_SUCCESS) 391 + ehca_err(&shca->ib_device, "Can't clear notification events."); 392 + 393 + return; 394 + } 395 + 396 + irqreturn_t ehca_interrupt_eq(int irq, void *dev_id, struct pt_regs *regs) 397 + { 398 + struct ehca_shca *shca = (struct ehca_shca*)dev_id; 399 + 400 + tasklet_hi_schedule(&shca->eq.interrupt_task); 401 + 402 + return IRQ_HANDLED; 403 + } 404 + 405 + void ehca_tasklet_eq(unsigned long data) 406 + { 407 + struct ehca_shca *shca = (struct ehca_shca*)data; 408 + struct ehca_eqe *eqe; 409 + int int_state; 410 + int query_cnt = 0; 411 + 412 + do { 413 + eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq); 414 + 415 + if ((shca->hw_level >= 2) && eqe) 416 + int_state = 1; 417 + else 418 + int_state = 0; 419 + 420 + while ((int_state == 1) || eqe) { 421 + while (eqe) { 422 + u64 eqe_value = eqe->entry; 423 + 424 + ehca_dbg(&shca->ib_device, 425 + "eqe_value=%lx", eqe_value); 426 + 427 + /* TODO: better structure */ 428 + if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, 429 + eqe_value)) { 430 + unsigned long flags; 431 + u32 token; 432 + struct ehca_cq *cq; 433 + 434 + ehca_dbg(&shca->ib_device, 435 + "... completion event"); 436 + token = 437 + EHCA_BMASK_GET(EQE_CQ_TOKEN, 438 + eqe_value); 439 + spin_lock_irqsave(&ehca_cq_idr_lock, 440 + flags); 441 + cq = idr_find(&ehca_cq_idr, token); 442 + 443 + if (cq == NULL) { 444 + spin_unlock(&ehca_cq_idr_lock); 445 + break; 446 + } 447 + 448 + reset_eq_pending(cq); 449 + #ifdef CONFIG_INFINIBAND_EHCA_SCALING 450 + queue_comp_task(cq); 451 + spin_unlock_irqrestore(&ehca_cq_idr_lock, 452 + flags); 453 + #else 454 + spin_unlock_irqrestore(&ehca_cq_idr_lock, 455 + flags); 456 + comp_event_callback(cq); 457 + #endif 458 + } else { 459 + ehca_dbg(&shca->ib_device, 460 + "... non completion event"); 461 + parse_identifier(shca, eqe_value); 462 + } 463 + eqe = 464 + (struct ehca_eqe *)ehca_poll_eq(shca, 465 + &shca->eq); 466 + } 467 + 468 + if (shca->hw_level >= 2) { 469 + int_state = 470 + hipz_h_query_int_state(shca->ipz_hca_handle, 471 + shca->eq.ist); 472 + query_cnt++; 473 + iosync(); 474 + if (query_cnt >= 100) { 475 + query_cnt = 0; 476 + int_state = 0; 477 + } 478 + } 479 + eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq); 480 + 481 + } 482 + } while (int_state != 0); 483 + 484 + return; 485 + } 486 + 487 + #ifdef CONFIG_INFINIBAND_EHCA_SCALING 488 + 489 + static inline int find_next_online_cpu(struct ehca_comp_pool* pool) 490 + { 491 + unsigned long flags_last_cpu; 492 + 493 + if (ehca_debug_level) 494 + ehca_dmp(&cpu_online_map, sizeof(cpumask_t), ""); 495 + 496 + spin_lock_irqsave(&pool->last_cpu_lock, flags_last_cpu); 497 + pool->last_cpu = next_cpu(pool->last_cpu, cpu_online_map); 498 + if (pool->last_cpu == NR_CPUS) 499 + pool->last_cpu = first_cpu(cpu_online_map); 500 + spin_unlock_irqrestore(&pool->last_cpu_lock, flags_last_cpu); 501 + 502 + return pool->last_cpu; 503 + } 504 + 505 + static void __queue_comp_task(struct ehca_cq *__cq, 506 + struct ehca_cpu_comp_task *cct) 507 + { 508 + unsigned long flags_cct; 509 + unsigned long flags_cq; 510 + 511 + spin_lock_irqsave(&cct->task_lock, flags_cct); 512 + spin_lock_irqsave(&__cq->task_lock, flags_cq); 513 + 514 + if (__cq->nr_callbacks == 0) { 515 + __cq->nr_callbacks++; 516 + list_add_tail(&__cq->entry, &cct->cq_list); 517 + cct->cq_jobs++; 518 + wake_up(&cct->wait_queue); 519 + } 520 + else 521 + __cq->nr_callbacks++; 522 + 523 + spin_unlock_irqrestore(&__cq->task_lock, flags_cq); 524 + spin_unlock_irqrestore(&cct->task_lock, flags_cct); 525 + } 526 + 527 + static void queue_comp_task(struct ehca_cq *__cq) 528 + { 529 + int cpu; 530 + int cpu_id; 531 + struct ehca_cpu_comp_task *cct; 532 + 533 + cpu = get_cpu(); 534 + cpu_id = find_next_online_cpu(pool); 535 + 536 + BUG_ON(!cpu_online(cpu_id)); 537 + 538 + cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id); 539 + 540 + if (cct->cq_jobs > 0) { 541 + cpu_id = find_next_online_cpu(pool); 542 + cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id); 543 + } 544 + 545 + __queue_comp_task(__cq, cct); 546 + 547 + put_cpu(); 548 + 549 + return; 550 + } 551 + 552 + static void run_comp_task(struct ehca_cpu_comp_task* cct) 553 + { 554 + struct ehca_cq *cq; 555 + unsigned long flags_cct; 556 + unsigned long flags_cq; 557 + 558 + spin_lock_irqsave(&cct->task_lock, flags_cct); 559 + 560 + while (!list_empty(&cct->cq_list)) { 561 + cq = list_entry(cct->cq_list.next, struct ehca_cq, entry); 562 + spin_unlock_irqrestore(&cct->task_lock, flags_cct); 563 + comp_event_callback(cq); 564 + spin_lock_irqsave(&cct->task_lock, flags_cct); 565 + 566 + spin_lock_irqsave(&cq->task_lock, flags_cq); 567 + cq->nr_callbacks--; 568 + if (cq->nr_callbacks == 0) { 569 + list_del_init(cct->cq_list.next); 570 + cct->cq_jobs--; 571 + } 572 + spin_unlock_irqrestore(&cq->task_lock, flags_cq); 573 + 574 + } 575 + 576 + spin_unlock_irqrestore(&cct->task_lock, flags_cct); 577 + 578 + return; 579 + } 580 + 581 + static int comp_task(void *__cct) 582 + { 583 + struct ehca_cpu_comp_task* cct = __cct; 584 + DECLARE_WAITQUEUE(wait, current); 585 + 586 + set_current_state(TASK_INTERRUPTIBLE); 587 + while(!kthread_should_stop()) { 588 + add_wait_queue(&cct->wait_queue, &wait); 589 + 590 + if (list_empty(&cct->cq_list)) 591 + schedule(); 592 + else 593 + __set_current_state(TASK_RUNNING); 594 + 595 + remove_wait_queue(&cct->wait_queue, &wait); 596 + 597 + if (!list_empty(&cct->cq_list)) 598 + run_comp_task(__cct); 599 + 600 + set_current_state(TASK_INTERRUPTIBLE); 601 + } 602 + __set_current_state(TASK_RUNNING); 603 + 604 + return 0; 605 + } 606 + 607 + static struct task_struct *create_comp_task(struct ehca_comp_pool *pool, 608 + int cpu) 609 + { 610 + struct ehca_cpu_comp_task *cct; 611 + 612 + cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); 613 + spin_lock_init(&cct->task_lock); 614 + INIT_LIST_HEAD(&cct->cq_list); 615 + init_waitqueue_head(&cct->wait_queue); 616 + cct->task = kthread_create(comp_task, cct, "ehca_comp/%d", cpu); 617 + 618 + return cct->task; 619 + } 620 + 621 + static void destroy_comp_task(struct ehca_comp_pool *pool, 622 + int cpu) 623 + { 624 + struct ehca_cpu_comp_task *cct; 625 + struct task_struct *task; 626 + unsigned long flags_cct; 627 + 628 + cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); 629 + 630 + spin_lock_irqsave(&cct->task_lock, flags_cct); 631 + 632 + task = cct->task; 633 + cct->task = NULL; 634 + cct->cq_jobs = 0; 635 + 636 + spin_unlock_irqrestore(&cct->task_lock, flags_cct); 637 + 638 + if (task) 639 + kthread_stop(task); 640 + 641 + return; 642 + } 643 + 644 + static void take_over_work(struct ehca_comp_pool *pool, 645 + int cpu) 646 + { 647 + struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); 648 + LIST_HEAD(list); 649 + struct ehca_cq *cq; 650 + unsigned long flags_cct; 651 + 652 + spin_lock_irqsave(&cct->task_lock, flags_cct); 653 + 654 + list_splice_init(&cct->cq_list, &list); 655 + 656 + while(!list_empty(&list)) { 657 + cq = list_entry(cct->cq_list.next, struct ehca_cq, entry); 658 + 659 + list_del(&cq->entry); 660 + __queue_comp_task(cq, per_cpu_ptr(pool->cpu_comp_tasks, 661 + smp_processor_id())); 662 + } 663 + 664 + spin_unlock_irqrestore(&cct->task_lock, flags_cct); 665 + 666 + } 667 + 668 + static int comp_pool_callback(struct notifier_block *nfb, 669 + unsigned long action, 670 + void *hcpu) 671 + { 672 + unsigned int cpu = (unsigned long)hcpu; 673 + struct ehca_cpu_comp_task *cct; 674 + 675 + switch (action) { 676 + case CPU_UP_PREPARE: 677 + ehca_gen_dbg("CPU: %x (CPU_PREPARE)", cpu); 678 + if(!create_comp_task(pool, cpu)) { 679 + ehca_gen_err("Can't create comp_task for cpu: %x", cpu); 680 + return NOTIFY_BAD; 681 + } 682 + break; 683 + case CPU_UP_CANCELED: 684 + ehca_gen_dbg("CPU: %x (CPU_CANCELED)", cpu); 685 + cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); 686 + kthread_bind(cct->task, any_online_cpu(cpu_online_map)); 687 + destroy_comp_task(pool, cpu); 688 + break; 689 + case CPU_ONLINE: 690 + ehca_gen_dbg("CPU: %x (CPU_ONLINE)", cpu); 691 + cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); 692 + kthread_bind(cct->task, cpu); 693 + wake_up_process(cct->task); 694 + break; 695 + case CPU_DOWN_PREPARE: 696 + ehca_gen_dbg("CPU: %x (CPU_DOWN_PREPARE)", cpu); 697 + break; 698 + case CPU_DOWN_FAILED: 699 + ehca_gen_dbg("CPU: %x (CPU_DOWN_FAILED)", cpu); 700 + break; 701 + case CPU_DEAD: 702 + ehca_gen_dbg("CPU: %x (CPU_DEAD)", cpu); 703 + destroy_comp_task(pool, cpu); 704 + take_over_work(pool, cpu); 705 + break; 706 + } 707 + 708 + return NOTIFY_OK; 709 + } 710 + 711 + #endif 712 + 713 + int ehca_create_comp_pool(void) 714 + { 715 + #ifdef CONFIG_INFINIBAND_EHCA_SCALING 716 + int cpu; 717 + struct task_struct *task; 718 + 719 + pool = kzalloc(sizeof(struct ehca_comp_pool), GFP_KERNEL); 720 + if (pool == NULL) 721 + return -ENOMEM; 722 + 723 + spin_lock_init(&pool->last_cpu_lock); 724 + pool->last_cpu = any_online_cpu(cpu_online_map); 725 + 726 + pool->cpu_comp_tasks = alloc_percpu(struct ehca_cpu_comp_task); 727 + if (pool->cpu_comp_tasks == NULL) { 728 + kfree(pool); 729 + return -EINVAL; 730 + } 731 + 732 + for_each_online_cpu(cpu) { 733 + task = create_comp_task(pool, cpu); 734 + if (task) { 735 + kthread_bind(task, cpu); 736 + wake_up_process(task); 737 + } 738 + } 739 + 740 + comp_pool_callback_nb.notifier_call = comp_pool_callback; 741 + comp_pool_callback_nb.priority =0; 742 + register_cpu_notifier(&comp_pool_callback_nb); 743 + #endif 744 + 745 + return 0; 746 + } 747 + 748 + void ehca_destroy_comp_pool(void) 749 + { 750 + #ifdef CONFIG_INFINIBAND_EHCA_SCALING 751 + int i; 752 + 753 + unregister_cpu_notifier(&comp_pool_callback_nb); 754 + 755 + for (i = 0; i < NR_CPUS; i++) { 756 + if (cpu_online(i)) 757 + destroy_comp_task(pool, i); 758 + } 759 + #endif 760 + 761 + return; 762 + }
+77
drivers/infiniband/hw/ehca/ehca_irq.h
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * Function definitions and structs for EQs, NEQs and interrupts 5 + * 6 + * Authors: Heiko J Schick <schickhj@de.ibm.com> 7 + * Khadija Souissi <souissi@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 + #ifndef __EHCA_IRQ_H 43 + #define __EHCA_IRQ_H 44 + 45 + 46 + struct ehca_shca; 47 + 48 + #include <linux/interrupt.h> 49 + #include <linux/types.h> 50 + #include <asm/atomic.h> 51 + 52 + int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource); 53 + 54 + irqreturn_t ehca_interrupt_neq(int irq, void *dev_id, struct pt_regs *regs); 55 + void ehca_tasklet_neq(unsigned long data); 56 + 57 + irqreturn_t ehca_interrupt_eq(int irq, void *dev_id, struct pt_regs *regs); 58 + void ehca_tasklet_eq(unsigned long data); 59 + 60 + struct ehca_cpu_comp_task { 61 + wait_queue_head_t wait_queue; 62 + struct list_head cq_list; 63 + struct task_struct *task; 64 + spinlock_t task_lock; 65 + int cq_jobs; 66 + }; 67 + 68 + struct ehca_comp_pool { 69 + struct ehca_cpu_comp_task *cpu_comp_tasks; 70 + int last_cpu; 71 + spinlock_t last_cpu_lock; 72 + }; 73 + 74 + int ehca_create_comp_pool(void); 75 + void ehca_destroy_comp_pool(void); 76 + 77 + #endif
+181
drivers/infiniband/hw/ehca/ehca_iverbs.h
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * Function definitions for internal functions 5 + * 6 + * Authors: Heiko J Schick <schickhj@de.ibm.com> 7 + * Dietmar Decker <ddecker@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 + #ifndef __EHCA_IVERBS_H__ 43 + #define __EHCA_IVERBS_H__ 44 + 45 + #include "ehca_classes.h" 46 + 47 + int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props); 48 + 49 + int ehca_query_port(struct ib_device *ibdev, u8 port, 50 + struct ib_port_attr *props); 51 + 52 + int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 * pkey); 53 + 54 + int ehca_query_gid(struct ib_device *ibdev, u8 port, int index, 55 + union ib_gid *gid); 56 + 57 + int ehca_modify_port(struct ib_device *ibdev, u8 port, int port_modify_mask, 58 + struct ib_port_modify *props); 59 + 60 + struct ib_pd *ehca_alloc_pd(struct ib_device *device, 61 + struct ib_ucontext *context, 62 + struct ib_udata *udata); 63 + 64 + int ehca_dealloc_pd(struct ib_pd *pd); 65 + 66 + struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr); 67 + 68 + int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr); 69 + 70 + int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr); 71 + 72 + int ehca_destroy_ah(struct ib_ah *ah); 73 + 74 + struct ib_mr *ehca_get_dma_mr(struct ib_pd *pd, int mr_access_flags); 75 + 76 + struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd, 77 + struct ib_phys_buf *phys_buf_array, 78 + int num_phys_buf, 79 + int mr_access_flags, u64 *iova_start); 80 + 81 + struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, 82 + struct ib_umem *region, 83 + int mr_access_flags, struct ib_udata *udata); 84 + 85 + int ehca_rereg_phys_mr(struct ib_mr *mr, 86 + int mr_rereg_mask, 87 + struct ib_pd *pd, 88 + struct ib_phys_buf *phys_buf_array, 89 + int num_phys_buf, int mr_access_flags, u64 *iova_start); 90 + 91 + int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr); 92 + 93 + int ehca_dereg_mr(struct ib_mr *mr); 94 + 95 + struct ib_mw *ehca_alloc_mw(struct ib_pd *pd); 96 + 97 + int ehca_bind_mw(struct ib_qp *qp, struct ib_mw *mw, 98 + struct ib_mw_bind *mw_bind); 99 + 100 + int ehca_dealloc_mw(struct ib_mw *mw); 101 + 102 + struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd, 103 + int mr_access_flags, 104 + struct ib_fmr_attr *fmr_attr); 105 + 106 + int ehca_map_phys_fmr(struct ib_fmr *fmr, 107 + u64 *page_list, int list_len, u64 iova); 108 + 109 + int ehca_unmap_fmr(struct list_head *fmr_list); 110 + 111 + int ehca_dealloc_fmr(struct ib_fmr *fmr); 112 + 113 + enum ehca_eq_type { 114 + EHCA_EQ = 0, /* Event Queue */ 115 + EHCA_NEQ /* Notification Event Queue */ 116 + }; 117 + 118 + int ehca_create_eq(struct ehca_shca *shca, struct ehca_eq *eq, 119 + enum ehca_eq_type type, const u32 length); 120 + 121 + int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq); 122 + 123 + void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq); 124 + 125 + 126 + struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, 127 + struct ib_ucontext *context, 128 + struct ib_udata *udata); 129 + 130 + int ehca_destroy_cq(struct ib_cq *cq); 131 + 132 + int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata); 133 + 134 + int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc); 135 + 136 + int ehca_peek_cq(struct ib_cq *cq, int wc_cnt); 137 + 138 + int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify cq_notify); 139 + 140 + struct ib_qp *ehca_create_qp(struct ib_pd *pd, 141 + struct ib_qp_init_attr *init_attr, 142 + struct ib_udata *udata); 143 + 144 + int ehca_destroy_qp(struct ib_qp *qp); 145 + 146 + int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask); 147 + 148 + int ehca_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr, 149 + int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr); 150 + 151 + int ehca_post_send(struct ib_qp *qp, struct ib_send_wr *send_wr, 152 + struct ib_send_wr **bad_send_wr); 153 + 154 + int ehca_post_recv(struct ib_qp *qp, struct ib_recv_wr *recv_wr, 155 + struct ib_recv_wr **bad_recv_wr); 156 + 157 + u64 ehca_define_sqp(struct ehca_shca *shca, struct ehca_qp *ibqp, 158 + struct ib_qp_init_attr *qp_init_attr); 159 + 160 + int ehca_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid); 161 + 162 + int ehca_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid); 163 + 164 + struct ib_ucontext *ehca_alloc_ucontext(struct ib_device *device, 165 + struct ib_udata *udata); 166 + 167 + int ehca_dealloc_ucontext(struct ib_ucontext *context); 168 + 169 + int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); 170 + 171 + void ehca_poll_eqs(unsigned long data); 172 + 173 + int ehca_mmap_nopage(u64 foffset,u64 length,void **mapped, 174 + struct vm_area_struct **vma); 175 + 176 + int ehca_mmap_register(u64 physical,void **mapped, 177 + struct vm_area_struct **vma); 178 + 179 + int ehca_munmap(unsigned long addr, size_t len); 180 + 181 + #endif
+818
drivers/infiniband/hw/ehca/ehca_main.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * module start stop, hca detection 5 + * 6 + * Authors: Heiko J Schick <schickhj@de.ibm.com> 7 + * Hoang-Nam Nguyen <hnguyen@de.ibm.com> 8 + * Joachim Fenkes <fenkes@de.ibm.com> 9 + * 10 + * Copyright (c) 2005 IBM Corporation 11 + * 12 + * All rights reserved. 13 + * 14 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 15 + * BSD. 16 + * 17 + * OpenIB BSD License 18 + * 19 + * Redistribution and use in source and binary forms, with or without 20 + * modification, are permitted provided that the following conditions are met: 21 + * 22 + * Redistributions of source code must retain the above copyright notice, this 23 + * list of conditions and the following disclaimer. 24 + * 25 + * Redistributions in binary form must reproduce the above copyright notice, 26 + * this list of conditions and the following disclaimer in the documentation 27 + * and/or other materials 28 + * provided with the distribution. 29 + * 30 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 31 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 34 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 37 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 38 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 + * POSSIBILITY OF SUCH DAMAGE. 41 + */ 42 + 43 + #include "ehca_classes.h" 44 + #include "ehca_iverbs.h" 45 + #include "ehca_mrmw.h" 46 + #include "ehca_tools.h" 47 + #include "hcp_if.h" 48 + 49 + MODULE_LICENSE("Dual BSD/GPL"); 50 + MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>"); 51 + MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); 52 + MODULE_VERSION("SVNEHCA_0016"); 53 + 54 + int ehca_open_aqp1 = 0; 55 + int ehca_debug_level = 0; 56 + int ehca_hw_level = 0; 57 + int ehca_nr_ports = 2; 58 + int ehca_use_hp_mr = 0; 59 + int ehca_port_act_time = 30; 60 + int ehca_poll_all_eqs = 1; 61 + int ehca_static_rate = -1; 62 + 63 + module_param_named(open_aqp1, ehca_open_aqp1, int, 0); 64 + module_param_named(debug_level, ehca_debug_level, int, 0); 65 + module_param_named(hw_level, ehca_hw_level, int, 0); 66 + module_param_named(nr_ports, ehca_nr_ports, int, 0); 67 + module_param_named(use_hp_mr, ehca_use_hp_mr, int, 0); 68 + module_param_named(port_act_time, ehca_port_act_time, int, 0); 69 + module_param_named(poll_all_eqs, ehca_poll_all_eqs, int, 0); 70 + module_param_named(static_rate, ehca_static_rate, int, 0); 71 + 72 + MODULE_PARM_DESC(open_aqp1, 73 + "AQP1 on startup (0: no (default), 1: yes)"); 74 + MODULE_PARM_DESC(debug_level, 75 + "debug level" 76 + " (0: no debug traces (default), 1: with debug traces)"); 77 + MODULE_PARM_DESC(hw_level, 78 + "hardware level" 79 + " (0: autosensing (default), 1: v. 0.20, 2: v. 0.21)"); 80 + MODULE_PARM_DESC(nr_ports, 81 + "number of connected ports (default: 2)"); 82 + MODULE_PARM_DESC(use_hp_mr, 83 + "high performance MRs (0: no (default), 1: yes)"); 84 + MODULE_PARM_DESC(port_act_time, 85 + "time to wait for port activation (default: 30 sec)"); 86 + MODULE_PARM_DESC(poll_all_eqs, 87 + "polls all event queues periodically" 88 + " (0: no, 1: yes (default))"); 89 + MODULE_PARM_DESC(static_rate, 90 + "set permanent static rate (default: disabled)"); 91 + 92 + spinlock_t ehca_qp_idr_lock; 93 + spinlock_t ehca_cq_idr_lock; 94 + DEFINE_IDR(ehca_qp_idr); 95 + DEFINE_IDR(ehca_cq_idr); 96 + 97 + static struct list_head shca_list; /* list of all registered ehcas */ 98 + static spinlock_t shca_list_lock; 99 + 100 + static struct timer_list poll_eqs_timer; 101 + 102 + static int ehca_create_slab_caches(void) 103 + { 104 + int ret; 105 + 106 + ret = ehca_init_pd_cache(); 107 + if (ret) { 108 + ehca_gen_err("Cannot create PD SLAB cache."); 109 + return ret; 110 + } 111 + 112 + ret = ehca_init_cq_cache(); 113 + if (ret) { 114 + ehca_gen_err("Cannot create CQ SLAB cache."); 115 + goto create_slab_caches2; 116 + } 117 + 118 + ret = ehca_init_qp_cache(); 119 + if (ret) { 120 + ehca_gen_err("Cannot create QP SLAB cache."); 121 + goto create_slab_caches3; 122 + } 123 + 124 + ret = ehca_init_av_cache(); 125 + if (ret) { 126 + ehca_gen_err("Cannot create AV SLAB cache."); 127 + goto create_slab_caches4; 128 + } 129 + 130 + ret = ehca_init_mrmw_cache(); 131 + if (ret) { 132 + ehca_gen_err("Cannot create MR&MW SLAB cache."); 133 + goto create_slab_caches5; 134 + } 135 + 136 + return 0; 137 + 138 + create_slab_caches5: 139 + ehca_cleanup_av_cache(); 140 + 141 + create_slab_caches4: 142 + ehca_cleanup_qp_cache(); 143 + 144 + create_slab_caches3: 145 + ehca_cleanup_cq_cache(); 146 + 147 + create_slab_caches2: 148 + ehca_cleanup_pd_cache(); 149 + 150 + return ret; 151 + } 152 + 153 + static void ehca_destroy_slab_caches(void) 154 + { 155 + ehca_cleanup_mrmw_cache(); 156 + ehca_cleanup_av_cache(); 157 + ehca_cleanup_qp_cache(); 158 + ehca_cleanup_cq_cache(); 159 + ehca_cleanup_pd_cache(); 160 + } 161 + 162 + #define EHCA_HCAAVER EHCA_BMASK_IBM(32,39) 163 + #define EHCA_REVID EHCA_BMASK_IBM(40,63) 164 + 165 + int ehca_sense_attributes(struct ehca_shca *shca) 166 + { 167 + int ret = 0; 168 + u64 h_ret; 169 + struct hipz_query_hca *rblock; 170 + 171 + rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); 172 + if (!rblock) { 173 + ehca_gen_err("Cannot allocate rblock memory."); 174 + return -ENOMEM; 175 + } 176 + 177 + h_ret = hipz_h_query_hca(shca->ipz_hca_handle, rblock); 178 + if (h_ret != H_SUCCESS) { 179 + ehca_gen_err("Cannot query device properties. h_ret=%lx", 180 + h_ret); 181 + ret = -EPERM; 182 + goto num_ports1; 183 + } 184 + 185 + if (ehca_nr_ports == 1) 186 + shca->num_ports = 1; 187 + else 188 + shca->num_ports = (u8)rblock->num_ports; 189 + 190 + ehca_gen_dbg(" ... found %x ports", rblock->num_ports); 191 + 192 + if (ehca_hw_level == 0) { 193 + u32 hcaaver; 194 + u32 revid; 195 + 196 + hcaaver = EHCA_BMASK_GET(EHCA_HCAAVER, rblock->hw_ver); 197 + revid = EHCA_BMASK_GET(EHCA_REVID, rblock->hw_ver); 198 + 199 + ehca_gen_dbg(" ... hardware version=%x:%x", hcaaver, revid); 200 + 201 + if ((hcaaver == 1) && (revid == 0)) 202 + shca->hw_level = 0; 203 + else if ((hcaaver == 1) && (revid == 1)) 204 + shca->hw_level = 1; 205 + else if ((hcaaver == 1) && (revid == 2)) 206 + shca->hw_level = 2; 207 + } 208 + ehca_gen_dbg(" ... hardware level=%x", shca->hw_level); 209 + 210 + shca->sport[0].rate = IB_RATE_30_GBPS; 211 + shca->sport[1].rate = IB_RATE_30_GBPS; 212 + 213 + num_ports1: 214 + kfree(rblock); 215 + return ret; 216 + } 217 + 218 + static int init_node_guid(struct ehca_shca *shca) 219 + { 220 + int ret = 0; 221 + struct hipz_query_hca *rblock; 222 + 223 + rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); 224 + if (!rblock) { 225 + ehca_err(&shca->ib_device, "Can't allocate rblock memory."); 226 + return -ENOMEM; 227 + } 228 + 229 + if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { 230 + ehca_err(&shca->ib_device, "Can't query device properties"); 231 + ret = -EINVAL; 232 + goto init_node_guid1; 233 + } 234 + 235 + memcpy(&shca->ib_device.node_guid, &rblock->node_guid, sizeof(u64)); 236 + 237 + init_node_guid1: 238 + kfree(rblock); 239 + return ret; 240 + } 241 + 242 + int ehca_register_device(struct ehca_shca *shca) 243 + { 244 + int ret; 245 + 246 + ret = init_node_guid(shca); 247 + if (ret) 248 + return ret; 249 + 250 + strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX); 251 + shca->ib_device.owner = THIS_MODULE; 252 + 253 + shca->ib_device.uverbs_abi_ver = 5; 254 + shca->ib_device.uverbs_cmd_mask = 255 + (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | 256 + (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | 257 + (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | 258 + (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | 259 + (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | 260 + (1ull << IB_USER_VERBS_CMD_REG_MR) | 261 + (1ull << IB_USER_VERBS_CMD_DEREG_MR) | 262 + (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | 263 + (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | 264 + (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | 265 + (1ull << IB_USER_VERBS_CMD_CREATE_QP) | 266 + (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | 267 + (1ull << IB_USER_VERBS_CMD_QUERY_QP) | 268 + (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | 269 + (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | 270 + (1ull << IB_USER_VERBS_CMD_DETACH_MCAST); 271 + 272 + shca->ib_device.node_type = IB_NODE_CA; 273 + shca->ib_device.phys_port_cnt = shca->num_ports; 274 + shca->ib_device.dma_device = &shca->ibmebus_dev->ofdev.dev; 275 + shca->ib_device.query_device = ehca_query_device; 276 + shca->ib_device.query_port = ehca_query_port; 277 + shca->ib_device.query_gid = ehca_query_gid; 278 + shca->ib_device.query_pkey = ehca_query_pkey; 279 + /* shca->in_device.modify_device = ehca_modify_device */ 280 + shca->ib_device.modify_port = ehca_modify_port; 281 + shca->ib_device.alloc_ucontext = ehca_alloc_ucontext; 282 + shca->ib_device.dealloc_ucontext = ehca_dealloc_ucontext; 283 + shca->ib_device.alloc_pd = ehca_alloc_pd; 284 + shca->ib_device.dealloc_pd = ehca_dealloc_pd; 285 + shca->ib_device.create_ah = ehca_create_ah; 286 + /* shca->ib_device.modify_ah = ehca_modify_ah; */ 287 + shca->ib_device.query_ah = ehca_query_ah; 288 + shca->ib_device.destroy_ah = ehca_destroy_ah; 289 + shca->ib_device.create_qp = ehca_create_qp; 290 + shca->ib_device.modify_qp = ehca_modify_qp; 291 + shca->ib_device.query_qp = ehca_query_qp; 292 + shca->ib_device.destroy_qp = ehca_destroy_qp; 293 + shca->ib_device.post_send = ehca_post_send; 294 + shca->ib_device.post_recv = ehca_post_recv; 295 + shca->ib_device.create_cq = ehca_create_cq; 296 + shca->ib_device.destroy_cq = ehca_destroy_cq; 297 + shca->ib_device.resize_cq = ehca_resize_cq; 298 + shca->ib_device.poll_cq = ehca_poll_cq; 299 + /* shca->ib_device.peek_cq = ehca_peek_cq; */ 300 + shca->ib_device.req_notify_cq = ehca_req_notify_cq; 301 + /* shca->ib_device.req_ncomp_notif = ehca_req_ncomp_notif; */ 302 + shca->ib_device.get_dma_mr = ehca_get_dma_mr; 303 + shca->ib_device.reg_phys_mr = ehca_reg_phys_mr; 304 + shca->ib_device.reg_user_mr = ehca_reg_user_mr; 305 + shca->ib_device.query_mr = ehca_query_mr; 306 + shca->ib_device.dereg_mr = ehca_dereg_mr; 307 + shca->ib_device.rereg_phys_mr = ehca_rereg_phys_mr; 308 + shca->ib_device.alloc_mw = ehca_alloc_mw; 309 + shca->ib_device.bind_mw = ehca_bind_mw; 310 + shca->ib_device.dealloc_mw = ehca_dealloc_mw; 311 + shca->ib_device.alloc_fmr = ehca_alloc_fmr; 312 + shca->ib_device.map_phys_fmr = ehca_map_phys_fmr; 313 + shca->ib_device.unmap_fmr = ehca_unmap_fmr; 314 + shca->ib_device.dealloc_fmr = ehca_dealloc_fmr; 315 + shca->ib_device.attach_mcast = ehca_attach_mcast; 316 + shca->ib_device.detach_mcast = ehca_detach_mcast; 317 + /* shca->ib_device.process_mad = ehca_process_mad; */ 318 + shca->ib_device.mmap = ehca_mmap; 319 + 320 + ret = ib_register_device(&shca->ib_device); 321 + if (ret) 322 + ehca_err(&shca->ib_device, 323 + "ib_register_device() failed ret=%x", ret); 324 + 325 + return ret; 326 + } 327 + 328 + static int ehca_create_aqp1(struct ehca_shca *shca, u32 port) 329 + { 330 + struct ehca_sport *sport = &shca->sport[port - 1]; 331 + struct ib_cq *ibcq; 332 + struct ib_qp *ibqp; 333 + struct ib_qp_init_attr qp_init_attr; 334 + int ret; 335 + 336 + if (sport->ibcq_aqp1) { 337 + ehca_err(&shca->ib_device, "AQP1 CQ is already created."); 338 + return -EPERM; 339 + } 340 + 341 + ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void*)(-1), 10); 342 + if (IS_ERR(ibcq)) { 343 + ehca_err(&shca->ib_device, "Cannot create AQP1 CQ."); 344 + return PTR_ERR(ibcq); 345 + } 346 + sport->ibcq_aqp1 = ibcq; 347 + 348 + if (sport->ibqp_aqp1) { 349 + ehca_err(&shca->ib_device, "AQP1 QP is already created."); 350 + ret = -EPERM; 351 + goto create_aqp1; 352 + } 353 + 354 + memset(&qp_init_attr, 0, sizeof(struct ib_qp_init_attr)); 355 + qp_init_attr.send_cq = ibcq; 356 + qp_init_attr.recv_cq = ibcq; 357 + qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR; 358 + qp_init_attr.cap.max_send_wr = 100; 359 + qp_init_attr.cap.max_recv_wr = 100; 360 + qp_init_attr.cap.max_send_sge = 2; 361 + qp_init_attr.cap.max_recv_sge = 1; 362 + qp_init_attr.qp_type = IB_QPT_GSI; 363 + qp_init_attr.port_num = port; 364 + qp_init_attr.qp_context = NULL; 365 + qp_init_attr.event_handler = NULL; 366 + qp_init_attr.srq = NULL; 367 + 368 + ibqp = ib_create_qp(&shca->pd->ib_pd, &qp_init_attr); 369 + if (IS_ERR(ibqp)) { 370 + ehca_err(&shca->ib_device, "Cannot create AQP1 QP."); 371 + ret = PTR_ERR(ibqp); 372 + goto create_aqp1; 373 + } 374 + sport->ibqp_aqp1 = ibqp; 375 + 376 + return 0; 377 + 378 + create_aqp1: 379 + ib_destroy_cq(sport->ibcq_aqp1); 380 + return ret; 381 + } 382 + 383 + static int ehca_destroy_aqp1(struct ehca_sport *sport) 384 + { 385 + int ret; 386 + 387 + ret = ib_destroy_qp(sport->ibqp_aqp1); 388 + if (ret) { 389 + ehca_gen_err("Cannot destroy AQP1 QP. ret=%x", ret); 390 + return ret; 391 + } 392 + 393 + ret = ib_destroy_cq(sport->ibcq_aqp1); 394 + if (ret) 395 + ehca_gen_err("Cannot destroy AQP1 CQ. ret=%x", ret); 396 + 397 + return ret; 398 + } 399 + 400 + static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf) 401 + { 402 + return snprintf(buf, PAGE_SIZE, "%d\n", 403 + ehca_debug_level); 404 + } 405 + 406 + static ssize_t ehca_store_debug_level(struct device_driver *ddp, 407 + const char *buf, size_t count) 408 + { 409 + int value = (*buf) - '0'; 410 + if (value >= 0 && value <= 9) 411 + ehca_debug_level = value; 412 + return 1; 413 + } 414 + 415 + DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR, 416 + ehca_show_debug_level, ehca_store_debug_level); 417 + 418 + void ehca_create_driver_sysfs(struct ibmebus_driver *drv) 419 + { 420 + driver_create_file(&drv->driver, &driver_attr_debug_level); 421 + } 422 + 423 + void ehca_remove_driver_sysfs(struct ibmebus_driver *drv) 424 + { 425 + driver_remove_file(&drv->driver, &driver_attr_debug_level); 426 + } 427 + 428 + #define EHCA_RESOURCE_ATTR(name) \ 429 + static ssize_t ehca_show_##name(struct device *dev, \ 430 + struct device_attribute *attr, \ 431 + char *buf) \ 432 + { \ 433 + struct ehca_shca *shca; \ 434 + struct hipz_query_hca *rblock; \ 435 + int data; \ 436 + \ 437 + shca = dev->driver_data; \ 438 + \ 439 + rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); \ 440 + if (!rblock) { \ 441 + dev_err(dev, "Can't allocate rblock memory."); \ 442 + return 0; \ 443 + } \ 444 + \ 445 + if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { \ 446 + dev_err(dev, "Can't query device properties"); \ 447 + kfree(rblock); \ 448 + return 0; \ 449 + } \ 450 + \ 451 + data = rblock->name; \ 452 + kfree(rblock); \ 453 + \ 454 + if ((strcmp(#name, "num_ports") == 0) && (ehca_nr_ports == 1)) \ 455 + return snprintf(buf, 256, "1\n"); \ 456 + else \ 457 + return snprintf(buf, 256, "%d\n", data); \ 458 + \ 459 + } \ 460 + static DEVICE_ATTR(name, S_IRUGO, ehca_show_##name, NULL); 461 + 462 + EHCA_RESOURCE_ATTR(num_ports); 463 + EHCA_RESOURCE_ATTR(hw_ver); 464 + EHCA_RESOURCE_ATTR(max_eq); 465 + EHCA_RESOURCE_ATTR(cur_eq); 466 + EHCA_RESOURCE_ATTR(max_cq); 467 + EHCA_RESOURCE_ATTR(cur_cq); 468 + EHCA_RESOURCE_ATTR(max_qp); 469 + EHCA_RESOURCE_ATTR(cur_qp); 470 + EHCA_RESOURCE_ATTR(max_mr); 471 + EHCA_RESOURCE_ATTR(cur_mr); 472 + EHCA_RESOURCE_ATTR(max_mw); 473 + EHCA_RESOURCE_ATTR(cur_mw); 474 + EHCA_RESOURCE_ATTR(max_pd); 475 + EHCA_RESOURCE_ATTR(max_ah); 476 + 477 + static ssize_t ehca_show_adapter_handle(struct device *dev, 478 + struct device_attribute *attr, 479 + char *buf) 480 + { 481 + struct ehca_shca *shca = dev->driver_data; 482 + 483 + return sprintf(buf, "%lx\n", shca->ipz_hca_handle.handle); 484 + 485 + } 486 + static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL); 487 + 488 + 489 + void ehca_create_device_sysfs(struct ibmebus_dev *dev) 490 + { 491 + device_create_file(&dev->ofdev.dev, &dev_attr_adapter_handle); 492 + device_create_file(&dev->ofdev.dev, &dev_attr_num_ports); 493 + device_create_file(&dev->ofdev.dev, &dev_attr_hw_ver); 494 + device_create_file(&dev->ofdev.dev, &dev_attr_max_eq); 495 + device_create_file(&dev->ofdev.dev, &dev_attr_cur_eq); 496 + device_create_file(&dev->ofdev.dev, &dev_attr_max_cq); 497 + device_create_file(&dev->ofdev.dev, &dev_attr_cur_cq); 498 + device_create_file(&dev->ofdev.dev, &dev_attr_max_qp); 499 + device_create_file(&dev->ofdev.dev, &dev_attr_cur_qp); 500 + device_create_file(&dev->ofdev.dev, &dev_attr_max_mr); 501 + device_create_file(&dev->ofdev.dev, &dev_attr_cur_mr); 502 + device_create_file(&dev->ofdev.dev, &dev_attr_max_mw); 503 + device_create_file(&dev->ofdev.dev, &dev_attr_cur_mw); 504 + device_create_file(&dev->ofdev.dev, &dev_attr_max_pd); 505 + device_create_file(&dev->ofdev.dev, &dev_attr_max_ah); 506 + } 507 + 508 + void ehca_remove_device_sysfs(struct ibmebus_dev *dev) 509 + { 510 + device_remove_file(&dev->ofdev.dev, &dev_attr_adapter_handle); 511 + device_remove_file(&dev->ofdev.dev, &dev_attr_num_ports); 512 + device_remove_file(&dev->ofdev.dev, &dev_attr_hw_ver); 513 + device_remove_file(&dev->ofdev.dev, &dev_attr_max_eq); 514 + device_remove_file(&dev->ofdev.dev, &dev_attr_cur_eq); 515 + device_remove_file(&dev->ofdev.dev, &dev_attr_max_cq); 516 + device_remove_file(&dev->ofdev.dev, &dev_attr_cur_cq); 517 + device_remove_file(&dev->ofdev.dev, &dev_attr_max_qp); 518 + device_remove_file(&dev->ofdev.dev, &dev_attr_cur_qp); 519 + device_remove_file(&dev->ofdev.dev, &dev_attr_max_mr); 520 + device_remove_file(&dev->ofdev.dev, &dev_attr_cur_mr); 521 + device_remove_file(&dev->ofdev.dev, &dev_attr_max_mw); 522 + device_remove_file(&dev->ofdev.dev, &dev_attr_cur_mw); 523 + device_remove_file(&dev->ofdev.dev, &dev_attr_max_pd); 524 + device_remove_file(&dev->ofdev.dev, &dev_attr_max_ah); 525 + } 526 + 527 + static int __devinit ehca_probe(struct ibmebus_dev *dev, 528 + const struct of_device_id *id) 529 + { 530 + struct ehca_shca *shca; 531 + u64 *handle; 532 + struct ib_pd *ibpd; 533 + int ret; 534 + 535 + handle = (u64 *)get_property(dev->ofdev.node, "ibm,hca-handle", NULL); 536 + if (!handle) { 537 + ehca_gen_err("Cannot get eHCA handle for adapter: %s.", 538 + dev->ofdev.node->full_name); 539 + return -ENODEV; 540 + } 541 + 542 + if (!(*handle)) { 543 + ehca_gen_err("Wrong eHCA handle for adapter: %s.", 544 + dev->ofdev.node->full_name); 545 + return -ENODEV; 546 + } 547 + 548 + shca = (struct ehca_shca *)ib_alloc_device(sizeof(*shca)); 549 + if (!shca) { 550 + ehca_gen_err("Cannot allocate shca memory."); 551 + return -ENOMEM; 552 + } 553 + 554 + shca->ibmebus_dev = dev; 555 + shca->ipz_hca_handle.handle = *handle; 556 + dev->ofdev.dev.driver_data = shca; 557 + 558 + ret = ehca_sense_attributes(shca); 559 + if (ret < 0) { 560 + ehca_gen_err("Cannot sense eHCA attributes."); 561 + goto probe1; 562 + } 563 + 564 + ret = ehca_register_device(shca); 565 + if (ret) { 566 + ehca_gen_err("Cannot register Infiniband device"); 567 + goto probe1; 568 + } 569 + 570 + /* create event queues */ 571 + ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, 2048); 572 + if (ret) { 573 + ehca_err(&shca->ib_device, "Cannot create EQ."); 574 + goto probe2; 575 + } 576 + 577 + ret = ehca_create_eq(shca, &shca->neq, EHCA_NEQ, 513); 578 + if (ret) { 579 + ehca_err(&shca->ib_device, "Cannot create NEQ."); 580 + goto probe3; 581 + } 582 + 583 + /* create internal protection domain */ 584 + ibpd = ehca_alloc_pd(&shca->ib_device, (void*)(-1), NULL); 585 + if (IS_ERR(ibpd)) { 586 + ehca_err(&shca->ib_device, "Cannot create internal PD."); 587 + ret = PTR_ERR(ibpd); 588 + goto probe4; 589 + } 590 + 591 + shca->pd = container_of(ibpd, struct ehca_pd, ib_pd); 592 + shca->pd->ib_pd.device = &shca->ib_device; 593 + 594 + /* create internal max MR */ 595 + ret = ehca_reg_internal_maxmr(shca, shca->pd, &shca->maxmr); 596 + 597 + if (ret) { 598 + ehca_err(&shca->ib_device, "Cannot create internal MR ret=%x", 599 + ret); 600 + goto probe5; 601 + } 602 + 603 + /* create AQP1 for port 1 */ 604 + if (ehca_open_aqp1 == 1) { 605 + shca->sport[0].port_state = IB_PORT_DOWN; 606 + ret = ehca_create_aqp1(shca, 1); 607 + if (ret) { 608 + ehca_err(&shca->ib_device, 609 + "Cannot create AQP1 for port 1."); 610 + goto probe6; 611 + } 612 + } 613 + 614 + /* create AQP1 for port 2 */ 615 + if ((ehca_open_aqp1 == 1) && (shca->num_ports == 2)) { 616 + shca->sport[1].port_state = IB_PORT_DOWN; 617 + ret = ehca_create_aqp1(shca, 2); 618 + if (ret) { 619 + ehca_err(&shca->ib_device, 620 + "Cannot create AQP1 for port 2."); 621 + goto probe7; 622 + } 623 + } 624 + 625 + ehca_create_device_sysfs(dev); 626 + 627 + spin_lock(&shca_list_lock); 628 + list_add(&shca->shca_list, &shca_list); 629 + spin_unlock(&shca_list_lock); 630 + 631 + return 0; 632 + 633 + probe7: 634 + ret = ehca_destroy_aqp1(&shca->sport[0]); 635 + if (ret) 636 + ehca_err(&shca->ib_device, 637 + "Cannot destroy AQP1 for port 1. ret=%x", ret); 638 + 639 + probe6: 640 + ret = ehca_dereg_internal_maxmr(shca); 641 + if (ret) 642 + ehca_err(&shca->ib_device, 643 + "Cannot destroy internal MR. ret=%x", ret); 644 + 645 + probe5: 646 + ret = ehca_dealloc_pd(&shca->pd->ib_pd); 647 + if (ret) 648 + ehca_err(&shca->ib_device, 649 + "Cannot destroy internal PD. ret=%x", ret); 650 + 651 + probe4: 652 + ret = ehca_destroy_eq(shca, &shca->neq); 653 + if (ret) 654 + ehca_err(&shca->ib_device, 655 + "Cannot destroy NEQ. ret=%x", ret); 656 + 657 + probe3: 658 + ret = ehca_destroy_eq(shca, &shca->eq); 659 + if (ret) 660 + ehca_err(&shca->ib_device, 661 + "Cannot destroy EQ. ret=%x", ret); 662 + 663 + probe2: 664 + ib_unregister_device(&shca->ib_device); 665 + 666 + probe1: 667 + ib_dealloc_device(&shca->ib_device); 668 + 669 + return -EINVAL; 670 + } 671 + 672 + static int __devexit ehca_remove(struct ibmebus_dev *dev) 673 + { 674 + struct ehca_shca *shca = dev->ofdev.dev.driver_data; 675 + int ret; 676 + 677 + ehca_remove_device_sysfs(dev); 678 + 679 + if (ehca_open_aqp1 == 1) { 680 + int i; 681 + for (i = 0; i < shca->num_ports; i++) { 682 + ret = ehca_destroy_aqp1(&shca->sport[i]); 683 + if (ret) 684 + ehca_err(&shca->ib_device, 685 + "Cannot destroy AQP1 for port %x " 686 + "ret=%x", ret, i); 687 + } 688 + } 689 + 690 + ib_unregister_device(&shca->ib_device); 691 + 692 + ret = ehca_dereg_internal_maxmr(shca); 693 + if (ret) 694 + ehca_err(&shca->ib_device, 695 + "Cannot destroy internal MR. ret=%x", ret); 696 + 697 + ret = ehca_dealloc_pd(&shca->pd->ib_pd); 698 + if (ret) 699 + ehca_err(&shca->ib_device, 700 + "Cannot destroy internal PD. ret=%x", ret); 701 + 702 + ret = ehca_destroy_eq(shca, &shca->eq); 703 + if (ret) 704 + ehca_err(&shca->ib_device, "Cannot destroy EQ. ret=%x", ret); 705 + 706 + ret = ehca_destroy_eq(shca, &shca->neq); 707 + if (ret) 708 + ehca_err(&shca->ib_device, "Canot destroy NEQ. ret=%x", ret); 709 + 710 + ib_dealloc_device(&shca->ib_device); 711 + 712 + spin_lock(&shca_list_lock); 713 + list_del(&shca->shca_list); 714 + spin_unlock(&shca_list_lock); 715 + 716 + return ret; 717 + } 718 + 719 + static struct of_device_id ehca_device_table[] = 720 + { 721 + { 722 + .name = "lhca", 723 + .compatible = "IBM,lhca", 724 + }, 725 + {}, 726 + }; 727 + 728 + static struct ibmebus_driver ehca_driver = { 729 + .name = "ehca", 730 + .id_table = ehca_device_table, 731 + .probe = ehca_probe, 732 + .remove = ehca_remove, 733 + }; 734 + 735 + void ehca_poll_eqs(unsigned long data) 736 + { 737 + struct ehca_shca *shca; 738 + 739 + spin_lock(&shca_list_lock); 740 + list_for_each_entry(shca, &shca_list, shca_list) { 741 + if (shca->eq.is_initialized) 742 + ehca_tasklet_eq((unsigned long)(void*)shca); 743 + } 744 + mod_timer(&poll_eqs_timer, jiffies + HZ); 745 + spin_unlock(&shca_list_lock); 746 + } 747 + 748 + int __init ehca_module_init(void) 749 + { 750 + int ret; 751 + 752 + printk(KERN_INFO "eHCA Infiniband Device Driver " 753 + "(Rel.: SVNEHCA_0016)\n"); 754 + idr_init(&ehca_qp_idr); 755 + idr_init(&ehca_cq_idr); 756 + spin_lock_init(&ehca_qp_idr_lock); 757 + spin_lock_init(&ehca_cq_idr_lock); 758 + 759 + INIT_LIST_HEAD(&shca_list); 760 + spin_lock_init(&shca_list_lock); 761 + 762 + if ((ret = ehca_create_comp_pool())) { 763 + ehca_gen_err("Cannot create comp pool."); 764 + return ret; 765 + } 766 + 767 + if ((ret = ehca_create_slab_caches())) { 768 + ehca_gen_err("Cannot create SLAB caches"); 769 + ret = -ENOMEM; 770 + goto module_init1; 771 + } 772 + 773 + if ((ret = ibmebus_register_driver(&ehca_driver))) { 774 + ehca_gen_err("Cannot register eHCA device driver"); 775 + ret = -EINVAL; 776 + goto module_init2; 777 + } 778 + 779 + ehca_create_driver_sysfs(&ehca_driver); 780 + 781 + if (ehca_poll_all_eqs != 1) { 782 + ehca_gen_err("WARNING!!!"); 783 + ehca_gen_err("It is possible to lose interrupts."); 784 + } else { 785 + init_timer(&poll_eqs_timer); 786 + poll_eqs_timer.function = ehca_poll_eqs; 787 + poll_eqs_timer.expires = jiffies + HZ; 788 + add_timer(&poll_eqs_timer); 789 + } 790 + 791 + return 0; 792 + 793 + module_init2: 794 + ehca_destroy_slab_caches(); 795 + 796 + module_init1: 797 + ehca_destroy_comp_pool(); 798 + return ret; 799 + }; 800 + 801 + void __exit ehca_module_exit(void) 802 + { 803 + if (ehca_poll_all_eqs == 1) 804 + del_timer_sync(&poll_eqs_timer); 805 + 806 + ehca_remove_driver_sysfs(&ehca_driver); 807 + ibmebus_unregister_driver(&ehca_driver); 808 + 809 + ehca_destroy_slab_caches(); 810 + 811 + ehca_destroy_comp_pool(); 812 + 813 + idr_destroy(&ehca_cq_idr); 814 + idr_destroy(&ehca_qp_idr); 815 + }; 816 + 817 + module_init(ehca_module_init); 818 + module_exit(ehca_module_exit);
+131
drivers/infiniband/hw/ehca/ehca_mcast.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * mcast functions 5 + * 6 + * Authors: Khadija Souissi <souissik@de.ibm.com> 7 + * Waleri Fomin <fomin@de.ibm.com> 8 + * Reinhard Ernst <rernst@de.ibm.com> 9 + * Hoang-Nam Nguyen <hnguyen@de.ibm.com> 10 + * Heiko J Schick <schickhj@de.ibm.com> 11 + * 12 + * Copyright (c) 2005 IBM Corporation 13 + * 14 + * All rights reserved. 15 + * 16 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 17 + * BSD. 18 + * 19 + * OpenIB BSD License 20 + * 21 + * Redistribution and use in source and binary forms, with or without 22 + * modification, are permitted provided that the following conditions are met: 23 + * 24 + * Redistributions of source code must retain the above copyright notice, this 25 + * list of conditions and the following disclaimer. 26 + * 27 + * Redistributions in binary form must reproduce the above copyright notice, 28 + * this list of conditions and the following disclaimer in the documentation 29 + * and/or other materials 30 + * provided with the distribution. 31 + * 32 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 33 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 36 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 37 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 38 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 39 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 40 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 41 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 + * POSSIBILITY OF SUCH DAMAGE. 43 + */ 44 + 45 + #include <linux/module.h> 46 + #include <linux/err.h> 47 + #include "ehca_classes.h" 48 + #include "ehca_tools.h" 49 + #include "ehca_qes.h" 50 + #include "ehca_iverbs.h" 51 + #include "hcp_if.h" 52 + 53 + #define MAX_MC_LID 0xFFFE 54 + #define MIN_MC_LID 0xC000 /* Multicast limits */ 55 + #define EHCA_VALID_MULTICAST_GID(gid) ((gid)[0] == 0xFF) 56 + #define EHCA_VALID_MULTICAST_LID(lid) \ 57 + (((lid) >= MIN_MC_LID) && ((lid) <= MAX_MC_LID)) 58 + 59 + int ehca_attach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) 60 + { 61 + struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); 62 + struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca, 63 + ib_device); 64 + union ib_gid my_gid; 65 + u64 subnet_prefix, interface_id, h_ret; 66 + 67 + if (ibqp->qp_type != IB_QPT_UD) { 68 + ehca_err(ibqp->device, "invalid qp_type=%x", ibqp->qp_type); 69 + return -EINVAL; 70 + } 71 + 72 + if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) { 73 + ehca_err(ibqp->device, "invalid mulitcast gid"); 74 + return -EINVAL; 75 + } else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) { 76 + ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid); 77 + return -EINVAL; 78 + } 79 + 80 + memcpy(&my_gid.raw, gid->raw, sizeof(union ib_gid)); 81 + 82 + subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix); 83 + interface_id = be64_to_cpu(my_gid.global.interface_id); 84 + h_ret = hipz_h_attach_mcqp(shca->ipz_hca_handle, 85 + my_qp->ipz_qp_handle, 86 + my_qp->galpas.kernel, 87 + lid, subnet_prefix, interface_id); 88 + if (h_ret != H_SUCCESS) 89 + ehca_err(ibqp->device, 90 + "ehca_qp=%p qp_num=%x hipz_h_attach_mcqp() failed " 91 + "h_ret=%lx", my_qp, ibqp->qp_num, h_ret); 92 + 93 + return ehca2ib_return_code(h_ret); 94 + } 95 + 96 + int ehca_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) 97 + { 98 + struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); 99 + struct ehca_shca *shca = container_of(ibqp->pd->device, 100 + struct ehca_shca, ib_device); 101 + union ib_gid my_gid; 102 + u64 subnet_prefix, interface_id, h_ret; 103 + 104 + if (ibqp->qp_type != IB_QPT_UD) { 105 + ehca_err(ibqp->device, "invalid qp_type %x", ibqp->qp_type); 106 + return -EINVAL; 107 + } 108 + 109 + if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) { 110 + ehca_err(ibqp->device, "invalid mulitcast gid"); 111 + return -EINVAL; 112 + } else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) { 113 + ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid); 114 + return -EINVAL; 115 + } 116 + 117 + memcpy(&my_gid.raw, gid->raw, sizeof(union ib_gid)); 118 + 119 + subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix); 120 + interface_id = be64_to_cpu(my_gid.global.interface_id); 121 + h_ret = hipz_h_detach_mcqp(shca->ipz_hca_handle, 122 + my_qp->ipz_qp_handle, 123 + my_qp->galpas.kernel, 124 + lid, subnet_prefix, interface_id); 125 + if (h_ret != H_SUCCESS) 126 + ehca_err(ibqp->device, 127 + "ehca_qp=%p qp_num=%x hipz_h_detach_mcqp() failed " 128 + "h_ret=%lx", my_qp, ibqp->qp_num, h_ret); 129 + 130 + return ehca2ib_return_code(h_ret); 131 + }
+2261
drivers/infiniband/hw/ehca/ehca_mrmw.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * MR/MW functions 5 + * 6 + * Authors: Dietmar Decker <ddecker@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 <asm/current.h> 43 + 44 + #include "ehca_iverbs.h" 45 + #include "ehca_mrmw.h" 46 + #include "hcp_if.h" 47 + #include "hipz_hw.h" 48 + 49 + static struct kmem_cache *mr_cache; 50 + static struct kmem_cache *mw_cache; 51 + 52 + static struct ehca_mr *ehca_mr_new(void) 53 + { 54 + struct ehca_mr *me; 55 + 56 + me = kmem_cache_alloc(mr_cache, SLAB_KERNEL); 57 + if (me) { 58 + memset(me, 0, sizeof(struct ehca_mr)); 59 + spin_lock_init(&me->mrlock); 60 + } else 61 + ehca_gen_err("alloc failed"); 62 + 63 + return me; 64 + } 65 + 66 + static void ehca_mr_delete(struct ehca_mr *me) 67 + { 68 + kmem_cache_free(mr_cache, me); 69 + } 70 + 71 + static struct ehca_mw *ehca_mw_new(void) 72 + { 73 + struct ehca_mw *me; 74 + 75 + me = kmem_cache_alloc(mw_cache, SLAB_KERNEL); 76 + if (me) { 77 + memset(me, 0, sizeof(struct ehca_mw)); 78 + spin_lock_init(&me->mwlock); 79 + } else 80 + ehca_gen_err("alloc failed"); 81 + 82 + return me; 83 + } 84 + 85 + static void ehca_mw_delete(struct ehca_mw *me) 86 + { 87 + kmem_cache_free(mw_cache, me); 88 + } 89 + 90 + /*----------------------------------------------------------------------*/ 91 + 92 + struct ib_mr *ehca_get_dma_mr(struct ib_pd *pd, int mr_access_flags) 93 + { 94 + struct ib_mr *ib_mr; 95 + int ret; 96 + struct ehca_mr *e_maxmr; 97 + struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); 98 + struct ehca_shca *shca = 99 + container_of(pd->device, struct ehca_shca, ib_device); 100 + 101 + if (shca->maxmr) { 102 + e_maxmr = ehca_mr_new(); 103 + if (!e_maxmr) { 104 + ehca_err(&shca->ib_device, "out of memory"); 105 + ib_mr = ERR_PTR(-ENOMEM); 106 + goto get_dma_mr_exit0; 107 + } 108 + 109 + ret = ehca_reg_maxmr(shca, e_maxmr, (u64*)KERNELBASE, 110 + mr_access_flags, e_pd, 111 + &e_maxmr->ib.ib_mr.lkey, 112 + &e_maxmr->ib.ib_mr.rkey); 113 + if (ret) { 114 + ib_mr = ERR_PTR(ret); 115 + goto get_dma_mr_exit0; 116 + } 117 + ib_mr = &e_maxmr->ib.ib_mr; 118 + } else { 119 + ehca_err(&shca->ib_device, "no internal max-MR exist!"); 120 + ib_mr = ERR_PTR(-EINVAL); 121 + goto get_dma_mr_exit0; 122 + } 123 + 124 + get_dma_mr_exit0: 125 + if (IS_ERR(ib_mr)) 126 + ehca_err(&shca->ib_device, "rc=%lx pd=%p mr_access_flags=%x ", 127 + PTR_ERR(ib_mr), pd, mr_access_flags); 128 + return ib_mr; 129 + } /* end ehca_get_dma_mr() */ 130 + 131 + /*----------------------------------------------------------------------*/ 132 + 133 + struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd, 134 + struct ib_phys_buf *phys_buf_array, 135 + int num_phys_buf, 136 + int mr_access_flags, 137 + u64 *iova_start) 138 + { 139 + struct ib_mr *ib_mr; 140 + int ret; 141 + struct ehca_mr *e_mr; 142 + struct ehca_shca *shca = 143 + container_of(pd->device, struct ehca_shca, ib_device); 144 + struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); 145 + 146 + u64 size; 147 + struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; 148 + u32 num_pages_mr; 149 + u32 num_pages_4k; /* 4k portion "pages" */ 150 + 151 + if ((num_phys_buf <= 0) || !phys_buf_array) { 152 + ehca_err(pd->device, "bad input values: num_phys_buf=%x " 153 + "phys_buf_array=%p", num_phys_buf, phys_buf_array); 154 + ib_mr = ERR_PTR(-EINVAL); 155 + goto reg_phys_mr_exit0; 156 + } 157 + if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) && 158 + !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) || 159 + ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) && 160 + !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) { 161 + /* 162 + * Remote Write Access requires Local Write Access 163 + * Remote Atomic Access requires Local Write Access 164 + */ 165 + ehca_err(pd->device, "bad input values: mr_access_flags=%x", 166 + mr_access_flags); 167 + ib_mr = ERR_PTR(-EINVAL); 168 + goto reg_phys_mr_exit0; 169 + } 170 + 171 + /* check physical buffer list and calculate size */ 172 + ret = ehca_mr_chk_buf_and_calc_size(phys_buf_array, num_phys_buf, 173 + iova_start, &size); 174 + if (ret) { 175 + ib_mr = ERR_PTR(ret); 176 + goto reg_phys_mr_exit0; 177 + } 178 + if ((size == 0) || 179 + (((u64)iova_start + size) < (u64)iova_start)) { 180 + ehca_err(pd->device, "bad input values: size=%lx iova_start=%p", 181 + size, iova_start); 182 + ib_mr = ERR_PTR(-EINVAL); 183 + goto reg_phys_mr_exit0; 184 + } 185 + 186 + e_mr = ehca_mr_new(); 187 + if (!e_mr) { 188 + ehca_err(pd->device, "out of memory"); 189 + ib_mr = ERR_PTR(-ENOMEM); 190 + goto reg_phys_mr_exit0; 191 + } 192 + 193 + /* determine number of MR pages */ 194 + num_pages_mr = ((((u64)iova_start % PAGE_SIZE) + size + 195 + PAGE_SIZE - 1) / PAGE_SIZE); 196 + num_pages_4k = ((((u64)iova_start % EHCA_PAGESIZE) + size + 197 + EHCA_PAGESIZE - 1) / EHCA_PAGESIZE); 198 + 199 + /* register MR on HCA */ 200 + if (ehca_mr_is_maxmr(size, iova_start)) { 201 + e_mr->flags |= EHCA_MR_FLAG_MAXMR; 202 + ret = ehca_reg_maxmr(shca, e_mr, iova_start, mr_access_flags, 203 + e_pd, &e_mr->ib.ib_mr.lkey, 204 + &e_mr->ib.ib_mr.rkey); 205 + if (ret) { 206 + ib_mr = ERR_PTR(ret); 207 + goto reg_phys_mr_exit1; 208 + } 209 + } else { 210 + pginfo.type = EHCA_MR_PGI_PHYS; 211 + pginfo.num_pages = num_pages_mr; 212 + pginfo.num_4k = num_pages_4k; 213 + pginfo.num_phys_buf = num_phys_buf; 214 + pginfo.phys_buf_array = phys_buf_array; 215 + pginfo.next_4k = (((u64)iova_start & ~PAGE_MASK) / 216 + EHCA_PAGESIZE); 217 + 218 + ret = ehca_reg_mr(shca, e_mr, iova_start, size, mr_access_flags, 219 + e_pd, &pginfo, &e_mr->ib.ib_mr.lkey, 220 + &e_mr->ib.ib_mr.rkey); 221 + if (ret) { 222 + ib_mr = ERR_PTR(ret); 223 + goto reg_phys_mr_exit1; 224 + } 225 + } 226 + 227 + /* successful registration of all pages */ 228 + return &e_mr->ib.ib_mr; 229 + 230 + reg_phys_mr_exit1: 231 + ehca_mr_delete(e_mr); 232 + reg_phys_mr_exit0: 233 + if (IS_ERR(ib_mr)) 234 + ehca_err(pd->device, "rc=%lx pd=%p phys_buf_array=%p " 235 + "num_phys_buf=%x mr_access_flags=%x iova_start=%p", 236 + PTR_ERR(ib_mr), pd, phys_buf_array, 237 + num_phys_buf, mr_access_flags, iova_start); 238 + return ib_mr; 239 + } /* end ehca_reg_phys_mr() */ 240 + 241 + /*----------------------------------------------------------------------*/ 242 + 243 + struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, 244 + struct ib_umem *region, 245 + int mr_access_flags, 246 + struct ib_udata *udata) 247 + { 248 + struct ib_mr *ib_mr; 249 + struct ehca_mr *e_mr; 250 + struct ehca_shca *shca = 251 + container_of(pd->device, struct ehca_shca, ib_device); 252 + struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); 253 + struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; 254 + int ret; 255 + u32 num_pages_mr; 256 + u32 num_pages_4k; /* 4k portion "pages" */ 257 + 258 + if (!pd) { 259 + ehca_gen_err("bad pd=%p", pd); 260 + return ERR_PTR(-EFAULT); 261 + } 262 + if (!region) { 263 + ehca_err(pd->device, "bad input values: region=%p", region); 264 + ib_mr = ERR_PTR(-EINVAL); 265 + goto reg_user_mr_exit0; 266 + } 267 + if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) && 268 + !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) || 269 + ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) && 270 + !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) { 271 + /* 272 + * Remote Write Access requires Local Write Access 273 + * Remote Atomic Access requires Local Write Access 274 + */ 275 + ehca_err(pd->device, "bad input values: mr_access_flags=%x", 276 + mr_access_flags); 277 + ib_mr = ERR_PTR(-EINVAL); 278 + goto reg_user_mr_exit0; 279 + } 280 + if (region->page_size != PAGE_SIZE) { 281 + ehca_err(pd->device, "page size not supported, " 282 + "region->page_size=%x", region->page_size); 283 + ib_mr = ERR_PTR(-EINVAL); 284 + goto reg_user_mr_exit0; 285 + } 286 + 287 + if ((region->length == 0) || 288 + ((region->virt_base + region->length) < region->virt_base)) { 289 + ehca_err(pd->device, "bad input values: length=%lx " 290 + "virt_base=%lx", region->length, region->virt_base); 291 + ib_mr = ERR_PTR(-EINVAL); 292 + goto reg_user_mr_exit0; 293 + } 294 + 295 + e_mr = ehca_mr_new(); 296 + if (!e_mr) { 297 + ehca_err(pd->device, "out of memory"); 298 + ib_mr = ERR_PTR(-ENOMEM); 299 + goto reg_user_mr_exit0; 300 + } 301 + 302 + /* determine number of MR pages */ 303 + num_pages_mr = (((region->virt_base % PAGE_SIZE) + region->length + 304 + PAGE_SIZE - 1) / PAGE_SIZE); 305 + num_pages_4k = (((region->virt_base % EHCA_PAGESIZE) + region->length + 306 + EHCA_PAGESIZE - 1) / EHCA_PAGESIZE); 307 + 308 + /* register MR on HCA */ 309 + pginfo.type = EHCA_MR_PGI_USER; 310 + pginfo.num_pages = num_pages_mr; 311 + pginfo.num_4k = num_pages_4k; 312 + pginfo.region = region; 313 + pginfo.next_4k = region->offset / EHCA_PAGESIZE; 314 + pginfo.next_chunk = list_prepare_entry(pginfo.next_chunk, 315 + (&region->chunk_list), 316 + list); 317 + 318 + ret = ehca_reg_mr(shca, e_mr, (u64*)region->virt_base, 319 + region->length, mr_access_flags, e_pd, &pginfo, 320 + &e_mr->ib.ib_mr.lkey, &e_mr->ib.ib_mr.rkey); 321 + if (ret) { 322 + ib_mr = ERR_PTR(ret); 323 + goto reg_user_mr_exit1; 324 + } 325 + 326 + /* successful registration of all pages */ 327 + return &e_mr->ib.ib_mr; 328 + 329 + reg_user_mr_exit1: 330 + ehca_mr_delete(e_mr); 331 + reg_user_mr_exit0: 332 + if (IS_ERR(ib_mr)) 333 + ehca_err(pd->device, "rc=%lx pd=%p region=%p mr_access_flags=%x" 334 + " udata=%p", 335 + PTR_ERR(ib_mr), pd, region, mr_access_flags, udata); 336 + return ib_mr; 337 + } /* end ehca_reg_user_mr() */ 338 + 339 + /*----------------------------------------------------------------------*/ 340 + 341 + int ehca_rereg_phys_mr(struct ib_mr *mr, 342 + int mr_rereg_mask, 343 + struct ib_pd *pd, 344 + struct ib_phys_buf *phys_buf_array, 345 + int num_phys_buf, 346 + int mr_access_flags, 347 + u64 *iova_start) 348 + { 349 + int ret; 350 + 351 + struct ehca_shca *shca = 352 + container_of(mr->device, struct ehca_shca, ib_device); 353 + struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr); 354 + struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd); 355 + u64 new_size; 356 + u64 *new_start; 357 + u32 new_acl; 358 + struct ehca_pd *new_pd; 359 + u32 tmp_lkey, tmp_rkey; 360 + unsigned long sl_flags; 361 + u32 num_pages_mr = 0; 362 + u32 num_pages_4k = 0; /* 4k portion "pages" */ 363 + struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; 364 + u32 cur_pid = current->tgid; 365 + 366 + if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && 367 + (my_pd->ownpid != cur_pid)) { 368 + ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x", 369 + cur_pid, my_pd->ownpid); 370 + ret = -EINVAL; 371 + goto rereg_phys_mr_exit0; 372 + } 373 + 374 + if (!(mr_rereg_mask & IB_MR_REREG_TRANS)) { 375 + /* TODO not supported, because PHYP rereg hCall needs pages */ 376 + ehca_err(mr->device, "rereg without IB_MR_REREG_TRANS not " 377 + "supported yet, mr_rereg_mask=%x", mr_rereg_mask); 378 + ret = -EINVAL; 379 + goto rereg_phys_mr_exit0; 380 + } 381 + 382 + if (mr_rereg_mask & IB_MR_REREG_PD) { 383 + if (!pd) { 384 + ehca_err(mr->device, "rereg with bad pd, pd=%p " 385 + "mr_rereg_mask=%x", pd, mr_rereg_mask); 386 + ret = -EINVAL; 387 + goto rereg_phys_mr_exit0; 388 + } 389 + } 390 + 391 + if ((mr_rereg_mask & 392 + ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) || 393 + (mr_rereg_mask == 0)) { 394 + ret = -EINVAL; 395 + goto rereg_phys_mr_exit0; 396 + } 397 + 398 + /* check other parameters */ 399 + if (e_mr == shca->maxmr) { 400 + /* should be impossible, however reject to be sure */ 401 + ehca_err(mr->device, "rereg internal max-MR impossible, mr=%p " 402 + "shca->maxmr=%p mr->lkey=%x", 403 + mr, shca->maxmr, mr->lkey); 404 + ret = -EINVAL; 405 + goto rereg_phys_mr_exit0; 406 + } 407 + if (mr_rereg_mask & IB_MR_REREG_TRANS) { /* transl., i.e. addr/size */ 408 + if (e_mr->flags & EHCA_MR_FLAG_FMR) { 409 + ehca_err(mr->device, "not supported for FMR, mr=%p " 410 + "flags=%x", mr, e_mr->flags); 411 + ret = -EINVAL; 412 + goto rereg_phys_mr_exit0; 413 + } 414 + if (!phys_buf_array || num_phys_buf <= 0) { 415 + ehca_err(mr->device, "bad input values: mr_rereg_mask=%x" 416 + " phys_buf_array=%p num_phys_buf=%x", 417 + mr_rereg_mask, phys_buf_array, num_phys_buf); 418 + ret = -EINVAL; 419 + goto rereg_phys_mr_exit0; 420 + } 421 + } 422 + if ((mr_rereg_mask & IB_MR_REREG_ACCESS) && /* change ACL */ 423 + (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) && 424 + !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) || 425 + ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) && 426 + !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)))) { 427 + /* 428 + * Remote Write Access requires Local Write Access 429 + * Remote Atomic Access requires Local Write Access 430 + */ 431 + ehca_err(mr->device, "bad input values: mr_rereg_mask=%x " 432 + "mr_access_flags=%x", mr_rereg_mask, mr_access_flags); 433 + ret = -EINVAL; 434 + goto rereg_phys_mr_exit0; 435 + } 436 + 437 + /* set requested values dependent on rereg request */ 438 + spin_lock_irqsave(&e_mr->mrlock, sl_flags); 439 + new_start = e_mr->start; /* new == old address */ 440 + new_size = e_mr->size; /* new == old length */ 441 + new_acl = e_mr->acl; /* new == old access control */ 442 + new_pd = container_of(mr->pd,struct ehca_pd,ib_pd); /*new == old PD*/ 443 + 444 + if (mr_rereg_mask & IB_MR_REREG_TRANS) { 445 + new_start = iova_start; /* change address */ 446 + /* check physical buffer list and calculate size */ 447 + ret = ehca_mr_chk_buf_and_calc_size(phys_buf_array, 448 + num_phys_buf, iova_start, 449 + &new_size); 450 + if (ret) 451 + goto rereg_phys_mr_exit1; 452 + if ((new_size == 0) || 453 + (((u64)iova_start + new_size) < (u64)iova_start)) { 454 + ehca_err(mr->device, "bad input values: new_size=%lx " 455 + "iova_start=%p", new_size, iova_start); 456 + ret = -EINVAL; 457 + goto rereg_phys_mr_exit1; 458 + } 459 + num_pages_mr = ((((u64)new_start % PAGE_SIZE) + new_size + 460 + PAGE_SIZE - 1) / PAGE_SIZE); 461 + num_pages_4k = ((((u64)new_start % EHCA_PAGESIZE) + new_size + 462 + EHCA_PAGESIZE - 1) / EHCA_PAGESIZE); 463 + pginfo.type = EHCA_MR_PGI_PHYS; 464 + pginfo.num_pages = num_pages_mr; 465 + pginfo.num_4k = num_pages_4k; 466 + pginfo.num_phys_buf = num_phys_buf; 467 + pginfo.phys_buf_array = phys_buf_array; 468 + pginfo.next_4k = (((u64)iova_start & ~PAGE_MASK) / 469 + EHCA_PAGESIZE); 470 + } 471 + if (mr_rereg_mask & IB_MR_REREG_ACCESS) 472 + new_acl = mr_access_flags; 473 + if (mr_rereg_mask & IB_MR_REREG_PD) 474 + new_pd = container_of(pd, struct ehca_pd, ib_pd); 475 + 476 + ret = ehca_rereg_mr(shca, e_mr, new_start, new_size, new_acl, 477 + new_pd, &pginfo, &tmp_lkey, &tmp_rkey); 478 + if (ret) 479 + goto rereg_phys_mr_exit1; 480 + 481 + /* successful reregistration */ 482 + if (mr_rereg_mask & IB_MR_REREG_PD) 483 + mr->pd = pd; 484 + mr->lkey = tmp_lkey; 485 + mr->rkey = tmp_rkey; 486 + 487 + rereg_phys_mr_exit1: 488 + spin_unlock_irqrestore(&e_mr->mrlock, sl_flags); 489 + rereg_phys_mr_exit0: 490 + if (ret) 491 + ehca_err(mr->device, "ret=%x mr=%p mr_rereg_mask=%x pd=%p " 492 + "phys_buf_array=%p num_phys_buf=%x mr_access_flags=%x " 493 + "iova_start=%p", 494 + ret, mr, mr_rereg_mask, pd, phys_buf_array, 495 + num_phys_buf, mr_access_flags, iova_start); 496 + return ret; 497 + } /* end ehca_rereg_phys_mr() */ 498 + 499 + /*----------------------------------------------------------------------*/ 500 + 501 + int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr) 502 + { 503 + int ret = 0; 504 + u64 h_ret; 505 + struct ehca_shca *shca = 506 + container_of(mr->device, struct ehca_shca, ib_device); 507 + struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr); 508 + struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd); 509 + u32 cur_pid = current->tgid; 510 + unsigned long sl_flags; 511 + struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0}; 512 + 513 + if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && 514 + (my_pd->ownpid != cur_pid)) { 515 + ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x", 516 + cur_pid, my_pd->ownpid); 517 + ret = -EINVAL; 518 + goto query_mr_exit0; 519 + } 520 + 521 + if ((e_mr->flags & EHCA_MR_FLAG_FMR)) { 522 + ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p " 523 + "e_mr->flags=%x", mr, e_mr, e_mr->flags); 524 + ret = -EINVAL; 525 + goto query_mr_exit0; 526 + } 527 + 528 + memset(mr_attr, 0, sizeof(struct ib_mr_attr)); 529 + spin_lock_irqsave(&e_mr->mrlock, sl_flags); 530 + 531 + h_ret = hipz_h_query_mr(shca->ipz_hca_handle, e_mr, &hipzout); 532 + if (h_ret != H_SUCCESS) { 533 + ehca_err(mr->device, "hipz_mr_query failed, h_ret=%lx mr=%p " 534 + "hca_hndl=%lx mr_hndl=%lx lkey=%x", 535 + h_ret, mr, shca->ipz_hca_handle.handle, 536 + e_mr->ipz_mr_handle.handle, mr->lkey); 537 + ret = ehca_mrmw_map_hrc_query_mr(h_ret); 538 + goto query_mr_exit1; 539 + } 540 + mr_attr->pd = mr->pd; 541 + mr_attr->device_virt_addr = hipzout.vaddr; 542 + mr_attr->size = hipzout.len; 543 + mr_attr->lkey = hipzout.lkey; 544 + mr_attr->rkey = hipzout.rkey; 545 + ehca_mrmw_reverse_map_acl(&hipzout.acl, &mr_attr->mr_access_flags); 546 + 547 + query_mr_exit1: 548 + spin_unlock_irqrestore(&e_mr->mrlock, sl_flags); 549 + query_mr_exit0: 550 + if (ret) 551 + ehca_err(mr->device, "ret=%x mr=%p mr_attr=%p", 552 + ret, mr, mr_attr); 553 + return ret; 554 + } /* end ehca_query_mr() */ 555 + 556 + /*----------------------------------------------------------------------*/ 557 + 558 + int ehca_dereg_mr(struct ib_mr *mr) 559 + { 560 + int ret = 0; 561 + u64 h_ret; 562 + struct ehca_shca *shca = 563 + container_of(mr->device, struct ehca_shca, ib_device); 564 + struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr); 565 + struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd); 566 + u32 cur_pid = current->tgid; 567 + 568 + if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && 569 + (my_pd->ownpid != cur_pid)) { 570 + ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x", 571 + cur_pid, my_pd->ownpid); 572 + ret = -EINVAL; 573 + goto dereg_mr_exit0; 574 + } 575 + 576 + if ((e_mr->flags & EHCA_MR_FLAG_FMR)) { 577 + ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p " 578 + "e_mr->flags=%x", mr, e_mr, e_mr->flags); 579 + ret = -EINVAL; 580 + goto dereg_mr_exit0; 581 + } else if (e_mr == shca->maxmr) { 582 + /* should be impossible, however reject to be sure */ 583 + ehca_err(mr->device, "dereg internal max-MR impossible, mr=%p " 584 + "shca->maxmr=%p mr->lkey=%x", 585 + mr, shca->maxmr, mr->lkey); 586 + ret = -EINVAL; 587 + goto dereg_mr_exit0; 588 + } 589 + 590 + /* TODO: BUSY: MR still has bound window(s) */ 591 + h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr); 592 + if (h_ret != H_SUCCESS) { 593 + ehca_err(mr->device, "hipz_free_mr failed, h_ret=%lx shca=%p " 594 + "e_mr=%p hca_hndl=%lx mr_hndl=%lx mr->lkey=%x", 595 + h_ret, shca, e_mr, shca->ipz_hca_handle.handle, 596 + e_mr->ipz_mr_handle.handle, mr->lkey); 597 + ret = ehca_mrmw_map_hrc_free_mr(h_ret); 598 + goto dereg_mr_exit0; 599 + } 600 + 601 + /* successful deregistration */ 602 + ehca_mr_delete(e_mr); 603 + 604 + dereg_mr_exit0: 605 + if (ret) 606 + ehca_err(mr->device, "ret=%x mr=%p", ret, mr); 607 + return ret; 608 + } /* end ehca_dereg_mr() */ 609 + 610 + /*----------------------------------------------------------------------*/ 611 + 612 + struct ib_mw *ehca_alloc_mw(struct ib_pd *pd) 613 + { 614 + struct ib_mw *ib_mw; 615 + u64 h_ret; 616 + struct ehca_mw *e_mw; 617 + struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); 618 + struct ehca_shca *shca = 619 + container_of(pd->device, struct ehca_shca, ib_device); 620 + struct ehca_mw_hipzout_parms hipzout = {{0},0}; 621 + 622 + e_mw = ehca_mw_new(); 623 + if (!e_mw) { 624 + ib_mw = ERR_PTR(-ENOMEM); 625 + goto alloc_mw_exit0; 626 + } 627 + 628 + h_ret = hipz_h_alloc_resource_mw(shca->ipz_hca_handle, e_mw, 629 + e_pd->fw_pd, &hipzout); 630 + if (h_ret != H_SUCCESS) { 631 + ehca_err(pd->device, "hipz_mw_allocate failed, h_ret=%lx " 632 + "shca=%p hca_hndl=%lx mw=%p", 633 + h_ret, shca, shca->ipz_hca_handle.handle, e_mw); 634 + ib_mw = ERR_PTR(ehca_mrmw_map_hrc_alloc(h_ret)); 635 + goto alloc_mw_exit1; 636 + } 637 + /* successful MW allocation */ 638 + e_mw->ipz_mw_handle = hipzout.handle; 639 + e_mw->ib_mw.rkey = hipzout.rkey; 640 + return &e_mw->ib_mw; 641 + 642 + alloc_mw_exit1: 643 + ehca_mw_delete(e_mw); 644 + alloc_mw_exit0: 645 + if (IS_ERR(ib_mw)) 646 + ehca_err(pd->device, "rc=%lx pd=%p", PTR_ERR(ib_mw), pd); 647 + return ib_mw; 648 + } /* end ehca_alloc_mw() */ 649 + 650 + /*----------------------------------------------------------------------*/ 651 + 652 + int ehca_bind_mw(struct ib_qp *qp, 653 + struct ib_mw *mw, 654 + struct ib_mw_bind *mw_bind) 655 + { 656 + /* TODO: not supported up to now */ 657 + ehca_gen_err("bind MW currently not supported by HCAD"); 658 + 659 + return -EPERM; 660 + } /* end ehca_bind_mw() */ 661 + 662 + /*----------------------------------------------------------------------*/ 663 + 664 + int ehca_dealloc_mw(struct ib_mw *mw) 665 + { 666 + u64 h_ret; 667 + struct ehca_shca *shca = 668 + container_of(mw->device, struct ehca_shca, ib_device); 669 + struct ehca_mw *e_mw = container_of(mw, struct ehca_mw, ib_mw); 670 + 671 + h_ret = hipz_h_free_resource_mw(shca->ipz_hca_handle, e_mw); 672 + if (h_ret != H_SUCCESS) { 673 + ehca_err(mw->device, "hipz_free_mw failed, h_ret=%lx shca=%p " 674 + "mw=%p rkey=%x hca_hndl=%lx mw_hndl=%lx", 675 + h_ret, shca, mw, mw->rkey, shca->ipz_hca_handle.handle, 676 + e_mw->ipz_mw_handle.handle); 677 + return ehca_mrmw_map_hrc_free_mw(h_ret); 678 + } 679 + /* successful deallocation */ 680 + ehca_mw_delete(e_mw); 681 + return 0; 682 + } /* end ehca_dealloc_mw() */ 683 + 684 + /*----------------------------------------------------------------------*/ 685 + 686 + struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd, 687 + int mr_access_flags, 688 + struct ib_fmr_attr *fmr_attr) 689 + { 690 + struct ib_fmr *ib_fmr; 691 + struct ehca_shca *shca = 692 + container_of(pd->device, struct ehca_shca, ib_device); 693 + struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); 694 + struct ehca_mr *e_fmr; 695 + int ret; 696 + u32 tmp_lkey, tmp_rkey; 697 + struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; 698 + 699 + /* check other parameters */ 700 + if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) && 701 + !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) || 702 + ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) && 703 + !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) { 704 + /* 705 + * Remote Write Access requires Local Write Access 706 + * Remote Atomic Access requires Local Write Access 707 + */ 708 + ehca_err(pd->device, "bad input values: mr_access_flags=%x", 709 + mr_access_flags); 710 + ib_fmr = ERR_PTR(-EINVAL); 711 + goto alloc_fmr_exit0; 712 + } 713 + if (mr_access_flags & IB_ACCESS_MW_BIND) { 714 + ehca_err(pd->device, "bad input values: mr_access_flags=%x", 715 + mr_access_flags); 716 + ib_fmr = ERR_PTR(-EINVAL); 717 + goto alloc_fmr_exit0; 718 + } 719 + if ((fmr_attr->max_pages == 0) || (fmr_attr->max_maps == 0)) { 720 + ehca_err(pd->device, "bad input values: fmr_attr->max_pages=%x " 721 + "fmr_attr->max_maps=%x fmr_attr->page_shift=%x", 722 + fmr_attr->max_pages, fmr_attr->max_maps, 723 + fmr_attr->page_shift); 724 + ib_fmr = ERR_PTR(-EINVAL); 725 + goto alloc_fmr_exit0; 726 + } 727 + if (((1 << fmr_attr->page_shift) != EHCA_PAGESIZE) && 728 + ((1 << fmr_attr->page_shift) != PAGE_SIZE)) { 729 + ehca_err(pd->device, "unsupported fmr_attr->page_shift=%x", 730 + fmr_attr->page_shift); 731 + ib_fmr = ERR_PTR(-EINVAL); 732 + goto alloc_fmr_exit0; 733 + } 734 + 735 + e_fmr = ehca_mr_new(); 736 + if (!e_fmr) { 737 + ib_fmr = ERR_PTR(-ENOMEM); 738 + goto alloc_fmr_exit0; 739 + } 740 + e_fmr->flags |= EHCA_MR_FLAG_FMR; 741 + 742 + /* register MR on HCA */ 743 + ret = ehca_reg_mr(shca, e_fmr, NULL, 744 + fmr_attr->max_pages * (1 << fmr_attr->page_shift), 745 + mr_access_flags, e_pd, &pginfo, 746 + &tmp_lkey, &tmp_rkey); 747 + if (ret) { 748 + ib_fmr = ERR_PTR(ret); 749 + goto alloc_fmr_exit1; 750 + } 751 + 752 + /* successful */ 753 + e_fmr->fmr_page_size = 1 << fmr_attr->page_shift; 754 + e_fmr->fmr_max_pages = fmr_attr->max_pages; 755 + e_fmr->fmr_max_maps = fmr_attr->max_maps; 756 + e_fmr->fmr_map_cnt = 0; 757 + return &e_fmr->ib.ib_fmr; 758 + 759 + alloc_fmr_exit1: 760 + ehca_mr_delete(e_fmr); 761 + alloc_fmr_exit0: 762 + if (IS_ERR(ib_fmr)) 763 + ehca_err(pd->device, "rc=%lx pd=%p mr_access_flags=%x " 764 + "fmr_attr=%p", PTR_ERR(ib_fmr), pd, 765 + mr_access_flags, fmr_attr); 766 + return ib_fmr; 767 + } /* end ehca_alloc_fmr() */ 768 + 769 + /*----------------------------------------------------------------------*/ 770 + 771 + int ehca_map_phys_fmr(struct ib_fmr *fmr, 772 + u64 *page_list, 773 + int list_len, 774 + u64 iova) 775 + { 776 + int ret; 777 + struct ehca_shca *shca = 778 + container_of(fmr->device, struct ehca_shca, ib_device); 779 + struct ehca_mr *e_fmr = container_of(fmr, struct ehca_mr, ib.ib_fmr); 780 + struct ehca_pd *e_pd = container_of(fmr->pd, struct ehca_pd, ib_pd); 781 + struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; 782 + u32 tmp_lkey, tmp_rkey; 783 + 784 + if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) { 785 + ehca_err(fmr->device, "not a FMR, e_fmr=%p e_fmr->flags=%x", 786 + e_fmr, e_fmr->flags); 787 + ret = -EINVAL; 788 + goto map_phys_fmr_exit0; 789 + } 790 + ret = ehca_fmr_check_page_list(e_fmr, page_list, list_len); 791 + if (ret) 792 + goto map_phys_fmr_exit0; 793 + if (iova % e_fmr->fmr_page_size) { 794 + /* only whole-numbered pages */ 795 + ehca_err(fmr->device, "bad iova, iova=%lx fmr_page_size=%x", 796 + iova, e_fmr->fmr_page_size); 797 + ret = -EINVAL; 798 + goto map_phys_fmr_exit0; 799 + } 800 + if (e_fmr->fmr_map_cnt >= e_fmr->fmr_max_maps) { 801 + /* HCAD does not limit the maps, however trace this anyway */ 802 + ehca_info(fmr->device, "map limit exceeded, fmr=%p " 803 + "e_fmr->fmr_map_cnt=%x e_fmr->fmr_max_maps=%x", 804 + fmr, e_fmr->fmr_map_cnt, e_fmr->fmr_max_maps); 805 + } 806 + 807 + pginfo.type = EHCA_MR_PGI_FMR; 808 + pginfo.num_pages = list_len; 809 + pginfo.num_4k = list_len * (e_fmr->fmr_page_size / EHCA_PAGESIZE); 810 + pginfo.page_list = page_list; 811 + pginfo.next_4k = ((iova & (e_fmr->fmr_page_size-1)) / 812 + EHCA_PAGESIZE); 813 + 814 + ret = ehca_rereg_mr(shca, e_fmr, (u64*)iova, 815 + list_len * e_fmr->fmr_page_size, 816 + e_fmr->acl, e_pd, &pginfo, &tmp_lkey, &tmp_rkey); 817 + if (ret) 818 + goto map_phys_fmr_exit0; 819 + 820 + /* successful reregistration */ 821 + e_fmr->fmr_map_cnt++; 822 + e_fmr->ib.ib_fmr.lkey = tmp_lkey; 823 + e_fmr->ib.ib_fmr.rkey = tmp_rkey; 824 + return 0; 825 + 826 + map_phys_fmr_exit0: 827 + if (ret) 828 + ehca_err(fmr->device, "ret=%x fmr=%p page_list=%p list_len=%x " 829 + "iova=%lx", 830 + ret, fmr, page_list, list_len, iova); 831 + return ret; 832 + } /* end ehca_map_phys_fmr() */ 833 + 834 + /*----------------------------------------------------------------------*/ 835 + 836 + int ehca_unmap_fmr(struct list_head *fmr_list) 837 + { 838 + int ret = 0; 839 + struct ib_fmr *ib_fmr; 840 + struct ehca_shca *shca = NULL; 841 + struct ehca_shca *prev_shca; 842 + struct ehca_mr *e_fmr; 843 + u32 num_fmr = 0; 844 + u32 unmap_fmr_cnt = 0; 845 + 846 + /* check all FMR belong to same SHCA, and check internal flag */ 847 + list_for_each_entry(ib_fmr, fmr_list, list) { 848 + prev_shca = shca; 849 + if (!ib_fmr) { 850 + ehca_gen_err("bad fmr=%p in list", ib_fmr); 851 + ret = -EINVAL; 852 + goto unmap_fmr_exit0; 853 + } 854 + shca = container_of(ib_fmr->device, struct ehca_shca, 855 + ib_device); 856 + e_fmr = container_of(ib_fmr, struct ehca_mr, ib.ib_fmr); 857 + if ((shca != prev_shca) && prev_shca) { 858 + ehca_err(&shca->ib_device, "SHCA mismatch, shca=%p " 859 + "prev_shca=%p e_fmr=%p", 860 + shca, prev_shca, e_fmr); 861 + ret = -EINVAL; 862 + goto unmap_fmr_exit0; 863 + } 864 + if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) { 865 + ehca_err(&shca->ib_device, "not a FMR, e_fmr=%p " 866 + "e_fmr->flags=%x", e_fmr, e_fmr->flags); 867 + ret = -EINVAL; 868 + goto unmap_fmr_exit0; 869 + } 870 + num_fmr++; 871 + } 872 + 873 + /* loop over all FMRs to unmap */ 874 + list_for_each_entry(ib_fmr, fmr_list, list) { 875 + unmap_fmr_cnt++; 876 + e_fmr = container_of(ib_fmr, struct ehca_mr, ib.ib_fmr); 877 + shca = container_of(ib_fmr->device, struct ehca_shca, 878 + ib_device); 879 + ret = ehca_unmap_one_fmr(shca, e_fmr); 880 + if (ret) { 881 + /* unmap failed, stop unmapping of rest of FMRs */ 882 + ehca_err(&shca->ib_device, "unmap of one FMR failed, " 883 + "stop rest, e_fmr=%p num_fmr=%x " 884 + "unmap_fmr_cnt=%x lkey=%x", e_fmr, num_fmr, 885 + unmap_fmr_cnt, e_fmr->ib.ib_fmr.lkey); 886 + goto unmap_fmr_exit0; 887 + } 888 + } 889 + 890 + unmap_fmr_exit0: 891 + if (ret) 892 + ehca_gen_err("ret=%x fmr_list=%p num_fmr=%x unmap_fmr_cnt=%x", 893 + ret, fmr_list, num_fmr, unmap_fmr_cnt); 894 + return ret; 895 + } /* end ehca_unmap_fmr() */ 896 + 897 + /*----------------------------------------------------------------------*/ 898 + 899 + int ehca_dealloc_fmr(struct ib_fmr *fmr) 900 + { 901 + int ret; 902 + u64 h_ret; 903 + struct ehca_shca *shca = 904 + container_of(fmr->device, struct ehca_shca, ib_device); 905 + struct ehca_mr *e_fmr = container_of(fmr, struct ehca_mr, ib.ib_fmr); 906 + 907 + if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) { 908 + ehca_err(fmr->device, "not a FMR, e_fmr=%p e_fmr->flags=%x", 909 + e_fmr, e_fmr->flags); 910 + ret = -EINVAL; 911 + goto free_fmr_exit0; 912 + } 913 + 914 + h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr); 915 + if (h_ret != H_SUCCESS) { 916 + ehca_err(fmr->device, "hipz_free_mr failed, h_ret=%lx e_fmr=%p " 917 + "hca_hndl=%lx fmr_hndl=%lx fmr->lkey=%x", 918 + h_ret, e_fmr, shca->ipz_hca_handle.handle, 919 + e_fmr->ipz_mr_handle.handle, fmr->lkey); 920 + ret = ehca_mrmw_map_hrc_free_mr(h_ret); 921 + goto free_fmr_exit0; 922 + } 923 + /* successful deregistration */ 924 + ehca_mr_delete(e_fmr); 925 + return 0; 926 + 927 + free_fmr_exit0: 928 + if (ret) 929 + ehca_err(&shca->ib_device, "ret=%x fmr=%p", ret, fmr); 930 + return ret; 931 + } /* end ehca_dealloc_fmr() */ 932 + 933 + /*----------------------------------------------------------------------*/ 934 + 935 + int ehca_reg_mr(struct ehca_shca *shca, 936 + struct ehca_mr *e_mr, 937 + u64 *iova_start, 938 + u64 size, 939 + int acl, 940 + struct ehca_pd *e_pd, 941 + struct ehca_mr_pginfo *pginfo, 942 + u32 *lkey, /*OUT*/ 943 + u32 *rkey) /*OUT*/ 944 + { 945 + int ret; 946 + u64 h_ret; 947 + u32 hipz_acl; 948 + struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0}; 949 + 950 + ehca_mrmw_map_acl(acl, &hipz_acl); 951 + ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl); 952 + if (ehca_use_hp_mr == 1) 953 + hipz_acl |= 0x00000001; 954 + 955 + h_ret = hipz_h_alloc_resource_mr(shca->ipz_hca_handle, e_mr, 956 + (u64)iova_start, size, hipz_acl, 957 + e_pd->fw_pd, &hipzout); 958 + if (h_ret != H_SUCCESS) { 959 + ehca_err(&shca->ib_device, "hipz_alloc_mr failed, h_ret=%lx " 960 + "hca_hndl=%lx", h_ret, shca->ipz_hca_handle.handle); 961 + ret = ehca_mrmw_map_hrc_alloc(h_ret); 962 + goto ehca_reg_mr_exit0; 963 + } 964 + 965 + e_mr->ipz_mr_handle = hipzout.handle; 966 + 967 + ret = ehca_reg_mr_rpages(shca, e_mr, pginfo); 968 + if (ret) 969 + goto ehca_reg_mr_exit1; 970 + 971 + /* successful registration */ 972 + e_mr->num_pages = pginfo->num_pages; 973 + e_mr->num_4k = pginfo->num_4k; 974 + e_mr->start = iova_start; 975 + e_mr->size = size; 976 + e_mr->acl = acl; 977 + *lkey = hipzout.lkey; 978 + *rkey = hipzout.rkey; 979 + return 0; 980 + 981 + ehca_reg_mr_exit1: 982 + h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr); 983 + if (h_ret != H_SUCCESS) { 984 + ehca_err(&shca->ib_device, "h_ret=%lx shca=%p e_mr=%p " 985 + "iova_start=%p size=%lx acl=%x e_pd=%p lkey=%x " 986 + "pginfo=%p num_pages=%lx num_4k=%lx ret=%x", 987 + h_ret, shca, e_mr, iova_start, size, acl, e_pd, 988 + hipzout.lkey, pginfo, pginfo->num_pages, 989 + pginfo->num_4k, ret); 990 + ehca_err(&shca->ib_device, "internal error in ehca_reg_mr, " 991 + "not recoverable"); 992 + } 993 + ehca_reg_mr_exit0: 994 + if (ret) 995 + ehca_err(&shca->ib_device, "ret=%x shca=%p e_mr=%p " 996 + "iova_start=%p size=%lx acl=%x e_pd=%p pginfo=%p " 997 + "num_pages=%lx num_4k=%lx", 998 + ret, shca, e_mr, iova_start, size, acl, e_pd, pginfo, 999 + pginfo->num_pages, pginfo->num_4k); 1000 + return ret; 1001 + } /* end ehca_reg_mr() */ 1002 + 1003 + /*----------------------------------------------------------------------*/ 1004 + 1005 + int ehca_reg_mr_rpages(struct ehca_shca *shca, 1006 + struct ehca_mr *e_mr, 1007 + struct ehca_mr_pginfo *pginfo) 1008 + { 1009 + int ret = 0; 1010 + u64 h_ret; 1011 + u32 rnum; 1012 + u64 rpage; 1013 + u32 i; 1014 + u64 *kpage; 1015 + 1016 + kpage = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); 1017 + if (!kpage) { 1018 + ehca_err(&shca->ib_device, "kpage alloc failed"); 1019 + ret = -ENOMEM; 1020 + goto ehca_reg_mr_rpages_exit0; 1021 + } 1022 + 1023 + /* max 512 pages per shot */ 1024 + for (i = 0; i < ((pginfo->num_4k + 512 - 1) / 512); i++) { 1025 + 1026 + if (i == ((pginfo->num_4k + 512 - 1) / 512) - 1) { 1027 + rnum = pginfo->num_4k % 512; /* last shot */ 1028 + if (rnum == 0) 1029 + rnum = 512; /* last shot is full */ 1030 + } else 1031 + rnum = 512; 1032 + 1033 + if (rnum > 1) { 1034 + ret = ehca_set_pagebuf(e_mr, pginfo, rnum, kpage); 1035 + if (ret) { 1036 + ehca_err(&shca->ib_device, "ehca_set_pagebuf " 1037 + "bad rc, ret=%x rnum=%x kpage=%p", 1038 + ret, rnum, kpage); 1039 + ret = -EFAULT; 1040 + goto ehca_reg_mr_rpages_exit1; 1041 + } 1042 + rpage = virt_to_abs(kpage); 1043 + if (!rpage) { 1044 + ehca_err(&shca->ib_device, "kpage=%p i=%x", 1045 + kpage, i); 1046 + ret = -EFAULT; 1047 + goto ehca_reg_mr_rpages_exit1; 1048 + } 1049 + } else { /* rnum==1 */ 1050 + ret = ehca_set_pagebuf_1(e_mr, pginfo, &rpage); 1051 + if (ret) { 1052 + ehca_err(&shca->ib_device, "ehca_set_pagebuf_1 " 1053 + "bad rc, ret=%x i=%x", ret, i); 1054 + ret = -EFAULT; 1055 + goto ehca_reg_mr_rpages_exit1; 1056 + } 1057 + } 1058 + 1059 + h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, e_mr, 1060 + 0, /* pagesize 4k */ 1061 + 0, rpage, rnum); 1062 + 1063 + if (i == ((pginfo->num_4k + 512 - 1) / 512) - 1) { 1064 + /* 1065 + * check for 'registration complete'==H_SUCCESS 1066 + * and for 'page registered'==H_PAGE_REGISTERED 1067 + */ 1068 + if (h_ret != H_SUCCESS) { 1069 + ehca_err(&shca->ib_device, "last " 1070 + "hipz_reg_rpage_mr failed, h_ret=%lx " 1071 + "e_mr=%p i=%x hca_hndl=%lx mr_hndl=%lx" 1072 + " lkey=%x", h_ret, e_mr, i, 1073 + shca->ipz_hca_handle.handle, 1074 + e_mr->ipz_mr_handle.handle, 1075 + e_mr->ib.ib_mr.lkey); 1076 + ret = ehca_mrmw_map_hrc_rrpg_last(h_ret); 1077 + break; 1078 + } else 1079 + ret = 0; 1080 + } else if (h_ret != H_PAGE_REGISTERED) { 1081 + ehca_err(&shca->ib_device, "hipz_reg_rpage_mr failed, " 1082 + "h_ret=%lx e_mr=%p i=%x lkey=%x hca_hndl=%lx " 1083 + "mr_hndl=%lx", h_ret, e_mr, i, 1084 + e_mr->ib.ib_mr.lkey, 1085 + shca->ipz_hca_handle.handle, 1086 + e_mr->ipz_mr_handle.handle); 1087 + ret = ehca_mrmw_map_hrc_rrpg_notlast(h_ret); 1088 + break; 1089 + } else 1090 + ret = 0; 1091 + } /* end for(i) */ 1092 + 1093 + 1094 + ehca_reg_mr_rpages_exit1: 1095 + kfree(kpage); 1096 + ehca_reg_mr_rpages_exit0: 1097 + if (ret) 1098 + ehca_err(&shca->ib_device, "ret=%x shca=%p e_mr=%p pginfo=%p " 1099 + "num_pages=%lx num_4k=%lx", ret, shca, e_mr, pginfo, 1100 + pginfo->num_pages, pginfo->num_4k); 1101 + return ret; 1102 + } /* end ehca_reg_mr_rpages() */ 1103 + 1104 + /*----------------------------------------------------------------------*/ 1105 + 1106 + inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca, 1107 + struct ehca_mr *e_mr, 1108 + u64 *iova_start, 1109 + u64 size, 1110 + u32 acl, 1111 + struct ehca_pd *e_pd, 1112 + struct ehca_mr_pginfo *pginfo, 1113 + u32 *lkey, /*OUT*/ 1114 + u32 *rkey) /*OUT*/ 1115 + { 1116 + int ret; 1117 + u64 h_ret; 1118 + u32 hipz_acl; 1119 + u64 *kpage; 1120 + u64 rpage; 1121 + struct ehca_mr_pginfo pginfo_save; 1122 + struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0}; 1123 + 1124 + ehca_mrmw_map_acl(acl, &hipz_acl); 1125 + ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl); 1126 + 1127 + kpage = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); 1128 + if (!kpage) { 1129 + ehca_err(&shca->ib_device, "kpage alloc failed"); 1130 + ret = -ENOMEM; 1131 + goto ehca_rereg_mr_rereg1_exit0; 1132 + } 1133 + 1134 + pginfo_save = *pginfo; 1135 + ret = ehca_set_pagebuf(e_mr, pginfo, pginfo->num_4k, kpage); 1136 + if (ret) { 1137 + ehca_err(&shca->ib_device, "set pagebuf failed, e_mr=%p " 1138 + "pginfo=%p type=%x num_pages=%lx num_4k=%lx kpage=%p", 1139 + e_mr, pginfo, pginfo->type, pginfo->num_pages, 1140 + pginfo->num_4k,kpage); 1141 + goto ehca_rereg_mr_rereg1_exit1; 1142 + } 1143 + rpage = virt_to_abs(kpage); 1144 + if (!rpage) { 1145 + ehca_err(&shca->ib_device, "kpage=%p", kpage); 1146 + ret = -EFAULT; 1147 + goto ehca_rereg_mr_rereg1_exit1; 1148 + } 1149 + h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_mr, 1150 + (u64)iova_start, size, hipz_acl, 1151 + e_pd->fw_pd, rpage, &hipzout); 1152 + if (h_ret != H_SUCCESS) { 1153 + /* 1154 + * reregistration unsuccessful, try it again with the 3 hCalls, 1155 + * e.g. this is required in case H_MR_CONDITION 1156 + * (MW bound or MR is shared) 1157 + */ 1158 + ehca_warn(&shca->ib_device, "hipz_h_reregister_pmr failed " 1159 + "(Rereg1), h_ret=%lx e_mr=%p", h_ret, e_mr); 1160 + *pginfo = pginfo_save; 1161 + ret = -EAGAIN; 1162 + } else if ((u64*)hipzout.vaddr != iova_start) { 1163 + ehca_err(&shca->ib_device, "PHYP changed iova_start in " 1164 + "rereg_pmr, iova_start=%p iova_start_out=%lx e_mr=%p " 1165 + "mr_handle=%lx lkey=%x lkey_out=%x", iova_start, 1166 + hipzout.vaddr, e_mr, e_mr->ipz_mr_handle.handle, 1167 + e_mr->ib.ib_mr.lkey, hipzout.lkey); 1168 + ret = -EFAULT; 1169 + } else { 1170 + /* 1171 + * successful reregistration 1172 + * note: start and start_out are identical for eServer HCAs 1173 + */ 1174 + e_mr->num_pages = pginfo->num_pages; 1175 + e_mr->num_4k = pginfo->num_4k; 1176 + e_mr->start = iova_start; 1177 + e_mr->size = size; 1178 + e_mr->acl = acl; 1179 + *lkey = hipzout.lkey; 1180 + *rkey = hipzout.rkey; 1181 + } 1182 + 1183 + ehca_rereg_mr_rereg1_exit1: 1184 + kfree(kpage); 1185 + ehca_rereg_mr_rereg1_exit0: 1186 + if ( ret && (ret != -EAGAIN) ) 1187 + ehca_err(&shca->ib_device, "ret=%x lkey=%x rkey=%x " 1188 + "pginfo=%p num_pages=%lx num_4k=%lx", 1189 + ret, *lkey, *rkey, pginfo, pginfo->num_pages, 1190 + pginfo->num_4k); 1191 + return ret; 1192 + } /* end ehca_rereg_mr_rereg1() */ 1193 + 1194 + /*----------------------------------------------------------------------*/ 1195 + 1196 + int ehca_rereg_mr(struct ehca_shca *shca, 1197 + struct ehca_mr *e_mr, 1198 + u64 *iova_start, 1199 + u64 size, 1200 + int acl, 1201 + struct ehca_pd *e_pd, 1202 + struct ehca_mr_pginfo *pginfo, 1203 + u32 *lkey, 1204 + u32 *rkey) 1205 + { 1206 + int ret = 0; 1207 + u64 h_ret; 1208 + int rereg_1_hcall = 1; /* 1: use hipz_h_reregister_pmr directly */ 1209 + int rereg_3_hcall = 0; /* 1: use 3 hipz calls for reregistration */ 1210 + 1211 + /* first determine reregistration hCall(s) */ 1212 + if ((pginfo->num_4k > 512) || (e_mr->num_4k > 512) || 1213 + (pginfo->num_4k > e_mr->num_4k)) { 1214 + ehca_dbg(&shca->ib_device, "Rereg3 case, pginfo->num_4k=%lx " 1215 + "e_mr->num_4k=%x", pginfo->num_4k, e_mr->num_4k); 1216 + rereg_1_hcall = 0; 1217 + rereg_3_hcall = 1; 1218 + } 1219 + 1220 + if (e_mr->flags & EHCA_MR_FLAG_MAXMR) { /* check for max-MR */ 1221 + rereg_1_hcall = 0; 1222 + rereg_3_hcall = 1; 1223 + e_mr->flags &= ~EHCA_MR_FLAG_MAXMR; 1224 + ehca_err(&shca->ib_device, "Rereg MR for max-MR! e_mr=%p", 1225 + e_mr); 1226 + } 1227 + 1228 + if (rereg_1_hcall) { 1229 + ret = ehca_rereg_mr_rereg1(shca, e_mr, iova_start, size, 1230 + acl, e_pd, pginfo, lkey, rkey); 1231 + if (ret) { 1232 + if (ret == -EAGAIN) 1233 + rereg_3_hcall = 1; 1234 + else 1235 + goto ehca_rereg_mr_exit0; 1236 + } 1237 + } 1238 + 1239 + if (rereg_3_hcall) { 1240 + struct ehca_mr save_mr; 1241 + 1242 + /* first deregister old MR */ 1243 + h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr); 1244 + if (h_ret != H_SUCCESS) { 1245 + ehca_err(&shca->ib_device, "hipz_free_mr failed, " 1246 + "h_ret=%lx e_mr=%p hca_hndl=%lx mr_hndl=%lx " 1247 + "mr->lkey=%x", 1248 + h_ret, e_mr, shca->ipz_hca_handle.handle, 1249 + e_mr->ipz_mr_handle.handle, 1250 + e_mr->ib.ib_mr.lkey); 1251 + ret = ehca_mrmw_map_hrc_free_mr(h_ret); 1252 + goto ehca_rereg_mr_exit0; 1253 + } 1254 + /* clean ehca_mr_t, without changing struct ib_mr and lock */ 1255 + save_mr = *e_mr; 1256 + ehca_mr_deletenew(e_mr); 1257 + 1258 + /* set some MR values */ 1259 + e_mr->flags = save_mr.flags; 1260 + e_mr->fmr_page_size = save_mr.fmr_page_size; 1261 + e_mr->fmr_max_pages = save_mr.fmr_max_pages; 1262 + e_mr->fmr_max_maps = save_mr.fmr_max_maps; 1263 + e_mr->fmr_map_cnt = save_mr.fmr_map_cnt; 1264 + 1265 + ret = ehca_reg_mr(shca, e_mr, iova_start, size, acl, 1266 + e_pd, pginfo, lkey, rkey); 1267 + if (ret) { 1268 + u32 offset = (u64)(&e_mr->flags) - (u64)e_mr; 1269 + memcpy(&e_mr->flags, &(save_mr.flags), 1270 + sizeof(struct ehca_mr) - offset); 1271 + goto ehca_rereg_mr_exit0; 1272 + } 1273 + } 1274 + 1275 + ehca_rereg_mr_exit0: 1276 + if (ret) 1277 + ehca_err(&shca->ib_device, "ret=%x shca=%p e_mr=%p " 1278 + "iova_start=%p size=%lx acl=%x e_pd=%p pginfo=%p " 1279 + "num_pages=%lx lkey=%x rkey=%x rereg_1_hcall=%x " 1280 + "rereg_3_hcall=%x", ret, shca, e_mr, iova_start, size, 1281 + acl, e_pd, pginfo, pginfo->num_pages, *lkey, *rkey, 1282 + rereg_1_hcall, rereg_3_hcall); 1283 + return ret; 1284 + } /* end ehca_rereg_mr() */ 1285 + 1286 + /*----------------------------------------------------------------------*/ 1287 + 1288 + int ehca_unmap_one_fmr(struct ehca_shca *shca, 1289 + struct ehca_mr *e_fmr) 1290 + { 1291 + int ret = 0; 1292 + u64 h_ret; 1293 + int rereg_1_hcall = 1; /* 1: use hipz_mr_reregister directly */ 1294 + int rereg_3_hcall = 0; /* 1: use 3 hipz calls for unmapping */ 1295 + struct ehca_pd *e_pd = 1296 + container_of(e_fmr->ib.ib_fmr.pd, struct ehca_pd, ib_pd); 1297 + struct ehca_mr save_fmr; 1298 + u32 tmp_lkey, tmp_rkey; 1299 + struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; 1300 + struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0}; 1301 + 1302 + /* first check if reregistration hCall can be used for unmap */ 1303 + if (e_fmr->fmr_max_pages > 512) { 1304 + rereg_1_hcall = 0; 1305 + rereg_3_hcall = 1; 1306 + } 1307 + 1308 + if (rereg_1_hcall) { 1309 + /* 1310 + * note: after using rereg hcall with len=0, 1311 + * rereg hcall must be used again for registering pages 1312 + */ 1313 + h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_fmr, 0, 1314 + 0, 0, e_pd->fw_pd, 0, &hipzout); 1315 + if (h_ret != H_SUCCESS) { 1316 + /* 1317 + * should not happen, because length checked above, 1318 + * FMRs are not shared and no MW bound to FMRs 1319 + */ 1320 + ehca_err(&shca->ib_device, "hipz_reregister_pmr failed " 1321 + "(Rereg1), h_ret=%lx e_fmr=%p hca_hndl=%lx " 1322 + "mr_hndl=%lx lkey=%x lkey_out=%x", 1323 + h_ret, e_fmr, shca->ipz_hca_handle.handle, 1324 + e_fmr->ipz_mr_handle.handle, 1325 + e_fmr->ib.ib_fmr.lkey, hipzout.lkey); 1326 + rereg_3_hcall = 1; 1327 + } else { 1328 + /* successful reregistration */ 1329 + e_fmr->start = NULL; 1330 + e_fmr->size = 0; 1331 + tmp_lkey = hipzout.lkey; 1332 + tmp_rkey = hipzout.rkey; 1333 + } 1334 + } 1335 + 1336 + if (rereg_3_hcall) { 1337 + struct ehca_mr save_mr; 1338 + 1339 + /* first free old FMR */ 1340 + h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr); 1341 + if (h_ret != H_SUCCESS) { 1342 + ehca_err(&shca->ib_device, "hipz_free_mr failed, " 1343 + "h_ret=%lx e_fmr=%p hca_hndl=%lx mr_hndl=%lx " 1344 + "lkey=%x", 1345 + h_ret, e_fmr, shca->ipz_hca_handle.handle, 1346 + e_fmr->ipz_mr_handle.handle, 1347 + e_fmr->ib.ib_fmr.lkey); 1348 + ret = ehca_mrmw_map_hrc_free_mr(h_ret); 1349 + goto ehca_unmap_one_fmr_exit0; 1350 + } 1351 + /* clean ehca_mr_t, without changing lock */ 1352 + save_fmr = *e_fmr; 1353 + ehca_mr_deletenew(e_fmr); 1354 + 1355 + /* set some MR values */ 1356 + e_fmr->flags = save_fmr.flags; 1357 + e_fmr->fmr_page_size = save_fmr.fmr_page_size; 1358 + e_fmr->fmr_max_pages = save_fmr.fmr_max_pages; 1359 + e_fmr->fmr_max_maps = save_fmr.fmr_max_maps; 1360 + e_fmr->fmr_map_cnt = save_fmr.fmr_map_cnt; 1361 + e_fmr->acl = save_fmr.acl; 1362 + 1363 + pginfo.type = EHCA_MR_PGI_FMR; 1364 + pginfo.num_pages = 0; 1365 + pginfo.num_4k = 0; 1366 + ret = ehca_reg_mr(shca, e_fmr, NULL, 1367 + (e_fmr->fmr_max_pages * e_fmr->fmr_page_size), 1368 + e_fmr->acl, e_pd, &pginfo, &tmp_lkey, 1369 + &tmp_rkey); 1370 + if (ret) { 1371 + u32 offset = (u64)(&e_fmr->flags) - (u64)e_fmr; 1372 + memcpy(&e_fmr->flags, &(save_mr.flags), 1373 + sizeof(struct ehca_mr) - offset); 1374 + goto ehca_unmap_one_fmr_exit0; 1375 + } 1376 + } 1377 + 1378 + ehca_unmap_one_fmr_exit0: 1379 + if (ret) 1380 + ehca_err(&shca->ib_device, "ret=%x tmp_lkey=%x tmp_rkey=%x " 1381 + "fmr_max_pages=%x rereg_1_hcall=%x rereg_3_hcall=%x", 1382 + ret, tmp_lkey, tmp_rkey, e_fmr->fmr_max_pages, 1383 + rereg_1_hcall, rereg_3_hcall); 1384 + return ret; 1385 + } /* end ehca_unmap_one_fmr() */ 1386 + 1387 + /*----------------------------------------------------------------------*/ 1388 + 1389 + int ehca_reg_smr(struct ehca_shca *shca, 1390 + struct ehca_mr *e_origmr, 1391 + struct ehca_mr *e_newmr, 1392 + u64 *iova_start, 1393 + int acl, 1394 + struct ehca_pd *e_pd, 1395 + u32 *lkey, /*OUT*/ 1396 + u32 *rkey) /*OUT*/ 1397 + { 1398 + int ret = 0; 1399 + u64 h_ret; 1400 + u32 hipz_acl; 1401 + struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0}; 1402 + 1403 + ehca_mrmw_map_acl(acl, &hipz_acl); 1404 + ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl); 1405 + 1406 + h_ret = hipz_h_register_smr(shca->ipz_hca_handle, e_newmr, e_origmr, 1407 + (u64)iova_start, hipz_acl, e_pd->fw_pd, 1408 + &hipzout); 1409 + if (h_ret != H_SUCCESS) { 1410 + ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%lx " 1411 + "shca=%p e_origmr=%p e_newmr=%p iova_start=%p acl=%x " 1412 + "e_pd=%p hca_hndl=%lx mr_hndl=%lx lkey=%x", 1413 + h_ret, shca, e_origmr, e_newmr, iova_start, acl, e_pd, 1414 + shca->ipz_hca_handle.handle, 1415 + e_origmr->ipz_mr_handle.handle, 1416 + e_origmr->ib.ib_mr.lkey); 1417 + ret = ehca_mrmw_map_hrc_reg_smr(h_ret); 1418 + goto ehca_reg_smr_exit0; 1419 + } 1420 + /* successful registration */ 1421 + e_newmr->num_pages = e_origmr->num_pages; 1422 + e_newmr->num_4k = e_origmr->num_4k; 1423 + e_newmr->start = iova_start; 1424 + e_newmr->size = e_origmr->size; 1425 + e_newmr->acl = acl; 1426 + e_newmr->ipz_mr_handle = hipzout.handle; 1427 + *lkey = hipzout.lkey; 1428 + *rkey = hipzout.rkey; 1429 + return 0; 1430 + 1431 + ehca_reg_smr_exit0: 1432 + if (ret) 1433 + ehca_err(&shca->ib_device, "ret=%x shca=%p e_origmr=%p " 1434 + "e_newmr=%p iova_start=%p acl=%x e_pd=%p", 1435 + ret, shca, e_origmr, e_newmr, iova_start, acl, e_pd); 1436 + return ret; 1437 + } /* end ehca_reg_smr() */ 1438 + 1439 + /*----------------------------------------------------------------------*/ 1440 + 1441 + /* register internal max-MR to internal SHCA */ 1442 + int ehca_reg_internal_maxmr( 1443 + struct ehca_shca *shca, 1444 + struct ehca_pd *e_pd, 1445 + struct ehca_mr **e_maxmr) /*OUT*/ 1446 + { 1447 + int ret; 1448 + struct ehca_mr *e_mr; 1449 + u64 *iova_start; 1450 + u64 size_maxmr; 1451 + struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; 1452 + struct ib_phys_buf ib_pbuf; 1453 + u32 num_pages_mr; 1454 + u32 num_pages_4k; /* 4k portion "pages" */ 1455 + 1456 + e_mr = ehca_mr_new(); 1457 + if (!e_mr) { 1458 + ehca_err(&shca->ib_device, "out of memory"); 1459 + ret = -ENOMEM; 1460 + goto ehca_reg_internal_maxmr_exit0; 1461 + } 1462 + e_mr->flags |= EHCA_MR_FLAG_MAXMR; 1463 + 1464 + /* register internal max-MR on HCA */ 1465 + size_maxmr = (u64)high_memory - PAGE_OFFSET; 1466 + iova_start = (u64*)KERNELBASE; 1467 + ib_pbuf.addr = 0; 1468 + ib_pbuf.size = size_maxmr; 1469 + num_pages_mr = ((((u64)iova_start % PAGE_SIZE) + size_maxmr + 1470 + PAGE_SIZE - 1) / PAGE_SIZE); 1471 + num_pages_4k = ((((u64)iova_start % EHCA_PAGESIZE) + size_maxmr + 1472 + EHCA_PAGESIZE - 1) / EHCA_PAGESIZE); 1473 + 1474 + pginfo.type = EHCA_MR_PGI_PHYS; 1475 + pginfo.num_pages = num_pages_mr; 1476 + pginfo.num_4k = num_pages_4k; 1477 + pginfo.num_phys_buf = 1; 1478 + pginfo.phys_buf_array = &ib_pbuf; 1479 + 1480 + ret = ehca_reg_mr(shca, e_mr, iova_start, size_maxmr, 0, e_pd, 1481 + &pginfo, &e_mr->ib.ib_mr.lkey, 1482 + &e_mr->ib.ib_mr.rkey); 1483 + if (ret) { 1484 + ehca_err(&shca->ib_device, "reg of internal max MR failed, " 1485 + "e_mr=%p iova_start=%p size_maxmr=%lx num_pages_mr=%x " 1486 + "num_pages_4k=%x", e_mr, iova_start, size_maxmr, 1487 + num_pages_mr, num_pages_4k); 1488 + goto ehca_reg_internal_maxmr_exit1; 1489 + } 1490 + 1491 + /* successful registration of all pages */ 1492 + e_mr->ib.ib_mr.device = e_pd->ib_pd.device; 1493 + e_mr->ib.ib_mr.pd = &e_pd->ib_pd; 1494 + e_mr->ib.ib_mr.uobject = NULL; 1495 + atomic_inc(&(e_pd->ib_pd.usecnt)); 1496 + atomic_set(&(e_mr->ib.ib_mr.usecnt), 0); 1497 + *e_maxmr = e_mr; 1498 + return 0; 1499 + 1500 + ehca_reg_internal_maxmr_exit1: 1501 + ehca_mr_delete(e_mr); 1502 + ehca_reg_internal_maxmr_exit0: 1503 + if (ret) 1504 + ehca_err(&shca->ib_device, "ret=%x shca=%p e_pd=%p e_maxmr=%p", 1505 + ret, shca, e_pd, e_maxmr); 1506 + return ret; 1507 + } /* end ehca_reg_internal_maxmr() */ 1508 + 1509 + /*----------------------------------------------------------------------*/ 1510 + 1511 + int ehca_reg_maxmr(struct ehca_shca *shca, 1512 + struct ehca_mr *e_newmr, 1513 + u64 *iova_start, 1514 + int acl, 1515 + struct ehca_pd *e_pd, 1516 + u32 *lkey, 1517 + u32 *rkey) 1518 + { 1519 + u64 h_ret; 1520 + struct ehca_mr *e_origmr = shca->maxmr; 1521 + u32 hipz_acl; 1522 + struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0}; 1523 + 1524 + ehca_mrmw_map_acl(acl, &hipz_acl); 1525 + ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl); 1526 + 1527 + h_ret = hipz_h_register_smr(shca->ipz_hca_handle, e_newmr, e_origmr, 1528 + (u64)iova_start, hipz_acl, e_pd->fw_pd, 1529 + &hipzout); 1530 + if (h_ret != H_SUCCESS) { 1531 + ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%lx " 1532 + "e_origmr=%p hca_hndl=%lx mr_hndl=%lx lkey=%x", 1533 + h_ret, e_origmr, shca->ipz_hca_handle.handle, 1534 + e_origmr->ipz_mr_handle.handle, 1535 + e_origmr->ib.ib_mr.lkey); 1536 + return ehca_mrmw_map_hrc_reg_smr(h_ret); 1537 + } 1538 + /* successful registration */ 1539 + e_newmr->num_pages = e_origmr->num_pages; 1540 + e_newmr->num_4k = e_origmr->num_4k; 1541 + e_newmr->start = iova_start; 1542 + e_newmr->size = e_origmr->size; 1543 + e_newmr->acl = acl; 1544 + e_newmr->ipz_mr_handle = hipzout.handle; 1545 + *lkey = hipzout.lkey; 1546 + *rkey = hipzout.rkey; 1547 + return 0; 1548 + } /* end ehca_reg_maxmr() */ 1549 + 1550 + /*----------------------------------------------------------------------*/ 1551 + 1552 + int ehca_dereg_internal_maxmr(struct ehca_shca *shca) 1553 + { 1554 + int ret; 1555 + struct ehca_mr *e_maxmr; 1556 + struct ib_pd *ib_pd; 1557 + 1558 + if (!shca->maxmr) { 1559 + ehca_err(&shca->ib_device, "bad call, shca=%p", shca); 1560 + ret = -EINVAL; 1561 + goto ehca_dereg_internal_maxmr_exit0; 1562 + } 1563 + 1564 + e_maxmr = shca->maxmr; 1565 + ib_pd = e_maxmr->ib.ib_mr.pd; 1566 + shca->maxmr = NULL; /* remove internal max-MR indication from SHCA */ 1567 + 1568 + ret = ehca_dereg_mr(&e_maxmr->ib.ib_mr); 1569 + if (ret) { 1570 + ehca_err(&shca->ib_device, "dereg internal max-MR failed, " 1571 + "ret=%x e_maxmr=%p shca=%p lkey=%x", 1572 + ret, e_maxmr, shca, e_maxmr->ib.ib_mr.lkey); 1573 + shca->maxmr = e_maxmr; 1574 + goto ehca_dereg_internal_maxmr_exit0; 1575 + } 1576 + 1577 + atomic_dec(&ib_pd->usecnt); 1578 + 1579 + ehca_dereg_internal_maxmr_exit0: 1580 + if (ret) 1581 + ehca_err(&shca->ib_device, "ret=%x shca=%p shca->maxmr=%p", 1582 + ret, shca, shca->maxmr); 1583 + return ret; 1584 + } /* end ehca_dereg_internal_maxmr() */ 1585 + 1586 + /*----------------------------------------------------------------------*/ 1587 + 1588 + /* 1589 + * check physical buffer array of MR verbs for validness and 1590 + * calculates MR size 1591 + */ 1592 + int ehca_mr_chk_buf_and_calc_size(struct ib_phys_buf *phys_buf_array, 1593 + int num_phys_buf, 1594 + u64 *iova_start, 1595 + u64 *size) 1596 + { 1597 + struct ib_phys_buf *pbuf = phys_buf_array; 1598 + u64 size_count = 0; 1599 + u32 i; 1600 + 1601 + if (num_phys_buf == 0) { 1602 + ehca_gen_err("bad phys buf array len, num_phys_buf=0"); 1603 + return -EINVAL; 1604 + } 1605 + /* check first buffer */ 1606 + if (((u64)iova_start & ~PAGE_MASK) != (pbuf->addr & ~PAGE_MASK)) { 1607 + ehca_gen_err("iova_start/addr mismatch, iova_start=%p " 1608 + "pbuf->addr=%lx pbuf->size=%lx", 1609 + iova_start, pbuf->addr, pbuf->size); 1610 + return -EINVAL; 1611 + } 1612 + if (((pbuf->addr + pbuf->size) % PAGE_SIZE) && 1613 + (num_phys_buf > 1)) { 1614 + ehca_gen_err("addr/size mismatch in 1st buf, pbuf->addr=%lx " 1615 + "pbuf->size=%lx", pbuf->addr, pbuf->size); 1616 + return -EINVAL; 1617 + } 1618 + 1619 + for (i = 0; i < num_phys_buf; i++) { 1620 + if ((i > 0) && (pbuf->addr % PAGE_SIZE)) { 1621 + ehca_gen_err("bad address, i=%x pbuf->addr=%lx " 1622 + "pbuf->size=%lx", 1623 + i, pbuf->addr, pbuf->size); 1624 + return -EINVAL; 1625 + } 1626 + if (((i > 0) && /* not 1st */ 1627 + (i < (num_phys_buf - 1)) && /* not last */ 1628 + (pbuf->size % PAGE_SIZE)) || (pbuf->size == 0)) { 1629 + ehca_gen_err("bad size, i=%x pbuf->size=%lx", 1630 + i, pbuf->size); 1631 + return -EINVAL; 1632 + } 1633 + size_count += pbuf->size; 1634 + pbuf++; 1635 + } 1636 + 1637 + *size = size_count; 1638 + return 0; 1639 + } /* end ehca_mr_chk_buf_and_calc_size() */ 1640 + 1641 + /*----------------------------------------------------------------------*/ 1642 + 1643 + /* check page list of map FMR verb for validness */ 1644 + int ehca_fmr_check_page_list(struct ehca_mr *e_fmr, 1645 + u64 *page_list, 1646 + int list_len) 1647 + { 1648 + u32 i; 1649 + u64 *page; 1650 + 1651 + if ((list_len == 0) || (list_len > e_fmr->fmr_max_pages)) { 1652 + ehca_gen_err("bad list_len, list_len=%x " 1653 + "e_fmr->fmr_max_pages=%x fmr=%p", 1654 + list_len, e_fmr->fmr_max_pages, e_fmr); 1655 + return -EINVAL; 1656 + } 1657 + 1658 + /* each page must be aligned */ 1659 + page = page_list; 1660 + for (i = 0; i < list_len; i++) { 1661 + if (*page % e_fmr->fmr_page_size) { 1662 + ehca_gen_err("bad page, i=%x *page=%lx page=%p fmr=%p " 1663 + "fmr_page_size=%x", i, *page, page, e_fmr, 1664 + e_fmr->fmr_page_size); 1665 + return -EINVAL; 1666 + } 1667 + page++; 1668 + } 1669 + 1670 + return 0; 1671 + } /* end ehca_fmr_check_page_list() */ 1672 + 1673 + /*----------------------------------------------------------------------*/ 1674 + 1675 + /* setup page buffer from page info */ 1676 + int ehca_set_pagebuf(struct ehca_mr *e_mr, 1677 + struct ehca_mr_pginfo *pginfo, 1678 + u32 number, 1679 + u64 *kpage) 1680 + { 1681 + int ret = 0; 1682 + struct ib_umem_chunk *prev_chunk; 1683 + struct ib_umem_chunk *chunk; 1684 + struct ib_phys_buf *pbuf; 1685 + u64 *fmrlist; 1686 + u64 num4k, pgaddr, offs4k; 1687 + u32 i = 0; 1688 + u32 j = 0; 1689 + 1690 + if (pginfo->type == EHCA_MR_PGI_PHYS) { 1691 + /* loop over desired phys_buf_array entries */ 1692 + while (i < number) { 1693 + pbuf = pginfo->phys_buf_array + pginfo->next_buf; 1694 + num4k = ((pbuf->addr % EHCA_PAGESIZE) + pbuf->size + 1695 + EHCA_PAGESIZE - 1) / EHCA_PAGESIZE; 1696 + offs4k = (pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE; 1697 + while (pginfo->next_4k < offs4k + num4k) { 1698 + /* sanity check */ 1699 + if ((pginfo->page_cnt >= pginfo->num_pages) || 1700 + (pginfo->page_4k_cnt >= pginfo->num_4k)) { 1701 + ehca_gen_err("page_cnt >= num_pages, " 1702 + "page_cnt=%lx " 1703 + "num_pages=%lx " 1704 + "page_4k_cnt=%lx " 1705 + "num_4k=%lx i=%x", 1706 + pginfo->page_cnt, 1707 + pginfo->num_pages, 1708 + pginfo->page_4k_cnt, 1709 + pginfo->num_4k, i); 1710 + ret = -EFAULT; 1711 + goto ehca_set_pagebuf_exit0; 1712 + } 1713 + *kpage = phys_to_abs( 1714 + (pbuf->addr & EHCA_PAGEMASK) 1715 + + (pginfo->next_4k * EHCA_PAGESIZE)); 1716 + if ( !(*kpage) && pbuf->addr ) { 1717 + ehca_gen_err("pbuf->addr=%lx " 1718 + "pbuf->size=%lx " 1719 + "next_4k=%lx", pbuf->addr, 1720 + pbuf->size, 1721 + pginfo->next_4k); 1722 + ret = -EFAULT; 1723 + goto ehca_set_pagebuf_exit0; 1724 + } 1725 + (pginfo->page_4k_cnt)++; 1726 + (pginfo->next_4k)++; 1727 + if (pginfo->next_4k % 1728 + (PAGE_SIZE / EHCA_PAGESIZE) == 0) 1729 + (pginfo->page_cnt)++; 1730 + kpage++; 1731 + i++; 1732 + if (i >= number) break; 1733 + } 1734 + if (pginfo->next_4k >= offs4k + num4k) { 1735 + (pginfo->next_buf)++; 1736 + pginfo->next_4k = 0; 1737 + } 1738 + } 1739 + } else if (pginfo->type == EHCA_MR_PGI_USER) { 1740 + /* loop over desired chunk entries */ 1741 + chunk = pginfo->next_chunk; 1742 + prev_chunk = pginfo->next_chunk; 1743 + list_for_each_entry_continue(chunk, 1744 + (&(pginfo->region->chunk_list)), 1745 + list) { 1746 + for (i = pginfo->next_nmap; i < chunk->nmap; ) { 1747 + pgaddr = ( page_to_pfn(chunk->page_list[i].page) 1748 + << PAGE_SHIFT ); 1749 + *kpage = phys_to_abs(pgaddr + 1750 + (pginfo->next_4k * 1751 + EHCA_PAGESIZE)); 1752 + if ( !(*kpage) ) { 1753 + ehca_gen_err("pgaddr=%lx " 1754 + "chunk->page_list[i]=%lx " 1755 + "i=%x next_4k=%lx mr=%p", 1756 + pgaddr, 1757 + (u64)sg_dma_address( 1758 + &chunk-> 1759 + page_list[i]), 1760 + i, pginfo->next_4k, e_mr); 1761 + ret = -EFAULT; 1762 + goto ehca_set_pagebuf_exit0; 1763 + } 1764 + (pginfo->page_4k_cnt)++; 1765 + (pginfo->next_4k)++; 1766 + kpage++; 1767 + if (pginfo->next_4k % 1768 + (PAGE_SIZE / EHCA_PAGESIZE) == 0) { 1769 + (pginfo->page_cnt)++; 1770 + (pginfo->next_nmap)++; 1771 + pginfo->next_4k = 0; 1772 + i++; 1773 + } 1774 + j++; 1775 + if (j >= number) break; 1776 + } 1777 + if ((pginfo->next_nmap >= chunk->nmap) && 1778 + (j >= number)) { 1779 + pginfo->next_nmap = 0; 1780 + prev_chunk = chunk; 1781 + break; 1782 + } else if (pginfo->next_nmap >= chunk->nmap) { 1783 + pginfo->next_nmap = 0; 1784 + prev_chunk = chunk; 1785 + } else if (j >= number) 1786 + break; 1787 + else 1788 + prev_chunk = chunk; 1789 + } 1790 + pginfo->next_chunk = 1791 + list_prepare_entry(prev_chunk, 1792 + (&(pginfo->region->chunk_list)), 1793 + list); 1794 + } else if (pginfo->type == EHCA_MR_PGI_FMR) { 1795 + /* loop over desired page_list entries */ 1796 + fmrlist = pginfo->page_list + pginfo->next_listelem; 1797 + for (i = 0; i < number; i++) { 1798 + *kpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) + 1799 + pginfo->next_4k * EHCA_PAGESIZE); 1800 + if ( !(*kpage) ) { 1801 + ehca_gen_err("*fmrlist=%lx fmrlist=%p " 1802 + "next_listelem=%lx next_4k=%lx", 1803 + *fmrlist, fmrlist, 1804 + pginfo->next_listelem, 1805 + pginfo->next_4k); 1806 + ret = -EFAULT; 1807 + goto ehca_set_pagebuf_exit0; 1808 + } 1809 + (pginfo->page_4k_cnt)++; 1810 + (pginfo->next_4k)++; 1811 + kpage++; 1812 + if (pginfo->next_4k % 1813 + (e_mr->fmr_page_size / EHCA_PAGESIZE) == 0) { 1814 + (pginfo->page_cnt)++; 1815 + (pginfo->next_listelem)++; 1816 + fmrlist++; 1817 + pginfo->next_4k = 0; 1818 + } 1819 + } 1820 + } else { 1821 + ehca_gen_err("bad pginfo->type=%x", pginfo->type); 1822 + ret = -EFAULT; 1823 + goto ehca_set_pagebuf_exit0; 1824 + } 1825 + 1826 + ehca_set_pagebuf_exit0: 1827 + if (ret) 1828 + ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_pages=%lx " 1829 + "num_4k=%lx next_buf=%lx next_4k=%lx number=%x " 1830 + "kpage=%p page_cnt=%lx page_4k_cnt=%lx i=%x " 1831 + "next_listelem=%lx region=%p next_chunk=%p " 1832 + "next_nmap=%lx", ret, e_mr, pginfo, pginfo->type, 1833 + pginfo->num_pages, pginfo->num_4k, 1834 + pginfo->next_buf, pginfo->next_4k, number, kpage, 1835 + pginfo->page_cnt, pginfo->page_4k_cnt, i, 1836 + pginfo->next_listelem, pginfo->region, 1837 + pginfo->next_chunk, pginfo->next_nmap); 1838 + return ret; 1839 + } /* end ehca_set_pagebuf() */ 1840 + 1841 + /*----------------------------------------------------------------------*/ 1842 + 1843 + /* setup 1 page from page info page buffer */ 1844 + int ehca_set_pagebuf_1(struct ehca_mr *e_mr, 1845 + struct ehca_mr_pginfo *pginfo, 1846 + u64 *rpage) 1847 + { 1848 + int ret = 0; 1849 + struct ib_phys_buf *tmp_pbuf; 1850 + u64 *fmrlist; 1851 + struct ib_umem_chunk *chunk; 1852 + struct ib_umem_chunk *prev_chunk; 1853 + u64 pgaddr, num4k, offs4k; 1854 + 1855 + if (pginfo->type == EHCA_MR_PGI_PHYS) { 1856 + /* sanity check */ 1857 + if ((pginfo->page_cnt >= pginfo->num_pages) || 1858 + (pginfo->page_4k_cnt >= pginfo->num_4k)) { 1859 + ehca_gen_err("page_cnt >= num_pages, page_cnt=%lx " 1860 + "num_pages=%lx page_4k_cnt=%lx num_4k=%lx", 1861 + pginfo->page_cnt, pginfo->num_pages, 1862 + pginfo->page_4k_cnt, pginfo->num_4k); 1863 + ret = -EFAULT; 1864 + goto ehca_set_pagebuf_1_exit0; 1865 + } 1866 + tmp_pbuf = pginfo->phys_buf_array + pginfo->next_buf; 1867 + num4k = ((tmp_pbuf->addr % EHCA_PAGESIZE) + tmp_pbuf->size + 1868 + EHCA_PAGESIZE - 1) / EHCA_PAGESIZE; 1869 + offs4k = (tmp_pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE; 1870 + *rpage = phys_to_abs((tmp_pbuf->addr & EHCA_PAGEMASK) + 1871 + (pginfo->next_4k * EHCA_PAGESIZE)); 1872 + if ( !(*rpage) && tmp_pbuf->addr ) { 1873 + ehca_gen_err("tmp_pbuf->addr=%lx" 1874 + " tmp_pbuf->size=%lx next_4k=%lx", 1875 + tmp_pbuf->addr, tmp_pbuf->size, 1876 + pginfo->next_4k); 1877 + ret = -EFAULT; 1878 + goto ehca_set_pagebuf_1_exit0; 1879 + } 1880 + (pginfo->page_4k_cnt)++; 1881 + (pginfo->next_4k)++; 1882 + if (pginfo->next_4k % (PAGE_SIZE / EHCA_PAGESIZE) == 0) 1883 + (pginfo->page_cnt)++; 1884 + if (pginfo->next_4k >= offs4k + num4k) { 1885 + (pginfo->next_buf)++; 1886 + pginfo->next_4k = 0; 1887 + } 1888 + } else if (pginfo->type == EHCA_MR_PGI_USER) { 1889 + chunk = pginfo->next_chunk; 1890 + prev_chunk = pginfo->next_chunk; 1891 + list_for_each_entry_continue(chunk, 1892 + (&(pginfo->region->chunk_list)), 1893 + list) { 1894 + pgaddr = ( page_to_pfn(chunk->page_list[ 1895 + pginfo->next_nmap].page) 1896 + << PAGE_SHIFT); 1897 + *rpage = phys_to_abs(pgaddr + 1898 + (pginfo->next_4k * EHCA_PAGESIZE)); 1899 + if ( !(*rpage) ) { 1900 + ehca_gen_err("pgaddr=%lx chunk->page_list[]=%lx" 1901 + " next_nmap=%lx next_4k=%lx mr=%p", 1902 + pgaddr, (u64)sg_dma_address( 1903 + &chunk->page_list[ 1904 + pginfo-> 1905 + next_nmap]), 1906 + pginfo->next_nmap, pginfo->next_4k, 1907 + e_mr); 1908 + ret = -EFAULT; 1909 + goto ehca_set_pagebuf_1_exit0; 1910 + } 1911 + (pginfo->page_4k_cnt)++; 1912 + (pginfo->next_4k)++; 1913 + if (pginfo->next_4k % 1914 + (PAGE_SIZE / EHCA_PAGESIZE) == 0) { 1915 + (pginfo->page_cnt)++; 1916 + (pginfo->next_nmap)++; 1917 + pginfo->next_4k = 0; 1918 + } 1919 + if (pginfo->next_nmap >= chunk->nmap) { 1920 + pginfo->next_nmap = 0; 1921 + prev_chunk = chunk; 1922 + } 1923 + break; 1924 + } 1925 + pginfo->next_chunk = 1926 + list_prepare_entry(prev_chunk, 1927 + (&(pginfo->region->chunk_list)), 1928 + list); 1929 + } else if (pginfo->type == EHCA_MR_PGI_FMR) { 1930 + fmrlist = pginfo->page_list + pginfo->next_listelem; 1931 + *rpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) + 1932 + pginfo->next_4k * EHCA_PAGESIZE); 1933 + if ( !(*rpage) ) { 1934 + ehca_gen_err("*fmrlist=%lx fmrlist=%p " 1935 + "next_listelem=%lx next_4k=%lx", 1936 + *fmrlist, fmrlist, pginfo->next_listelem, 1937 + pginfo->next_4k); 1938 + ret = -EFAULT; 1939 + goto ehca_set_pagebuf_1_exit0; 1940 + } 1941 + (pginfo->page_4k_cnt)++; 1942 + (pginfo->next_4k)++; 1943 + if (pginfo->next_4k % 1944 + (e_mr->fmr_page_size / EHCA_PAGESIZE) == 0) { 1945 + (pginfo->page_cnt)++; 1946 + (pginfo->next_listelem)++; 1947 + pginfo->next_4k = 0; 1948 + } 1949 + } else { 1950 + ehca_gen_err("bad pginfo->type=%x", pginfo->type); 1951 + ret = -EFAULT; 1952 + goto ehca_set_pagebuf_1_exit0; 1953 + } 1954 + 1955 + ehca_set_pagebuf_1_exit0: 1956 + if (ret) 1957 + ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_pages=%lx " 1958 + "num_4k=%lx next_buf=%lx next_4k=%lx rpage=%p " 1959 + "page_cnt=%lx page_4k_cnt=%lx next_listelem=%lx " 1960 + "region=%p next_chunk=%p next_nmap=%lx", ret, e_mr, 1961 + pginfo, pginfo->type, pginfo->num_pages, 1962 + pginfo->num_4k, pginfo->next_buf, pginfo->next_4k, 1963 + rpage, pginfo->page_cnt, pginfo->page_4k_cnt, 1964 + pginfo->next_listelem, pginfo->region, 1965 + pginfo->next_chunk, pginfo->next_nmap); 1966 + return ret; 1967 + } /* end ehca_set_pagebuf_1() */ 1968 + 1969 + /*----------------------------------------------------------------------*/ 1970 + 1971 + /* 1972 + * check MR if it is a max-MR, i.e. uses whole memory 1973 + * in case it's a max-MR 1 is returned, else 0 1974 + */ 1975 + int ehca_mr_is_maxmr(u64 size, 1976 + u64 *iova_start) 1977 + { 1978 + /* a MR is treated as max-MR only if it fits following: */ 1979 + if ((size == ((u64)high_memory - PAGE_OFFSET)) && 1980 + (iova_start == (void*)KERNELBASE)) { 1981 + ehca_gen_dbg("this is a max-MR"); 1982 + return 1; 1983 + } else 1984 + return 0; 1985 + } /* end ehca_mr_is_maxmr() */ 1986 + 1987 + /*----------------------------------------------------------------------*/ 1988 + 1989 + /* map access control for MR/MW. This routine is used for MR and MW. */ 1990 + void ehca_mrmw_map_acl(int ib_acl, 1991 + u32 *hipz_acl) 1992 + { 1993 + *hipz_acl = 0; 1994 + if (ib_acl & IB_ACCESS_REMOTE_READ) 1995 + *hipz_acl |= HIPZ_ACCESSCTRL_R_READ; 1996 + if (ib_acl & IB_ACCESS_REMOTE_WRITE) 1997 + *hipz_acl |= HIPZ_ACCESSCTRL_R_WRITE; 1998 + if (ib_acl & IB_ACCESS_REMOTE_ATOMIC) 1999 + *hipz_acl |= HIPZ_ACCESSCTRL_R_ATOMIC; 2000 + if (ib_acl & IB_ACCESS_LOCAL_WRITE) 2001 + *hipz_acl |= HIPZ_ACCESSCTRL_L_WRITE; 2002 + if (ib_acl & IB_ACCESS_MW_BIND) 2003 + *hipz_acl |= HIPZ_ACCESSCTRL_MW_BIND; 2004 + } /* end ehca_mrmw_map_acl() */ 2005 + 2006 + /*----------------------------------------------------------------------*/ 2007 + 2008 + /* sets page size in hipz access control for MR/MW. */ 2009 + void ehca_mrmw_set_pgsize_hipz_acl(u32 *hipz_acl) /*INOUT*/ 2010 + { 2011 + return; /* HCA supports only 4k */ 2012 + } /* end ehca_mrmw_set_pgsize_hipz_acl() */ 2013 + 2014 + /*----------------------------------------------------------------------*/ 2015 + 2016 + /* 2017 + * reverse map access control for MR/MW. 2018 + * This routine is used for MR and MW. 2019 + */ 2020 + void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl, 2021 + int *ib_acl) /*OUT*/ 2022 + { 2023 + *ib_acl = 0; 2024 + if (*hipz_acl & HIPZ_ACCESSCTRL_R_READ) 2025 + *ib_acl |= IB_ACCESS_REMOTE_READ; 2026 + if (*hipz_acl & HIPZ_ACCESSCTRL_R_WRITE) 2027 + *ib_acl |= IB_ACCESS_REMOTE_WRITE; 2028 + if (*hipz_acl & HIPZ_ACCESSCTRL_R_ATOMIC) 2029 + *ib_acl |= IB_ACCESS_REMOTE_ATOMIC; 2030 + if (*hipz_acl & HIPZ_ACCESSCTRL_L_WRITE) 2031 + *ib_acl |= IB_ACCESS_LOCAL_WRITE; 2032 + if (*hipz_acl & HIPZ_ACCESSCTRL_MW_BIND) 2033 + *ib_acl |= IB_ACCESS_MW_BIND; 2034 + } /* end ehca_mrmw_reverse_map_acl() */ 2035 + 2036 + 2037 + /*----------------------------------------------------------------------*/ 2038 + 2039 + /* 2040 + * map HIPZ rc to IB retcodes for MR/MW allocations 2041 + * Used for hipz_mr_reg_alloc and hipz_mw_alloc. 2042 + */ 2043 + int ehca_mrmw_map_hrc_alloc(const u64 hipz_rc) 2044 + { 2045 + switch (hipz_rc) { 2046 + case H_SUCCESS: /* successful completion */ 2047 + return 0; 2048 + case H_ADAPTER_PARM: /* invalid adapter handle */ 2049 + case H_RT_PARM: /* invalid resource type */ 2050 + case H_NOT_ENOUGH_RESOURCES: /* insufficient resources */ 2051 + case H_MLENGTH_PARM: /* invalid memory length */ 2052 + case H_MEM_ACCESS_PARM: /* invalid access controls */ 2053 + case H_CONSTRAINED: /* resource constraint */ 2054 + return -EINVAL; 2055 + case H_BUSY: /* long busy */ 2056 + return -EBUSY; 2057 + default: 2058 + return -EINVAL; 2059 + } 2060 + } /* end ehca_mrmw_map_hrc_alloc() */ 2061 + 2062 + /*----------------------------------------------------------------------*/ 2063 + 2064 + /* 2065 + * map HIPZ rc to IB retcodes for MR register rpage 2066 + * Used for hipz_h_register_rpage_mr at registering last page 2067 + */ 2068 + int ehca_mrmw_map_hrc_rrpg_last(const u64 hipz_rc) 2069 + { 2070 + switch (hipz_rc) { 2071 + case H_SUCCESS: /* registration complete */ 2072 + return 0; 2073 + case H_PAGE_REGISTERED: /* page registered */ 2074 + case H_ADAPTER_PARM: /* invalid adapter handle */ 2075 + case H_RH_PARM: /* invalid resource handle */ 2076 + /* case H_QT_PARM: invalid queue type */ 2077 + case H_PARAMETER: /* 2078 + * invalid logical address, 2079 + * or count zero or greater 512 2080 + */ 2081 + case H_TABLE_FULL: /* page table full */ 2082 + case H_HARDWARE: /* HCA not operational */ 2083 + return -EINVAL; 2084 + case H_BUSY: /* long busy */ 2085 + return -EBUSY; 2086 + default: 2087 + return -EINVAL; 2088 + } 2089 + } /* end ehca_mrmw_map_hrc_rrpg_last() */ 2090 + 2091 + /*----------------------------------------------------------------------*/ 2092 + 2093 + /* 2094 + * map HIPZ rc to IB retcodes for MR register rpage 2095 + * Used for hipz_h_register_rpage_mr at registering one page, but not last page 2096 + */ 2097 + int ehca_mrmw_map_hrc_rrpg_notlast(const u64 hipz_rc) 2098 + { 2099 + switch (hipz_rc) { 2100 + case H_PAGE_REGISTERED: /* page registered */ 2101 + return 0; 2102 + case H_SUCCESS: /* registration complete */ 2103 + case H_ADAPTER_PARM: /* invalid adapter handle */ 2104 + case H_RH_PARM: /* invalid resource handle */ 2105 + /* case H_QT_PARM: invalid queue type */ 2106 + case H_PARAMETER: /* 2107 + * invalid logical address, 2108 + * or count zero or greater 512 2109 + */ 2110 + case H_TABLE_FULL: /* page table full */ 2111 + case H_HARDWARE: /* HCA not operational */ 2112 + return -EINVAL; 2113 + case H_BUSY: /* long busy */ 2114 + return -EBUSY; 2115 + default: 2116 + return -EINVAL; 2117 + } 2118 + } /* end ehca_mrmw_map_hrc_rrpg_notlast() */ 2119 + 2120 + /*----------------------------------------------------------------------*/ 2121 + 2122 + /* map HIPZ rc to IB retcodes for MR query. Used for hipz_mr_query. */ 2123 + int ehca_mrmw_map_hrc_query_mr(const u64 hipz_rc) 2124 + { 2125 + switch (hipz_rc) { 2126 + case H_SUCCESS: /* successful completion */ 2127 + return 0; 2128 + case H_ADAPTER_PARM: /* invalid adapter handle */ 2129 + case H_RH_PARM: /* invalid resource handle */ 2130 + return -EINVAL; 2131 + case H_BUSY: /* long busy */ 2132 + return -EBUSY; 2133 + default: 2134 + return -EINVAL; 2135 + } 2136 + } /* end ehca_mrmw_map_hrc_query_mr() */ 2137 + 2138 + /*----------------------------------------------------------------------*/ 2139 + /*----------------------------------------------------------------------*/ 2140 + 2141 + /* 2142 + * map HIPZ rc to IB retcodes for freeing MR resource 2143 + * Used for hipz_h_free_resource_mr 2144 + */ 2145 + int ehca_mrmw_map_hrc_free_mr(const u64 hipz_rc) 2146 + { 2147 + switch (hipz_rc) { 2148 + case H_SUCCESS: /* resource freed */ 2149 + return 0; 2150 + case H_ADAPTER_PARM: /* invalid adapter handle */ 2151 + case H_RH_PARM: /* invalid resource handle */ 2152 + case H_R_STATE: /* invalid resource state */ 2153 + case H_HARDWARE: /* HCA not operational */ 2154 + return -EINVAL; 2155 + case H_RESOURCE: /* Resource in use */ 2156 + case H_BUSY: /* long busy */ 2157 + return -EBUSY; 2158 + default: 2159 + return -EINVAL; 2160 + } 2161 + } /* end ehca_mrmw_map_hrc_free_mr() */ 2162 + 2163 + /*----------------------------------------------------------------------*/ 2164 + 2165 + /* 2166 + * map HIPZ rc to IB retcodes for freeing MW resource 2167 + * Used for hipz_h_free_resource_mw 2168 + */ 2169 + int ehca_mrmw_map_hrc_free_mw(const u64 hipz_rc) 2170 + { 2171 + switch (hipz_rc) { 2172 + case H_SUCCESS: /* resource freed */ 2173 + return 0; 2174 + case H_ADAPTER_PARM: /* invalid adapter handle */ 2175 + case H_RH_PARM: /* invalid resource handle */ 2176 + case H_R_STATE: /* invalid resource state */ 2177 + case H_HARDWARE: /* HCA not operational */ 2178 + return -EINVAL; 2179 + case H_RESOURCE: /* Resource in use */ 2180 + case H_BUSY: /* long busy */ 2181 + return -EBUSY; 2182 + default: 2183 + return -EINVAL; 2184 + } 2185 + } /* end ehca_mrmw_map_hrc_free_mw() */ 2186 + 2187 + /*----------------------------------------------------------------------*/ 2188 + 2189 + /* 2190 + * map HIPZ rc to IB retcodes for SMR registrations 2191 + * Used for hipz_h_register_smr. 2192 + */ 2193 + int ehca_mrmw_map_hrc_reg_smr(const u64 hipz_rc) 2194 + { 2195 + switch (hipz_rc) { 2196 + case H_SUCCESS: /* successful completion */ 2197 + return 0; 2198 + case H_ADAPTER_PARM: /* invalid adapter handle */ 2199 + case H_RH_PARM: /* invalid resource handle */ 2200 + case H_MEM_PARM: /* invalid MR virtual address */ 2201 + case H_MEM_ACCESS_PARM: /* invalid access controls */ 2202 + case H_NOT_ENOUGH_RESOURCES: /* insufficient resources */ 2203 + return -EINVAL; 2204 + case H_BUSY: /* long busy */ 2205 + return -EBUSY; 2206 + default: 2207 + return -EINVAL; 2208 + } 2209 + } /* end ehca_mrmw_map_hrc_reg_smr() */ 2210 + 2211 + /*----------------------------------------------------------------------*/ 2212 + 2213 + /* 2214 + * MR destructor and constructor 2215 + * used in Reregister MR verb, sets all fields in ehca_mr_t to 0, 2216 + * except struct ib_mr and spinlock 2217 + */ 2218 + void ehca_mr_deletenew(struct ehca_mr *mr) 2219 + { 2220 + mr->flags = 0; 2221 + mr->num_pages = 0; 2222 + mr->num_4k = 0; 2223 + mr->acl = 0; 2224 + mr->start = NULL; 2225 + mr->fmr_page_size = 0; 2226 + mr->fmr_max_pages = 0; 2227 + mr->fmr_max_maps = 0; 2228 + mr->fmr_map_cnt = 0; 2229 + memset(&mr->ipz_mr_handle, 0, sizeof(mr->ipz_mr_handle)); 2230 + memset(&mr->galpas, 0, sizeof(mr->galpas)); 2231 + mr->nr_of_pages = 0; 2232 + mr->pagearray = NULL; 2233 + } /* end ehca_mr_deletenew() */ 2234 + 2235 + int ehca_init_mrmw_cache(void) 2236 + { 2237 + mr_cache = kmem_cache_create("ehca_cache_mr", 2238 + sizeof(struct ehca_mr), 0, 2239 + SLAB_HWCACHE_ALIGN, 2240 + NULL, NULL); 2241 + if (!mr_cache) 2242 + return -ENOMEM; 2243 + mw_cache = kmem_cache_create("ehca_cache_mw", 2244 + sizeof(struct ehca_mw), 0, 2245 + SLAB_HWCACHE_ALIGN, 2246 + NULL, NULL); 2247 + if (!mw_cache) { 2248 + kmem_cache_destroy(mr_cache); 2249 + mr_cache = NULL; 2250 + return -ENOMEM; 2251 + } 2252 + return 0; 2253 + } 2254 + 2255 + void ehca_cleanup_mrmw_cache(void) 2256 + { 2257 + if (mr_cache) 2258 + kmem_cache_destroy(mr_cache); 2259 + if (mw_cache) 2260 + kmem_cache_destroy(mw_cache); 2261 + }
+140
drivers/infiniband/hw/ehca/ehca_mrmw.h
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * MR/MW declarations and inline functions 5 + * 6 + * Authors: Dietmar Decker <ddecker@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 + #ifndef _EHCA_MRMW_H_ 43 + #define _EHCA_MRMW_H_ 44 + 45 + int ehca_reg_mr(struct ehca_shca *shca, 46 + struct ehca_mr *e_mr, 47 + u64 *iova_start, 48 + u64 size, 49 + int acl, 50 + struct ehca_pd *e_pd, 51 + struct ehca_mr_pginfo *pginfo, 52 + u32 *lkey, 53 + u32 *rkey); 54 + 55 + int ehca_reg_mr_rpages(struct ehca_shca *shca, 56 + struct ehca_mr *e_mr, 57 + struct ehca_mr_pginfo *pginfo); 58 + 59 + int ehca_rereg_mr(struct ehca_shca *shca, 60 + struct ehca_mr *e_mr, 61 + u64 *iova_start, 62 + u64 size, 63 + int mr_access_flags, 64 + struct ehca_pd *e_pd, 65 + struct ehca_mr_pginfo *pginfo, 66 + u32 *lkey, 67 + u32 *rkey); 68 + 69 + int ehca_unmap_one_fmr(struct ehca_shca *shca, 70 + struct ehca_mr *e_fmr); 71 + 72 + int ehca_reg_smr(struct ehca_shca *shca, 73 + struct ehca_mr *e_origmr, 74 + struct ehca_mr *e_newmr, 75 + u64 *iova_start, 76 + int acl, 77 + struct ehca_pd *e_pd, 78 + u32 *lkey, 79 + u32 *rkey); 80 + 81 + int ehca_reg_internal_maxmr(struct ehca_shca *shca, 82 + struct ehca_pd *e_pd, 83 + struct ehca_mr **maxmr); 84 + 85 + int ehca_reg_maxmr(struct ehca_shca *shca, 86 + struct ehca_mr *e_newmr, 87 + u64 *iova_start, 88 + int acl, 89 + struct ehca_pd *e_pd, 90 + u32 *lkey, 91 + u32 *rkey); 92 + 93 + int ehca_dereg_internal_maxmr(struct ehca_shca *shca); 94 + 95 + int ehca_mr_chk_buf_and_calc_size(struct ib_phys_buf *phys_buf_array, 96 + int num_phys_buf, 97 + u64 *iova_start, 98 + u64 *size); 99 + 100 + int ehca_fmr_check_page_list(struct ehca_mr *e_fmr, 101 + u64 *page_list, 102 + int list_len); 103 + 104 + int ehca_set_pagebuf(struct ehca_mr *e_mr, 105 + struct ehca_mr_pginfo *pginfo, 106 + u32 number, 107 + u64 *kpage); 108 + 109 + int ehca_set_pagebuf_1(struct ehca_mr *e_mr, 110 + struct ehca_mr_pginfo *pginfo, 111 + u64 *rpage); 112 + 113 + int ehca_mr_is_maxmr(u64 size, 114 + u64 *iova_start); 115 + 116 + void ehca_mrmw_map_acl(int ib_acl, 117 + u32 *hipz_acl); 118 + 119 + void ehca_mrmw_set_pgsize_hipz_acl(u32 *hipz_acl); 120 + 121 + void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl, 122 + int *ib_acl); 123 + 124 + int ehca_mrmw_map_hrc_alloc(const u64 hipz_rc); 125 + 126 + int ehca_mrmw_map_hrc_rrpg_last(const u64 hipz_rc); 127 + 128 + int ehca_mrmw_map_hrc_rrpg_notlast(const u64 hipz_rc); 129 + 130 + int ehca_mrmw_map_hrc_query_mr(const u64 hipz_rc); 131 + 132 + int ehca_mrmw_map_hrc_free_mr(const u64 hipz_rc); 133 + 134 + int ehca_mrmw_map_hrc_free_mw(const u64 hipz_rc); 135 + 136 + int ehca_mrmw_map_hrc_reg_smr(const u64 hipz_rc); 137 + 138 + void ehca_mr_deletenew(struct ehca_mr *mr); 139 + 140 + #endif /*_EHCA_MRMW_H_*/
+114
drivers/infiniband/hw/ehca/ehca_pd.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * PD functions 5 + * 6 + * Authors: Christoph Raisch <raisch@de.ibm.com> 7 + * 8 + * Copyright (c) 2005 IBM Corporation 9 + * 10 + * All rights reserved. 11 + * 12 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 13 + * BSD. 14 + * 15 + * OpenIB BSD License 16 + * 17 + * Redistribution and use in source and binary forms, with or without 18 + * modification, are permitted provided that the following conditions are met: 19 + * 20 + * Redistributions of source code must retain the above copyright notice, this 21 + * list of conditions and the following disclaimer. 22 + * 23 + * Redistributions in binary form must reproduce the above copyright notice, 24 + * this list of conditions and the following disclaimer in the documentation 25 + * and/or other materials 26 + * provided with the distribution. 27 + * 28 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 32 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 36 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 + * POSSIBILITY OF SUCH DAMAGE. 39 + */ 40 + 41 + #include <asm/current.h> 42 + 43 + #include "ehca_tools.h" 44 + #include "ehca_iverbs.h" 45 + 46 + static struct kmem_cache *pd_cache; 47 + 48 + struct ib_pd *ehca_alloc_pd(struct ib_device *device, 49 + struct ib_ucontext *context, struct ib_udata *udata) 50 + { 51 + struct ehca_pd *pd; 52 + 53 + pd = kmem_cache_alloc(pd_cache, SLAB_KERNEL); 54 + if (!pd) { 55 + ehca_err(device, "device=%p context=%p out of memory", 56 + device, context); 57 + return ERR_PTR(-ENOMEM); 58 + } 59 + 60 + memset(pd, 0, sizeof(struct ehca_pd)); 61 + pd->ownpid = current->tgid; 62 + 63 + /* 64 + * Kernel PD: when device = -1, 0 65 + * User PD: when context != -1 66 + */ 67 + if (!context) { 68 + /* 69 + * Kernel PDs after init reuses always 70 + * the one created in ehca_shca_reopen() 71 + */ 72 + struct ehca_shca *shca = container_of(device, struct ehca_shca, 73 + ib_device); 74 + pd->fw_pd.value = shca->pd->fw_pd.value; 75 + } else 76 + pd->fw_pd.value = (u64)pd; 77 + 78 + return &pd->ib_pd; 79 + } 80 + 81 + int ehca_dealloc_pd(struct ib_pd *pd) 82 + { 83 + u32 cur_pid = current->tgid; 84 + struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd); 85 + 86 + if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && 87 + my_pd->ownpid != cur_pid) { 88 + ehca_err(pd->device, "Invalid caller pid=%x ownpid=%x", 89 + cur_pid, my_pd->ownpid); 90 + return -EINVAL; 91 + } 92 + 93 + kmem_cache_free(pd_cache, 94 + container_of(pd, struct ehca_pd, ib_pd)); 95 + 96 + return 0; 97 + } 98 + 99 + int ehca_init_pd_cache(void) 100 + { 101 + pd_cache = kmem_cache_create("ehca_cache_pd", 102 + sizeof(struct ehca_pd), 0, 103 + SLAB_HWCACHE_ALIGN, 104 + NULL, NULL); 105 + if (!pd_cache) 106 + return -ENOMEM; 107 + return 0; 108 + } 109 + 110 + void ehca_cleanup_pd_cache(void) 111 + { 112 + if (pd_cache) 113 + kmem_cache_destroy(pd_cache); 114 + }
+259
drivers/infiniband/hw/ehca/ehca_qes.h
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * Hardware request structures 5 + * 6 + * Authors: Waleri Fomin <fomin@de.ibm.com> 7 + * Reinhard Ernst <rernst@de.ibm.com> 8 + * Christoph Raisch <raisch@de.ibm.com> 9 + * 10 + * Copyright (c) 2005 IBM Corporation 11 + * 12 + * All rights reserved. 13 + * 14 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 15 + * BSD. 16 + * 17 + * OpenIB BSD License 18 + * 19 + * Redistribution and use in source and binary forms, with or without 20 + * modification, are permitted provided that the following conditions are met: 21 + * 22 + * Redistributions of source code must retain the above copyright notice, this 23 + * list of conditions and the following disclaimer. 24 + * 25 + * Redistributions in binary form must reproduce the above copyright notice, 26 + * this list of conditions and the following disclaimer in the documentation 27 + * and/or other materials 28 + * provided with the distribution. 29 + * 30 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 31 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 34 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 37 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 38 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 + * POSSIBILITY OF SUCH DAMAGE. 41 + */ 42 + 43 + 44 + #ifndef _EHCA_QES_H_ 45 + #define _EHCA_QES_H_ 46 + 47 + #include "ehca_tools.h" 48 + 49 + /* virtual scatter gather entry to specify remote adresses with length */ 50 + struct ehca_vsgentry { 51 + u64 vaddr; 52 + u32 lkey; 53 + u32 length; 54 + }; 55 + 56 + #define GRH_FLAG_MASK EHCA_BMASK_IBM(7,7) 57 + #define GRH_IPVERSION_MASK EHCA_BMASK_IBM(0,3) 58 + #define GRH_TCLASS_MASK EHCA_BMASK_IBM(4,12) 59 + #define GRH_FLOWLABEL_MASK EHCA_BMASK_IBM(13,31) 60 + #define GRH_PAYLEN_MASK EHCA_BMASK_IBM(32,47) 61 + #define GRH_NEXTHEADER_MASK EHCA_BMASK_IBM(48,55) 62 + #define GRH_HOPLIMIT_MASK EHCA_BMASK_IBM(56,63) 63 + 64 + /* 65 + * Unreliable Datagram Address Vector Format 66 + * see IBTA Vol1 chapter 8.3 Global Routing Header 67 + */ 68 + struct ehca_ud_av { 69 + u8 sl; 70 + u8 lnh; 71 + u16 dlid; 72 + u8 reserved1; 73 + u8 reserved2; 74 + u8 reserved3; 75 + u8 slid_path_bits; 76 + u8 reserved4; 77 + u8 ipd; 78 + u8 reserved5; 79 + u8 pmtu; 80 + u32 reserved6; 81 + u64 reserved7; 82 + union { 83 + struct { 84 + u64 word_0; /* always set to 6 */ 85 + /*should be 0x1B for IB transport */ 86 + u64 word_1; 87 + u64 word_2; 88 + u64 word_3; 89 + u64 word_4; 90 + } grh; 91 + struct { 92 + u32 wd_0; 93 + u32 wd_1; 94 + /* DWord_1 --> SGID */ 95 + 96 + u32 sgid_wd3; 97 + u32 sgid_wd2; 98 + 99 + u32 sgid_wd1; 100 + u32 sgid_wd0; 101 + /* DWord_3 --> DGID */ 102 + 103 + u32 dgid_wd3; 104 + u32 dgid_wd2; 105 + 106 + u32 dgid_wd1; 107 + u32 dgid_wd0; 108 + } grh_l; 109 + }; 110 + }; 111 + 112 + /* maximum number of sg entries allowed in a WQE */ 113 + #define MAX_WQE_SG_ENTRIES 252 114 + 115 + #define WQE_OPTYPE_SEND 0x80 116 + #define WQE_OPTYPE_RDMAREAD 0x40 117 + #define WQE_OPTYPE_RDMAWRITE 0x20 118 + #define WQE_OPTYPE_CMPSWAP 0x10 119 + #define WQE_OPTYPE_FETCHADD 0x08 120 + #define WQE_OPTYPE_BIND 0x04 121 + 122 + #define WQE_WRFLAG_REQ_SIGNAL_COM 0x80 123 + #define WQE_WRFLAG_FENCE 0x40 124 + #define WQE_WRFLAG_IMM_DATA_PRESENT 0x20 125 + #define WQE_WRFLAG_SOLIC_EVENT 0x10 126 + 127 + #define WQEF_CACHE_HINT 0x80 128 + #define WQEF_CACHE_HINT_RD_WR 0x40 129 + #define WQEF_TIMED_WQE 0x20 130 + #define WQEF_PURGE 0x08 131 + #define WQEF_HIGH_NIBBLE 0xF0 132 + 133 + #define MW_BIND_ACCESSCTRL_R_WRITE 0x40 134 + #define MW_BIND_ACCESSCTRL_R_READ 0x20 135 + #define MW_BIND_ACCESSCTRL_R_ATOMIC 0x10 136 + 137 + struct ehca_wqe { 138 + u64 work_request_id; 139 + u8 optype; 140 + u8 wr_flag; 141 + u16 pkeyi; 142 + u8 wqef; 143 + u8 nr_of_data_seg; 144 + u16 wqe_provided_slid; 145 + u32 destination_qp_number; 146 + u32 resync_psn_sqp; 147 + u32 local_ee_context_qkey; 148 + u32 immediate_data; 149 + union { 150 + struct { 151 + u64 remote_virtual_adress; 152 + u32 rkey; 153 + u32 reserved; 154 + u64 atomic_1st_op_dma_len; 155 + u64 atomic_2nd_op; 156 + struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES]; 157 + 158 + } nud; 159 + struct { 160 + u64 ehca_ud_av_ptr; 161 + u64 reserved1; 162 + u64 reserved2; 163 + u64 reserved3; 164 + struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES]; 165 + } ud_avp; 166 + struct { 167 + struct ehca_ud_av ud_av; 168 + struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES - 169 + 2]; 170 + } ud_av; 171 + struct { 172 + u64 reserved0; 173 + u64 reserved1; 174 + u64 reserved2; 175 + u64 reserved3; 176 + struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES]; 177 + } all_rcv; 178 + 179 + struct { 180 + u64 reserved; 181 + u32 rkey; 182 + u32 old_rkey; 183 + u64 reserved1; 184 + u64 reserved2; 185 + u64 virtual_address; 186 + u32 reserved3; 187 + u32 length; 188 + u32 reserved4; 189 + u16 reserved5; 190 + u8 reserved6; 191 + u8 lr_ctl; 192 + u32 lkey; 193 + u32 reserved7; 194 + u64 reserved8; 195 + u64 reserved9; 196 + u64 reserved10; 197 + u64 reserved11; 198 + } bind; 199 + struct { 200 + u64 reserved12; 201 + u64 reserved13; 202 + u32 size; 203 + u32 start; 204 + } inline_data; 205 + } u; 206 + 207 + }; 208 + 209 + #define WC_SEND_RECEIVE EHCA_BMASK_IBM(0,0) 210 + #define WC_IMM_DATA EHCA_BMASK_IBM(1,1) 211 + #define WC_GRH_PRESENT EHCA_BMASK_IBM(2,2) 212 + #define WC_SE_BIT EHCA_BMASK_IBM(3,3) 213 + #define WC_STATUS_ERROR_BIT 0x80000000 214 + #define WC_STATUS_REMOTE_ERROR_FLAGS 0x0000F800 215 + #define WC_STATUS_PURGE_BIT 0x10 216 + 217 + struct ehca_cqe { 218 + u64 work_request_id; 219 + u8 optype; 220 + u8 w_completion_flags; 221 + u16 reserved1; 222 + u32 nr_bytes_transferred; 223 + u32 immediate_data; 224 + u32 local_qp_number; 225 + u8 freed_resource_count; 226 + u8 service_level; 227 + u16 wqe_count; 228 + u32 qp_token; 229 + u32 qkey_ee_token; 230 + u32 remote_qp_number; 231 + u16 dlid; 232 + u16 rlid; 233 + u16 reserved2; 234 + u16 pkey_index; 235 + u32 cqe_timestamp; 236 + u32 wqe_timestamp; 237 + u8 wqe_timestamp_valid; 238 + u8 reserved3; 239 + u8 reserved4; 240 + u8 cqe_flags; 241 + u32 status; 242 + }; 243 + 244 + struct ehca_eqe { 245 + u64 entry; 246 + }; 247 + 248 + struct ehca_mrte { 249 + u64 starting_va; 250 + u64 length; /* length of memory region in bytes*/ 251 + u32 pd; 252 + u8 key_instance; 253 + u8 pagesize; 254 + u8 mr_control; 255 + u8 local_remote_access_ctrl; 256 + u8 reserved[0x20 - 0x18]; 257 + u64 at_pointer[4]; 258 + }; 259 + #endif /*_EHCA_QES_H_*/
+1506
drivers/infiniband/hw/ehca/ehca_qp.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * QP functions 5 + * 6 + * Authors: Waleri Fomin <fomin@de.ibm.com> 7 + * Hoang-Nam Nguyen <hnguyen@de.ibm.com> 8 + * Reinhard Ernst <rernst@de.ibm.com> 9 + * Heiko J Schick <schickhj@de.ibm.com> 10 + * 11 + * Copyright (c) 2005 IBM Corporation 12 + * 13 + * All rights reserved. 14 + * 15 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 16 + * BSD. 17 + * 18 + * OpenIB BSD License 19 + * 20 + * Redistribution and use in source and binary forms, with or without 21 + * modification, are permitted provided that the following conditions are met: 22 + * 23 + * Redistributions of source code must retain the above copyright notice, this 24 + * list of conditions and the following disclaimer. 25 + * 26 + * Redistributions in binary form must reproduce the above copyright notice, 27 + * this list of conditions and the following disclaimer in the documentation 28 + * and/or other materials 29 + * provided with the distribution. 30 + * 31 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 32 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 35 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 36 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 38 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 39 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 + * POSSIBILITY OF SUCH DAMAGE. 42 + */ 43 + 44 + 45 + #include <asm/current.h> 46 + 47 + #include "ehca_classes.h" 48 + #include "ehca_tools.h" 49 + #include "ehca_qes.h" 50 + #include "ehca_iverbs.h" 51 + #include "hcp_if.h" 52 + #include "hipz_fns.h" 53 + 54 + static struct kmem_cache *qp_cache; 55 + 56 + /* 57 + * attributes not supported by query qp 58 + */ 59 + #define QP_ATTR_QUERY_NOT_SUPPORTED (IB_QP_MAX_DEST_RD_ATOMIC | \ 60 + IB_QP_MAX_QP_RD_ATOMIC | \ 61 + IB_QP_ACCESS_FLAGS | \ 62 + IB_QP_EN_SQD_ASYNC_NOTIFY) 63 + 64 + /* 65 + * ehca (internal) qp state values 66 + */ 67 + enum ehca_qp_state { 68 + EHCA_QPS_RESET = 1, 69 + EHCA_QPS_INIT = 2, 70 + EHCA_QPS_RTR = 3, 71 + EHCA_QPS_RTS = 5, 72 + EHCA_QPS_SQD = 6, 73 + EHCA_QPS_SQE = 8, 74 + EHCA_QPS_ERR = 128 75 + }; 76 + 77 + /* 78 + * qp state transitions as defined by IB Arch Rel 1.1 page 431 79 + */ 80 + enum ib_qp_statetrans { 81 + IB_QPST_ANY2RESET, 82 + IB_QPST_ANY2ERR, 83 + IB_QPST_RESET2INIT, 84 + IB_QPST_INIT2RTR, 85 + IB_QPST_INIT2INIT, 86 + IB_QPST_RTR2RTS, 87 + IB_QPST_RTS2SQD, 88 + IB_QPST_RTS2RTS, 89 + IB_QPST_SQD2RTS, 90 + IB_QPST_SQE2RTS, 91 + IB_QPST_SQD2SQD, 92 + IB_QPST_MAX /* nr of transitions, this must be last!!! */ 93 + }; 94 + 95 + /* 96 + * ib2ehca_qp_state maps IB to ehca qp_state 97 + * returns ehca qp state corresponding to given ib qp state 98 + */ 99 + static inline enum ehca_qp_state ib2ehca_qp_state(enum ib_qp_state ib_qp_state) 100 + { 101 + switch (ib_qp_state) { 102 + case IB_QPS_RESET: 103 + return EHCA_QPS_RESET; 104 + case IB_QPS_INIT: 105 + return EHCA_QPS_INIT; 106 + case IB_QPS_RTR: 107 + return EHCA_QPS_RTR; 108 + case IB_QPS_RTS: 109 + return EHCA_QPS_RTS; 110 + case IB_QPS_SQD: 111 + return EHCA_QPS_SQD; 112 + case IB_QPS_SQE: 113 + return EHCA_QPS_SQE; 114 + case IB_QPS_ERR: 115 + return EHCA_QPS_ERR; 116 + default: 117 + ehca_gen_err("invalid ib_qp_state=%x", ib_qp_state); 118 + return -EINVAL; 119 + } 120 + } 121 + 122 + /* 123 + * ehca2ib_qp_state maps ehca to IB qp_state 124 + * returns ib qp state corresponding to given ehca qp state 125 + */ 126 + static inline enum ib_qp_state ehca2ib_qp_state(enum ehca_qp_state 127 + ehca_qp_state) 128 + { 129 + switch (ehca_qp_state) { 130 + case EHCA_QPS_RESET: 131 + return IB_QPS_RESET; 132 + case EHCA_QPS_INIT: 133 + return IB_QPS_INIT; 134 + case EHCA_QPS_RTR: 135 + return IB_QPS_RTR; 136 + case EHCA_QPS_RTS: 137 + return IB_QPS_RTS; 138 + case EHCA_QPS_SQD: 139 + return IB_QPS_SQD; 140 + case EHCA_QPS_SQE: 141 + return IB_QPS_SQE; 142 + case EHCA_QPS_ERR: 143 + return IB_QPS_ERR; 144 + default: 145 + ehca_gen_err("invalid ehca_qp_state=%x", ehca_qp_state); 146 + return -EINVAL; 147 + } 148 + } 149 + 150 + /* 151 + * ehca_qp_type used as index for req_attr and opt_attr of 152 + * struct ehca_modqp_statetrans 153 + */ 154 + enum ehca_qp_type { 155 + QPT_RC = 0, 156 + QPT_UC = 1, 157 + QPT_UD = 2, 158 + QPT_SQP = 3, 159 + QPT_MAX 160 + }; 161 + 162 + /* 163 + * ib2ehcaqptype maps Ib to ehca qp_type 164 + * returns ehca qp type corresponding to ib qp type 165 + */ 166 + static inline enum ehca_qp_type ib2ehcaqptype(enum ib_qp_type ibqptype) 167 + { 168 + switch (ibqptype) { 169 + case IB_QPT_SMI: 170 + case IB_QPT_GSI: 171 + return QPT_SQP; 172 + case IB_QPT_RC: 173 + return QPT_RC; 174 + case IB_QPT_UC: 175 + return QPT_UC; 176 + case IB_QPT_UD: 177 + return QPT_UD; 178 + default: 179 + ehca_gen_err("Invalid ibqptype=%x", ibqptype); 180 + return -EINVAL; 181 + } 182 + } 183 + 184 + static inline enum ib_qp_statetrans get_modqp_statetrans(int ib_fromstate, 185 + int ib_tostate) 186 + { 187 + int index = -EINVAL; 188 + switch (ib_tostate) { 189 + case IB_QPS_RESET: 190 + index = IB_QPST_ANY2RESET; 191 + break; 192 + case IB_QPS_INIT: 193 + switch (ib_fromstate) { 194 + case IB_QPS_RESET: 195 + index = IB_QPST_RESET2INIT; 196 + break; 197 + case IB_QPS_INIT: 198 + index = IB_QPST_INIT2INIT; 199 + break; 200 + } 201 + break; 202 + case IB_QPS_RTR: 203 + if (ib_fromstate == IB_QPS_INIT) 204 + index = IB_QPST_INIT2RTR; 205 + break; 206 + case IB_QPS_RTS: 207 + switch (ib_fromstate) { 208 + case IB_QPS_RTR: 209 + index = IB_QPST_RTR2RTS; 210 + break; 211 + case IB_QPS_RTS: 212 + index = IB_QPST_RTS2RTS; 213 + break; 214 + case IB_QPS_SQD: 215 + index = IB_QPST_SQD2RTS; 216 + break; 217 + case IB_QPS_SQE: 218 + index = IB_QPST_SQE2RTS; 219 + break; 220 + } 221 + break; 222 + case IB_QPS_SQD: 223 + if (ib_fromstate == IB_QPS_RTS) 224 + index = IB_QPST_RTS2SQD; 225 + break; 226 + case IB_QPS_SQE: 227 + break; 228 + case IB_QPS_ERR: 229 + index = IB_QPST_ANY2ERR; 230 + break; 231 + default: 232 + break; 233 + } 234 + return index; 235 + } 236 + 237 + enum ehca_service_type { 238 + ST_RC = 0, 239 + ST_UC = 1, 240 + ST_RD = 2, 241 + ST_UD = 3 242 + }; 243 + 244 + /* 245 + * ibqptype2servicetype returns hcp service type corresponding to given 246 + * ib qp type used by create_qp() 247 + */ 248 + static inline int ibqptype2servicetype(enum ib_qp_type ibqptype) 249 + { 250 + switch (ibqptype) { 251 + case IB_QPT_SMI: 252 + case IB_QPT_GSI: 253 + return ST_UD; 254 + case IB_QPT_RC: 255 + return ST_RC; 256 + case IB_QPT_UC: 257 + return ST_UC; 258 + case IB_QPT_UD: 259 + return ST_UD; 260 + case IB_QPT_RAW_IPV6: 261 + return -EINVAL; 262 + case IB_QPT_RAW_ETY: 263 + return -EINVAL; 264 + default: 265 + ehca_gen_err("Invalid ibqptype=%x", ibqptype); 266 + return -EINVAL; 267 + } 268 + } 269 + 270 + /* 271 + * init_qp_queues initializes/constructs r/squeue and registers queue pages. 272 + */ 273 + static inline int init_qp_queues(struct ehca_shca *shca, 274 + struct ehca_qp *my_qp, 275 + int nr_sq_pages, 276 + int nr_rq_pages, 277 + int swqe_size, 278 + int rwqe_size, 279 + int nr_send_sges, int nr_receive_sges) 280 + { 281 + int ret, cnt, ipz_rc; 282 + void *vpage; 283 + u64 rpage, h_ret; 284 + struct ib_device *ib_dev = &shca->ib_device; 285 + struct ipz_adapter_handle ipz_hca_handle = shca->ipz_hca_handle; 286 + 287 + ipz_rc = ipz_queue_ctor(&my_qp->ipz_squeue, 288 + nr_sq_pages, 289 + EHCA_PAGESIZE, swqe_size, nr_send_sges); 290 + if (!ipz_rc) { 291 + ehca_err(ib_dev,"Cannot allocate page for squeue. ipz_rc=%x", 292 + ipz_rc); 293 + return -EBUSY; 294 + } 295 + 296 + ipz_rc = ipz_queue_ctor(&my_qp->ipz_rqueue, 297 + nr_rq_pages, 298 + EHCA_PAGESIZE, rwqe_size, nr_receive_sges); 299 + if (!ipz_rc) { 300 + ehca_err(ib_dev, "Cannot allocate page for rqueue. ipz_rc=%x", 301 + ipz_rc); 302 + ret = -EBUSY; 303 + goto init_qp_queues0; 304 + } 305 + /* register SQ pages */ 306 + for (cnt = 0; cnt < nr_sq_pages; cnt++) { 307 + vpage = ipz_qpageit_get_inc(&my_qp->ipz_squeue); 308 + if (!vpage) { 309 + ehca_err(ib_dev, "SQ ipz_qpageit_get_inc() " 310 + "failed p_vpage= %p", vpage); 311 + ret = -EINVAL; 312 + goto init_qp_queues1; 313 + } 314 + rpage = virt_to_abs(vpage); 315 + 316 + h_ret = hipz_h_register_rpage_qp(ipz_hca_handle, 317 + my_qp->ipz_qp_handle, 318 + &my_qp->pf, 0, 0, 319 + rpage, 1, 320 + my_qp->galpas.kernel); 321 + if (h_ret < H_SUCCESS) { 322 + ehca_err(ib_dev, "SQ hipz_qp_register_rpage()" 323 + " failed rc=%lx", h_ret); 324 + ret = ehca2ib_return_code(h_ret); 325 + goto init_qp_queues1; 326 + } 327 + } 328 + 329 + ipz_qeit_reset(&my_qp->ipz_squeue); 330 + 331 + /* register RQ pages */ 332 + for (cnt = 0; cnt < nr_rq_pages; cnt++) { 333 + vpage = ipz_qpageit_get_inc(&my_qp->ipz_rqueue); 334 + if (!vpage) { 335 + ehca_err(ib_dev, "RQ ipz_qpageit_get_inc() " 336 + "failed p_vpage = %p", vpage); 337 + ret = -EINVAL; 338 + goto init_qp_queues1; 339 + } 340 + 341 + rpage = virt_to_abs(vpage); 342 + 343 + h_ret = hipz_h_register_rpage_qp(ipz_hca_handle, 344 + my_qp->ipz_qp_handle, 345 + &my_qp->pf, 0, 1, 346 + rpage, 1,my_qp->galpas.kernel); 347 + if (h_ret < H_SUCCESS) { 348 + ehca_err(ib_dev, "RQ hipz_qp_register_rpage() failed " 349 + "rc=%lx", h_ret); 350 + ret = ehca2ib_return_code(h_ret); 351 + goto init_qp_queues1; 352 + } 353 + if (cnt == (nr_rq_pages - 1)) { /* last page! */ 354 + if (h_ret != H_SUCCESS) { 355 + ehca_err(ib_dev, "RQ hipz_qp_register_rpage() " 356 + "h_ret= %lx ", h_ret); 357 + ret = ehca2ib_return_code(h_ret); 358 + goto init_qp_queues1; 359 + } 360 + vpage = ipz_qpageit_get_inc(&my_qp->ipz_rqueue); 361 + if (vpage) { 362 + ehca_err(ib_dev, "ipz_qpageit_get_inc() " 363 + "should not succeed vpage=%p", vpage); 364 + ret = -EINVAL; 365 + goto init_qp_queues1; 366 + } 367 + } else { 368 + if (h_ret != H_PAGE_REGISTERED) { 369 + ehca_err(ib_dev, "RQ hipz_qp_register_rpage() " 370 + "h_ret= %lx ", h_ret); 371 + ret = ehca2ib_return_code(h_ret); 372 + goto init_qp_queues1; 373 + } 374 + } 375 + } 376 + 377 + ipz_qeit_reset(&my_qp->ipz_rqueue); 378 + 379 + return 0; 380 + 381 + init_qp_queues1: 382 + ipz_queue_dtor(&my_qp->ipz_rqueue); 383 + init_qp_queues0: 384 + ipz_queue_dtor(&my_qp->ipz_squeue); 385 + return ret; 386 + } 387 + 388 + struct ib_qp *ehca_create_qp(struct ib_pd *pd, 389 + struct ib_qp_init_attr *init_attr, 390 + struct ib_udata *udata) 391 + { 392 + static int da_rc_msg_size[]={ 128, 256, 512, 1024, 2048, 4096 }; 393 + static int da_ud_sq_msg_size[]={ 128, 384, 896, 1920, 3968 }; 394 + struct ehca_qp *my_qp; 395 + struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd); 396 + struct ehca_shca *shca = container_of(pd->device, struct ehca_shca, 397 + ib_device); 398 + struct ib_ucontext *context = NULL; 399 + u64 h_ret; 400 + int max_send_sge, max_recv_sge, ret; 401 + 402 + /* h_call's out parameters */ 403 + struct ehca_alloc_qp_parms parms; 404 + u32 swqe_size = 0, rwqe_size = 0; 405 + u8 daqp_completion, isdaqp; 406 + unsigned long flags; 407 + 408 + if (init_attr->sq_sig_type != IB_SIGNAL_REQ_WR && 409 + init_attr->sq_sig_type != IB_SIGNAL_ALL_WR) { 410 + ehca_err(pd->device, "init_attr->sg_sig_type=%x not allowed", 411 + init_attr->sq_sig_type); 412 + return ERR_PTR(-EINVAL); 413 + } 414 + 415 + /* save daqp completion bits */ 416 + daqp_completion = init_attr->qp_type & 0x60; 417 + /* save daqp bit */ 418 + isdaqp = (init_attr->qp_type & 0x80) ? 1 : 0; 419 + init_attr->qp_type = init_attr->qp_type & 0x1F; 420 + 421 + if (init_attr->qp_type != IB_QPT_UD && 422 + init_attr->qp_type != IB_QPT_SMI && 423 + init_attr->qp_type != IB_QPT_GSI && 424 + init_attr->qp_type != IB_QPT_UC && 425 + init_attr->qp_type != IB_QPT_RC) { 426 + ehca_err(pd->device, "wrong QP Type=%x", init_attr->qp_type); 427 + return ERR_PTR(-EINVAL); 428 + } 429 + if ((init_attr->qp_type != IB_QPT_RC && init_attr->qp_type != IB_QPT_UD) 430 + && isdaqp) { 431 + ehca_err(pd->device, "unsupported LL QP Type=%x", 432 + init_attr->qp_type); 433 + return ERR_PTR(-EINVAL); 434 + } else if (init_attr->qp_type == IB_QPT_RC && isdaqp && 435 + (init_attr->cap.max_send_wr > 255 || 436 + init_attr->cap.max_recv_wr > 255 )) { 437 + ehca_err(pd->device, "Invalid Number of max_sq_wr =%x " 438 + "or max_rq_wr=%x for QP Type=%x", 439 + init_attr->cap.max_send_wr, 440 + init_attr->cap.max_recv_wr,init_attr->qp_type); 441 + return ERR_PTR(-EINVAL); 442 + } else if (init_attr->qp_type == IB_QPT_UD && isdaqp && 443 + init_attr->cap.max_send_wr > 255) { 444 + ehca_err(pd->device, 445 + "Invalid Number of max_send_wr=%x for UD QP_TYPE=%x", 446 + init_attr->cap.max_send_wr, init_attr->qp_type); 447 + return ERR_PTR(-EINVAL); 448 + } 449 + 450 + if (pd->uobject && udata) 451 + context = pd->uobject->context; 452 + 453 + my_qp = kmem_cache_alloc(qp_cache, SLAB_KERNEL); 454 + if (!my_qp) { 455 + ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd); 456 + return ERR_PTR(-ENOMEM); 457 + } 458 + 459 + memset(my_qp, 0, sizeof(struct ehca_qp)); 460 + memset (&parms, 0, sizeof(struct ehca_alloc_qp_parms)); 461 + spin_lock_init(&my_qp->spinlock_s); 462 + spin_lock_init(&my_qp->spinlock_r); 463 + 464 + my_qp->recv_cq = 465 + container_of(init_attr->recv_cq, struct ehca_cq, ib_cq); 466 + my_qp->send_cq = 467 + container_of(init_attr->send_cq, struct ehca_cq, ib_cq); 468 + 469 + my_qp->init_attr = *init_attr; 470 + 471 + do { 472 + if (!idr_pre_get(&ehca_qp_idr, GFP_KERNEL)) { 473 + ret = -ENOMEM; 474 + ehca_err(pd->device, "Can't reserve idr resources."); 475 + goto create_qp_exit0; 476 + } 477 + 478 + spin_lock_irqsave(&ehca_qp_idr_lock, flags); 479 + ret = idr_get_new(&ehca_qp_idr, my_qp, &my_qp->token); 480 + spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); 481 + 482 + } while (ret == -EAGAIN); 483 + 484 + if (ret) { 485 + ret = -ENOMEM; 486 + ehca_err(pd->device, "Can't allocate new idr entry."); 487 + goto create_qp_exit0; 488 + } 489 + 490 + parms.servicetype = ibqptype2servicetype(init_attr->qp_type); 491 + if (parms.servicetype < 0) { 492 + ret = -EINVAL; 493 + ehca_err(pd->device, "Invalid qp_type=%x", init_attr->qp_type); 494 + goto create_qp_exit0; 495 + } 496 + 497 + if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) 498 + parms.sigtype = HCALL_SIGT_EVERY; 499 + else 500 + parms.sigtype = HCALL_SIGT_BY_WQE; 501 + 502 + /* UD_AV CIRCUMVENTION */ 503 + max_send_sge = init_attr->cap.max_send_sge; 504 + max_recv_sge = init_attr->cap.max_recv_sge; 505 + if (IB_QPT_UD == init_attr->qp_type || 506 + IB_QPT_GSI == init_attr->qp_type || 507 + IB_QPT_SMI == init_attr->qp_type) { 508 + max_send_sge += 2; 509 + max_recv_sge += 2; 510 + } 511 + 512 + parms.ipz_eq_handle = shca->eq.ipz_eq_handle; 513 + parms.daqp_ctrl = isdaqp | daqp_completion; 514 + parms.pd = my_pd->fw_pd; 515 + parms.max_recv_sge = max_recv_sge; 516 + parms.max_send_sge = max_send_sge; 517 + 518 + h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, my_qp, &parms); 519 + 520 + if (h_ret != H_SUCCESS) { 521 + ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lx", 522 + h_ret); 523 + ret = ehca2ib_return_code(h_ret); 524 + goto create_qp_exit1; 525 + } 526 + 527 + switch (init_attr->qp_type) { 528 + case IB_QPT_RC: 529 + if (isdaqp == 0) { 530 + swqe_size = offsetof(struct ehca_wqe, u.nud.sg_list[ 531 + (parms.act_nr_send_sges)]); 532 + rwqe_size = offsetof(struct ehca_wqe, u.nud.sg_list[ 533 + (parms.act_nr_recv_sges)]); 534 + } else { /* for daqp we need to use msg size, not wqe size */ 535 + swqe_size = da_rc_msg_size[max_send_sge]; 536 + rwqe_size = da_rc_msg_size[max_recv_sge]; 537 + parms.act_nr_send_sges = 1; 538 + parms.act_nr_recv_sges = 1; 539 + } 540 + break; 541 + case IB_QPT_UC: 542 + swqe_size = offsetof(struct ehca_wqe, 543 + u.nud.sg_list[parms.act_nr_send_sges]); 544 + rwqe_size = offsetof(struct ehca_wqe, 545 + u.nud.sg_list[parms.act_nr_recv_sges]); 546 + break; 547 + 548 + case IB_QPT_UD: 549 + case IB_QPT_GSI: 550 + case IB_QPT_SMI: 551 + /* UD circumvention */ 552 + parms.act_nr_recv_sges -= 2; 553 + parms.act_nr_send_sges -= 2; 554 + if (isdaqp) { 555 + swqe_size = da_ud_sq_msg_size[max_send_sge]; 556 + rwqe_size = da_rc_msg_size[max_recv_sge]; 557 + parms.act_nr_send_sges = 1; 558 + parms.act_nr_recv_sges = 1; 559 + } else { 560 + swqe_size = offsetof(struct ehca_wqe, 561 + u.ud_av.sg_list[parms.act_nr_send_sges]); 562 + rwqe_size = offsetof(struct ehca_wqe, 563 + u.ud_av.sg_list[parms.act_nr_recv_sges]); 564 + } 565 + 566 + if (IB_QPT_GSI == init_attr->qp_type || 567 + IB_QPT_SMI == init_attr->qp_type) { 568 + parms.act_nr_send_wqes = init_attr->cap.max_send_wr; 569 + parms.act_nr_recv_wqes = init_attr->cap.max_recv_wr; 570 + parms.act_nr_send_sges = init_attr->cap.max_send_sge; 571 + parms.act_nr_recv_sges = init_attr->cap.max_recv_sge; 572 + my_qp->real_qp_num = 573 + (init_attr->qp_type == IB_QPT_SMI) ? 0 : 1; 574 + } 575 + 576 + break; 577 + 578 + default: 579 + break; 580 + } 581 + 582 + /* initializes r/squeue and registers queue pages */ 583 + ret = init_qp_queues(shca, my_qp, 584 + parms.nr_sq_pages, parms.nr_rq_pages, 585 + swqe_size, rwqe_size, 586 + parms.act_nr_send_sges, parms.act_nr_recv_sges); 587 + if (ret) { 588 + ehca_err(pd->device, 589 + "Couldn't initialize r/squeue and pages ret=%x", ret); 590 + goto create_qp_exit2; 591 + } 592 + 593 + my_qp->ib_qp.pd = &my_pd->ib_pd; 594 + my_qp->ib_qp.device = my_pd->ib_pd.device; 595 + 596 + my_qp->ib_qp.recv_cq = init_attr->recv_cq; 597 + my_qp->ib_qp.send_cq = init_attr->send_cq; 598 + 599 + my_qp->ib_qp.qp_num = my_qp->real_qp_num; 600 + my_qp->ib_qp.qp_type = init_attr->qp_type; 601 + 602 + my_qp->qp_type = init_attr->qp_type; 603 + my_qp->ib_qp.srq = init_attr->srq; 604 + 605 + my_qp->ib_qp.qp_context = init_attr->qp_context; 606 + my_qp->ib_qp.event_handler = init_attr->event_handler; 607 + 608 + init_attr->cap.max_inline_data = 0; /* not supported yet */ 609 + init_attr->cap.max_recv_sge = parms.act_nr_recv_sges; 610 + init_attr->cap.max_recv_wr = parms.act_nr_recv_wqes; 611 + init_attr->cap.max_send_sge = parms.act_nr_send_sges; 612 + init_attr->cap.max_send_wr = parms.act_nr_send_wqes; 613 + 614 + /* NOTE: define_apq0() not supported yet */ 615 + if (init_attr->qp_type == IB_QPT_GSI) { 616 + h_ret = ehca_define_sqp(shca, my_qp, init_attr); 617 + if (h_ret != H_SUCCESS) { 618 + ehca_err(pd->device, "ehca_define_sqp() failed rc=%lx", 619 + h_ret); 620 + ret = ehca2ib_return_code(h_ret); 621 + goto create_qp_exit3; 622 + } 623 + } 624 + if (init_attr->send_cq) { 625 + struct ehca_cq *cq = container_of(init_attr->send_cq, 626 + struct ehca_cq, ib_cq); 627 + ret = ehca_cq_assign_qp(cq, my_qp); 628 + if (ret) { 629 + ehca_err(pd->device, "Couldn't assign qp to send_cq ret=%x", 630 + ret); 631 + goto create_qp_exit3; 632 + } 633 + my_qp->send_cq = cq; 634 + } 635 + /* copy queues, galpa data to user space */ 636 + if (context && udata) { 637 + struct ipz_queue *ipz_rqueue = &my_qp->ipz_rqueue; 638 + struct ipz_queue *ipz_squeue = &my_qp->ipz_squeue; 639 + struct ehca_create_qp_resp resp; 640 + struct vm_area_struct * vma; 641 + memset(&resp, 0, sizeof(resp)); 642 + 643 + resp.qp_num = my_qp->real_qp_num; 644 + resp.token = my_qp->token; 645 + resp.qp_type = my_qp->qp_type; 646 + resp.qkey = my_qp->qkey; 647 + resp.real_qp_num = my_qp->real_qp_num; 648 + /* rqueue properties */ 649 + resp.ipz_rqueue.qe_size = ipz_rqueue->qe_size; 650 + resp.ipz_rqueue.act_nr_of_sg = ipz_rqueue->act_nr_of_sg; 651 + resp.ipz_rqueue.queue_length = ipz_rqueue->queue_length; 652 + resp.ipz_rqueue.pagesize = ipz_rqueue->pagesize; 653 + resp.ipz_rqueue.toggle_state = ipz_rqueue->toggle_state; 654 + ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x22000000, 655 + ipz_rqueue->queue_length, 656 + (void**)&resp.ipz_rqueue.queue, 657 + &vma); 658 + if (ret) { 659 + ehca_err(pd->device, "Could not mmap rqueue pages"); 660 + goto create_qp_exit3; 661 + } 662 + my_qp->uspace_rqueue = resp.ipz_rqueue.queue; 663 + /* squeue properties */ 664 + resp.ipz_squeue.qe_size = ipz_squeue->qe_size; 665 + resp.ipz_squeue.act_nr_of_sg = ipz_squeue->act_nr_of_sg; 666 + resp.ipz_squeue.queue_length = ipz_squeue->queue_length; 667 + resp.ipz_squeue.pagesize = ipz_squeue->pagesize; 668 + resp.ipz_squeue.toggle_state = ipz_squeue->toggle_state; 669 + ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x23000000, 670 + ipz_squeue->queue_length, 671 + (void**)&resp.ipz_squeue.queue, 672 + &vma); 673 + if (ret) { 674 + ehca_err(pd->device, "Could not mmap squeue pages"); 675 + goto create_qp_exit4; 676 + } 677 + my_qp->uspace_squeue = resp.ipz_squeue.queue; 678 + /* fw_handle */ 679 + resp.galpas = my_qp->galpas; 680 + ret = ehca_mmap_register(my_qp->galpas.user.fw_handle, 681 + (void**)&resp.galpas.kernel.fw_handle, 682 + &vma); 683 + if (ret) { 684 + ehca_err(pd->device, "Could not mmap fw_handle"); 685 + goto create_qp_exit5; 686 + } 687 + my_qp->uspace_fwh = (u64)resp.galpas.kernel.fw_handle; 688 + 689 + if (ib_copy_to_udata(udata, &resp, sizeof resp)) { 690 + ehca_err(pd->device, "Copy to udata failed"); 691 + ret = -EINVAL; 692 + goto create_qp_exit6; 693 + } 694 + } 695 + 696 + return &my_qp->ib_qp; 697 + 698 + create_qp_exit6: 699 + ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE); 700 + 701 + create_qp_exit5: 702 + ehca_munmap(my_qp->uspace_squeue, my_qp->ipz_squeue.queue_length); 703 + 704 + create_qp_exit4: 705 + ehca_munmap(my_qp->uspace_rqueue, my_qp->ipz_rqueue.queue_length); 706 + 707 + create_qp_exit3: 708 + ipz_queue_dtor(&my_qp->ipz_rqueue); 709 + ipz_queue_dtor(&my_qp->ipz_squeue); 710 + 711 + create_qp_exit2: 712 + hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp); 713 + 714 + create_qp_exit1: 715 + spin_lock_irqsave(&ehca_qp_idr_lock, flags); 716 + idr_remove(&ehca_qp_idr, my_qp->token); 717 + spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); 718 + 719 + create_qp_exit0: 720 + kmem_cache_free(qp_cache, my_qp); 721 + return ERR_PTR(ret); 722 + } 723 + 724 + /* 725 + * prepare_sqe_rts called by internal_modify_qp() at trans sqe -> rts 726 + * set purge bit of bad wqe and subsequent wqes to avoid reentering sqe 727 + * returns total number of bad wqes in bad_wqe_cnt 728 + */ 729 + static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca, 730 + int *bad_wqe_cnt) 731 + { 732 + u64 h_ret; 733 + struct ipz_queue *squeue; 734 + void *bad_send_wqe_p, *bad_send_wqe_v; 735 + void *squeue_start_p, *squeue_end_p; 736 + void *squeue_start_v, *squeue_end_v; 737 + struct ehca_wqe *wqe; 738 + int qp_num = my_qp->ib_qp.qp_num; 739 + 740 + /* get send wqe pointer */ 741 + h_ret = hipz_h_disable_and_get_wqe(shca->ipz_hca_handle, 742 + my_qp->ipz_qp_handle, &my_qp->pf, 743 + &bad_send_wqe_p, NULL, 2); 744 + if (h_ret != H_SUCCESS) { 745 + ehca_err(&shca->ib_device, "hipz_h_disable_and_get_wqe() failed" 746 + " ehca_qp=%p qp_num=%x h_ret=%lx", 747 + my_qp, qp_num, h_ret); 748 + return ehca2ib_return_code(h_ret); 749 + } 750 + bad_send_wqe_p = (void*)((u64)bad_send_wqe_p & (~(1L<<63))); 751 + ehca_dbg(&shca->ib_device, "qp_num=%x bad_send_wqe_p=%p", 752 + qp_num, bad_send_wqe_p); 753 + /* convert wqe pointer to vadr */ 754 + bad_send_wqe_v = abs_to_virt((u64)bad_send_wqe_p); 755 + if (ehca_debug_level) 756 + ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num); 757 + squeue = &my_qp->ipz_squeue; 758 + squeue_start_p = (void*)virt_to_abs(ipz_qeit_calc(squeue, 0L)); 759 + squeue_end_p = squeue_start_p+squeue->queue_length; 760 + squeue_start_v = abs_to_virt((u64)squeue_start_p); 761 + squeue_end_v = abs_to_virt((u64)squeue_end_p); 762 + ehca_dbg(&shca->ib_device, "qp_num=%x squeue_start_v=%p squeue_end_v=%p", 763 + qp_num, squeue_start_v, squeue_end_v); 764 + 765 + /* loop sets wqe's purge bit */ 766 + wqe = (struct ehca_wqe*)bad_send_wqe_v; 767 + *bad_wqe_cnt = 0; 768 + while (wqe->optype != 0xff && wqe->wqef != 0xff) { 769 + if (ehca_debug_level) 770 + ehca_dmp(wqe, 32, "qp_num=%x wqe", qp_num); 771 + wqe->nr_of_data_seg = 0; /* suppress data access */ 772 + wqe->wqef = WQEF_PURGE; /* WQE to be purged */ 773 + wqe = (struct ehca_wqe*)((u8*)wqe+squeue->qe_size); 774 + *bad_wqe_cnt = (*bad_wqe_cnt)+1; 775 + if ((void*)wqe >= squeue_end_v) { 776 + wqe = squeue_start_v; 777 + } 778 + } 779 + /* 780 + * bad wqe will be reprocessed and ignored when pol_cq() is called, 781 + * i.e. nr of wqes with flush error status is one less 782 + */ 783 + ehca_dbg(&shca->ib_device, "qp_num=%x flusherr_wqe_cnt=%x", 784 + qp_num, (*bad_wqe_cnt)-1); 785 + wqe->wqef = 0; 786 + 787 + return 0; 788 + } 789 + 790 + /* 791 + * internal_modify_qp with circumvention to handle aqp0 properly 792 + * smi_reset2init indicates if this is an internal reset-to-init-call for 793 + * smi. This flag must always be zero if called from ehca_modify_qp()! 794 + * This internal func was intorduced to avoid recursion of ehca_modify_qp()! 795 + */ 796 + static int internal_modify_qp(struct ib_qp *ibqp, 797 + struct ib_qp_attr *attr, 798 + int attr_mask, int smi_reset2init) 799 + { 800 + enum ib_qp_state qp_cur_state, qp_new_state; 801 + int cnt, qp_attr_idx, ret = 0; 802 + enum ib_qp_statetrans statetrans; 803 + struct hcp_modify_qp_control_block *mqpcb; 804 + struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); 805 + struct ehca_shca *shca = 806 + container_of(ibqp->pd->device, struct ehca_shca, ib_device); 807 + u64 update_mask; 808 + u64 h_ret; 809 + int bad_wqe_cnt = 0; 810 + int squeue_locked = 0; 811 + unsigned long spl_flags = 0; 812 + 813 + /* do query_qp to obtain current attr values */ 814 + mqpcb = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); 815 + if (mqpcb == NULL) { 816 + ehca_err(ibqp->device, "Could not get zeroed page for mqpcb " 817 + "ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num); 818 + return -ENOMEM; 819 + } 820 + 821 + h_ret = hipz_h_query_qp(shca->ipz_hca_handle, 822 + my_qp->ipz_qp_handle, 823 + &my_qp->pf, 824 + mqpcb, my_qp->galpas.kernel); 825 + if (h_ret != H_SUCCESS) { 826 + ehca_err(ibqp->device, "hipz_h_query_qp() failed " 827 + "ehca_qp=%p qp_num=%x h_ret=%lx", 828 + my_qp, ibqp->qp_num, h_ret); 829 + ret = ehca2ib_return_code(h_ret); 830 + goto modify_qp_exit1; 831 + } 832 + 833 + qp_cur_state = ehca2ib_qp_state(mqpcb->qp_state); 834 + 835 + if (qp_cur_state == -EINVAL) { /* invalid qp state */ 836 + ret = -EINVAL; 837 + ehca_err(ibqp->device, "Invalid current ehca_qp_state=%x " 838 + "ehca_qp=%p qp_num=%x", 839 + mqpcb->qp_state, my_qp, ibqp->qp_num); 840 + goto modify_qp_exit1; 841 + } 842 + /* 843 + * circumvention to set aqp0 initial state to init 844 + * as expected by IB spec 845 + */ 846 + if (smi_reset2init == 0 && 847 + ibqp->qp_type == IB_QPT_SMI && 848 + qp_cur_state == IB_QPS_RESET && 849 + (attr_mask & IB_QP_STATE) && 850 + attr->qp_state == IB_QPS_INIT) { /* RESET -> INIT */ 851 + struct ib_qp_attr smiqp_attr = { 852 + .qp_state = IB_QPS_INIT, 853 + .port_num = my_qp->init_attr.port_num, 854 + .pkey_index = 0, 855 + .qkey = 0 856 + }; 857 + int smiqp_attr_mask = IB_QP_STATE | IB_QP_PORT | 858 + IB_QP_PKEY_INDEX | IB_QP_QKEY; 859 + int smirc = internal_modify_qp( 860 + ibqp, &smiqp_attr, smiqp_attr_mask, 1); 861 + if (smirc) { 862 + ehca_err(ibqp->device, "SMI RESET -> INIT failed. " 863 + "ehca_modify_qp() rc=%x", smirc); 864 + ret = H_PARAMETER; 865 + goto modify_qp_exit1; 866 + } 867 + qp_cur_state = IB_QPS_INIT; 868 + ehca_dbg(ibqp->device, "SMI RESET -> INIT succeeded"); 869 + } 870 + /* is transmitted current state equal to "real" current state */ 871 + if ((attr_mask & IB_QP_CUR_STATE) && 872 + qp_cur_state != attr->cur_qp_state) { 873 + ret = -EINVAL; 874 + ehca_err(ibqp->device, 875 + "Invalid IB_QP_CUR_STATE attr->curr_qp_state=%x <>" 876 + " actual cur_qp_state=%x. ehca_qp=%p qp_num=%x", 877 + attr->cur_qp_state, qp_cur_state, my_qp, ibqp->qp_num); 878 + goto modify_qp_exit1; 879 + } 880 + 881 + ehca_dbg(ibqp->device,"ehca_qp=%p qp_num=%x current qp_state=%x " 882 + "new qp_state=%x attribute_mask=%x", 883 + my_qp, ibqp->qp_num, qp_cur_state, attr->qp_state, attr_mask); 884 + 885 + qp_new_state = attr_mask & IB_QP_STATE ? attr->qp_state : qp_cur_state; 886 + if (!smi_reset2init && 887 + !ib_modify_qp_is_ok(qp_cur_state, qp_new_state, ibqp->qp_type, 888 + attr_mask)) { 889 + ret = -EINVAL; 890 + ehca_err(ibqp->device, 891 + "Invalid qp transition new_state=%x cur_state=%x " 892 + "ehca_qp=%p qp_num=%x attr_mask=%x", qp_new_state, 893 + qp_cur_state, my_qp, ibqp->qp_num, attr_mask); 894 + goto modify_qp_exit1; 895 + } 896 + 897 + if ((mqpcb->qp_state = ib2ehca_qp_state(qp_new_state))) 898 + update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1); 899 + else { 900 + ret = -EINVAL; 901 + ehca_err(ibqp->device, "Invalid new qp state=%x " 902 + "ehca_qp=%p qp_num=%x", 903 + qp_new_state, my_qp, ibqp->qp_num); 904 + goto modify_qp_exit1; 905 + } 906 + 907 + /* retrieve state transition struct to get req and opt attrs */ 908 + statetrans = get_modqp_statetrans(qp_cur_state, qp_new_state); 909 + if (statetrans < 0) { 910 + ret = -EINVAL; 911 + ehca_err(ibqp->device, "<INVALID STATE CHANGE> qp_cur_state=%x " 912 + "new_qp_state=%x State_xsition=%x ehca_qp=%p " 913 + "qp_num=%x", qp_cur_state, qp_new_state, 914 + statetrans, my_qp, ibqp->qp_num); 915 + goto modify_qp_exit1; 916 + } 917 + 918 + qp_attr_idx = ib2ehcaqptype(ibqp->qp_type); 919 + 920 + if (qp_attr_idx < 0) { 921 + ret = qp_attr_idx; 922 + ehca_err(ibqp->device, 923 + "Invalid QP type=%x ehca_qp=%p qp_num=%x", 924 + ibqp->qp_type, my_qp, ibqp->qp_num); 925 + goto modify_qp_exit1; 926 + } 927 + 928 + ehca_dbg(ibqp->device, 929 + "ehca_qp=%p qp_num=%x <VALID STATE CHANGE> qp_state_xsit=%x", 930 + my_qp, ibqp->qp_num, statetrans); 931 + 932 + /* sqe -> rts: set purge bit of bad wqe before actual trans */ 933 + if ((my_qp->qp_type == IB_QPT_UD || 934 + my_qp->qp_type == IB_QPT_GSI || 935 + my_qp->qp_type == IB_QPT_SMI) && 936 + statetrans == IB_QPST_SQE2RTS) { 937 + /* mark next free wqe if kernel */ 938 + if (my_qp->uspace_squeue == 0) { 939 + struct ehca_wqe *wqe; 940 + /* lock send queue */ 941 + spin_lock_irqsave(&my_qp->spinlock_s, spl_flags); 942 + squeue_locked = 1; 943 + /* mark next free wqe */ 944 + wqe = (struct ehca_wqe*) 945 + ipz_qeit_get(&my_qp->ipz_squeue); 946 + wqe->optype = wqe->wqef = 0xff; 947 + ehca_dbg(ibqp->device, "qp_num=%x next_free_wqe=%p", 948 + ibqp->qp_num, wqe); 949 + } 950 + ret = prepare_sqe_rts(my_qp, shca, &bad_wqe_cnt); 951 + if (ret) { 952 + ehca_err(ibqp->device, "prepare_sqe_rts() failed " 953 + "ehca_qp=%p qp_num=%x ret=%x", 954 + my_qp, ibqp->qp_num, ret); 955 + goto modify_qp_exit2; 956 + } 957 + } 958 + 959 + /* 960 + * enable RDMA_Atomic_Control if reset->init und reliable con 961 + * this is necessary since gen2 does not provide that flag, 962 + * but pHyp requires it 963 + */ 964 + if (statetrans == IB_QPST_RESET2INIT && 965 + (ibqp->qp_type == IB_QPT_RC || ibqp->qp_type == IB_QPT_UC)) { 966 + mqpcb->rdma_atomic_ctrl = 3; 967 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RDMA_ATOMIC_CTRL, 1); 968 + } 969 + /* circ. pHyp requires #RDMA/Atomic Resp Res for UC INIT -> RTR */ 970 + if (statetrans == IB_QPST_INIT2RTR && 971 + (ibqp->qp_type == IB_QPT_UC) && 972 + !(attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)) { 973 + mqpcb->rdma_nr_atomic_resp_res = 1; /* default to 1 */ 974 + update_mask |= 975 + EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1); 976 + } 977 + 978 + if (attr_mask & IB_QP_PKEY_INDEX) { 979 + mqpcb->prim_p_key_idx = attr->pkey_index; 980 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_P_KEY_IDX, 1); 981 + } 982 + if (attr_mask & IB_QP_PORT) { 983 + if (attr->port_num < 1 || attr->port_num > shca->num_ports) { 984 + ret = -EINVAL; 985 + ehca_err(ibqp->device, "Invalid port=%x. " 986 + "ehca_qp=%p qp_num=%x num_ports=%x", 987 + attr->port_num, my_qp, ibqp->qp_num, 988 + shca->num_ports); 989 + goto modify_qp_exit2; 990 + } 991 + mqpcb->prim_phys_port = attr->port_num; 992 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_PHYS_PORT, 1); 993 + } 994 + if (attr_mask & IB_QP_QKEY) { 995 + mqpcb->qkey = attr->qkey; 996 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_QKEY, 1); 997 + } 998 + if (attr_mask & IB_QP_AV) { 999 + int ah_mult = ib_rate_to_mult(attr->ah_attr.static_rate); 1000 + int ehca_mult = ib_rate_to_mult(shca->sport[my_qp-> 1001 + init_attr.port_num].rate); 1002 + 1003 + mqpcb->dlid = attr->ah_attr.dlid; 1004 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID, 1); 1005 + mqpcb->source_path_bits = attr->ah_attr.src_path_bits; 1006 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS, 1); 1007 + mqpcb->service_level = attr->ah_attr.sl; 1008 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL, 1); 1009 + 1010 + if (ah_mult < ehca_mult) 1011 + mqpcb->max_static_rate = (ah_mult > 0) ? 1012 + ((ehca_mult - 1) / ah_mult) : 0; 1013 + else 1014 + mqpcb->max_static_rate = 0; 1015 + 1016 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1); 1017 + 1018 + /* 1019 + * only if GRH is TRUE we might consider SOURCE_GID_IDX 1020 + * and DEST_GID otherwise phype will return H_ATTR_PARM!!! 1021 + */ 1022 + if (attr->ah_attr.ah_flags == IB_AH_GRH) { 1023 + mqpcb->send_grh_flag = 1 << 31; 1024 + update_mask |= 1025 + EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1); 1026 + mqpcb->source_gid_idx = attr->ah_attr.grh.sgid_index; 1027 + update_mask |= 1028 + EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX, 1); 1029 + 1030 + for (cnt = 0; cnt < 16; cnt++) 1031 + mqpcb->dest_gid.byte[cnt] = 1032 + attr->ah_attr.grh.dgid.raw[cnt]; 1033 + 1034 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_GID, 1); 1035 + mqpcb->flow_label = attr->ah_attr.grh.flow_label; 1036 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL, 1); 1037 + mqpcb->hop_limit = attr->ah_attr.grh.hop_limit; 1038 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT, 1); 1039 + mqpcb->traffic_class = attr->ah_attr.grh.traffic_class; 1040 + update_mask |= 1041 + EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS, 1); 1042 + } 1043 + } 1044 + 1045 + if (attr_mask & IB_QP_PATH_MTU) { 1046 + mqpcb->path_mtu = attr->path_mtu; 1047 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PATH_MTU, 1); 1048 + } 1049 + if (attr_mask & IB_QP_TIMEOUT) { 1050 + mqpcb->timeout = attr->timeout; 1051 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_TIMEOUT, 1); 1052 + } 1053 + if (attr_mask & IB_QP_RETRY_CNT) { 1054 + mqpcb->retry_count = attr->retry_cnt; 1055 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RETRY_COUNT, 1); 1056 + } 1057 + if (attr_mask & IB_QP_RNR_RETRY) { 1058 + mqpcb->rnr_retry_count = attr->rnr_retry; 1059 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RNR_RETRY_COUNT, 1); 1060 + } 1061 + if (attr_mask & IB_QP_RQ_PSN) { 1062 + mqpcb->receive_psn = attr->rq_psn; 1063 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RECEIVE_PSN, 1); 1064 + } 1065 + if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { 1066 + mqpcb->rdma_nr_atomic_resp_res = attr->max_dest_rd_atomic < 3 ? 1067 + attr->max_dest_rd_atomic : 2; 1068 + update_mask |= 1069 + EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1); 1070 + } 1071 + if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { 1072 + mqpcb->rdma_atomic_outst_dest_qp = attr->max_rd_atomic < 3 ? 1073 + attr->max_rd_atomic : 2; 1074 + update_mask |= 1075 + EHCA_BMASK_SET 1076 + (MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP, 1); 1077 + } 1078 + if (attr_mask & IB_QP_ALT_PATH) { 1079 + int ah_mult = ib_rate_to_mult(attr->alt_ah_attr.static_rate); 1080 + int ehca_mult = ib_rate_to_mult( 1081 + shca->sport[my_qp->init_attr.port_num].rate); 1082 + 1083 + mqpcb->dlid_al = attr->alt_ah_attr.dlid; 1084 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID_AL, 1); 1085 + mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits; 1086 + update_mask |= 1087 + EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS_AL, 1); 1088 + mqpcb->service_level_al = attr->alt_ah_attr.sl; 1089 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL_AL, 1); 1090 + 1091 + if (ah_mult < ehca_mult) 1092 + mqpcb->max_static_rate = (ah_mult > 0) ? 1093 + ((ehca_mult - 1) / ah_mult) : 0; 1094 + else 1095 + mqpcb->max_static_rate_al = 0; 1096 + 1097 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE_AL, 1); 1098 + 1099 + /* 1100 + * only if GRH is TRUE we might consider SOURCE_GID_IDX 1101 + * and DEST_GID otherwise phype will return H_ATTR_PARM!!! 1102 + */ 1103 + if (attr->alt_ah_attr.ah_flags == IB_AH_GRH) { 1104 + mqpcb->send_grh_flag_al = 1 << 31; 1105 + update_mask |= 1106 + EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG_AL, 1); 1107 + mqpcb->source_gid_idx_al = 1108 + attr->alt_ah_attr.grh.sgid_index; 1109 + update_mask |= 1110 + EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX_AL, 1); 1111 + 1112 + for (cnt = 0; cnt < 16; cnt++) 1113 + mqpcb->dest_gid_al.byte[cnt] = 1114 + attr->alt_ah_attr.grh.dgid.raw[cnt]; 1115 + 1116 + update_mask |= 1117 + EHCA_BMASK_SET(MQPCB_MASK_DEST_GID_AL, 1); 1118 + mqpcb->flow_label_al = attr->alt_ah_attr.grh.flow_label; 1119 + update_mask |= 1120 + EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL_AL, 1); 1121 + mqpcb->hop_limit_al = attr->alt_ah_attr.grh.hop_limit; 1122 + update_mask |= 1123 + EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT_AL, 1); 1124 + mqpcb->traffic_class_al = 1125 + attr->alt_ah_attr.grh.traffic_class; 1126 + update_mask |= 1127 + EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS_AL, 1); 1128 + } 1129 + } 1130 + 1131 + if (attr_mask & IB_QP_MIN_RNR_TIMER) { 1132 + mqpcb->min_rnr_nak_timer_field = attr->min_rnr_timer; 1133 + update_mask |= 1134 + EHCA_BMASK_SET(MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD, 1); 1135 + } 1136 + 1137 + if (attr_mask & IB_QP_SQ_PSN) { 1138 + mqpcb->send_psn = attr->sq_psn; 1139 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_PSN, 1); 1140 + } 1141 + 1142 + if (attr_mask & IB_QP_DEST_QPN) { 1143 + mqpcb->dest_qp_nr = attr->dest_qp_num; 1144 + update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_QP_NR, 1); 1145 + } 1146 + 1147 + if (attr_mask & IB_QP_PATH_MIG_STATE) { 1148 + mqpcb->path_migration_state = attr->path_mig_state; 1149 + update_mask |= 1150 + EHCA_BMASK_SET(MQPCB_MASK_PATH_MIGRATION_STATE, 1); 1151 + } 1152 + 1153 + if (attr_mask & IB_QP_CAP) { 1154 + mqpcb->max_nr_outst_send_wr = attr->cap.max_send_wr+1; 1155 + update_mask |= 1156 + EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_SEND_WR, 1); 1157 + mqpcb->max_nr_outst_recv_wr = attr->cap.max_recv_wr+1; 1158 + update_mask |= 1159 + EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_RECV_WR, 1); 1160 + /* no support for max_send/recv_sge yet */ 1161 + } 1162 + 1163 + if (ehca_debug_level) 1164 + ehca_dmp(mqpcb, 4*70, "qp_num=%x", ibqp->qp_num); 1165 + 1166 + h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, 1167 + my_qp->ipz_qp_handle, 1168 + &my_qp->pf, 1169 + update_mask, 1170 + mqpcb, my_qp->galpas.kernel); 1171 + 1172 + if (h_ret != H_SUCCESS) { 1173 + ret = ehca2ib_return_code(h_ret); 1174 + ehca_err(ibqp->device, "hipz_h_modify_qp() failed rc=%lx " 1175 + "ehca_qp=%p qp_num=%x",h_ret, my_qp, ibqp->qp_num); 1176 + goto modify_qp_exit2; 1177 + } 1178 + 1179 + if ((my_qp->qp_type == IB_QPT_UD || 1180 + my_qp->qp_type == IB_QPT_GSI || 1181 + my_qp->qp_type == IB_QPT_SMI) && 1182 + statetrans == IB_QPST_SQE2RTS) { 1183 + /* doorbell to reprocessing wqes */ 1184 + iosync(); /* serialize GAL register access */ 1185 + hipz_update_sqa(my_qp, bad_wqe_cnt-1); 1186 + ehca_gen_dbg("doorbell for %x wqes", bad_wqe_cnt); 1187 + } 1188 + 1189 + if (statetrans == IB_QPST_RESET2INIT || 1190 + statetrans == IB_QPST_INIT2INIT) { 1191 + mqpcb->qp_enable = 1; 1192 + mqpcb->qp_state = EHCA_QPS_INIT; 1193 + update_mask = 0; 1194 + update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_ENABLE, 1); 1195 + 1196 + h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, 1197 + my_qp->ipz_qp_handle, 1198 + &my_qp->pf, 1199 + update_mask, 1200 + mqpcb, 1201 + my_qp->galpas.kernel); 1202 + 1203 + if (h_ret != H_SUCCESS) { 1204 + ret = ehca2ib_return_code(h_ret); 1205 + ehca_err(ibqp->device, "ENABLE in context of " 1206 + "RESET_2_INIT failed! Maybe you didn't get " 1207 + "a LID h_ret=%lx ehca_qp=%p qp_num=%x", 1208 + h_ret, my_qp, ibqp->qp_num); 1209 + goto modify_qp_exit2; 1210 + } 1211 + } 1212 + 1213 + if (statetrans == IB_QPST_ANY2RESET) { 1214 + ipz_qeit_reset(&my_qp->ipz_rqueue); 1215 + ipz_qeit_reset(&my_qp->ipz_squeue); 1216 + } 1217 + 1218 + if (attr_mask & IB_QP_QKEY) 1219 + my_qp->qkey = attr->qkey; 1220 + 1221 + modify_qp_exit2: 1222 + if (squeue_locked) { /* this means: sqe -> rts */ 1223 + spin_unlock_irqrestore(&my_qp->spinlock_s, spl_flags); 1224 + my_qp->sqerr_purgeflag = 1; 1225 + } 1226 + 1227 + modify_qp_exit1: 1228 + kfree(mqpcb); 1229 + 1230 + return ret; 1231 + } 1232 + 1233 + int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) 1234 + { 1235 + struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); 1236 + struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd, 1237 + ib_pd); 1238 + u32 cur_pid = current->tgid; 1239 + 1240 + if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && 1241 + my_pd->ownpid != cur_pid) { 1242 + ehca_err(ibqp->pd->device, "Invalid caller pid=%x ownpid=%x", 1243 + cur_pid, my_pd->ownpid); 1244 + return -EINVAL; 1245 + } 1246 + 1247 + return internal_modify_qp(ibqp, attr, attr_mask, 0); 1248 + } 1249 + 1250 + int ehca_query_qp(struct ib_qp *qp, 1251 + struct ib_qp_attr *qp_attr, 1252 + int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr) 1253 + { 1254 + struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp); 1255 + struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd, 1256 + ib_pd); 1257 + struct ehca_shca *shca = container_of(qp->device, struct ehca_shca, 1258 + ib_device); 1259 + struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle; 1260 + struct hcp_modify_qp_control_block *qpcb; 1261 + u32 cur_pid = current->tgid; 1262 + int cnt, ret = 0; 1263 + u64 h_ret; 1264 + 1265 + if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && 1266 + my_pd->ownpid != cur_pid) { 1267 + ehca_err(qp->device, "Invalid caller pid=%x ownpid=%x", 1268 + cur_pid, my_pd->ownpid); 1269 + return -EINVAL; 1270 + } 1271 + 1272 + if (qp_attr_mask & QP_ATTR_QUERY_NOT_SUPPORTED) { 1273 + ehca_err(qp->device,"Invalid attribute mask " 1274 + "ehca_qp=%p qp_num=%x qp_attr_mask=%x ", 1275 + my_qp, qp->qp_num, qp_attr_mask); 1276 + return -EINVAL; 1277 + } 1278 + 1279 + qpcb = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL ); 1280 + if (!qpcb) { 1281 + ehca_err(qp->device,"Out of memory for qpcb " 1282 + "ehca_qp=%p qp_num=%x", my_qp, qp->qp_num); 1283 + return -ENOMEM; 1284 + } 1285 + 1286 + h_ret = hipz_h_query_qp(adapter_handle, 1287 + my_qp->ipz_qp_handle, 1288 + &my_qp->pf, 1289 + qpcb, my_qp->galpas.kernel); 1290 + 1291 + if (h_ret != H_SUCCESS) { 1292 + ret = ehca2ib_return_code(h_ret); 1293 + ehca_err(qp->device,"hipz_h_query_qp() failed " 1294 + "ehca_qp=%p qp_num=%x h_ret=%lx", 1295 + my_qp, qp->qp_num, h_ret); 1296 + goto query_qp_exit1; 1297 + } 1298 + 1299 + qp_attr->cur_qp_state = ehca2ib_qp_state(qpcb->qp_state); 1300 + qp_attr->qp_state = qp_attr->cur_qp_state; 1301 + 1302 + if (qp_attr->cur_qp_state == -EINVAL) { 1303 + ret = -EINVAL; 1304 + ehca_err(qp->device,"Got invalid ehca_qp_state=%x " 1305 + "ehca_qp=%p qp_num=%x", 1306 + qpcb->qp_state, my_qp, qp->qp_num); 1307 + goto query_qp_exit1; 1308 + } 1309 + 1310 + if (qp_attr->qp_state == IB_QPS_SQD) 1311 + qp_attr->sq_draining = 1; 1312 + 1313 + qp_attr->qkey = qpcb->qkey; 1314 + qp_attr->path_mtu = qpcb->path_mtu; 1315 + qp_attr->path_mig_state = qpcb->path_migration_state; 1316 + qp_attr->rq_psn = qpcb->receive_psn; 1317 + qp_attr->sq_psn = qpcb->send_psn; 1318 + qp_attr->min_rnr_timer = qpcb->min_rnr_nak_timer_field; 1319 + qp_attr->cap.max_send_wr = qpcb->max_nr_outst_send_wr-1; 1320 + qp_attr->cap.max_recv_wr = qpcb->max_nr_outst_recv_wr-1; 1321 + /* UD_AV CIRCUMVENTION */ 1322 + if (my_qp->qp_type == IB_QPT_UD) { 1323 + qp_attr->cap.max_send_sge = 1324 + qpcb->actual_nr_sges_in_sq_wqe - 2; 1325 + qp_attr->cap.max_recv_sge = 1326 + qpcb->actual_nr_sges_in_rq_wqe - 2; 1327 + } else { 1328 + qp_attr->cap.max_send_sge = 1329 + qpcb->actual_nr_sges_in_sq_wqe; 1330 + qp_attr->cap.max_recv_sge = 1331 + qpcb->actual_nr_sges_in_rq_wqe; 1332 + } 1333 + 1334 + qp_attr->cap.max_inline_data = my_qp->sq_max_inline_data_size; 1335 + qp_attr->dest_qp_num = qpcb->dest_qp_nr; 1336 + 1337 + qp_attr->pkey_index = 1338 + EHCA_BMASK_GET(MQPCB_PRIM_P_KEY_IDX, qpcb->prim_p_key_idx); 1339 + 1340 + qp_attr->port_num = 1341 + EHCA_BMASK_GET(MQPCB_PRIM_PHYS_PORT, qpcb->prim_phys_port); 1342 + 1343 + qp_attr->timeout = qpcb->timeout; 1344 + qp_attr->retry_cnt = qpcb->retry_count; 1345 + qp_attr->rnr_retry = qpcb->rnr_retry_count; 1346 + 1347 + qp_attr->alt_pkey_index = 1348 + EHCA_BMASK_GET(MQPCB_PRIM_P_KEY_IDX, qpcb->alt_p_key_idx); 1349 + 1350 + qp_attr->alt_port_num = qpcb->alt_phys_port; 1351 + qp_attr->alt_timeout = qpcb->timeout_al; 1352 + 1353 + /* primary av */ 1354 + qp_attr->ah_attr.sl = qpcb->service_level; 1355 + 1356 + if (qpcb->send_grh_flag) { 1357 + qp_attr->ah_attr.ah_flags = IB_AH_GRH; 1358 + } 1359 + 1360 + qp_attr->ah_attr.static_rate = qpcb->max_static_rate; 1361 + qp_attr->ah_attr.dlid = qpcb->dlid; 1362 + qp_attr->ah_attr.src_path_bits = qpcb->source_path_bits; 1363 + qp_attr->ah_attr.port_num = qp_attr->port_num; 1364 + 1365 + /* primary GRH */ 1366 + qp_attr->ah_attr.grh.traffic_class = qpcb->traffic_class; 1367 + qp_attr->ah_attr.grh.hop_limit = qpcb->hop_limit; 1368 + qp_attr->ah_attr.grh.sgid_index = qpcb->source_gid_idx; 1369 + qp_attr->ah_attr.grh.flow_label = qpcb->flow_label; 1370 + 1371 + for (cnt = 0; cnt < 16; cnt++) 1372 + qp_attr->ah_attr.grh.dgid.raw[cnt] = 1373 + qpcb->dest_gid.byte[cnt]; 1374 + 1375 + /* alternate AV */ 1376 + qp_attr->alt_ah_attr.sl = qpcb->service_level_al; 1377 + if (qpcb->send_grh_flag_al) { 1378 + qp_attr->alt_ah_attr.ah_flags = IB_AH_GRH; 1379 + } 1380 + 1381 + qp_attr->alt_ah_attr.static_rate = qpcb->max_static_rate_al; 1382 + qp_attr->alt_ah_attr.dlid = qpcb->dlid_al; 1383 + qp_attr->alt_ah_attr.src_path_bits = qpcb->source_path_bits_al; 1384 + 1385 + /* alternate GRH */ 1386 + qp_attr->alt_ah_attr.grh.traffic_class = qpcb->traffic_class_al; 1387 + qp_attr->alt_ah_attr.grh.hop_limit = qpcb->hop_limit_al; 1388 + qp_attr->alt_ah_attr.grh.sgid_index = qpcb->source_gid_idx_al; 1389 + qp_attr->alt_ah_attr.grh.flow_label = qpcb->flow_label_al; 1390 + 1391 + for (cnt = 0; cnt < 16; cnt++) 1392 + qp_attr->alt_ah_attr.grh.dgid.raw[cnt] = 1393 + qpcb->dest_gid_al.byte[cnt]; 1394 + 1395 + /* return init attributes given in ehca_create_qp */ 1396 + if (qp_init_attr) 1397 + *qp_init_attr = my_qp->init_attr; 1398 + 1399 + if (ehca_debug_level) 1400 + ehca_dmp(qpcb, 4*70, "qp_num=%x", qp->qp_num); 1401 + 1402 + query_qp_exit1: 1403 + kfree(qpcb); 1404 + 1405 + return ret; 1406 + } 1407 + 1408 + int ehca_destroy_qp(struct ib_qp *ibqp) 1409 + { 1410 + struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); 1411 + struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca, 1412 + ib_device); 1413 + struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd, 1414 + ib_pd); 1415 + u32 cur_pid = current->tgid; 1416 + u32 qp_num = ibqp->qp_num; 1417 + int ret; 1418 + u64 h_ret; 1419 + u8 port_num; 1420 + enum ib_qp_type qp_type; 1421 + unsigned long flags; 1422 + 1423 + if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && 1424 + my_pd->ownpid != cur_pid) { 1425 + ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x", 1426 + cur_pid, my_pd->ownpid); 1427 + return -EINVAL; 1428 + } 1429 + 1430 + if (my_qp->send_cq) { 1431 + ret = ehca_cq_unassign_qp(my_qp->send_cq, 1432 + my_qp->real_qp_num); 1433 + if (ret) { 1434 + ehca_err(ibqp->device, "Couldn't unassign qp from " 1435 + "send_cq ret=%x qp_num=%x cq_num=%x", ret, 1436 + my_qp->ib_qp.qp_num, my_qp->send_cq->cq_number); 1437 + return ret; 1438 + } 1439 + } 1440 + 1441 + spin_lock_irqsave(&ehca_qp_idr_lock, flags); 1442 + idr_remove(&ehca_qp_idr, my_qp->token); 1443 + spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); 1444 + 1445 + /* un-mmap if vma alloc */ 1446 + if (my_qp->uspace_rqueue) { 1447 + ret = ehca_munmap(my_qp->uspace_rqueue, 1448 + my_qp->ipz_rqueue.queue_length); 1449 + if (ret) 1450 + ehca_err(ibqp->device, "Could not munmap rqueue " 1451 + "qp_num=%x", qp_num); 1452 + ret = ehca_munmap(my_qp->uspace_squeue, 1453 + my_qp->ipz_squeue.queue_length); 1454 + if (ret) 1455 + ehca_err(ibqp->device, "Could not munmap squeue " 1456 + "qp_num=%x", qp_num); 1457 + ret = ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE); 1458 + if (ret) 1459 + ehca_err(ibqp->device, "Could not munmap fwh qp_num=%x", 1460 + qp_num); 1461 + } 1462 + 1463 + h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp); 1464 + if (h_ret != H_SUCCESS) { 1465 + ehca_err(ibqp->device, "hipz_h_destroy_qp() failed rc=%lx " 1466 + "ehca_qp=%p qp_num=%x", h_ret, my_qp, qp_num); 1467 + return ehca2ib_return_code(h_ret); 1468 + } 1469 + 1470 + port_num = my_qp->init_attr.port_num; 1471 + qp_type = my_qp->init_attr.qp_type; 1472 + 1473 + /* no support for IB_QPT_SMI yet */ 1474 + if (qp_type == IB_QPT_GSI) { 1475 + struct ib_event event; 1476 + ehca_info(ibqp->device, "device %s: port %x is inactive.", 1477 + shca->ib_device.name, port_num); 1478 + event.device = &shca->ib_device; 1479 + event.event = IB_EVENT_PORT_ERR; 1480 + event.element.port_num = port_num; 1481 + shca->sport[port_num - 1].port_state = IB_PORT_DOWN; 1482 + ib_dispatch_event(&event); 1483 + } 1484 + 1485 + ipz_queue_dtor(&my_qp->ipz_rqueue); 1486 + ipz_queue_dtor(&my_qp->ipz_squeue); 1487 + kmem_cache_free(qp_cache, my_qp); 1488 + return 0; 1489 + } 1490 + 1491 + int ehca_init_qp_cache(void) 1492 + { 1493 + qp_cache = kmem_cache_create("ehca_cache_qp", 1494 + sizeof(struct ehca_qp), 0, 1495 + SLAB_HWCACHE_ALIGN, 1496 + NULL, NULL); 1497 + if (!qp_cache) 1498 + return -ENOMEM; 1499 + return 0; 1500 + } 1501 + 1502 + void ehca_cleanup_qp_cache(void) 1503 + { 1504 + if (qp_cache) 1505 + kmem_cache_destroy(qp_cache); 1506 + }
+653
drivers/infiniband/hw/ehca/ehca_reqs.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * post_send/recv, poll_cq, req_notify 5 + * 6 + * Authors: Waleri Fomin <fomin@de.ibm.com> 7 + * Hoang-Nam Nguyen <hnguyen@de.ibm.com> 8 + * Reinhard Ernst <rernst@de.ibm.com> 9 + * 10 + * Copyright (c) 2005 IBM Corporation 11 + * 12 + * All rights reserved. 13 + * 14 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 15 + * BSD. 16 + * 17 + * OpenIB BSD License 18 + * 19 + * Redistribution and use in source and binary forms, with or without 20 + * modification, are permitted provided that the following conditions are met: 21 + * 22 + * Redistributions of source code must retain the above copyright notice, this 23 + * list of conditions and the following disclaimer. 24 + * 25 + * Redistributions in binary form must reproduce the above copyright notice, 26 + * this list of conditions and the following disclaimer in the documentation 27 + * and/or other materials 28 + * provided with the distribution. 29 + * 30 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 31 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 34 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 37 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 38 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 + * POSSIBILITY OF SUCH DAMAGE. 41 + */ 42 + 43 + 44 + #include <asm-powerpc/system.h> 45 + #include "ehca_classes.h" 46 + #include "ehca_tools.h" 47 + #include "ehca_qes.h" 48 + #include "ehca_iverbs.h" 49 + #include "hcp_if.h" 50 + #include "hipz_fns.h" 51 + 52 + static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue, 53 + struct ehca_wqe *wqe_p, 54 + struct ib_recv_wr *recv_wr) 55 + { 56 + u8 cnt_ds; 57 + if (unlikely((recv_wr->num_sge < 0) || 58 + (recv_wr->num_sge > ipz_rqueue->act_nr_of_sg))) { 59 + ehca_gen_err("Invalid number of WQE SGE. " 60 + "num_sqe=%x max_nr_of_sg=%x", 61 + recv_wr->num_sge, ipz_rqueue->act_nr_of_sg); 62 + return -EINVAL; /* invalid SG list length */ 63 + } 64 + 65 + /* clear wqe header until sglist */ 66 + memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list)); 67 + 68 + wqe_p->work_request_id = recv_wr->wr_id; 69 + wqe_p->nr_of_data_seg = recv_wr->num_sge; 70 + 71 + for (cnt_ds = 0; cnt_ds < recv_wr->num_sge; cnt_ds++) { 72 + wqe_p->u.all_rcv.sg_list[cnt_ds].vaddr = 73 + recv_wr->sg_list[cnt_ds].addr; 74 + wqe_p->u.all_rcv.sg_list[cnt_ds].lkey = 75 + recv_wr->sg_list[cnt_ds].lkey; 76 + wqe_p->u.all_rcv.sg_list[cnt_ds].length = 77 + recv_wr->sg_list[cnt_ds].length; 78 + } 79 + 80 + if (ehca_debug_level) { 81 + ehca_gen_dbg("RECEIVE WQE written into ipz_rqueue=%p", ipz_rqueue); 82 + ehca_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe"); 83 + } 84 + 85 + return 0; 86 + } 87 + 88 + #if defined(DEBUG_GSI_SEND_WR) 89 + 90 + /* need ib_mad struct */ 91 + #include <rdma/ib_mad.h> 92 + 93 + static void trace_send_wr_ud(const struct ib_send_wr *send_wr) 94 + { 95 + int idx; 96 + int j; 97 + while (send_wr) { 98 + struct ib_mad_hdr *mad_hdr = send_wr->wr.ud.mad_hdr; 99 + struct ib_sge *sge = send_wr->sg_list; 100 + ehca_gen_dbg("send_wr#%x wr_id=%lx num_sge=%x " 101 + "send_flags=%x opcode=%x",idx, send_wr->wr_id, 102 + send_wr->num_sge, send_wr->send_flags, 103 + send_wr->opcode); 104 + if (mad_hdr) { 105 + ehca_gen_dbg("send_wr#%x mad_hdr base_version=%x " 106 + "mgmt_class=%x class_version=%x method=%x " 107 + "status=%x class_specific=%x tid=%lx " 108 + "attr_id=%x resv=%x attr_mod=%x", 109 + idx, mad_hdr->base_version, 110 + mad_hdr->mgmt_class, 111 + mad_hdr->class_version, mad_hdr->method, 112 + mad_hdr->status, mad_hdr->class_specific, 113 + mad_hdr->tid, mad_hdr->attr_id, 114 + mad_hdr->resv, 115 + mad_hdr->attr_mod); 116 + } 117 + for (j = 0; j < send_wr->num_sge; j++) { 118 + u8 *data = (u8 *) abs_to_virt(sge->addr); 119 + ehca_gen_dbg("send_wr#%x sge#%x addr=%p length=%x " 120 + "lkey=%x", 121 + idx, j, data, sge->length, sge->lkey); 122 + /* assume length is n*16 */ 123 + ehca_dmp(data, sge->length, "send_wr#%x sge#%x", 124 + idx, j); 125 + sge++; 126 + } /* eof for j */ 127 + idx++; 128 + send_wr = send_wr->next; 129 + } /* eof while send_wr */ 130 + } 131 + 132 + #endif /* DEBUG_GSI_SEND_WR */ 133 + 134 + static inline int ehca_write_swqe(struct ehca_qp *qp, 135 + struct ehca_wqe *wqe_p, 136 + const struct ib_send_wr *send_wr) 137 + { 138 + u32 idx; 139 + u64 dma_length; 140 + struct ehca_av *my_av; 141 + u32 remote_qkey = send_wr->wr.ud.remote_qkey; 142 + 143 + if (unlikely((send_wr->num_sge < 0) || 144 + (send_wr->num_sge > qp->ipz_squeue.act_nr_of_sg))) { 145 + ehca_gen_err("Invalid number of WQE SGE. " 146 + "num_sqe=%x max_nr_of_sg=%x", 147 + send_wr->num_sge, qp->ipz_squeue.act_nr_of_sg); 148 + return -EINVAL; /* invalid SG list length */ 149 + } 150 + 151 + /* clear wqe header until sglist */ 152 + memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list)); 153 + 154 + wqe_p->work_request_id = send_wr->wr_id; 155 + 156 + switch (send_wr->opcode) { 157 + case IB_WR_SEND: 158 + case IB_WR_SEND_WITH_IMM: 159 + wqe_p->optype = WQE_OPTYPE_SEND; 160 + break; 161 + case IB_WR_RDMA_WRITE: 162 + case IB_WR_RDMA_WRITE_WITH_IMM: 163 + wqe_p->optype = WQE_OPTYPE_RDMAWRITE; 164 + break; 165 + case IB_WR_RDMA_READ: 166 + wqe_p->optype = WQE_OPTYPE_RDMAREAD; 167 + break; 168 + default: 169 + ehca_gen_err("Invalid opcode=%x", send_wr->opcode); 170 + return -EINVAL; /* invalid opcode */ 171 + } 172 + 173 + wqe_p->wqef = (send_wr->opcode) & WQEF_HIGH_NIBBLE; 174 + 175 + wqe_p->wr_flag = 0; 176 + 177 + if (send_wr->send_flags & IB_SEND_SIGNALED) 178 + wqe_p->wr_flag |= WQE_WRFLAG_REQ_SIGNAL_COM; 179 + 180 + if (send_wr->opcode == IB_WR_SEND_WITH_IMM || 181 + send_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) { 182 + /* this might not work as long as HW does not support it */ 183 + wqe_p->immediate_data = be32_to_cpu(send_wr->imm_data); 184 + wqe_p->wr_flag |= WQE_WRFLAG_IMM_DATA_PRESENT; 185 + } 186 + 187 + wqe_p->nr_of_data_seg = send_wr->num_sge; 188 + 189 + switch (qp->qp_type) { 190 + case IB_QPT_SMI: 191 + case IB_QPT_GSI: 192 + /* no break is intential here */ 193 + case IB_QPT_UD: 194 + /* IB 1.2 spec C10-15 compliance */ 195 + if (send_wr->wr.ud.remote_qkey & 0x80000000) 196 + remote_qkey = qp->qkey; 197 + 198 + wqe_p->destination_qp_number = send_wr->wr.ud.remote_qpn << 8; 199 + wqe_p->local_ee_context_qkey = remote_qkey; 200 + if (!send_wr->wr.ud.ah) { 201 + ehca_gen_err("wr.ud.ah is NULL. qp=%p", qp); 202 + return -EINVAL; 203 + } 204 + my_av = container_of(send_wr->wr.ud.ah, struct ehca_av, ib_ah); 205 + wqe_p->u.ud_av.ud_av = my_av->av; 206 + 207 + /* 208 + * omitted check of IB_SEND_INLINE 209 + * since HW does not support it 210 + */ 211 + for (idx = 0; idx < send_wr->num_sge; idx++) { 212 + wqe_p->u.ud_av.sg_list[idx].vaddr = 213 + send_wr->sg_list[idx].addr; 214 + wqe_p->u.ud_av.sg_list[idx].lkey = 215 + send_wr->sg_list[idx].lkey; 216 + wqe_p->u.ud_av.sg_list[idx].length = 217 + send_wr->sg_list[idx].length; 218 + } /* eof for idx */ 219 + if (qp->qp_type == IB_QPT_SMI || 220 + qp->qp_type == IB_QPT_GSI) 221 + wqe_p->u.ud_av.ud_av.pmtu = 1; 222 + if (qp->qp_type == IB_QPT_GSI) { 223 + wqe_p->pkeyi = send_wr->wr.ud.pkey_index; 224 + #ifdef DEBUG_GSI_SEND_WR 225 + trace_send_wr_ud(send_wr); 226 + #endif /* DEBUG_GSI_SEND_WR */ 227 + } 228 + break; 229 + 230 + case IB_QPT_UC: 231 + if (send_wr->send_flags & IB_SEND_FENCE) 232 + wqe_p->wr_flag |= WQE_WRFLAG_FENCE; 233 + /* no break is intentional here */ 234 + case IB_QPT_RC: 235 + /* TODO: atomic not implemented */ 236 + wqe_p->u.nud.remote_virtual_adress = 237 + send_wr->wr.rdma.remote_addr; 238 + wqe_p->u.nud.rkey = send_wr->wr.rdma.rkey; 239 + 240 + /* 241 + * omitted checking of IB_SEND_INLINE 242 + * since HW does not support it 243 + */ 244 + dma_length = 0; 245 + for (idx = 0; idx < send_wr->num_sge; idx++) { 246 + wqe_p->u.nud.sg_list[idx].vaddr = 247 + send_wr->sg_list[idx].addr; 248 + wqe_p->u.nud.sg_list[idx].lkey = 249 + send_wr->sg_list[idx].lkey; 250 + wqe_p->u.nud.sg_list[idx].length = 251 + send_wr->sg_list[idx].length; 252 + dma_length += send_wr->sg_list[idx].length; 253 + } /* eof idx */ 254 + wqe_p->u.nud.atomic_1st_op_dma_len = dma_length; 255 + 256 + break; 257 + 258 + default: 259 + ehca_gen_err("Invalid qptype=%x", qp->qp_type); 260 + return -EINVAL; 261 + } 262 + 263 + if (ehca_debug_level) { 264 + ehca_gen_dbg("SEND WQE written into queue qp=%p ", qp); 265 + ehca_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "send wqe"); 266 + } 267 + return 0; 268 + } 269 + 270 + /* map_ib_wc_status converts raw cqe_status to ib_wc_status */ 271 + static inline void map_ib_wc_status(u32 cqe_status, 272 + enum ib_wc_status *wc_status) 273 + { 274 + if (unlikely(cqe_status & WC_STATUS_ERROR_BIT)) { 275 + switch (cqe_status & 0x3F) { 276 + case 0x01: 277 + case 0x21: 278 + *wc_status = IB_WC_LOC_LEN_ERR; 279 + break; 280 + case 0x02: 281 + case 0x22: 282 + *wc_status = IB_WC_LOC_QP_OP_ERR; 283 + break; 284 + case 0x03: 285 + case 0x23: 286 + *wc_status = IB_WC_LOC_EEC_OP_ERR; 287 + break; 288 + case 0x04: 289 + case 0x24: 290 + *wc_status = IB_WC_LOC_PROT_ERR; 291 + break; 292 + case 0x05: 293 + case 0x25: 294 + *wc_status = IB_WC_WR_FLUSH_ERR; 295 + break; 296 + case 0x06: 297 + *wc_status = IB_WC_MW_BIND_ERR; 298 + break; 299 + case 0x07: /* remote error - look into bits 20:24 */ 300 + switch ((cqe_status 301 + & WC_STATUS_REMOTE_ERROR_FLAGS) >> 11) { 302 + case 0x0: 303 + /* 304 + * PSN Sequence Error! 305 + * couldn't find a matching status! 306 + */ 307 + *wc_status = IB_WC_GENERAL_ERR; 308 + break; 309 + case 0x1: 310 + *wc_status = IB_WC_REM_INV_REQ_ERR; 311 + break; 312 + case 0x2: 313 + *wc_status = IB_WC_REM_ACCESS_ERR; 314 + break; 315 + case 0x3: 316 + *wc_status = IB_WC_REM_OP_ERR; 317 + break; 318 + case 0x4: 319 + *wc_status = IB_WC_REM_INV_RD_REQ_ERR; 320 + break; 321 + } 322 + break; 323 + case 0x08: 324 + *wc_status = IB_WC_RETRY_EXC_ERR; 325 + break; 326 + case 0x09: 327 + *wc_status = IB_WC_RNR_RETRY_EXC_ERR; 328 + break; 329 + case 0x0A: 330 + case 0x2D: 331 + *wc_status = IB_WC_REM_ABORT_ERR; 332 + break; 333 + case 0x0B: 334 + case 0x2E: 335 + *wc_status = IB_WC_INV_EECN_ERR; 336 + break; 337 + case 0x0C: 338 + case 0x2F: 339 + *wc_status = IB_WC_INV_EEC_STATE_ERR; 340 + break; 341 + case 0x0D: 342 + *wc_status = IB_WC_BAD_RESP_ERR; 343 + break; 344 + case 0x10: 345 + /* WQE purged */ 346 + *wc_status = IB_WC_WR_FLUSH_ERR; 347 + break; 348 + default: 349 + *wc_status = IB_WC_FATAL_ERR; 350 + 351 + } 352 + } else 353 + *wc_status = IB_WC_SUCCESS; 354 + } 355 + 356 + int ehca_post_send(struct ib_qp *qp, 357 + struct ib_send_wr *send_wr, 358 + struct ib_send_wr **bad_send_wr) 359 + { 360 + struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp); 361 + struct ib_send_wr *cur_send_wr; 362 + struct ehca_wqe *wqe_p; 363 + int wqe_cnt = 0; 364 + int ret = 0; 365 + unsigned long spl_flags; 366 + 367 + /* LOCK the QUEUE */ 368 + spin_lock_irqsave(&my_qp->spinlock_s, spl_flags); 369 + 370 + /* loop processes list of send reqs */ 371 + for (cur_send_wr = send_wr; cur_send_wr != NULL; 372 + cur_send_wr = cur_send_wr->next) { 373 + u64 start_offset = my_qp->ipz_squeue.current_q_offset; 374 + /* get pointer next to free WQE */ 375 + wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue); 376 + if (unlikely(!wqe_p)) { 377 + /* too many posted work requests: queue overflow */ 378 + if (bad_send_wr) 379 + *bad_send_wr = cur_send_wr; 380 + if (wqe_cnt == 0) { 381 + ret = -ENOMEM; 382 + ehca_err(qp->device, "Too many posted WQEs " 383 + "qp_num=%x", qp->qp_num); 384 + } 385 + goto post_send_exit0; 386 + } 387 + /* write a SEND WQE into the QUEUE */ 388 + ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr); 389 + /* 390 + * if something failed, 391 + * reset the free entry pointer to the start value 392 + */ 393 + if (unlikely(ret)) { 394 + my_qp->ipz_squeue.current_q_offset = start_offset; 395 + *bad_send_wr = cur_send_wr; 396 + if (wqe_cnt == 0) { 397 + ret = -EINVAL; 398 + ehca_err(qp->device, "Could not write WQE " 399 + "qp_num=%x", qp->qp_num); 400 + } 401 + goto post_send_exit0; 402 + } 403 + wqe_cnt++; 404 + ehca_dbg(qp->device, "ehca_qp=%p qp_num=%x wqe_cnt=%d", 405 + my_qp, qp->qp_num, wqe_cnt); 406 + } /* eof for cur_send_wr */ 407 + 408 + post_send_exit0: 409 + /* UNLOCK the QUEUE */ 410 + spin_unlock_irqrestore(&my_qp->spinlock_s, spl_flags); 411 + iosync(); /* serialize GAL register access */ 412 + hipz_update_sqa(my_qp, wqe_cnt); 413 + return ret; 414 + } 415 + 416 + int ehca_post_recv(struct ib_qp *qp, 417 + struct ib_recv_wr *recv_wr, 418 + struct ib_recv_wr **bad_recv_wr) 419 + { 420 + struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp); 421 + struct ib_recv_wr *cur_recv_wr; 422 + struct ehca_wqe *wqe_p; 423 + int wqe_cnt = 0; 424 + int ret = 0; 425 + unsigned long spl_flags; 426 + 427 + /* LOCK the QUEUE */ 428 + spin_lock_irqsave(&my_qp->spinlock_r, spl_flags); 429 + 430 + /* loop processes list of send reqs */ 431 + for (cur_recv_wr = recv_wr; cur_recv_wr != NULL; 432 + cur_recv_wr = cur_recv_wr->next) { 433 + u64 start_offset = my_qp->ipz_rqueue.current_q_offset; 434 + /* get pointer next to free WQE */ 435 + wqe_p = ipz_qeit_get_inc(&my_qp->ipz_rqueue); 436 + if (unlikely(!wqe_p)) { 437 + /* too many posted work requests: queue overflow */ 438 + if (bad_recv_wr) 439 + *bad_recv_wr = cur_recv_wr; 440 + if (wqe_cnt == 0) { 441 + ret = -ENOMEM; 442 + ehca_err(qp->device, "Too many posted WQEs " 443 + "qp_num=%x", qp->qp_num); 444 + } 445 + goto post_recv_exit0; 446 + } 447 + /* write a RECV WQE into the QUEUE */ 448 + ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, cur_recv_wr); 449 + /* 450 + * if something failed, 451 + * reset the free entry pointer to the start value 452 + */ 453 + if (unlikely(ret)) { 454 + my_qp->ipz_rqueue.current_q_offset = start_offset; 455 + *bad_recv_wr = cur_recv_wr; 456 + if (wqe_cnt == 0) { 457 + ret = -EINVAL; 458 + ehca_err(qp->device, "Could not write WQE " 459 + "qp_num=%x", qp->qp_num); 460 + } 461 + goto post_recv_exit0; 462 + } 463 + wqe_cnt++; 464 + ehca_gen_dbg("ehca_qp=%p qp_num=%x wqe_cnt=%d", 465 + my_qp, qp->qp_num, wqe_cnt); 466 + } /* eof for cur_recv_wr */ 467 + 468 + post_recv_exit0: 469 + spin_unlock_irqrestore(&my_qp->spinlock_r, spl_flags); 470 + iosync(); /* serialize GAL register access */ 471 + hipz_update_rqa(my_qp, wqe_cnt); 472 + return ret; 473 + } 474 + 475 + /* 476 + * ib_wc_opcode table converts ehca wc opcode to ib 477 + * Since we use zero to indicate invalid opcode, the actual ib opcode must 478 + * be decremented!!! 479 + */ 480 + static const u8 ib_wc_opcode[255] = { 481 + [0x01] = IB_WC_RECV+1, 482 + [0x02] = IB_WC_RECV_RDMA_WITH_IMM+1, 483 + [0x04] = IB_WC_BIND_MW+1, 484 + [0x08] = IB_WC_FETCH_ADD+1, 485 + [0x10] = IB_WC_COMP_SWAP+1, 486 + [0x20] = IB_WC_RDMA_WRITE+1, 487 + [0x40] = IB_WC_RDMA_READ+1, 488 + [0x80] = IB_WC_SEND+1 489 + }; 490 + 491 + /* internal function to poll one entry of cq */ 492 + static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc) 493 + { 494 + int ret = 0; 495 + struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); 496 + struct ehca_cqe *cqe; 497 + int cqe_count = 0; 498 + 499 + poll_cq_one_read_cqe: 500 + cqe = (struct ehca_cqe *) 501 + ipz_qeit_get_inc_valid(&my_cq->ipz_queue); 502 + if (!cqe) { 503 + ret = -EAGAIN; 504 + ehca_dbg(cq->device, "Completion queue is empty ehca_cq=%p " 505 + "cq_num=%x ret=%x", my_cq, my_cq->cq_number, ret); 506 + goto poll_cq_one_exit0; 507 + } 508 + 509 + /* prevents loads being reordered across this point */ 510 + rmb(); 511 + 512 + cqe_count++; 513 + if (unlikely(cqe->status & WC_STATUS_PURGE_BIT)) { 514 + struct ehca_qp *qp=ehca_cq_get_qp(my_cq, cqe->local_qp_number); 515 + int purgeflag; 516 + unsigned long spl_flags; 517 + if (!qp) { 518 + ehca_err(cq->device, "cq_num=%x qp_num=%x " 519 + "could not find qp -> ignore cqe", 520 + my_cq->cq_number, cqe->local_qp_number); 521 + ehca_dmp(cqe, 64, "cq_num=%x qp_num=%x", 522 + my_cq->cq_number, cqe->local_qp_number); 523 + /* ignore this purged cqe */ 524 + goto poll_cq_one_read_cqe; 525 + } 526 + spin_lock_irqsave(&qp->spinlock_s, spl_flags); 527 + purgeflag = qp->sqerr_purgeflag; 528 + spin_unlock_irqrestore(&qp->spinlock_s, spl_flags); 529 + 530 + if (purgeflag) { 531 + ehca_dbg(cq->device, "Got CQE with purged bit qp_num=%x " 532 + "src_qp=%x", 533 + cqe->local_qp_number, cqe->remote_qp_number); 534 + if (ehca_debug_level) 535 + ehca_dmp(cqe, 64, "qp_num=%x src_qp=%x", 536 + cqe->local_qp_number, 537 + cqe->remote_qp_number); 538 + /* 539 + * ignore this to avoid double cqes of bad wqe 540 + * that caused sqe and turn off purge flag 541 + */ 542 + qp->sqerr_purgeflag = 0; 543 + goto poll_cq_one_read_cqe; 544 + } 545 + } 546 + 547 + /* tracing cqe */ 548 + if (ehca_debug_level) { 549 + ehca_dbg(cq->device, 550 + "Received COMPLETION ehca_cq=%p cq_num=%x -----", 551 + my_cq, my_cq->cq_number); 552 + ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x", 553 + my_cq, my_cq->cq_number); 554 + ehca_dbg(cq->device, 555 + "ehca_cq=%p cq_num=%x -------------------------", 556 + my_cq, my_cq->cq_number); 557 + } 558 + 559 + /* we got a completion! */ 560 + wc->wr_id = cqe->work_request_id; 561 + 562 + /* eval ib_wc_opcode */ 563 + wc->opcode = ib_wc_opcode[cqe->optype]-1; 564 + if (unlikely(wc->opcode == -1)) { 565 + ehca_err(cq->device, "Invalid cqe->OPType=%x cqe->status=%x " 566 + "ehca_cq=%p cq_num=%x", 567 + cqe->optype, cqe->status, my_cq, my_cq->cq_number); 568 + /* dump cqe for other infos */ 569 + ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x", 570 + my_cq, my_cq->cq_number); 571 + /* update also queue adder to throw away this entry!!! */ 572 + goto poll_cq_one_exit0; 573 + } 574 + /* eval ib_wc_status */ 575 + if (unlikely(cqe->status & WC_STATUS_ERROR_BIT)) { 576 + /* complete with errors */ 577 + map_ib_wc_status(cqe->status, &wc->status); 578 + wc->vendor_err = wc->status; 579 + } else 580 + wc->status = IB_WC_SUCCESS; 581 + 582 + wc->qp_num = cqe->local_qp_number; 583 + wc->byte_len = cqe->nr_bytes_transferred; 584 + wc->pkey_index = cqe->pkey_index; 585 + wc->slid = cqe->rlid; 586 + wc->dlid_path_bits = cqe->dlid; 587 + wc->src_qp = cqe->remote_qp_number; 588 + wc->wc_flags = cqe->w_completion_flags; 589 + wc->imm_data = cpu_to_be32(cqe->immediate_data); 590 + wc->sl = cqe->service_level; 591 + 592 + if (wc->status != IB_WC_SUCCESS) 593 + ehca_dbg(cq->device, 594 + "ehca_cq=%p cq_num=%x WARNING unsuccessful cqe " 595 + "OPType=%x status=%x qp_num=%x src_qp=%x wr_id=%lx " 596 + "cqe=%p", my_cq, my_cq->cq_number, cqe->optype, 597 + cqe->status, cqe->local_qp_number, 598 + cqe->remote_qp_number, cqe->work_request_id, cqe); 599 + 600 + poll_cq_one_exit0: 601 + if (cqe_count > 0) 602 + hipz_update_feca(my_cq, cqe_count); 603 + 604 + return ret; 605 + } 606 + 607 + int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc) 608 + { 609 + struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); 610 + int nr; 611 + struct ib_wc *current_wc = wc; 612 + int ret = 0; 613 + unsigned long spl_flags; 614 + 615 + if (num_entries < 1) { 616 + ehca_err(cq->device, "Invalid num_entries=%d ehca_cq=%p " 617 + "cq_num=%x", num_entries, my_cq, my_cq->cq_number); 618 + ret = -EINVAL; 619 + goto poll_cq_exit0; 620 + } 621 + 622 + spin_lock_irqsave(&my_cq->spinlock, spl_flags); 623 + for (nr = 0; nr < num_entries; nr++) { 624 + ret = ehca_poll_cq_one(cq, current_wc); 625 + if (ret) 626 + break; 627 + current_wc++; 628 + } /* eof for nr */ 629 + spin_unlock_irqrestore(&my_cq->spinlock, spl_flags); 630 + if (ret == -EAGAIN || !ret) 631 + ret = nr; 632 + 633 + poll_cq_exit0: 634 + return ret; 635 + } 636 + 637 + int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify cq_notify) 638 + { 639 + struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); 640 + 641 + switch (cq_notify) { 642 + case IB_CQ_SOLICITED: 643 + hipz_set_cqx_n0(my_cq, 1); 644 + break; 645 + case IB_CQ_NEXT_COMP: 646 + hipz_set_cqx_n1(my_cq, 1); 647 + break; 648 + default: 649 + return -EINVAL; 650 + } 651 + 652 + return 0; 653 + }
+111
drivers/infiniband/hw/ehca/ehca_sqp.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * SQP functions 5 + * 6 + * Authors: Khadija Souissi <souissi@de.ibm.com> 7 + * Heiko J Schick <schickhj@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 + 43 + #include <linux/module.h> 44 + #include <linux/err.h> 45 + #include "ehca_classes.h" 46 + #include "ehca_tools.h" 47 + #include "ehca_qes.h" 48 + #include "ehca_iverbs.h" 49 + #include "hcp_if.h" 50 + 51 + 52 + /** 53 + * ehca_define_sqp - Defines special queue pair 1 (GSI QP). When special queue 54 + * pair is created successfully, the corresponding port gets active. 55 + * 56 + * Define Special Queue pair 0 (SMI QP) is still not supported. 57 + * 58 + * @qp_init_attr: Queue pair init attributes with port and queue pair type 59 + */ 60 + 61 + u64 ehca_define_sqp(struct ehca_shca *shca, 62 + struct ehca_qp *ehca_qp, 63 + struct ib_qp_init_attr *qp_init_attr) 64 + { 65 + u32 pma_qp_nr, bma_qp_nr; 66 + u64 ret; 67 + u8 port = qp_init_attr->port_num; 68 + int counter; 69 + 70 + shca->sport[port - 1].port_state = IB_PORT_DOWN; 71 + 72 + switch (qp_init_attr->qp_type) { 73 + case IB_QPT_SMI: 74 + /* function not supported yet */ 75 + break; 76 + case IB_QPT_GSI: 77 + ret = hipz_h_define_aqp1(shca->ipz_hca_handle, 78 + ehca_qp->ipz_qp_handle, 79 + ehca_qp->galpas.kernel, 80 + (u32) qp_init_attr->port_num, 81 + &pma_qp_nr, &bma_qp_nr); 82 + 83 + if (ret != H_SUCCESS) { 84 + ehca_err(&shca->ib_device, 85 + "Can't define AQP1 for port %x. rc=%lx", 86 + port, ret); 87 + return ret; 88 + } 89 + break; 90 + default: 91 + ehca_err(&shca->ib_device, "invalid qp_type=%x", 92 + qp_init_attr->qp_type); 93 + return H_PARAMETER; 94 + } 95 + 96 + for (counter = 0; 97 + shca->sport[port - 1].port_state != IB_PORT_ACTIVE && 98 + counter < ehca_port_act_time; 99 + counter++) { 100 + ehca_dbg(&shca->ib_device, "... wait until port %x is active", 101 + port); 102 + msleep_interruptible(1000); 103 + } 104 + 105 + if (counter == ehca_port_act_time) { 106 + ehca_err(&shca->ib_device, "Port %x is not active.", port); 107 + return H_HARDWARE; 108 + } 109 + 110 + return H_SUCCESS; 111 + }
+172
drivers/infiniband/hw/ehca/ehca_tools.h
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * auxiliary functions 5 + * 6 + * Authors: Christoph Raisch <raisch@de.ibm.com> 7 + * Hoang-Nam Nguyen <hnguyen@de.ibm.com> 8 + * Khadija Souissi <souissik@de.ibm.com> 9 + * Waleri Fomin <fomin@de.ibm.com> 10 + * Heiko J Schick <schickhj@de.ibm.com> 11 + * 12 + * Copyright (c) 2005 IBM Corporation 13 + * 14 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 15 + * BSD. 16 + * 17 + * OpenIB BSD License 18 + * 19 + * Redistribution and use in source and binary forms, with or without 20 + * modification, are permitted provided that the following conditions are met: 21 + * 22 + * Redistributions of source code must retain the above copyright notice, this 23 + * list of conditions and the following disclaimer. 24 + * 25 + * Redistributions in binary form must reproduce the above copyright notice, 26 + * this list of conditions and the following disclaimer in the documentation 27 + * and/or other materials 28 + * provided with the distribution. 29 + * 30 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 31 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 34 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 37 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 38 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 + * POSSIBILITY OF SUCH DAMAGE. 41 + */ 42 + 43 + 44 + #ifndef EHCA_TOOLS_H 45 + #define EHCA_TOOLS_H 46 + 47 + #include <linux/kernel.h> 48 + #include <linux/spinlock.h> 49 + #include <linux/delay.h> 50 + #include <linux/idr.h> 51 + #include <linux/kthread.h> 52 + #include <linux/mm.h> 53 + #include <linux/mman.h> 54 + #include <linux/module.h> 55 + #include <linux/moduleparam.h> 56 + #include <linux/vmalloc.h> 57 + #include <linux/version.h> 58 + #include <linux/notifier.h> 59 + #include <linux/cpu.h> 60 + #include <linux/device.h> 61 + 62 + #include <asm/abs_addr.h> 63 + #include <asm/ibmebus.h> 64 + #include <asm/io.h> 65 + #include <asm/pgtable.h> 66 + 67 + extern int ehca_debug_level; 68 + 69 + #define ehca_dbg(ib_dev, format, arg...) \ 70 + do { \ 71 + if (unlikely(ehca_debug_level)) \ 72 + dev_printk(KERN_DEBUG, (ib_dev)->dma_device, \ 73 + "PU%04x EHCA_DBG:%s " format "\n", \ 74 + get_paca()->paca_index, __FUNCTION__, \ 75 + ## arg); \ 76 + } while (0) 77 + 78 + #define ehca_info(ib_dev, format, arg...) \ 79 + dev_info((ib_dev)->dma_device, "PU%04x EHCA_INFO:%s " format "\n", \ 80 + get_paca()->paca_index, __FUNCTION__, ## arg) 81 + 82 + #define ehca_warn(ib_dev, format, arg...) \ 83 + dev_warn((ib_dev)->dma_device, "PU%04x EHCA_WARN:%s " format "\n", \ 84 + get_paca()->paca_index, __FUNCTION__, ## arg) 85 + 86 + #define ehca_err(ib_dev, format, arg...) \ 87 + dev_err((ib_dev)->dma_device, "PU%04x EHCA_ERR:%s " format "\n", \ 88 + get_paca()->paca_index, __FUNCTION__, ## arg) 89 + 90 + /* use this one only if no ib_dev available */ 91 + #define ehca_gen_dbg(format, arg...) \ 92 + do { \ 93 + if (unlikely(ehca_debug_level)) \ 94 + printk(KERN_DEBUG "PU%04x EHCA_DBG:%s " format "\n",\ 95 + get_paca()->paca_index, __FUNCTION__, ## arg); \ 96 + } while (0) 97 + 98 + #define ehca_gen_warn(format, arg...) \ 99 + do { \ 100 + if (unlikely(ehca_debug_level)) \ 101 + printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n",\ 102 + get_paca()->paca_index, __FUNCTION__, ## arg); \ 103 + } while (0) 104 + 105 + #define ehca_gen_err(format, arg...) \ 106 + printk(KERN_ERR "PU%04x EHCA_ERR:%s " format "\n", \ 107 + get_paca()->paca_index, __FUNCTION__, ## arg) 108 + 109 + /** 110 + * ehca_dmp - printk a memory block, whose length is n*8 bytes. 111 + * Each line has the following layout: 112 + * <format string> adr=X ofs=Y <8 bytes hex> <8 bytes hex> 113 + */ 114 + #define ehca_dmp(adr, len, format, args...) \ 115 + do { \ 116 + unsigned int x; \ 117 + unsigned int l = (unsigned int)(len); \ 118 + unsigned char *deb = (unsigned char*)(adr); \ 119 + for (x = 0; x < l; x += 16) { \ 120 + printk("EHCA_DMP:%s" format \ 121 + " adr=%p ofs=%04x %016lx %016lx\n", \ 122 + __FUNCTION__, ##args, deb, x, \ 123 + *((u64 *)&deb[0]), *((u64 *)&deb[8])); \ 124 + deb += 16; \ 125 + } \ 126 + } while (0) 127 + 128 + /* define a bitmask, little endian version */ 129 + #define EHCA_BMASK(pos,length) (((pos)<<16)+(length)) 130 + 131 + /* define a bitmask, the ibm way... */ 132 + #define EHCA_BMASK_IBM(from,to) (((63-to)<<16)+((to)-(from)+1)) 133 + 134 + /* internal function, don't use */ 135 + #define EHCA_BMASK_SHIFTPOS(mask) (((mask)>>16)&0xffff) 136 + 137 + /* internal function, don't use */ 138 + #define EHCA_BMASK_MASK(mask) (0xffffffffffffffffULL >> ((64-(mask))&0xffff)) 139 + 140 + /** 141 + * EHCA_BMASK_SET - return value shifted and masked by mask 142 + * variable|=EHCA_BMASK_SET(MY_MASK,0x4711) ORs the bits in variable 143 + * variable&=~EHCA_BMASK_SET(MY_MASK,-1) clears the bits from the mask 144 + * in variable 145 + */ 146 + #define EHCA_BMASK_SET(mask,value) \ 147 + ((EHCA_BMASK_MASK(mask) & ((u64)(value)))<<EHCA_BMASK_SHIFTPOS(mask)) 148 + 149 + /** 150 + * EHCA_BMASK_GET - extract a parameter from value by mask 151 + */ 152 + #define EHCA_BMASK_GET(mask,value) \ 153 + (EHCA_BMASK_MASK(mask)& (((u64)(value))>>EHCA_BMASK_SHIFTPOS(mask))) 154 + 155 + 156 + /* Converts ehca to ib return code */ 157 + static inline int ehca2ib_return_code(u64 ehca_rc) 158 + { 159 + switch (ehca_rc) { 160 + case H_SUCCESS: 161 + return 0; 162 + case H_BUSY: 163 + return -EBUSY; 164 + case H_NO_MEM: 165 + return -ENOMEM; 166 + default: 167 + return -EINVAL; 168 + } 169 + } 170 + 171 + 172 + #endif /* EHCA_TOOLS_H */
+392
drivers/infiniband/hw/ehca/ehca_uverbs.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * userspace support verbs 5 + * 6 + * Authors: Christoph Raisch <raisch@de.ibm.com> 7 + * Hoang-Nam Nguyen <hnguyen@de.ibm.com> 8 + * Heiko J Schick <schickhj@de.ibm.com> 9 + * 10 + * Copyright (c) 2005 IBM Corporation 11 + * 12 + * All rights reserved. 13 + * 14 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 15 + * BSD. 16 + * 17 + * OpenIB BSD License 18 + * 19 + * Redistribution and use in source and binary forms, with or without 20 + * modification, are permitted provided that the following conditions are met: 21 + * 22 + * Redistributions of source code must retain the above copyright notice, this 23 + * list of conditions and the following disclaimer. 24 + * 25 + * Redistributions in binary form must reproduce the above copyright notice, 26 + * this list of conditions and the following disclaimer in the documentation 27 + * and/or other materials 28 + * provided with the distribution. 29 + * 30 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 31 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 34 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 37 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 38 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 + * POSSIBILITY OF SUCH DAMAGE. 41 + */ 42 + 43 + #include <asm/current.h> 44 + 45 + #include "ehca_classes.h" 46 + #include "ehca_iverbs.h" 47 + #include "ehca_mrmw.h" 48 + #include "ehca_tools.h" 49 + #include "hcp_if.h" 50 + 51 + struct ib_ucontext *ehca_alloc_ucontext(struct ib_device *device, 52 + struct ib_udata *udata) 53 + { 54 + struct ehca_ucontext *my_context; 55 + 56 + my_context = kzalloc(sizeof *my_context, GFP_KERNEL); 57 + if (!my_context) { 58 + ehca_err(device, "Out of memory device=%p", device); 59 + return ERR_PTR(-ENOMEM); 60 + } 61 + 62 + return &my_context->ib_ucontext; 63 + } 64 + 65 + int ehca_dealloc_ucontext(struct ib_ucontext *context) 66 + { 67 + kfree(container_of(context, struct ehca_ucontext, ib_ucontext)); 68 + return 0; 69 + } 70 + 71 + struct page *ehca_nopage(struct vm_area_struct *vma, 72 + unsigned long address, int *type) 73 + { 74 + struct page *mypage = NULL; 75 + u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT; 76 + u32 idr_handle = fileoffset >> 32; 77 + u32 q_type = (fileoffset >> 28) & 0xF; /* CQ, QP,... */ 78 + u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */ 79 + u32 cur_pid = current->tgid; 80 + unsigned long flags; 81 + struct ehca_cq *cq; 82 + struct ehca_qp *qp; 83 + struct ehca_pd *pd; 84 + u64 offset; 85 + void *vaddr; 86 + 87 + switch (q_type) { 88 + case 1: /* CQ */ 89 + spin_lock_irqsave(&ehca_cq_idr_lock, flags); 90 + cq = idr_find(&ehca_cq_idr, idr_handle); 91 + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); 92 + 93 + /* make sure this mmap really belongs to the authorized user */ 94 + if (!cq) { 95 + ehca_gen_err("cq is NULL ret=NOPAGE_SIGBUS"); 96 + return NOPAGE_SIGBUS; 97 + } 98 + 99 + if (cq->ownpid != cur_pid) { 100 + ehca_err(cq->ib_cq.device, 101 + "Invalid caller pid=%x ownpid=%x", 102 + cur_pid, cq->ownpid); 103 + return NOPAGE_SIGBUS; 104 + } 105 + 106 + if (rsrc_type == 2) { 107 + ehca_dbg(cq->ib_cq.device, "cq=%p cq queuearea", cq); 108 + offset = address - vma->vm_start; 109 + vaddr = ipz_qeit_calc(&cq->ipz_queue, offset); 110 + ehca_dbg(cq->ib_cq.device, "offset=%lx vaddr=%p", 111 + offset, vaddr); 112 + mypage = virt_to_page(vaddr); 113 + } 114 + break; 115 + 116 + case 2: /* QP */ 117 + spin_lock_irqsave(&ehca_qp_idr_lock, flags); 118 + qp = idr_find(&ehca_qp_idr, idr_handle); 119 + spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); 120 + 121 + /* make sure this mmap really belongs to the authorized user */ 122 + if (!qp) { 123 + ehca_gen_err("qp is NULL ret=NOPAGE_SIGBUS"); 124 + return NOPAGE_SIGBUS; 125 + } 126 + 127 + pd = container_of(qp->ib_qp.pd, struct ehca_pd, ib_pd); 128 + if (pd->ownpid != cur_pid) { 129 + ehca_err(qp->ib_qp.device, 130 + "Invalid caller pid=%x ownpid=%x", 131 + cur_pid, pd->ownpid); 132 + return NOPAGE_SIGBUS; 133 + } 134 + 135 + if (rsrc_type == 2) { /* rqueue */ 136 + ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueuearea", qp); 137 + offset = address - vma->vm_start; 138 + vaddr = ipz_qeit_calc(&qp->ipz_rqueue, offset); 139 + ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p", 140 + offset, vaddr); 141 + mypage = virt_to_page(vaddr); 142 + } else if (rsrc_type == 3) { /* squeue */ 143 + ehca_dbg(qp->ib_qp.device, "qp=%p qp squeuearea", qp); 144 + offset = address - vma->vm_start; 145 + vaddr = ipz_qeit_calc(&qp->ipz_squeue, offset); 146 + ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p", 147 + offset, vaddr); 148 + mypage = virt_to_page(vaddr); 149 + } 150 + break; 151 + 152 + default: 153 + ehca_gen_err("bad queue type %x", q_type); 154 + return NOPAGE_SIGBUS; 155 + } 156 + 157 + if (!mypage) { 158 + ehca_gen_err("Invalid page adr==NULL ret=NOPAGE_SIGBUS"); 159 + return NOPAGE_SIGBUS; 160 + } 161 + get_page(mypage); 162 + 163 + return mypage; 164 + } 165 + 166 + static struct vm_operations_struct ehcau_vm_ops = { 167 + .nopage = ehca_nopage, 168 + }; 169 + 170 + int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) 171 + { 172 + u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT; 173 + u32 idr_handle = fileoffset >> 32; 174 + u32 q_type = (fileoffset >> 28) & 0xF; /* CQ, QP,... */ 175 + u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */ 176 + u32 cur_pid = current->tgid; 177 + u32 ret; 178 + u64 vsize, physical; 179 + unsigned long flags; 180 + struct ehca_cq *cq; 181 + struct ehca_qp *qp; 182 + struct ehca_pd *pd; 183 + 184 + switch (q_type) { 185 + case 1: /* CQ */ 186 + spin_lock_irqsave(&ehca_cq_idr_lock, flags); 187 + cq = idr_find(&ehca_cq_idr, idr_handle); 188 + spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); 189 + 190 + /* make sure this mmap really belongs to the authorized user */ 191 + if (!cq) 192 + return -EINVAL; 193 + 194 + if (cq->ownpid != cur_pid) { 195 + ehca_err(cq->ib_cq.device, 196 + "Invalid caller pid=%x ownpid=%x", 197 + cur_pid, cq->ownpid); 198 + return -ENOMEM; 199 + } 200 + 201 + if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context) 202 + return -EINVAL; 203 + 204 + switch (rsrc_type) { 205 + case 1: /* galpa fw handle */ 206 + ehca_dbg(cq->ib_cq.device, "cq=%p cq triggerarea", cq); 207 + vma->vm_flags |= VM_RESERVED; 208 + vsize = vma->vm_end - vma->vm_start; 209 + if (vsize != EHCA_PAGESIZE) { 210 + ehca_err(cq->ib_cq.device, "invalid vsize=%lx", 211 + vma->vm_end - vma->vm_start); 212 + return -EINVAL; 213 + } 214 + 215 + physical = cq->galpas.user.fw_handle; 216 + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 217 + vma->vm_flags |= VM_IO | VM_RESERVED; 218 + 219 + ehca_dbg(cq->ib_cq.device, 220 + "vsize=%lx physical=%lx", vsize, physical); 221 + ret = remap_pfn_range(vma, vma->vm_start, 222 + physical >> PAGE_SHIFT, vsize, 223 + vma->vm_page_prot); 224 + if (ret) { 225 + ehca_err(cq->ib_cq.device, 226 + "remap_pfn_range() failed ret=%x", 227 + ret); 228 + return -ENOMEM; 229 + } 230 + break; 231 + 232 + case 2: /* cq queue_addr */ 233 + ehca_dbg(cq->ib_cq.device, "cq=%p cq q_addr", cq); 234 + vma->vm_flags |= VM_RESERVED; 235 + vma->vm_ops = &ehcau_vm_ops; 236 + break; 237 + 238 + default: 239 + ehca_err(cq->ib_cq.device, "bad resource type %x", 240 + rsrc_type); 241 + return -EINVAL; 242 + } 243 + break; 244 + 245 + case 2: /* QP */ 246 + spin_lock_irqsave(&ehca_qp_idr_lock, flags); 247 + qp = idr_find(&ehca_qp_idr, idr_handle); 248 + spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); 249 + 250 + /* make sure this mmap really belongs to the authorized user */ 251 + if (!qp) 252 + return -EINVAL; 253 + 254 + pd = container_of(qp->ib_qp.pd, struct ehca_pd, ib_pd); 255 + if (pd->ownpid != cur_pid) { 256 + ehca_err(qp->ib_qp.device, 257 + "Invalid caller pid=%x ownpid=%x", 258 + cur_pid, pd->ownpid); 259 + return -ENOMEM; 260 + } 261 + 262 + if (!qp->ib_qp.uobject || qp->ib_qp.uobject->context != context) 263 + return -EINVAL; 264 + 265 + switch (rsrc_type) { 266 + case 1: /* galpa fw handle */ 267 + ehca_dbg(qp->ib_qp.device, "qp=%p qp triggerarea", qp); 268 + vma->vm_flags |= VM_RESERVED; 269 + vsize = vma->vm_end - vma->vm_start; 270 + if (vsize != EHCA_PAGESIZE) { 271 + ehca_err(qp->ib_qp.device, "invalid vsize=%lx", 272 + vma->vm_end - vma->vm_start); 273 + return -EINVAL; 274 + } 275 + 276 + physical = qp->galpas.user.fw_handle; 277 + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 278 + vma->vm_flags |= VM_IO | VM_RESERVED; 279 + 280 + ehca_dbg(qp->ib_qp.device, "vsize=%lx physical=%lx", 281 + vsize, physical); 282 + ret = remap_pfn_range(vma, vma->vm_start, 283 + physical >> PAGE_SHIFT, vsize, 284 + vma->vm_page_prot); 285 + if (ret) { 286 + ehca_err(qp->ib_qp.device, 287 + "remap_pfn_range() failed ret=%x", 288 + ret); 289 + return -ENOMEM; 290 + } 291 + break; 292 + 293 + case 2: /* qp rqueue_addr */ 294 + ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueue_addr", qp); 295 + vma->vm_flags |= VM_RESERVED; 296 + vma->vm_ops = &ehcau_vm_ops; 297 + break; 298 + 299 + case 3: /* qp squeue_addr */ 300 + ehca_dbg(qp->ib_qp.device, "qp=%p qp squeue_addr", qp); 301 + vma->vm_flags |= VM_RESERVED; 302 + vma->vm_ops = &ehcau_vm_ops; 303 + break; 304 + 305 + default: 306 + ehca_err(qp->ib_qp.device, "bad resource type %x", 307 + rsrc_type); 308 + return -EINVAL; 309 + } 310 + break; 311 + 312 + default: 313 + ehca_gen_err("bad queue type %x", q_type); 314 + return -EINVAL; 315 + } 316 + 317 + return 0; 318 + } 319 + 320 + int ehca_mmap_nopage(u64 foffset, u64 length, void **mapped, 321 + struct vm_area_struct **vma) 322 + { 323 + down_write(&current->mm->mmap_sem); 324 + *mapped = (void*)do_mmap(NULL,0, length, PROT_WRITE, 325 + MAP_SHARED | MAP_ANONYMOUS, 326 + foffset); 327 + up_write(&current->mm->mmap_sem); 328 + if (!(*mapped)) { 329 + ehca_gen_err("couldn't mmap foffset=%lx length=%lx", 330 + foffset, length); 331 + return -EINVAL; 332 + } 333 + 334 + *vma = find_vma(current->mm, (u64)*mapped); 335 + if (!(*vma)) { 336 + down_write(&current->mm->mmap_sem); 337 + do_munmap(current->mm, 0, length); 338 + up_write(&current->mm->mmap_sem); 339 + ehca_gen_err("couldn't find vma queue=%p", *mapped); 340 + return -EINVAL; 341 + } 342 + (*vma)->vm_flags |= VM_RESERVED; 343 + (*vma)->vm_ops = &ehcau_vm_ops; 344 + 345 + return 0; 346 + } 347 + 348 + int ehca_mmap_register(u64 physical, void **mapped, 349 + struct vm_area_struct **vma) 350 + { 351 + int ret; 352 + unsigned long vsize; 353 + /* ehca hw supports only 4k page */ 354 + ret = ehca_mmap_nopage(0, EHCA_PAGESIZE, mapped, vma); 355 + if (ret) { 356 + ehca_gen_err("could'nt mmap physical=%lx", physical); 357 + return ret; 358 + } 359 + 360 + (*vma)->vm_flags |= VM_RESERVED; 361 + vsize = (*vma)->vm_end - (*vma)->vm_start; 362 + if (vsize != EHCA_PAGESIZE) { 363 + ehca_gen_err("invalid vsize=%lx", 364 + (*vma)->vm_end - (*vma)->vm_start); 365 + return -EINVAL; 366 + } 367 + 368 + (*vma)->vm_page_prot = pgprot_noncached((*vma)->vm_page_prot); 369 + (*vma)->vm_flags |= VM_IO | VM_RESERVED; 370 + 371 + ret = remap_pfn_range((*vma), (*vma)->vm_start, 372 + physical >> PAGE_SHIFT, vsize, 373 + (*vma)->vm_page_prot); 374 + if (ret) { 375 + ehca_gen_err("remap_pfn_range() failed ret=%x", ret); 376 + return -ENOMEM; 377 + } 378 + 379 + return 0; 380 + 381 + } 382 + 383 + int ehca_munmap(unsigned long addr, size_t len) { 384 + int ret = 0; 385 + struct mm_struct *mm = current->mm; 386 + if (mm) { 387 + down_write(&mm->mmap_sem); 388 + ret = do_munmap(mm, addr, len); 389 + up_write(&mm->mmap_sem); 390 + } 391 + return ret; 392 + }
+874
drivers/infiniband/hw/ehca/hcp_if.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * Firmware Infiniband Interface code for POWER 5 + * 6 + * Authors: Christoph Raisch <raisch@de.ibm.com> 7 + * Hoang-Nam Nguyen <hnguyen@de.ibm.com> 8 + * Gerd Bayer <gerd.bayer@de.ibm.com> 9 + * Waleri Fomin <fomin@de.ibm.com> 10 + * 11 + * Copyright (c) 2005 IBM Corporation 12 + * 13 + * All rights reserved. 14 + * 15 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 16 + * BSD. 17 + * 18 + * OpenIB BSD License 19 + * 20 + * Redistribution and use in source and binary forms, with or without 21 + * modification, are permitted provided that the following conditions are met: 22 + * 23 + * Redistributions of source code must retain the above copyright notice, this 24 + * list of conditions and the following disclaimer. 25 + * 26 + * Redistributions in binary form must reproduce the above copyright notice, 27 + * this list of conditions and the following disclaimer in the documentation 28 + * and/or other materials 29 + * provided with the distribution. 30 + * 31 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 32 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 35 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 36 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 38 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 39 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 + * POSSIBILITY OF SUCH DAMAGE. 42 + */ 43 + 44 + #include <asm/hvcall.h> 45 + #include "ehca_tools.h" 46 + #include "hcp_if.h" 47 + #include "hcp_phyp.h" 48 + #include "hipz_fns.h" 49 + #include "ipz_pt_fn.h" 50 + 51 + #define H_ALL_RES_QP_ENHANCED_OPS EHCA_BMASK_IBM(9, 11) 52 + #define H_ALL_RES_QP_PTE_PIN EHCA_BMASK_IBM(12, 12) 53 + #define H_ALL_RES_QP_SERVICE_TYPE EHCA_BMASK_IBM(13, 15) 54 + #define H_ALL_RES_QP_LL_RQ_CQE_POSTING EHCA_BMASK_IBM(18, 18) 55 + #define H_ALL_RES_QP_LL_SQ_CQE_POSTING EHCA_BMASK_IBM(19, 21) 56 + #define H_ALL_RES_QP_SIGNALING_TYPE EHCA_BMASK_IBM(22, 23) 57 + #define H_ALL_RES_QP_UD_AV_LKEY_CTRL EHCA_BMASK_IBM(31, 31) 58 + #define H_ALL_RES_QP_RESOURCE_TYPE EHCA_BMASK_IBM(56, 63) 59 + 60 + #define H_ALL_RES_QP_MAX_OUTST_SEND_WR EHCA_BMASK_IBM(0, 15) 61 + #define H_ALL_RES_QP_MAX_OUTST_RECV_WR EHCA_BMASK_IBM(16, 31) 62 + #define H_ALL_RES_QP_MAX_SEND_SGE EHCA_BMASK_IBM(32, 39) 63 + #define H_ALL_RES_QP_MAX_RECV_SGE EHCA_BMASK_IBM(40, 47) 64 + 65 + #define H_ALL_RES_QP_ACT_OUTST_SEND_WR EHCA_BMASK_IBM(16, 31) 66 + #define H_ALL_RES_QP_ACT_OUTST_RECV_WR EHCA_BMASK_IBM(48, 63) 67 + #define H_ALL_RES_QP_ACT_SEND_SGE EHCA_BMASK_IBM(8, 15) 68 + #define H_ALL_RES_QP_ACT_RECV_SGE EHCA_BMASK_IBM(24, 31) 69 + 70 + #define H_ALL_RES_QP_SQUEUE_SIZE_PAGES EHCA_BMASK_IBM(0, 31) 71 + #define H_ALL_RES_QP_RQUEUE_SIZE_PAGES EHCA_BMASK_IBM(32, 63) 72 + 73 + /* direct access qp controls */ 74 + #define DAQP_CTRL_ENABLE 0x01 75 + #define DAQP_CTRL_SEND_COMP 0x20 76 + #define DAQP_CTRL_RECV_COMP 0x40 77 + 78 + static u32 get_longbusy_msecs(int longbusy_rc) 79 + { 80 + switch (longbusy_rc) { 81 + case H_LONG_BUSY_ORDER_1_MSEC: 82 + return 1; 83 + case H_LONG_BUSY_ORDER_10_MSEC: 84 + return 10; 85 + case H_LONG_BUSY_ORDER_100_MSEC: 86 + return 100; 87 + case H_LONG_BUSY_ORDER_1_SEC: 88 + return 1000; 89 + case H_LONG_BUSY_ORDER_10_SEC: 90 + return 10000; 91 + case H_LONG_BUSY_ORDER_100_SEC: 92 + return 100000; 93 + default: 94 + return 1; 95 + } 96 + } 97 + 98 + static long ehca_plpar_hcall_norets(unsigned long opcode, 99 + unsigned long arg1, 100 + unsigned long arg2, 101 + unsigned long arg3, 102 + unsigned long arg4, 103 + unsigned long arg5, 104 + unsigned long arg6, 105 + unsigned long arg7) 106 + { 107 + long ret; 108 + int i, sleep_msecs; 109 + 110 + ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx " 111 + "arg5=%lx arg6=%lx arg7=%lx", 112 + opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7); 113 + 114 + for (i = 0; i < 5; i++) { 115 + ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4, 116 + arg5, arg6, arg7); 117 + 118 + if (H_IS_LONG_BUSY(ret)) { 119 + sleep_msecs = get_longbusy_msecs(ret); 120 + msleep_interruptible(sleep_msecs); 121 + continue; 122 + } 123 + 124 + if (ret < H_SUCCESS) 125 + ehca_gen_err("opcode=%lx ret=%lx" 126 + " arg1=%lx arg2=%lx arg3=%lx arg4=%lx" 127 + " arg5=%lx arg6=%lx arg7=%lx ", 128 + opcode, ret, 129 + arg1, arg2, arg3, arg4, arg5, 130 + arg6, arg7); 131 + 132 + ehca_gen_dbg("opcode=%lx ret=%lx", opcode, ret); 133 + return ret; 134 + 135 + } 136 + 137 + return H_BUSY; 138 + } 139 + 140 + static long ehca_plpar_hcall9(unsigned long opcode, 141 + unsigned long *outs, /* array of 9 outputs */ 142 + unsigned long arg1, 143 + unsigned long arg2, 144 + unsigned long arg3, 145 + unsigned long arg4, 146 + unsigned long arg5, 147 + unsigned long arg6, 148 + unsigned long arg7, 149 + unsigned long arg8, 150 + unsigned long arg9) 151 + { 152 + long ret; 153 + int i, sleep_msecs; 154 + 155 + ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx " 156 + "arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx", 157 + opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7, 158 + arg8, arg9); 159 + 160 + for (i = 0; i < 5; i++) { 161 + ret = plpar_hcall9(opcode, outs, 162 + arg1, arg2, arg3, arg4, arg5, 163 + arg6, arg7, arg8, arg9); 164 + 165 + if (H_IS_LONG_BUSY(ret)) { 166 + sleep_msecs = get_longbusy_msecs(ret); 167 + msleep_interruptible(sleep_msecs); 168 + continue; 169 + } 170 + 171 + if (ret < H_SUCCESS) 172 + ehca_gen_err("opcode=%lx ret=%lx" 173 + " arg1=%lx arg2=%lx arg3=%lx arg4=%lx" 174 + " arg5=%lx arg6=%lx arg7=%lx arg8=%lx" 175 + " arg9=%lx" 176 + " out1=%lx out2=%lx out3=%lx out4=%lx" 177 + " out5=%lx out6=%lx out7=%lx out8=%lx" 178 + " out9=%lx", 179 + opcode, ret, 180 + arg1, arg2, arg3, arg4, arg5, 181 + arg6, arg7, arg8, arg9, 182 + outs[0], outs[1], outs[2], outs[3], 183 + outs[4], outs[5], outs[6], outs[7], 184 + outs[8]); 185 + 186 + ehca_gen_dbg("opcode=%lx ret=%lx out1=%lx out2=%lx out3=%lx " 187 + "out4=%lx out5=%lx out6=%lx out7=%lx out8=%lx " 188 + "out9=%lx", 189 + opcode, ret, outs[0], outs[1], outs[2], outs[3], 190 + outs[4], outs[5], outs[6], outs[7], outs[8]); 191 + return ret; 192 + 193 + } 194 + 195 + return H_BUSY; 196 + } 197 + u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle, 198 + struct ehca_pfeq *pfeq, 199 + const u32 neq_control, 200 + const u32 number_of_entries, 201 + struct ipz_eq_handle *eq_handle, 202 + u32 *act_nr_of_entries, 203 + u32 *act_pages, 204 + u32 *eq_ist) 205 + { 206 + u64 ret; 207 + u64 outs[PLPAR_HCALL9_BUFSIZE]; 208 + u64 allocate_controls; 209 + 210 + /* resource type */ 211 + allocate_controls = 3ULL; 212 + 213 + /* ISN is associated */ 214 + if (neq_control != 1) 215 + allocate_controls = (1ULL << (63 - 7)) | allocate_controls; 216 + else /* notification event queue */ 217 + allocate_controls = (1ULL << 63) | allocate_controls; 218 + 219 + ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, 220 + adapter_handle.handle, /* r4 */ 221 + allocate_controls, /* r5 */ 222 + number_of_entries, /* r6 */ 223 + 0, 0, 0, 0, 0, 0); 224 + eq_handle->handle = outs[0]; 225 + *act_nr_of_entries = (u32)outs[3]; 226 + *act_pages = (u32)outs[4]; 227 + *eq_ist = (u32)outs[5]; 228 + 229 + if (ret == H_NOT_ENOUGH_RESOURCES) 230 + ehca_gen_err("Not enough resource - ret=%lx ", ret); 231 + 232 + return ret; 233 + } 234 + 235 + u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle, 236 + struct ipz_eq_handle eq_handle, 237 + const u64 event_mask) 238 + { 239 + return ehca_plpar_hcall_norets(H_RESET_EVENTS, 240 + adapter_handle.handle, /* r4 */ 241 + eq_handle.handle, /* r5 */ 242 + event_mask, /* r6 */ 243 + 0, 0, 0, 0); 244 + } 245 + 246 + u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle, 247 + struct ehca_cq *cq, 248 + struct ehca_alloc_cq_parms *param) 249 + { 250 + u64 ret; 251 + u64 outs[PLPAR_HCALL9_BUFSIZE]; 252 + 253 + ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, 254 + adapter_handle.handle, /* r4 */ 255 + 2, /* r5 */ 256 + param->eq_handle.handle, /* r6 */ 257 + cq->token, /* r7 */ 258 + param->nr_cqe, /* r8 */ 259 + 0, 0, 0, 0); 260 + cq->ipz_cq_handle.handle = outs[0]; 261 + param->act_nr_of_entries = (u32)outs[3]; 262 + param->act_pages = (u32)outs[4]; 263 + 264 + if (ret == H_SUCCESS) 265 + hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]); 266 + 267 + if (ret == H_NOT_ENOUGH_RESOURCES) 268 + ehca_gen_err("Not enough resources. ret=%lx", ret); 269 + 270 + return ret; 271 + } 272 + 273 + u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle, 274 + struct ehca_qp *qp, 275 + struct ehca_alloc_qp_parms *parms) 276 + { 277 + u64 ret; 278 + u64 allocate_controls; 279 + u64 max_r10_reg; 280 + u64 outs[PLPAR_HCALL9_BUFSIZE]; 281 + u16 max_nr_receive_wqes = qp->init_attr.cap.max_recv_wr + 1; 282 + u16 max_nr_send_wqes = qp->init_attr.cap.max_send_wr + 1; 283 + int daqp_ctrl = parms->daqp_ctrl; 284 + 285 + allocate_controls = 286 + EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, 287 + (daqp_ctrl & DAQP_CTRL_ENABLE) ? 1 : 0) 288 + | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0) 289 + | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype) 290 + | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype) 291 + | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING, 292 + (daqp_ctrl & DAQP_CTRL_RECV_COMP) ? 1 : 0) 293 + | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING, 294 + (daqp_ctrl & DAQP_CTRL_SEND_COMP) ? 1 : 0) 295 + | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL, 296 + parms->ud_av_l_key_ctl) 297 + | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1); 298 + 299 + max_r10_reg = 300 + EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR, 301 + max_nr_send_wqes) 302 + | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR, 303 + max_nr_receive_wqes) 304 + | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE, 305 + parms->max_send_sge) 306 + | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE, 307 + parms->max_recv_sge); 308 + 309 + ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, 310 + adapter_handle.handle, /* r4 */ 311 + allocate_controls, /* r5 */ 312 + qp->send_cq->ipz_cq_handle.handle, 313 + qp->recv_cq->ipz_cq_handle.handle, 314 + parms->ipz_eq_handle.handle, 315 + ((u64)qp->token << 32) | parms->pd.value, 316 + max_r10_reg, /* r10 */ 317 + parms->ud_av_l_key_ctl, /* r11 */ 318 + 0); 319 + qp->ipz_qp_handle.handle = outs[0]; 320 + qp->real_qp_num = (u32)outs[1]; 321 + parms->act_nr_send_sges = 322 + (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]); 323 + parms->act_nr_recv_wqes = 324 + (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]); 325 + parms->act_nr_send_sges = 326 + (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]); 327 + parms->act_nr_recv_sges = 328 + (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]); 329 + parms->nr_sq_pages = 330 + (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]); 331 + parms->nr_rq_pages = 332 + (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]); 333 + 334 + if (ret == H_SUCCESS) 335 + hcp_galpas_ctor(&qp->galpas, outs[6], outs[6]); 336 + 337 + if (ret == H_NOT_ENOUGH_RESOURCES) 338 + ehca_gen_err("Not enough resources. ret=%lx", ret); 339 + 340 + return ret; 341 + } 342 + 343 + u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle, 344 + const u8 port_id, 345 + struct hipz_query_port *query_port_response_block) 346 + { 347 + u64 ret; 348 + u64 r_cb = virt_to_abs(query_port_response_block); 349 + 350 + if (r_cb & (EHCA_PAGESIZE-1)) { 351 + ehca_gen_err("response block not page aligned"); 352 + return H_PARAMETER; 353 + } 354 + 355 + ret = ehca_plpar_hcall_norets(H_QUERY_PORT, 356 + adapter_handle.handle, /* r4 */ 357 + port_id, /* r5 */ 358 + r_cb, /* r6 */ 359 + 0, 0, 0, 0); 360 + 361 + if (ehca_debug_level) 362 + ehca_dmp(query_port_response_block, 64, "response_block"); 363 + 364 + return ret; 365 + } 366 + 367 + u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle, 368 + struct hipz_query_hca *query_hca_rblock) 369 + { 370 + u64 r_cb = virt_to_abs(query_hca_rblock); 371 + 372 + if (r_cb & (EHCA_PAGESIZE-1)) { 373 + ehca_gen_err("response_block=%p not page aligned", 374 + query_hca_rblock); 375 + return H_PARAMETER; 376 + } 377 + 378 + return ehca_plpar_hcall_norets(H_QUERY_HCA, 379 + adapter_handle.handle, /* r4 */ 380 + r_cb, /* r5 */ 381 + 0, 0, 0, 0, 0); 382 + } 383 + 384 + u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle, 385 + const u8 pagesize, 386 + const u8 queue_type, 387 + const u64 resource_handle, 388 + const u64 logical_address_of_page, 389 + u64 count) 390 + { 391 + return ehca_plpar_hcall_norets(H_REGISTER_RPAGES, 392 + adapter_handle.handle, /* r4 */ 393 + queue_type | pagesize << 8, /* r5 */ 394 + resource_handle, /* r6 */ 395 + logical_address_of_page, /* r7 */ 396 + count, /* r8 */ 397 + 0, 0); 398 + } 399 + 400 + u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle, 401 + const struct ipz_eq_handle eq_handle, 402 + struct ehca_pfeq *pfeq, 403 + const u8 pagesize, 404 + const u8 queue_type, 405 + const u64 logical_address_of_page, 406 + const u64 count) 407 + { 408 + if (count != 1) { 409 + ehca_gen_err("Ppage counter=%lx", count); 410 + return H_PARAMETER; 411 + } 412 + return hipz_h_register_rpage(adapter_handle, 413 + pagesize, 414 + queue_type, 415 + eq_handle.handle, 416 + logical_address_of_page, count); 417 + } 418 + 419 + u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle, 420 + u32 ist) 421 + { 422 + u64 ret; 423 + ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE, 424 + adapter_handle.handle, /* r4 */ 425 + ist, /* r5 */ 426 + 0, 0, 0, 0, 0); 427 + 428 + if (ret != H_SUCCESS && ret != H_BUSY) 429 + ehca_gen_err("Could not query interrupt state."); 430 + 431 + return ret; 432 + } 433 + 434 + u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle, 435 + const struct ipz_cq_handle cq_handle, 436 + struct ehca_pfcq *pfcq, 437 + const u8 pagesize, 438 + const u8 queue_type, 439 + const u64 logical_address_of_page, 440 + const u64 count, 441 + const struct h_galpa gal) 442 + { 443 + if (count != 1) { 444 + ehca_gen_err("Page counter=%lx", count); 445 + return H_PARAMETER; 446 + } 447 + 448 + return hipz_h_register_rpage(adapter_handle, pagesize, queue_type, 449 + cq_handle.handle, logical_address_of_page, 450 + count); 451 + } 452 + 453 + u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle, 454 + const struct ipz_qp_handle qp_handle, 455 + struct ehca_pfqp *pfqp, 456 + const u8 pagesize, 457 + const u8 queue_type, 458 + const u64 logical_address_of_page, 459 + const u64 count, 460 + const struct h_galpa galpa) 461 + { 462 + if (count != 1) { 463 + ehca_gen_err("Page counter=%lx", count); 464 + return H_PARAMETER; 465 + } 466 + 467 + return hipz_h_register_rpage(adapter_handle,pagesize,queue_type, 468 + qp_handle.handle,logical_address_of_page, 469 + count); 470 + } 471 + 472 + u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle, 473 + const struct ipz_qp_handle qp_handle, 474 + struct ehca_pfqp *pfqp, 475 + void **log_addr_next_sq_wqe2processed, 476 + void **log_addr_next_rq_wqe2processed, 477 + int dis_and_get_function_code) 478 + { 479 + u64 ret; 480 + u64 outs[PLPAR_HCALL9_BUFSIZE]; 481 + 482 + ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs, 483 + adapter_handle.handle, /* r4 */ 484 + dis_and_get_function_code, /* r5 */ 485 + qp_handle.handle, /* r6 */ 486 + 0, 0, 0, 0, 0, 0); 487 + if (log_addr_next_sq_wqe2processed) 488 + *log_addr_next_sq_wqe2processed = (void*)outs[0]; 489 + if (log_addr_next_rq_wqe2processed) 490 + *log_addr_next_rq_wqe2processed = (void*)outs[1]; 491 + 492 + return ret; 493 + } 494 + 495 + u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle, 496 + const struct ipz_qp_handle qp_handle, 497 + struct ehca_pfqp *pfqp, 498 + const u64 update_mask, 499 + struct hcp_modify_qp_control_block *mqpcb, 500 + struct h_galpa gal) 501 + { 502 + u64 ret; 503 + u64 outs[PLPAR_HCALL9_BUFSIZE]; 504 + ret = ehca_plpar_hcall9(H_MODIFY_QP, outs, 505 + adapter_handle.handle, /* r4 */ 506 + qp_handle.handle, /* r5 */ 507 + update_mask, /* r6 */ 508 + virt_to_abs(mqpcb), /* r7 */ 509 + 0, 0, 0, 0, 0); 510 + 511 + if (ret == H_NOT_ENOUGH_RESOURCES) 512 + ehca_gen_err("Insufficient resources ret=%lx", ret); 513 + 514 + return ret; 515 + } 516 + 517 + u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle, 518 + const struct ipz_qp_handle qp_handle, 519 + struct ehca_pfqp *pfqp, 520 + struct hcp_modify_qp_control_block *qqpcb, 521 + struct h_galpa gal) 522 + { 523 + return ehca_plpar_hcall_norets(H_QUERY_QP, 524 + adapter_handle.handle, /* r4 */ 525 + qp_handle.handle, /* r5 */ 526 + virt_to_abs(qqpcb), /* r6 */ 527 + 0, 0, 0, 0); 528 + } 529 + 530 + u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle, 531 + struct ehca_qp *qp) 532 + { 533 + u64 ret; 534 + u64 outs[PLPAR_HCALL9_BUFSIZE]; 535 + 536 + ret = hcp_galpas_dtor(&qp->galpas); 537 + if (ret) { 538 + ehca_gen_err("Could not destruct qp->galpas"); 539 + return H_RESOURCE; 540 + } 541 + ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs, 542 + adapter_handle.handle, /* r4 */ 543 + /* function code */ 544 + 1, /* r5 */ 545 + qp->ipz_qp_handle.handle, /* r6 */ 546 + 0, 0, 0, 0, 0, 0); 547 + if (ret == H_HARDWARE) 548 + ehca_gen_err("HCA not operational. ret=%lx", ret); 549 + 550 + ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE, 551 + adapter_handle.handle, /* r4 */ 552 + qp->ipz_qp_handle.handle, /* r5 */ 553 + 0, 0, 0, 0, 0); 554 + 555 + if (ret == H_RESOURCE) 556 + ehca_gen_err("Resource still in use. ret=%lx", ret); 557 + 558 + return ret; 559 + } 560 + 561 + u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle, 562 + const struct ipz_qp_handle qp_handle, 563 + struct h_galpa gal, 564 + u32 port) 565 + { 566 + return ehca_plpar_hcall_norets(H_DEFINE_AQP0, 567 + adapter_handle.handle, /* r4 */ 568 + qp_handle.handle, /* r5 */ 569 + port, /* r6 */ 570 + 0, 0, 0, 0); 571 + } 572 + 573 + u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle, 574 + const struct ipz_qp_handle qp_handle, 575 + struct h_galpa gal, 576 + u32 port, u32 * pma_qp_nr, 577 + u32 * bma_qp_nr) 578 + { 579 + u64 ret; 580 + u64 outs[PLPAR_HCALL9_BUFSIZE]; 581 + 582 + ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs, 583 + adapter_handle.handle, /* r4 */ 584 + qp_handle.handle, /* r5 */ 585 + port, /* r6 */ 586 + 0, 0, 0, 0, 0, 0); 587 + *pma_qp_nr = (u32)outs[0]; 588 + *bma_qp_nr = (u32)outs[1]; 589 + 590 + if (ret == H_ALIAS_EXIST) 591 + ehca_gen_err("AQP1 already exists. ret=%lx", ret); 592 + 593 + return ret; 594 + } 595 + 596 + u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle, 597 + const struct ipz_qp_handle qp_handle, 598 + struct h_galpa gal, 599 + u16 mcg_dlid, 600 + u64 subnet_prefix, u64 interface_id) 601 + { 602 + u64 ret; 603 + 604 + ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP, 605 + adapter_handle.handle, /* r4 */ 606 + qp_handle.handle, /* r5 */ 607 + mcg_dlid, /* r6 */ 608 + interface_id, /* r7 */ 609 + subnet_prefix, /* r8 */ 610 + 0, 0); 611 + 612 + if (ret == H_NOT_ENOUGH_RESOURCES) 613 + ehca_gen_err("Not enough resources. ret=%lx", ret); 614 + 615 + return ret; 616 + } 617 + 618 + u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle, 619 + const struct ipz_qp_handle qp_handle, 620 + struct h_galpa gal, 621 + u16 mcg_dlid, 622 + u64 subnet_prefix, u64 interface_id) 623 + { 624 + return ehca_plpar_hcall_norets(H_DETACH_MCQP, 625 + adapter_handle.handle, /* r4 */ 626 + qp_handle.handle, /* r5 */ 627 + mcg_dlid, /* r6 */ 628 + interface_id, /* r7 */ 629 + subnet_prefix, /* r8 */ 630 + 0, 0); 631 + } 632 + 633 + u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle, 634 + struct ehca_cq *cq, 635 + u8 force_flag) 636 + { 637 + u64 ret; 638 + 639 + ret = hcp_galpas_dtor(&cq->galpas); 640 + if (ret) { 641 + ehca_gen_err("Could not destruct cp->galpas"); 642 + return H_RESOURCE; 643 + } 644 + 645 + ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE, 646 + adapter_handle.handle, /* r4 */ 647 + cq->ipz_cq_handle.handle, /* r5 */ 648 + force_flag != 0 ? 1L : 0L, /* r6 */ 649 + 0, 0, 0, 0); 650 + 651 + if (ret == H_RESOURCE) 652 + ehca_gen_err("H_FREE_RESOURCE failed ret=%lx ", ret); 653 + 654 + return ret; 655 + } 656 + 657 + u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle, 658 + struct ehca_eq *eq) 659 + { 660 + u64 ret; 661 + 662 + ret = hcp_galpas_dtor(&eq->galpas); 663 + if (ret) { 664 + ehca_gen_err("Could not destruct eq->galpas"); 665 + return H_RESOURCE; 666 + } 667 + 668 + ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE, 669 + adapter_handle.handle, /* r4 */ 670 + eq->ipz_eq_handle.handle, /* r5 */ 671 + 0, 0, 0, 0, 0); 672 + 673 + if (ret == H_RESOURCE) 674 + ehca_gen_err("Resource in use. ret=%lx ", ret); 675 + 676 + return ret; 677 + } 678 + 679 + u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle, 680 + const struct ehca_mr *mr, 681 + const u64 vaddr, 682 + const u64 length, 683 + const u32 access_ctrl, 684 + const struct ipz_pd pd, 685 + struct ehca_mr_hipzout_parms *outparms) 686 + { 687 + u64 ret; 688 + u64 outs[PLPAR_HCALL9_BUFSIZE]; 689 + 690 + ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, 691 + adapter_handle.handle, /* r4 */ 692 + 5, /* r5 */ 693 + vaddr, /* r6 */ 694 + length, /* r7 */ 695 + (((u64)access_ctrl) << 32ULL), /* r8 */ 696 + pd.value, /* r9 */ 697 + 0, 0, 0); 698 + outparms->handle.handle = outs[0]; 699 + outparms->lkey = (u32)outs[2]; 700 + outparms->rkey = (u32)outs[3]; 701 + 702 + return ret; 703 + } 704 + 705 + u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle, 706 + const struct ehca_mr *mr, 707 + const u8 pagesize, 708 + const u8 queue_type, 709 + const u64 logical_address_of_page, 710 + const u64 count) 711 + { 712 + u64 ret; 713 + 714 + if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) { 715 + ehca_gen_err("logical_address_of_page not on a 4k boundary " 716 + "adapter_handle=%lx mr=%p mr_handle=%lx " 717 + "pagesize=%x queue_type=%x " 718 + "logical_address_of_page=%lx count=%lx", 719 + adapter_handle.handle, mr, 720 + mr->ipz_mr_handle.handle, pagesize, queue_type, 721 + logical_address_of_page, count); 722 + ret = H_PARAMETER; 723 + } else 724 + ret = hipz_h_register_rpage(adapter_handle, pagesize, 725 + queue_type, 726 + mr->ipz_mr_handle.handle, 727 + logical_address_of_page, count); 728 + return ret; 729 + } 730 + 731 + u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle, 732 + const struct ehca_mr *mr, 733 + struct ehca_mr_hipzout_parms *outparms) 734 + { 735 + u64 ret; 736 + u64 outs[PLPAR_HCALL9_BUFSIZE]; 737 + 738 + ret = ehca_plpar_hcall9(H_QUERY_MR, outs, 739 + adapter_handle.handle, /* r4 */ 740 + mr->ipz_mr_handle.handle, /* r5 */ 741 + 0, 0, 0, 0, 0, 0, 0); 742 + outparms->len = outs[0]; 743 + outparms->vaddr = outs[1]; 744 + outparms->acl = outs[4] >> 32; 745 + outparms->lkey = (u32)(outs[5] >> 32); 746 + outparms->rkey = (u32)(outs[5] & (0xffffffff)); 747 + 748 + return ret; 749 + } 750 + 751 + u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle, 752 + const struct ehca_mr *mr) 753 + { 754 + return ehca_plpar_hcall_norets(H_FREE_RESOURCE, 755 + adapter_handle.handle, /* r4 */ 756 + mr->ipz_mr_handle.handle, /* r5 */ 757 + 0, 0, 0, 0, 0); 758 + } 759 + 760 + u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle, 761 + const struct ehca_mr *mr, 762 + const u64 vaddr_in, 763 + const u64 length, 764 + const u32 access_ctrl, 765 + const struct ipz_pd pd, 766 + const u64 mr_addr_cb, 767 + struct ehca_mr_hipzout_parms *outparms) 768 + { 769 + u64 ret; 770 + u64 outs[PLPAR_HCALL9_BUFSIZE]; 771 + 772 + ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs, 773 + adapter_handle.handle, /* r4 */ 774 + mr->ipz_mr_handle.handle, /* r5 */ 775 + vaddr_in, /* r6 */ 776 + length, /* r7 */ 777 + /* r8 */ 778 + ((((u64)access_ctrl) << 32ULL) | pd.value), 779 + mr_addr_cb, /* r9 */ 780 + 0, 0, 0); 781 + outparms->vaddr = outs[1]; 782 + outparms->lkey = (u32)outs[2]; 783 + outparms->rkey = (u32)outs[3]; 784 + 785 + return ret; 786 + } 787 + 788 + u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle, 789 + const struct ehca_mr *mr, 790 + const struct ehca_mr *orig_mr, 791 + const u64 vaddr_in, 792 + const u32 access_ctrl, 793 + const struct ipz_pd pd, 794 + struct ehca_mr_hipzout_parms *outparms) 795 + { 796 + u64 ret; 797 + u64 outs[PLPAR_HCALL9_BUFSIZE]; 798 + 799 + ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs, 800 + adapter_handle.handle, /* r4 */ 801 + orig_mr->ipz_mr_handle.handle, /* r5 */ 802 + vaddr_in, /* r6 */ 803 + (((u64)access_ctrl) << 32ULL), /* r7 */ 804 + pd.value, /* r8 */ 805 + 0, 0, 0, 0); 806 + outparms->handle.handle = outs[0]; 807 + outparms->lkey = (u32)outs[2]; 808 + outparms->rkey = (u32)outs[3]; 809 + 810 + return ret; 811 + } 812 + 813 + u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle, 814 + const struct ehca_mw *mw, 815 + const struct ipz_pd pd, 816 + struct ehca_mw_hipzout_parms *outparms) 817 + { 818 + u64 ret; 819 + u64 outs[PLPAR_HCALL9_BUFSIZE]; 820 + 821 + ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, 822 + adapter_handle.handle, /* r4 */ 823 + 6, /* r5 */ 824 + pd.value, /* r6 */ 825 + 0, 0, 0, 0, 0, 0); 826 + outparms->handle.handle = outs[0]; 827 + outparms->rkey = (u32)outs[3]; 828 + 829 + return ret; 830 + } 831 + 832 + u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle, 833 + const struct ehca_mw *mw, 834 + struct ehca_mw_hipzout_parms *outparms) 835 + { 836 + u64 ret; 837 + u64 outs[PLPAR_HCALL9_BUFSIZE]; 838 + 839 + ret = ehca_plpar_hcall9(H_QUERY_MW, outs, 840 + adapter_handle.handle, /* r4 */ 841 + mw->ipz_mw_handle.handle, /* r5 */ 842 + 0, 0, 0, 0, 0, 0, 0); 843 + outparms->rkey = (u32)outs[3]; 844 + 845 + return ret; 846 + } 847 + 848 + u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle, 849 + const struct ehca_mw *mw) 850 + { 851 + return ehca_plpar_hcall_norets(H_FREE_RESOURCE, 852 + adapter_handle.handle, /* r4 */ 853 + mw->ipz_mw_handle.handle, /* r5 */ 854 + 0, 0, 0, 0, 0); 855 + } 856 + 857 + u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle, 858 + const u64 ressource_handle, 859 + void *rblock, 860 + unsigned long *byte_count) 861 + { 862 + u64 r_cb = virt_to_abs(rblock); 863 + 864 + if (r_cb & (EHCA_PAGESIZE-1)) { 865 + ehca_gen_err("rblock not page aligned."); 866 + return H_PARAMETER; 867 + } 868 + 869 + return ehca_plpar_hcall_norets(H_ERROR_DATA, 870 + adapter_handle.handle, 871 + ressource_handle, 872 + r_cb, 873 + 0, 0, 0, 0); 874 + }
+261
drivers/infiniband/hw/ehca/hcp_if.h
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * Firmware Infiniband Interface code for POWER 5 + * 6 + * Authors: Christoph Raisch <raisch@de.ibm.com> 7 + * Hoang-Nam Nguyen <hnguyen@de.ibm.com> 8 + * Gerd Bayer <gerd.bayer@de.ibm.com> 9 + * Waleri Fomin <fomin@de.ibm.com> 10 + * 11 + * Copyright (c) 2005 IBM Corporation 12 + * 13 + * All rights reserved. 14 + * 15 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 16 + * BSD. 17 + * 18 + * OpenIB BSD License 19 + * 20 + * Redistribution and use in source and binary forms, with or without 21 + * modification, are permitted provided that the following conditions are met: 22 + * 23 + * Redistributions of source code must retain the above copyright notice, this 24 + * list of conditions and the following disclaimer. 25 + * 26 + * Redistributions in binary form must reproduce the above copyright notice, 27 + * this list of conditions and the following disclaimer in the documentation 28 + * and/or other materials 29 + * provided with the distribution. 30 + * 31 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 32 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 35 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 36 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 38 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 39 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 + * POSSIBILITY OF SUCH DAMAGE. 42 + */ 43 + 44 + #ifndef __HCP_IF_H__ 45 + #define __HCP_IF_H__ 46 + 47 + #include "ehca_classes.h" 48 + #include "ehca_tools.h" 49 + #include "hipz_hw.h" 50 + 51 + /* 52 + * hipz_h_alloc_resource_eq allocates EQ resources in HW and FW, initalize 53 + * resources, create the empty EQPT (ring). 54 + */ 55 + u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle, 56 + struct ehca_pfeq *pfeq, 57 + const u32 neq_control, 58 + const u32 number_of_entries, 59 + struct ipz_eq_handle *eq_handle, 60 + u32 * act_nr_of_entries, 61 + u32 * act_pages, 62 + u32 * eq_ist); 63 + 64 + u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle, 65 + struct ipz_eq_handle eq_handle, 66 + const u64 event_mask); 67 + /* 68 + * hipz_h_allocate_resource_cq allocates CQ resources in HW and FW, initialize 69 + * resources, create the empty CQPT (ring). 70 + */ 71 + u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle, 72 + struct ehca_cq *cq, 73 + struct ehca_alloc_cq_parms *param); 74 + 75 + 76 + /* 77 + * hipz_h_alloc_resource_qp allocates QP resources in HW and FW, 78 + * initialize resources, create empty QPPTs (2 rings). 79 + */ 80 + u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle, 81 + struct ehca_qp *qp, 82 + struct ehca_alloc_qp_parms *parms); 83 + 84 + u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle, 85 + const u8 port_id, 86 + struct hipz_query_port *query_port_response_block); 87 + 88 + u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle, 89 + struct hipz_query_hca *query_hca_rblock); 90 + 91 + /* 92 + * hipz_h_register_rpage internal function in hcp_if.h for all 93 + * hcp_H_REGISTER_RPAGE calls. 94 + */ 95 + u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle, 96 + const u8 pagesize, 97 + const u8 queue_type, 98 + const u64 resource_handle, 99 + const u64 logical_address_of_page, 100 + u64 count); 101 + 102 + u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle, 103 + const struct ipz_eq_handle eq_handle, 104 + struct ehca_pfeq *pfeq, 105 + const u8 pagesize, 106 + const u8 queue_type, 107 + const u64 logical_address_of_page, 108 + const u64 count); 109 + 110 + u64 hipz_h_query_int_state(const struct ipz_adapter_handle 111 + hcp_adapter_handle, 112 + u32 ist); 113 + 114 + u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle, 115 + const struct ipz_cq_handle cq_handle, 116 + struct ehca_pfcq *pfcq, 117 + const u8 pagesize, 118 + const u8 queue_type, 119 + const u64 logical_address_of_page, 120 + const u64 count, 121 + const struct h_galpa gal); 122 + 123 + u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle, 124 + const struct ipz_qp_handle qp_handle, 125 + struct ehca_pfqp *pfqp, 126 + const u8 pagesize, 127 + const u8 queue_type, 128 + const u64 logical_address_of_page, 129 + const u64 count, 130 + const struct h_galpa galpa); 131 + 132 + u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle, 133 + const struct ipz_qp_handle qp_handle, 134 + struct ehca_pfqp *pfqp, 135 + void **log_addr_next_sq_wqe_tb_processed, 136 + void **log_addr_next_rq_wqe_tb_processed, 137 + int dis_and_get_function_code); 138 + enum hcall_sigt { 139 + HCALL_SIGT_NO_CQE = 0, 140 + HCALL_SIGT_BY_WQE = 1, 141 + HCALL_SIGT_EVERY = 2 142 + }; 143 + 144 + u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle, 145 + const struct ipz_qp_handle qp_handle, 146 + struct ehca_pfqp *pfqp, 147 + const u64 update_mask, 148 + struct hcp_modify_qp_control_block *mqpcb, 149 + struct h_galpa gal); 150 + 151 + u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle, 152 + const struct ipz_qp_handle qp_handle, 153 + struct ehca_pfqp *pfqp, 154 + struct hcp_modify_qp_control_block *qqpcb, 155 + struct h_galpa gal); 156 + 157 + u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle, 158 + struct ehca_qp *qp); 159 + 160 + u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle, 161 + const struct ipz_qp_handle qp_handle, 162 + struct h_galpa gal, 163 + u32 port); 164 + 165 + u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle, 166 + const struct ipz_qp_handle qp_handle, 167 + struct h_galpa gal, 168 + u32 port, u32 * pma_qp_nr, 169 + u32 * bma_qp_nr); 170 + 171 + u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle, 172 + const struct ipz_qp_handle qp_handle, 173 + struct h_galpa gal, 174 + u16 mcg_dlid, 175 + u64 subnet_prefix, u64 interface_id); 176 + 177 + u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle, 178 + const struct ipz_qp_handle qp_handle, 179 + struct h_galpa gal, 180 + u16 mcg_dlid, 181 + u64 subnet_prefix, u64 interface_id); 182 + 183 + u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle, 184 + struct ehca_cq *cq, 185 + u8 force_flag); 186 + 187 + u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle, 188 + struct ehca_eq *eq); 189 + 190 + /* 191 + * hipz_h_alloc_resource_mr allocates MR resources in HW and FW, initialize 192 + * resources. 193 + */ 194 + u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle, 195 + const struct ehca_mr *mr, 196 + const u64 vaddr, 197 + const u64 length, 198 + const u32 access_ctrl, 199 + const struct ipz_pd pd, 200 + struct ehca_mr_hipzout_parms *outparms); 201 + 202 + /* hipz_h_register_rpage_mr registers MR resource pages in HW and FW */ 203 + u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle, 204 + const struct ehca_mr *mr, 205 + const u8 pagesize, 206 + const u8 queue_type, 207 + const u64 logical_address_of_page, 208 + const u64 count); 209 + 210 + /* hipz_h_query_mr queries MR in HW and FW */ 211 + u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle, 212 + const struct ehca_mr *mr, 213 + struct ehca_mr_hipzout_parms *outparms); 214 + 215 + /* hipz_h_free_resource_mr frees MR resources in HW and FW */ 216 + u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle, 217 + const struct ehca_mr *mr); 218 + 219 + /* hipz_h_reregister_pmr reregisters MR in HW and FW */ 220 + u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle, 221 + const struct ehca_mr *mr, 222 + const u64 vaddr_in, 223 + const u64 length, 224 + const u32 access_ctrl, 225 + const struct ipz_pd pd, 226 + const u64 mr_addr_cb, 227 + struct ehca_mr_hipzout_parms *outparms); 228 + 229 + /* hipz_h_register_smr register shared MR in HW and FW */ 230 + u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle, 231 + const struct ehca_mr *mr, 232 + const struct ehca_mr *orig_mr, 233 + const u64 vaddr_in, 234 + const u32 access_ctrl, 235 + const struct ipz_pd pd, 236 + struct ehca_mr_hipzout_parms *outparms); 237 + 238 + /* 239 + * hipz_h_alloc_resource_mw allocates MW resources in HW and FW, initialize 240 + * resources. 241 + */ 242 + u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle, 243 + const struct ehca_mw *mw, 244 + const struct ipz_pd pd, 245 + struct ehca_mw_hipzout_parms *outparms); 246 + 247 + /* hipz_h_query_mw queries MW in HW and FW */ 248 + u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle, 249 + const struct ehca_mw *mw, 250 + struct ehca_mw_hipzout_parms *outparms); 251 + 252 + /* hipz_h_free_resource_mw frees MW resources in HW and FW */ 253 + u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle, 254 + const struct ehca_mw *mw); 255 + 256 + u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle, 257 + const u64 ressource_handle, 258 + void *rblock, 259 + unsigned long *byte_count); 260 + 261 + #endif /* __HCP_IF_H__ */
+80
drivers/infiniband/hw/ehca/hcp_phyp.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * load store abstraction for ehca register access with tracing 5 + * 6 + * Authors: Christoph Raisch <raisch@de.ibm.com> 7 + * Hoang-Nam Nguyen <hnguyen@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_classes.h" 43 + #include "hipz_hw.h" 44 + 45 + int hcall_map_page(u64 physaddr, u64 *mapaddr) 46 + { 47 + *mapaddr = (u64)(ioremap(physaddr, EHCA_PAGESIZE)); 48 + return 0; 49 + } 50 + 51 + int hcall_unmap_page(u64 mapaddr) 52 + { 53 + iounmap((volatile void __iomem*)mapaddr); 54 + return 0; 55 + } 56 + 57 + int hcp_galpas_ctor(struct h_galpas *galpas, 58 + u64 paddr_kernel, u64 paddr_user) 59 + { 60 + int ret = hcall_map_page(paddr_kernel, &galpas->kernel.fw_handle); 61 + if (ret) 62 + return ret; 63 + 64 + galpas->user.fw_handle = paddr_user; 65 + 66 + return 0; 67 + } 68 + 69 + int hcp_galpas_dtor(struct h_galpas *galpas) 70 + { 71 + if (galpas->kernel.fw_handle) { 72 + int ret = hcall_unmap_page(galpas->kernel.fw_handle); 73 + if (ret) 74 + return ret; 75 + } 76 + 77 + galpas->user.fw_handle = galpas->kernel.fw_handle = 0; 78 + 79 + return 0; 80 + }
+90
drivers/infiniband/hw/ehca/hcp_phyp.h
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * Firmware calls 5 + * 6 + * Authors: Christoph Raisch <raisch@de.ibm.com> 7 + * Hoang-Nam Nguyen <hnguyen@de.ibm.com> 8 + * Waleri Fomin <fomin@de.ibm.com> 9 + * Gerd Bayer <gerd.bayer@de.ibm.com> 10 + * 11 + * Copyright (c) 2005 IBM Corporation 12 + * 13 + * All rights reserved. 14 + * 15 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 16 + * BSD. 17 + * 18 + * OpenIB BSD License 19 + * 20 + * Redistribution and use in source and binary forms, with or without 21 + * modification, are permitted provided that the following conditions are met: 22 + * 23 + * Redistributions of source code must retain the above copyright notice, this 24 + * list of conditions and the following disclaimer. 25 + * 26 + * Redistributions in binary form must reproduce the above copyright notice, 27 + * this list of conditions and the following disclaimer in the documentation 28 + * and/or other materials 29 + * provided with the distribution. 30 + * 31 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 32 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 35 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 36 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 38 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 39 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 + * POSSIBILITY OF SUCH DAMAGE. 42 + */ 43 + 44 + #ifndef __HCP_PHYP_H__ 45 + #define __HCP_PHYP_H__ 46 + 47 + 48 + /* 49 + * eHCA page (mapped into memory) 50 + * resource to access eHCA register pages in CPU address space 51 + */ 52 + struct h_galpa { 53 + u64 fw_handle; 54 + /* for pSeries this is a 64bit memory address where 55 + I/O memory is mapped into CPU address space (kv) */ 56 + }; 57 + 58 + /* 59 + * resource to access eHCA address space registers, all types 60 + */ 61 + struct h_galpas { 62 + u32 pid; /*PID of userspace galpa checking */ 63 + struct h_galpa user; /* user space accessible resource, 64 + set to 0 if unused */ 65 + struct h_galpa kernel; /* kernel space accessible resource, 66 + set to 0 if unused */ 67 + }; 68 + 69 + static inline u64 hipz_galpa_load(struct h_galpa galpa, u32 offset) 70 + { 71 + u64 addr = galpa.fw_handle + offset; 72 + return *(volatile u64 __force *)addr; 73 + } 74 + 75 + static inline void hipz_galpa_store(struct h_galpa galpa, u32 offset, u64 value) 76 + { 77 + u64 addr = galpa.fw_handle + offset; 78 + *(volatile u64 __force *)addr = value; 79 + } 80 + 81 + int hcp_galpas_ctor(struct h_galpas *galpas, 82 + u64 paddr_kernel, u64 paddr_user); 83 + 84 + int hcp_galpas_dtor(struct h_galpas *galpas); 85 + 86 + int hcall_map_page(u64 physaddr, u64 * mapaddr); 87 + 88 + int hcall_unmap_page(u64 mapaddr); 89 + 90 + #endif
+68
drivers/infiniband/hw/ehca/hipz_fns.h
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * HW abstraction register functions 5 + * 6 + * Authors: Christoph Raisch <raisch@de.ibm.com> 7 + * Reinhard Ernst <rernst@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 + #ifndef __HIPZ_FNS_H__ 43 + #define __HIPZ_FNS_H__ 44 + 45 + #include "ehca_classes.h" 46 + #include "hipz_hw.h" 47 + 48 + #include "hipz_fns_core.h" 49 + 50 + #define hipz_galpa_store_eq(gal, offset, value) \ 51 + hipz_galpa_store(gal, EQTEMM_OFFSET(offset), value) 52 + 53 + #define hipz_galpa_load_eq(gal, offset) \ 54 + hipz_galpa_load(gal, EQTEMM_OFFSET(offset)) 55 + 56 + #define hipz_galpa_store_qped(gal, offset, value) \ 57 + hipz_galpa_store(gal, QPEDMM_OFFSET(offset), value) 58 + 59 + #define hipz_galpa_load_qped(gal, offset) \ 60 + hipz_galpa_load(gal, QPEDMM_OFFSET(offset)) 61 + 62 + #define hipz_galpa_store_mrmw(gal, offset, value) \ 63 + hipz_galpa_store(gal, MRMWMM_OFFSET(offset), value) 64 + 65 + #define hipz_galpa_load_mrmw(gal, offset) \ 66 + hipz_galpa_load(gal, MRMWMM_OFFSET(offset)) 67 + 68 + #endif
+100
drivers/infiniband/hw/ehca/hipz_fns_core.h
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * HW abstraction register functions 5 + * 6 + * Authors: Christoph Raisch <raisch@de.ibm.com> 7 + * Heiko J Schick <schickhj@de.ibm.com> 8 + * Hoang-Nam Nguyen <hnguyen@de.ibm.com> 9 + * Reinhard Ernst <rernst@de.ibm.com> 10 + * 11 + * Copyright (c) 2005 IBM Corporation 12 + * 13 + * All rights reserved. 14 + * 15 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 16 + * BSD. 17 + * 18 + * OpenIB BSD License 19 + * 20 + * Redistribution and use in source and binary forms, with or without 21 + * modification, are permitted provided that the following conditions are met: 22 + * 23 + * Redistributions of source code must retain the above copyright notice, this 24 + * list of conditions and the following disclaimer. 25 + * 26 + * Redistributions in binary form must reproduce the above copyright notice, 27 + * this list of conditions and the following disclaimer in the documentation 28 + * and/or other materials 29 + * provided with the distribution. 30 + * 31 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 32 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 35 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 36 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 38 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 39 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 + * POSSIBILITY OF SUCH DAMAGE. 42 + */ 43 + 44 + #ifndef __HIPZ_FNS_CORE_H__ 45 + #define __HIPZ_FNS_CORE_H__ 46 + 47 + #include "hcp_phyp.h" 48 + #include "hipz_hw.h" 49 + 50 + #define hipz_galpa_store_cq(gal, offset, value) \ 51 + hipz_galpa_store(gal, CQTEMM_OFFSET(offset), value) 52 + 53 + #define hipz_galpa_load_cq(gal, offset) \ 54 + hipz_galpa_load(gal, CQTEMM_OFFSET(offset)) 55 + 56 + #define hipz_galpa_store_qp(gal,offset, value) \ 57 + hipz_galpa_store(gal, QPTEMM_OFFSET(offset), value) 58 + #define hipz_galpa_load_qp(gal, offset) \ 59 + hipz_galpa_load(gal,QPTEMM_OFFSET(offset)) 60 + 61 + static inline void hipz_update_sqa(struct ehca_qp *qp, u16 nr_wqes) 62 + { 63 + /* ringing doorbell :-) */ 64 + hipz_galpa_store_qp(qp->galpas.kernel, qpx_sqa, 65 + EHCA_BMASK_SET(QPX_SQADDER, nr_wqes)); 66 + } 67 + 68 + static inline void hipz_update_rqa(struct ehca_qp *qp, u16 nr_wqes) 69 + { 70 + /* ringing doorbell :-) */ 71 + hipz_galpa_store_qp(qp->galpas.kernel, qpx_rqa, 72 + EHCA_BMASK_SET(QPX_RQADDER, nr_wqes)); 73 + } 74 + 75 + static inline void hipz_update_feca(struct ehca_cq *cq, u32 nr_cqes) 76 + { 77 + hipz_galpa_store_cq(cq->galpas.kernel, cqx_feca, 78 + EHCA_BMASK_SET(CQX_FECADDER, nr_cqes)); 79 + } 80 + 81 + static inline void hipz_set_cqx_n0(struct ehca_cq *cq, u32 value) 82 + { 83 + u64 cqx_n0_reg; 84 + 85 + hipz_galpa_store_cq(cq->galpas.kernel, cqx_n0, 86 + EHCA_BMASK_SET(CQX_N0_GENERATE_SOLICITED_COMP_EVENT, 87 + value)); 88 + cqx_n0_reg = hipz_galpa_load_cq(cq->galpas.kernel, cqx_n0); 89 + } 90 + 91 + static inline void hipz_set_cqx_n1(struct ehca_cq *cq, u32 value) 92 + { 93 + u64 cqx_n1_reg; 94 + 95 + hipz_galpa_store_cq(cq->galpas.kernel, cqx_n1, 96 + EHCA_BMASK_SET(CQX_N1_GENERATE_COMP_EVENT, value)); 97 + cqx_n1_reg = hipz_galpa_load_cq(cq->galpas.kernel, cqx_n1); 98 + } 99 + 100 + #endif /* __HIPZ_FNC_CORE_H__ */
+388
drivers/infiniband/hw/ehca/hipz_hw.h
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * eHCA register definitions 5 + * 6 + * Authors: Waleri Fomin <fomin@de.ibm.com> 7 + * Christoph Raisch <raisch@de.ibm.com> 8 + * Reinhard Ernst <rernst@de.ibm.com> 9 + * 10 + * Copyright (c) 2005 IBM Corporation 11 + * 12 + * All rights reserved. 13 + * 14 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 15 + * BSD. 16 + * 17 + * OpenIB BSD License 18 + * 19 + * Redistribution and use in source and binary forms, with or without 20 + * modification, are permitted provided that the following conditions are met: 21 + * 22 + * Redistributions of source code must retain the above copyright notice, this 23 + * list of conditions and the following disclaimer. 24 + * 25 + * Redistributions in binary form must reproduce the above copyright notice, 26 + * this list of conditions and the following disclaimer in the documentation 27 + * and/or other materials 28 + * provided with the distribution. 29 + * 30 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 31 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 34 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 37 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 38 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 + * POSSIBILITY OF SUCH DAMAGE. 41 + */ 42 + 43 + #ifndef __HIPZ_HW_H__ 44 + #define __HIPZ_HW_H__ 45 + 46 + #include "ehca_tools.h" 47 + 48 + /* QP Table Entry Memory Map */ 49 + struct hipz_qptemm { 50 + u64 qpx_hcr; 51 + u64 qpx_c; 52 + u64 qpx_herr; 53 + u64 qpx_aer; 54 + /* 0x20*/ 55 + u64 qpx_sqa; 56 + u64 qpx_sqc; 57 + u64 qpx_rqa; 58 + u64 qpx_rqc; 59 + /* 0x40*/ 60 + u64 qpx_st; 61 + u64 qpx_pmstate; 62 + u64 qpx_pmfa; 63 + u64 qpx_pkey; 64 + /* 0x60*/ 65 + u64 qpx_pkeya; 66 + u64 qpx_pkeyb; 67 + u64 qpx_pkeyc; 68 + u64 qpx_pkeyd; 69 + /* 0x80*/ 70 + u64 qpx_qkey; 71 + u64 qpx_dqp; 72 + u64 qpx_dlidp; 73 + u64 qpx_portp; 74 + /* 0xa0*/ 75 + u64 qpx_slidp; 76 + u64 qpx_slidpp; 77 + u64 qpx_dlida; 78 + u64 qpx_porta; 79 + /* 0xc0*/ 80 + u64 qpx_slida; 81 + u64 qpx_slidpa; 82 + u64 qpx_slvl; 83 + u64 qpx_ipd; 84 + /* 0xe0*/ 85 + u64 qpx_mtu; 86 + u64 qpx_lato; 87 + u64 qpx_rlimit; 88 + u64 qpx_rnrlimit; 89 + /* 0x100*/ 90 + u64 qpx_t; 91 + u64 qpx_sqhp; 92 + u64 qpx_sqptp; 93 + u64 qpx_nspsn; 94 + /* 0x120*/ 95 + u64 qpx_nspsnhwm; 96 + u64 reserved1; 97 + u64 qpx_sdsi; 98 + u64 qpx_sdsbc; 99 + /* 0x140*/ 100 + u64 qpx_sqwsize; 101 + u64 qpx_sqwts; 102 + u64 qpx_lsn; 103 + u64 qpx_nssn; 104 + /* 0x160 */ 105 + u64 qpx_mor; 106 + u64 qpx_cor; 107 + u64 qpx_sqsize; 108 + u64 qpx_erc; 109 + /* 0x180*/ 110 + u64 qpx_rnrrc; 111 + u64 qpx_ernrwt; 112 + u64 qpx_rnrresp; 113 + u64 qpx_lmsna; 114 + /* 0x1a0 */ 115 + u64 qpx_sqhpc; 116 + u64 qpx_sqcptp; 117 + u64 qpx_sigt; 118 + u64 qpx_wqecnt; 119 + /* 0x1c0*/ 120 + u64 qpx_rqhp; 121 + u64 qpx_rqptp; 122 + u64 qpx_rqsize; 123 + u64 qpx_nrr; 124 + /* 0x1e0*/ 125 + u64 qpx_rdmac; 126 + u64 qpx_nrpsn; 127 + u64 qpx_lapsn; 128 + u64 qpx_lcr; 129 + /* 0x200*/ 130 + u64 qpx_rwc; 131 + u64 qpx_rwva; 132 + u64 qpx_rdsi; 133 + u64 qpx_rdsbc; 134 + /* 0x220*/ 135 + u64 qpx_rqwsize; 136 + u64 qpx_crmsn; 137 + u64 qpx_rdd; 138 + u64 qpx_larpsn; 139 + /* 0x240*/ 140 + u64 qpx_pd; 141 + u64 qpx_scqn; 142 + u64 qpx_rcqn; 143 + u64 qpx_aeqn; 144 + /* 0x260*/ 145 + u64 qpx_aaelog; 146 + u64 qpx_ram; 147 + u64 qpx_rdmaqe0; 148 + u64 qpx_rdmaqe1; 149 + /* 0x280*/ 150 + u64 qpx_rdmaqe2; 151 + u64 qpx_rdmaqe3; 152 + u64 qpx_nrpsnhwm; 153 + /* 0x298*/ 154 + u64 reserved[(0x400 - 0x298) / 8]; 155 + /* 0x400 extended data */ 156 + u64 reserved_ext[(0x500 - 0x400) / 8]; 157 + /* 0x500 */ 158 + u64 reserved2[(0x1000 - 0x500) / 8]; 159 + /* 0x1000 */ 160 + }; 161 + 162 + #define QPX_SQADDER EHCA_BMASK_IBM(48,63) 163 + #define QPX_RQADDER EHCA_BMASK_IBM(48,63) 164 + 165 + #define QPTEMM_OFFSET(x) offsetof(struct hipz_qptemm,x) 166 + 167 + /* MRMWPT Entry Memory Map */ 168 + struct hipz_mrmwmm { 169 + /* 0x00 */ 170 + u64 mrx_hcr; 171 + 172 + u64 mrx_c; 173 + u64 mrx_herr; 174 + u64 mrx_aer; 175 + /* 0x20 */ 176 + u64 mrx_pp; 177 + u64 reserved1; 178 + u64 reserved2; 179 + u64 reserved3; 180 + /* 0x40 */ 181 + u64 reserved4[(0x200 - 0x40) / 8]; 182 + /* 0x200 */ 183 + u64 mrx_ctl[64]; 184 + 185 + }; 186 + 187 + #define MRMWMM_OFFSET(x) offsetof(struct hipz_mrmwmm,x) 188 + 189 + struct hipz_qpedmm { 190 + /* 0x00 */ 191 + u64 reserved0[(0x400) / 8]; 192 + /* 0x400 */ 193 + u64 qpedx_phh; 194 + u64 qpedx_ppsgp; 195 + /* 0x410 */ 196 + u64 qpedx_ppsgu; 197 + u64 qpedx_ppdgp; 198 + /* 0x420 */ 199 + u64 qpedx_ppdgu; 200 + u64 qpedx_aph; 201 + /* 0x430 */ 202 + u64 qpedx_apsgp; 203 + u64 qpedx_apsgu; 204 + /* 0x440 */ 205 + u64 qpedx_apdgp; 206 + u64 qpedx_apdgu; 207 + /* 0x450 */ 208 + u64 qpedx_apav; 209 + u64 qpedx_apsav; 210 + /* 0x460 */ 211 + u64 qpedx_hcr; 212 + u64 reserved1[4]; 213 + /* 0x488 */ 214 + u64 qpedx_rrl0; 215 + /* 0x490 */ 216 + u64 qpedx_rrrkey0; 217 + u64 qpedx_rrva0; 218 + /* 0x4a0 */ 219 + u64 reserved2; 220 + u64 qpedx_rrl1; 221 + /* 0x4b0 */ 222 + u64 qpedx_rrrkey1; 223 + u64 qpedx_rrva1; 224 + /* 0x4c0 */ 225 + u64 reserved3; 226 + u64 qpedx_rrl2; 227 + /* 0x4d0 */ 228 + u64 qpedx_rrrkey2; 229 + u64 qpedx_rrva2; 230 + /* 0x4e0 */ 231 + u64 reserved4; 232 + u64 qpedx_rrl3; 233 + /* 0x4f0 */ 234 + u64 qpedx_rrrkey3; 235 + u64 qpedx_rrva3; 236 + }; 237 + 238 + #define QPEDMM_OFFSET(x) offsetof(struct hipz_qpedmm,x) 239 + 240 + /* CQ Table Entry Memory Map */ 241 + struct hipz_cqtemm { 242 + u64 cqx_hcr; 243 + u64 cqx_c; 244 + u64 cqx_herr; 245 + u64 cqx_aer; 246 + /* 0x20 */ 247 + u64 cqx_ptp; 248 + u64 cqx_tp; 249 + u64 cqx_fec; 250 + u64 cqx_feca; 251 + /* 0x40 */ 252 + u64 cqx_ep; 253 + u64 cqx_eq; 254 + /* 0x50 */ 255 + u64 reserved1; 256 + u64 cqx_n0; 257 + /* 0x60 */ 258 + u64 cqx_n1; 259 + u64 reserved2[(0x1000 - 0x60) / 8]; 260 + /* 0x1000 */ 261 + }; 262 + 263 + #define CQX_FEC_CQE_CNT EHCA_BMASK_IBM(32,63) 264 + #define CQX_FECADDER EHCA_BMASK_IBM(32,63) 265 + #define CQX_N0_GENERATE_SOLICITED_COMP_EVENT EHCA_BMASK_IBM(0,0) 266 + #define CQX_N1_GENERATE_COMP_EVENT EHCA_BMASK_IBM(0,0) 267 + 268 + #define CQTEMM_OFFSET(x) offsetof(struct hipz_cqtemm,x) 269 + 270 + /* EQ Table Entry Memory Map */ 271 + struct hipz_eqtemm { 272 + u64 eqx_hcr; 273 + u64 eqx_c; 274 + 275 + u64 eqx_herr; 276 + u64 eqx_aer; 277 + /* 0x20 */ 278 + u64 eqx_ptp; 279 + u64 eqx_tp; 280 + u64 eqx_ssba; 281 + u64 eqx_psba; 282 + 283 + /* 0x40 */ 284 + u64 eqx_cec; 285 + u64 eqx_meql; 286 + u64 eqx_xisbi; 287 + u64 eqx_xisc; 288 + /* 0x60 */ 289 + u64 eqx_it; 290 + 291 + }; 292 + 293 + #define EQTEMM_OFFSET(x) offsetof(struct hipz_eqtemm,x) 294 + 295 + /* access control defines for MR/MW */ 296 + #define HIPZ_ACCESSCTRL_L_WRITE 0x00800000 297 + #define HIPZ_ACCESSCTRL_R_WRITE 0x00400000 298 + #define HIPZ_ACCESSCTRL_R_READ 0x00200000 299 + #define HIPZ_ACCESSCTRL_R_ATOMIC 0x00100000 300 + #define HIPZ_ACCESSCTRL_MW_BIND 0x00080000 301 + 302 + /* query hca response block */ 303 + struct hipz_query_hca { 304 + u32 cur_reliable_dg; 305 + u32 cur_qp; 306 + u32 cur_cq; 307 + u32 cur_eq; 308 + u32 cur_mr; 309 + u32 cur_mw; 310 + u32 cur_ee_context; 311 + u32 cur_mcast_grp; 312 + u32 cur_qp_attached_mcast_grp; 313 + u32 reserved1; 314 + u32 cur_ipv6_qp; 315 + u32 cur_eth_qp; 316 + u32 cur_hp_mr; 317 + u32 reserved2[3]; 318 + u32 max_rd_domain; 319 + u32 max_qp; 320 + u32 max_cq; 321 + u32 max_eq; 322 + u32 max_mr; 323 + u32 max_hp_mr; 324 + u32 max_mw; 325 + u32 max_mrwpte; 326 + u32 max_special_mrwpte; 327 + u32 max_rd_ee_context; 328 + u32 max_mcast_grp; 329 + u32 max_total_mcast_qp_attach; 330 + u32 max_mcast_qp_attach; 331 + u32 max_raw_ipv6_qp; 332 + u32 max_raw_ethy_qp; 333 + u32 internal_clock_frequency; 334 + u32 max_pd; 335 + u32 max_ah; 336 + u32 max_cqe; 337 + u32 max_wqes_wq; 338 + u32 max_partitions; 339 + u32 max_rr_ee_context; 340 + u32 max_rr_qp; 341 + u32 max_rr_hca; 342 + u32 max_act_wqs_ee_context; 343 + u32 max_act_wqs_qp; 344 + u32 max_sge; 345 + u32 max_sge_rd; 346 + u32 memory_page_size_supported; 347 + u64 max_mr_size; 348 + u32 local_ca_ack_delay; 349 + u32 num_ports; 350 + u32 vendor_id; 351 + u32 vendor_part_id; 352 + u32 hw_ver; 353 + u64 node_guid; 354 + u64 hca_cap_indicators; 355 + u32 data_counter_register_size; 356 + u32 max_shared_rq; 357 + u32 max_isns_eq; 358 + u32 max_neq; 359 + } __attribute__ ((packed)); 360 + 361 + /* query port response block */ 362 + struct hipz_query_port { 363 + u32 state; 364 + u32 bad_pkey_cntr; 365 + u32 lmc; 366 + u32 lid; 367 + u32 subnet_timeout; 368 + u32 qkey_viol_cntr; 369 + u32 sm_sl; 370 + u32 sm_lid; 371 + u32 capability_mask; 372 + u32 init_type_reply; 373 + u32 pkey_tbl_len; 374 + u32 gid_tbl_len; 375 + u64 gid_prefix; 376 + u32 port_nr; 377 + u16 pkey_entries[16]; 378 + u8 reserved1[32]; 379 + u32 trent_size; 380 + u32 trbuf_size; 381 + u64 max_msg_sz; 382 + u32 max_mtu; 383 + u32 vl_cap; 384 + u8 reserved2[1900]; 385 + u64 guid_entries[255]; 386 + } __attribute__ ((packed)); 387 + 388 + #endif
+149
drivers/infiniband/hw/ehca/ipz_pt_fn.c
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * internal queue handling 5 + * 6 + * Authors: Waleri Fomin <fomin@de.ibm.com> 7 + * Reinhard Ernst <rernst@de.ibm.com> 8 + * Christoph Raisch <raisch@de.ibm.com> 9 + * 10 + * Copyright (c) 2005 IBM Corporation 11 + * 12 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 13 + * BSD. 14 + * 15 + * OpenIB BSD License 16 + * 17 + * Redistribution and use in source and binary forms, with or without 18 + * modification, are permitted provided that the following conditions are met: 19 + * 20 + * Redistributions of source code must retain the above copyright notice, this 21 + * list of conditions and the following disclaimer. 22 + * 23 + * Redistributions in binary form must reproduce the above copyright notice, 24 + * this list of conditions and the following disclaimer in the documentation 25 + * and/or other materials 26 + * provided with the distribution. 27 + * 28 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 32 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 36 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 + * POSSIBILITY OF SUCH DAMAGE. 39 + */ 40 + 41 + #include "ehca_tools.h" 42 + #include "ipz_pt_fn.h" 43 + 44 + void *ipz_qpageit_get_inc(struct ipz_queue *queue) 45 + { 46 + void *ret = ipz_qeit_get(queue); 47 + queue->current_q_offset += queue->pagesize; 48 + if (queue->current_q_offset > queue->queue_length) { 49 + queue->current_q_offset -= queue->pagesize; 50 + ret = NULL; 51 + } 52 + if (((u64)ret) % EHCA_PAGESIZE) { 53 + ehca_gen_err("ERROR!! not at PAGE-Boundary"); 54 + return NULL; 55 + } 56 + return ret; 57 + } 58 + 59 + void *ipz_qeit_eq_get_inc(struct ipz_queue *queue) 60 + { 61 + void *ret = ipz_qeit_get(queue); 62 + u64 last_entry_in_q = queue->queue_length - queue->qe_size; 63 + 64 + queue->current_q_offset += queue->qe_size; 65 + if (queue->current_q_offset > last_entry_in_q) { 66 + queue->current_q_offset = 0; 67 + queue->toggle_state = (~queue->toggle_state) & 1; 68 + } 69 + 70 + return ret; 71 + } 72 + 73 + int ipz_queue_ctor(struct ipz_queue *queue, 74 + const u32 nr_of_pages, 75 + const u32 pagesize, const u32 qe_size, const u32 nr_of_sg) 76 + { 77 + int pages_per_kpage = PAGE_SIZE >> EHCA_PAGESHIFT; 78 + int f; 79 + 80 + if (pagesize > PAGE_SIZE) { 81 + ehca_gen_err("FATAL ERROR: pagesize=%x is greater " 82 + "than kernel page size", pagesize); 83 + return 0; 84 + } 85 + if (!pages_per_kpage) { 86 + ehca_gen_err("FATAL ERROR: invalid kernel page size. " 87 + "pages_per_kpage=%x", pages_per_kpage); 88 + return 0; 89 + } 90 + queue->queue_length = nr_of_pages * pagesize; 91 + queue->queue_pages = vmalloc(nr_of_pages * sizeof(void *)); 92 + if (!queue->queue_pages) { 93 + ehca_gen_err("ERROR!! didn't get the memory"); 94 + return 0; 95 + } 96 + memset(queue->queue_pages, 0, nr_of_pages * sizeof(void *)); 97 + /* 98 + * allocate pages for queue: 99 + * outer loop allocates whole kernel pages (page aligned) and 100 + * inner loop divides a kernel page into smaller hca queue pages 101 + */ 102 + f = 0; 103 + while (f < nr_of_pages) { 104 + u8 *kpage = (u8*)get_zeroed_page(GFP_KERNEL); 105 + int k; 106 + if (!kpage) 107 + goto ipz_queue_ctor_exit0; /*NOMEM*/ 108 + for (k = 0; k < pages_per_kpage && f < nr_of_pages; k++) { 109 + (queue->queue_pages)[f] = (struct ipz_page *)kpage; 110 + kpage += EHCA_PAGESIZE; 111 + f++; 112 + } 113 + } 114 + 115 + queue->current_q_offset = 0; 116 + queue->qe_size = qe_size; 117 + queue->act_nr_of_sg = nr_of_sg; 118 + queue->pagesize = pagesize; 119 + queue->toggle_state = 1; 120 + return 1; 121 + 122 + ipz_queue_ctor_exit0: 123 + ehca_gen_err("Couldn't get alloc pages queue=%p f=%x nr_of_pages=%x", 124 + queue, f, nr_of_pages); 125 + for (f = 0; f < nr_of_pages; f += pages_per_kpage) { 126 + if (!(queue->queue_pages)[f]) 127 + break; 128 + free_page((unsigned long)(queue->queue_pages)[f]); 129 + } 130 + return 0; 131 + } 132 + 133 + int ipz_queue_dtor(struct ipz_queue *queue) 134 + { 135 + int pages_per_kpage = PAGE_SIZE >> EHCA_PAGESHIFT; 136 + int g; 137 + int nr_pages; 138 + 139 + if (!queue || !queue->queue_pages) { 140 + ehca_gen_dbg("queue or queue_pages is NULL"); 141 + return 0; 142 + } 143 + nr_pages = queue->queue_length / queue->pagesize; 144 + for (g = 0; g < nr_pages; g += pages_per_kpage) 145 + free_page((unsigned long)(queue->queue_pages)[g]); 146 + vfree(queue->queue_pages); 147 + 148 + return 1; 149 + }
+247
drivers/infiniband/hw/ehca/ipz_pt_fn.h
··· 1 + /* 2 + * IBM eServer eHCA Infiniband device driver for Linux on POWER 3 + * 4 + * internal queue handling 5 + * 6 + * Authors: Waleri Fomin <fomin@de.ibm.com> 7 + * Reinhard Ernst <rernst@de.ibm.com> 8 + * Christoph Raisch <raisch@de.ibm.com> 9 + * 10 + * Copyright (c) 2005 IBM Corporation 11 + * 12 + * All rights reserved. 13 + * 14 + * This source code is distributed under a dual license of GPL v2.0 and OpenIB 15 + * BSD. 16 + * 17 + * OpenIB BSD License 18 + * 19 + * Redistribution and use in source and binary forms, with or without 20 + * modification, are permitted provided that the following conditions are met: 21 + * 22 + * Redistributions of source code must retain the above copyright notice, this 23 + * list of conditions and the following disclaimer. 24 + * 25 + * Redistributions in binary form must reproduce the above copyright notice, 26 + * this list of conditions and the following disclaimer in the documentation 27 + * and/or other materials 28 + * provided with the distribution. 29 + * 30 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 31 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 34 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 37 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 38 + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 + * POSSIBILITY OF SUCH DAMAGE. 41 + */ 42 + 43 + #ifndef __IPZ_PT_FN_H__ 44 + #define __IPZ_PT_FN_H__ 45 + 46 + #define EHCA_PAGESHIFT 12 47 + #define EHCA_PAGESIZE 4096UL 48 + #define EHCA_PAGEMASK (~(EHCA_PAGESIZE-1)) 49 + #define EHCA_PT_ENTRIES 512UL 50 + 51 + #include "ehca_tools.h" 52 + #include "ehca_qes.h" 53 + 54 + /* struct generic ehca page */ 55 + struct ipz_page { 56 + u8 entries[EHCA_PAGESIZE]; 57 + }; 58 + 59 + /* struct generic queue in linux kernel virtual memory (kv) */ 60 + struct ipz_queue { 61 + u64 current_q_offset; /* current queue entry */ 62 + 63 + struct ipz_page **queue_pages; /* array of pages belonging to queue */ 64 + u32 qe_size; /* queue entry size */ 65 + u32 act_nr_of_sg; 66 + u32 queue_length; /* queue length allocated in bytes */ 67 + u32 pagesize; 68 + u32 toggle_state; /* toggle flag - per page */ 69 + u32 dummy3; /* 64 bit alignment */ 70 + }; 71 + 72 + /* 73 + * return current Queue Entry for a certain q_offset 74 + * returns address (kv) of Queue Entry 75 + */ 76 + static inline void *ipz_qeit_calc(struct ipz_queue *queue, u64 q_offset) 77 + { 78 + struct ipz_page *current_page; 79 + if (q_offset >= queue->queue_length) 80 + return NULL; 81 + current_page = (queue->queue_pages)[q_offset >> EHCA_PAGESHIFT]; 82 + return &current_page->entries[q_offset & (EHCA_PAGESIZE - 1)]; 83 + } 84 + 85 + /* 86 + * return current Queue Entry 87 + * returns address (kv) of Queue Entry 88 + */ 89 + static inline void *ipz_qeit_get(struct ipz_queue *queue) 90 + { 91 + return ipz_qeit_calc(queue, queue->current_q_offset); 92 + } 93 + 94 + /* 95 + * return current Queue Page , increment Queue Page iterator from 96 + * page to page in struct ipz_queue, last increment will return 0! and 97 + * NOT wrap 98 + * returns address (kv) of Queue Page 99 + * warning don't use in parallel with ipz_QE_get_inc() 100 + */ 101 + void *ipz_qpageit_get_inc(struct ipz_queue *queue); 102 + 103 + /* 104 + * return current Queue Entry, increment Queue Entry iterator by one 105 + * step in struct ipz_queue, will wrap in ringbuffer 106 + * returns address (kv) of Queue Entry BEFORE increment 107 + * warning don't use in parallel with ipz_qpageit_get_inc() 108 + * warning unpredictable results may occur if steps>act_nr_of_queue_entries 109 + */ 110 + static inline void *ipz_qeit_get_inc(struct ipz_queue *queue) 111 + { 112 + void *ret = ipz_qeit_get(queue); 113 + queue->current_q_offset += queue->qe_size; 114 + if (queue->current_q_offset >= queue->queue_length) { 115 + queue->current_q_offset = 0; 116 + /* toggle the valid flag */ 117 + queue->toggle_state = (~queue->toggle_state) & 1; 118 + } 119 + 120 + return ret; 121 + } 122 + 123 + /* 124 + * return current Queue Entry, increment Queue Entry iterator by one 125 + * step in struct ipz_queue, will wrap in ringbuffer 126 + * returns address (kv) of Queue Entry BEFORE increment 127 + * returns 0 and does not increment, if wrong valid state 128 + * warning don't use in parallel with ipz_qpageit_get_inc() 129 + * warning unpredictable results may occur if steps>act_nr_of_queue_entries 130 + */ 131 + static inline void *ipz_qeit_get_inc_valid(struct ipz_queue *queue) 132 + { 133 + struct ehca_cqe *cqe = ipz_qeit_get(queue); 134 + u32 cqe_flags = cqe->cqe_flags; 135 + 136 + if ((cqe_flags >> 7) != (queue->toggle_state & 1)) 137 + return NULL; 138 + 139 + ipz_qeit_get_inc(queue); 140 + return cqe; 141 + } 142 + 143 + /* 144 + * returns and resets Queue Entry iterator 145 + * returns address (kv) of first Queue Entry 146 + */ 147 + static inline void *ipz_qeit_reset(struct ipz_queue *queue) 148 + { 149 + queue->current_q_offset = 0; 150 + return ipz_qeit_get(queue); 151 + } 152 + 153 + /* struct generic page table */ 154 + struct ipz_pt { 155 + u64 entries[EHCA_PT_ENTRIES]; 156 + }; 157 + 158 + /* struct page table for a queue, only to be used in pf */ 159 + struct ipz_qpt { 160 + /* queue page tables (kv), use u64 because we know the element length */ 161 + u64 *qpts; 162 + u32 n_qpts; 163 + u32 n_ptes; /* number of page table entries */ 164 + u64 *current_pte_addr; 165 + }; 166 + 167 + /* 168 + * constructor for a ipz_queue_t, placement new for ipz_queue_t, 169 + * new for all dependent datastructors 170 + * all QP Tables are the same 171 + * flow: 172 + * allocate+pin queue 173 + * see ipz_qpt_ctor() 174 + * returns true if ok, false if out of memory 175 + */ 176 + int ipz_queue_ctor(struct ipz_queue *queue, const u32 nr_of_pages, 177 + const u32 pagesize, const u32 qe_size, 178 + const u32 nr_of_sg); 179 + 180 + /* 181 + * destructor for a ipz_queue_t 182 + * -# free queue 183 + * see ipz_queue_ctor() 184 + * returns true if ok, false if queue was NULL-ptr of free failed 185 + */ 186 + int ipz_queue_dtor(struct ipz_queue *queue); 187 + 188 + /* 189 + * constructor for a ipz_qpt_t, 190 + * placement new for struct ipz_queue, new for all dependent datastructors 191 + * all QP Tables are the same, 192 + * flow: 193 + * -# allocate+pin queue 194 + * -# initialise ptcb 195 + * -# allocate+pin PTs 196 + * -# link PTs to a ring, according to HCA Arch, set bit62 id needed 197 + * -# the ring must have room for exactly nr_of_PTEs 198 + * see ipz_qpt_ctor() 199 + */ 200 + void ipz_qpt_ctor(struct ipz_qpt *qpt, 201 + const u32 nr_of_qes, 202 + const u32 pagesize, 203 + const u32 qe_size, 204 + const u8 lowbyte, const u8 toggle, 205 + u32 * act_nr_of_QEs, u32 * act_nr_of_pages); 206 + 207 + /* 208 + * return current Queue Entry, increment Queue Entry iterator by one 209 + * step in struct ipz_queue, will wrap in ringbuffer 210 + * returns address (kv) of Queue Entry BEFORE increment 211 + * warning don't use in parallel with ipz_qpageit_get_inc() 212 + * warning unpredictable results may occur if steps>act_nr_of_queue_entries 213 + * fix EQ page problems 214 + */ 215 + void *ipz_qeit_eq_get_inc(struct ipz_queue *queue); 216 + 217 + /* 218 + * return current Event Queue Entry, increment Queue Entry iterator 219 + * by one step in struct ipz_queue if valid, will wrap in ringbuffer 220 + * returns address (kv) of Queue Entry BEFORE increment 221 + * returns 0 and does not increment, if wrong valid state 222 + * warning don't use in parallel with ipz_queue_QPageit_get_inc() 223 + * warning unpredictable results may occur if steps>act_nr_of_queue_entries 224 + */ 225 + static inline void *ipz_eqit_eq_get_inc_valid(struct ipz_queue *queue) 226 + { 227 + void *ret = ipz_qeit_get(queue); 228 + u32 qe = *(u8 *) ret; 229 + if ((qe >> 7) != (queue->toggle_state & 1)) 230 + return NULL; 231 + ipz_qeit_eq_get_inc(queue); /* this is a good one */ 232 + return ret; 233 + } 234 + 235 + /* returns address (GX) of first queue entry */ 236 + static inline u64 ipz_qpt_get_firstpage(struct ipz_qpt *qpt) 237 + { 238 + return be64_to_cpu(qpt->qpts[0]); 239 + } 240 + 241 + /* returns address (kv) of first page of queue page table */ 242 + static inline void *ipz_qpt_get_qpt(struct ipz_qpt *qpt) 243 + { 244 + return qpt->qpts; 245 + } 246 + 247 + #endif /* __IPZ_PT_FN_H__ */