]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/infiniband/hw/ehca/ehca_hca.c
IB/ehca: Implement modify_port
[linux-2.6-omap-h63xx.git] / 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 "ehca_iverbs.h"
44 #include "hcp_if.h"
45
46 int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
47 {
48         int ret = 0;
49         struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
50                                               ib_device);
51         struct hipz_query_hca *rblock;
52
53         rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
54         if (!rblock) {
55                 ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
56                 return -ENOMEM;
57         }
58
59         if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) {
60                 ehca_err(&shca->ib_device, "Can't query device properties");
61                 ret = -EINVAL;
62                 goto query_device1;
63         }
64
65         memset(props, 0, sizeof(struct ib_device_attr));
66         props->fw_ver          = rblock->hw_ver;
67         props->max_mr_size     = rblock->max_mr_size;
68         props->vendor_id       = rblock->vendor_id >> 8;
69         props->vendor_part_id  = rblock->vendor_part_id >> 16;
70         props->hw_ver          = rblock->hw_ver;
71         props->max_qp          = min_t(int, rblock->max_qp, INT_MAX);
72         props->max_qp_wr       = min_t(int, rblock->max_wqes_wq, INT_MAX);
73         props->max_sge         = min_t(int, rblock->max_sge, INT_MAX);
74         props->max_sge_rd      = min_t(int, rblock->max_sge_rd, INT_MAX);
75         props->max_cq          = min_t(int, rblock->max_cq, INT_MAX);
76         props->max_cqe         = min_t(int, rblock->max_cqe, INT_MAX);
77         props->max_mr          = min_t(int, rblock->max_mr, INT_MAX);
78         props->max_mw          = min_t(int, rblock->max_mw, INT_MAX);
79         props->max_pd          = min_t(int, rblock->max_pd, INT_MAX);
80         props->max_ah          = min_t(int, rblock->max_ah, INT_MAX);
81         props->max_fmr         = min_t(int, rblock->max_mr, INT_MAX);
82         props->max_srq         = 0;
83         props->max_srq_wr      = 0;
84         props->max_srq_sge     = 0;
85         props->max_pkeys       = 16;
86         props->local_ca_ack_delay
87                 = rblock->local_ca_ack_delay;
88         props->max_raw_ipv6_qp
89                 = min_t(int, rblock->max_raw_ipv6_qp, INT_MAX);
90         props->max_raw_ethy_qp
91                 = min_t(int, rblock->max_raw_ethy_qp, INT_MAX);
92         props->max_mcast_grp
93                 = min_t(int, rblock->max_mcast_grp, INT_MAX);
94         props->max_mcast_qp_attach
95                 = min_t(int, rblock->max_mcast_qp_attach, INT_MAX);
96         props->max_total_mcast_qp_attach
97                 = min_t(int, rblock->max_total_mcast_qp_attach, INT_MAX);
98
99 query_device1:
100         ehca_free_fw_ctrlblock(rblock);
101
102         return ret;
103 }
104
105 int ehca_query_port(struct ib_device *ibdev,
106                     u8 port, struct ib_port_attr *props)
107 {
108         int ret = 0;
109         struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
110                                               ib_device);
111         struct hipz_query_port *rblock;
112
113         rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
114         if (!rblock) {
115                 ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
116                 return -ENOMEM;
117         }
118
119         if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
120                 ehca_err(&shca->ib_device, "Can't query port properties");
121                 ret = -EINVAL;
122                 goto query_port1;
123         }
124
125         memset(props, 0, sizeof(struct ib_port_attr));
126         props->state = rblock->state;
127
128         switch (rblock->max_mtu) {
129         case 0x1:
130                 props->active_mtu = props->max_mtu = IB_MTU_256;
131                 break;
132         case 0x2:
133                 props->active_mtu = props->max_mtu = IB_MTU_512;
134                 break;
135         case 0x3:
136                 props->active_mtu = props->max_mtu = IB_MTU_1024;
137                 break;
138         case 0x4:
139                 props->active_mtu = props->max_mtu = IB_MTU_2048;
140                 break;
141         case 0x5:
142                 props->active_mtu = props->max_mtu = IB_MTU_4096;
143                 break;
144         default:
145                 ehca_err(&shca->ib_device, "Unknown MTU size: %x.",
146                          rblock->max_mtu);
147                 break;
148         }
149
150         props->port_cap_flags  = rblock->capability_mask;
151         props->gid_tbl_len     = rblock->gid_tbl_len;
152         props->max_msg_sz      = rblock->max_msg_sz;
153         props->bad_pkey_cntr   = rblock->bad_pkey_cntr;
154         props->qkey_viol_cntr  = rblock->qkey_viol_cntr;
155         props->pkey_tbl_len    = rblock->pkey_tbl_len;
156         props->lid             = rblock->lid;
157         props->sm_lid          = rblock->sm_lid;
158         props->lmc             = rblock->lmc;
159         props->sm_sl           = rblock->sm_sl;
160         props->subnet_timeout  = rblock->subnet_timeout;
161         props->init_type_reply = rblock->init_type_reply;
162
163         props->active_width    = IB_WIDTH_12X;
164         props->active_speed    = 0x1;
165
166         /* at the moment (logical) link state is always LINK_UP */
167         props->phys_state      = 0x5;
168
169 query_port1:
170         ehca_free_fw_ctrlblock(rblock);
171
172         return ret;
173 }
174
175 int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
176 {
177         int ret = 0;
178         struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, ib_device);
179         struct hipz_query_port *rblock;
180
181         if (index > 16) {
182                 ehca_err(&shca->ib_device, "Invalid index: %x.", index);
183                 return -EINVAL;
184         }
185
186         rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
187         if (!rblock) {
188                 ehca_err(&shca->ib_device,  "Can't allocate rblock memory.");
189                 return -ENOMEM;
190         }
191
192         if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
193                 ehca_err(&shca->ib_device, "Can't query port properties");
194                 ret = -EINVAL;
195                 goto query_pkey1;
196         }
197
198         memcpy(pkey, &rblock->pkey_entries + index, sizeof(u16));
199
200 query_pkey1:
201         ehca_free_fw_ctrlblock(rblock);
202
203         return ret;
204 }
205
206 int ehca_query_gid(struct ib_device *ibdev, u8 port,
207                    int index, union ib_gid *gid)
208 {
209         int ret = 0;
210         struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
211                                               ib_device);
212         struct hipz_query_port *rblock;
213
214         if (index > 255) {
215                 ehca_err(&shca->ib_device, "Invalid index: %x.", index);
216                 return -EINVAL;
217         }
218
219         rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
220         if (!rblock) {
221                 ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
222                 return -ENOMEM;
223         }
224
225         if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
226                 ehca_err(&shca->ib_device, "Can't query port properties");
227                 ret = -EINVAL;
228                 goto query_gid1;
229         }
230
231         memcpy(&gid->raw[0], &rblock->gid_prefix, sizeof(u64));
232         memcpy(&gid->raw[8], &rblock->guid_entries[index], sizeof(u64));
233
234 query_gid1:
235         ehca_free_fw_ctrlblock(rblock);
236
237         return ret;
238 }
239
240 const u32 allowed_port_caps = (
241         IB_PORT_SM | IB_PORT_LED_INFO_SUP | IB_PORT_CM_SUP |
242         IB_PORT_SNMP_TUNNEL_SUP | IB_PORT_DEVICE_MGMT_SUP |
243         IB_PORT_VENDOR_CLASS_SUP);
244
245 int ehca_modify_port(struct ib_device *ibdev,
246                      u8 port, int port_modify_mask,
247                      struct ib_port_modify *props)
248 {
249         int ret = 0;
250         struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, ib_device);
251         struct hipz_query_port *rblock;
252         u32 cap;
253         u64 hret;
254
255         if ((props->set_port_cap_mask | props->clr_port_cap_mask)
256             & ~allowed_port_caps) {
257                 ehca_err(&shca->ib_device, "Non-changeable bits set in masks  "
258                          "set=%x  clr=%x  allowed=%x", props->set_port_cap_mask,
259                          props->clr_port_cap_mask, allowed_port_caps);
260                 return -EINVAL;
261         }
262
263         if (mutex_lock_interruptible(&shca->modify_mutex))
264                 return -ERESTARTSYS;
265
266         rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
267         if (!rblock) {
268                 ehca_err(&shca->ib_device,  "Can't allocate rblock memory.");
269                 ret = -ENOMEM;
270                 goto modify_port1;
271         }
272
273         if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
274                 ehca_err(&shca->ib_device, "Can't query port properties");
275                 ret = -EINVAL;
276                 goto modify_port2;
277         }
278
279         cap = (rblock->capability_mask | props->set_port_cap_mask)
280                 & ~props->clr_port_cap_mask;
281
282         hret = hipz_h_modify_port(shca->ipz_hca_handle, port,
283                                   cap, props->init_type, port_modify_mask);
284         if (hret != H_SUCCESS) {
285                 ehca_err(&shca->ib_device, "Modify port failed  hret=%lx", hret);
286                 ret = -EINVAL;
287         }
288
289 modify_port2:
290         ehca_free_fw_ctrlblock(rblock);
291
292 modify_port1:
293         mutex_unlock(&shca->modify_mutex);
294
295         return ret;
296 }