aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h6
-rw-r--r--drivers/infiniband/hw/ehca/ehca_hca.c34
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.c89
-rw-r--r--drivers/infiniband/hw/ehca/ehca_iverbs.h3
4 files changed, 101 insertions, 31 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index f1e0db2ff16c..daf823ea1ace 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -87,11 +87,17 @@ struct ehca_eq {
87 struct ehca_eqe_cache_entry eqe_cache[EHCA_EQE_CACHE_SIZE]; 87 struct ehca_eqe_cache_entry eqe_cache[EHCA_EQE_CACHE_SIZE];
88}; 88};
89 89
90struct ehca_sma_attr {
91 u16 lid, lmc, sm_sl, sm_lid;
92 u16 pkey_tbl_len, pkeys[16];
93};
94
90struct ehca_sport { 95struct ehca_sport {
91 struct ib_cq *ibcq_aqp1; 96 struct ib_cq *ibcq_aqp1;
92 struct ib_qp *ibqp_aqp1; 97 struct ib_qp *ibqp_aqp1;
93 enum ib_rate rate; 98 enum ib_rate rate;
94 enum ib_port_state port_state; 99 enum ib_port_state port_state;
100 struct ehca_sma_attr saved_attr;
95}; 101};
96 102
97struct ehca_shca { 103struct ehca_shca {
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index b310de5c94ae..bbd3c6a5822f 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -193,6 +193,40 @@ query_port1:
193 return ret; 193 return ret;
194} 194}
195 195
196int ehca_query_sma_attr(struct ehca_shca *shca,
197 u8 port, struct ehca_sma_attr *attr)
198{
199 int ret = 0;
200 struct hipz_query_port *rblock;
201
202 rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
203 if (!rblock) {
204 ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
205 return -ENOMEM;
206 }
207
208 if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
209 ehca_err(&shca->ib_device, "Can't query port properties");
210 ret = -EINVAL;
211 goto query_sma_attr1;
212 }
213
214 memset(attr, 0, sizeof(struct ehca_sma_attr));
215
216 attr->lid = rblock->lid;
217 attr->lmc = rblock->lmc;
218 attr->sm_sl = rblock->sm_sl;
219 attr->sm_lid = rblock->sm_lid;
220
221 attr->pkey_tbl_len = rblock->pkey_tbl_len;
222 memcpy(attr->pkeys, rblock->pkey_entries, sizeof(attr->pkeys));
223
224query_sma_attr1:
225 ehca_free_fw_ctrlblock(rblock);
226
227 return ret;
228}
229
196int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) 230int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
197{ 231{
198 int ret = 0; 232 int ret = 0;
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 02b73c84c49b..96eba3830754 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -61,6 +61,7 @@
61#define NEQE_EVENT_CODE EHCA_BMASK_IBM(2,7) 61#define NEQE_EVENT_CODE EHCA_BMASK_IBM(2,7)
62#define NEQE_PORT_NUMBER EHCA_BMASK_IBM(8,15) 62#define NEQE_PORT_NUMBER EHCA_BMASK_IBM(8,15)
63#define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16,16) 63#define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16,16)
64#define NEQE_DISRUPTIVE EHCA_BMASK_IBM(16,16)
64 65
65#define ERROR_DATA_LENGTH EHCA_BMASK_IBM(52,63) 66#define ERROR_DATA_LENGTH EHCA_BMASK_IBM(52,63)
66#define ERROR_DATA_TYPE EHCA_BMASK_IBM(0,7) 67#define ERROR_DATA_TYPE EHCA_BMASK_IBM(0,7)
@@ -286,30 +287,61 @@ static void parse_identifier(struct ehca_shca *shca, u64 eqe)
286 return; 287 return;
287} 288}
288 289
289static void parse_ec(struct ehca_shca *shca, u64 eqe) 290static void dispatch_port_event(struct ehca_shca *shca, int port_num,
291 enum ib_event_type type, const char *msg)
290{ 292{
291 struct ib_event event; 293 struct ib_event event;
294
295 ehca_info(&shca->ib_device, "port %d %s.", port_num, msg);
296 event.device = &shca->ib_device;
297 event.event = type;
298 event.element.port_num = port_num;
299 ib_dispatch_event(&event);
300}
301
302static void notify_port_conf_change(struct ehca_shca *shca, int port_num)
303{
304 struct ehca_sma_attr new_attr;
305 struct ehca_sma_attr *old_attr = &shca->sport[port_num - 1].saved_attr;
306
307 ehca_query_sma_attr(shca, port_num, &new_attr);
308
309 if (new_attr.sm_sl != old_attr->sm_sl ||
310 new_attr.sm_lid != old_attr->sm_lid)
311 dispatch_port_event(shca, port_num, IB_EVENT_SM_CHANGE,
312 "SM changed");
313
314 if (new_attr.lid != old_attr->lid ||
315 new_attr.lmc != old_attr->lmc)
316 dispatch_port_event(shca, port_num, IB_EVENT_LID_CHANGE,
317 "LID changed");
318
319 if (new_attr.pkey_tbl_len != old_attr->pkey_tbl_len ||
320 memcmp(new_attr.pkeys, old_attr->pkeys,
321 sizeof(u16) * new_attr.pkey_tbl_len))
322 dispatch_port_event(shca, port_num, IB_EVENT_PKEY_CHANGE,
323 "P_Key changed");
324
325 *old_attr = new_attr;
326}
327
328static void parse_ec(struct ehca_shca *shca, u64 eqe)
329{
292 u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); 330 u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
293 u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); 331 u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
294 332
295 switch (ec) { 333 switch (ec) {
296 case 0x30: /* port availability change */ 334 case 0x30: /* port availability change */
297 if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { 335 if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
298 ehca_info(&shca->ib_device,
299 "port %x is active.", port);
300 event.device = &shca->ib_device;
301 event.event = IB_EVENT_PORT_ACTIVE;
302 event.element.port_num = port;
303 shca->sport[port - 1].port_state = IB_PORT_ACTIVE; 336 shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
304 ib_dispatch_event(&event); 337 dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
338 "is active");
339 ehca_query_sma_attr(shca, port,
340 &shca->sport[port - 1].saved_attr);
305 } else { 341 } else {
306 ehca_info(&shca->ib_device,
307 "port %x is inactive.", port);
308 event.device = &shca->ib_device;
309 event.event = IB_EVENT_PORT_ERR;
310 event.element.port_num = port;
311 shca->sport[port - 1].port_state = IB_PORT_DOWN; 342 shca->sport[port - 1].port_state = IB_PORT_DOWN;
312 ib_dispatch_event(&event); 343 dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
344 "is inactive");
313 } 345 }
314 break; 346 break;
315 case 0x31: 347 case 0x31:
@@ -317,24 +349,19 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
317 * disruptive change is caused by 349 * disruptive change is caused by
318 * LID, PKEY or SM change 350 * LID, PKEY or SM change
319 */ 351 */
320 ehca_warn(&shca->ib_device, 352 if (EHCA_BMASK_GET(NEQE_DISRUPTIVE, eqe)) {
321 "disruptive port %x configuration change", port); 353 ehca_warn(&shca->ib_device, "disruptive port "
322 354 "%d configuration change", port);
323 ehca_info(&shca->ib_device, 355
324 "port %x is inactive.", port); 356 shca->sport[port - 1].port_state = IB_PORT_DOWN;
325 event.device = &shca->ib_device; 357 dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
326 event.event = IB_EVENT_PORT_ERR; 358 "is inactive");
327 event.element.port_num = port; 359
328 shca->sport[port - 1].port_state = IB_PORT_DOWN; 360 shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
329 ib_dispatch_event(&event); 361 dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
330 362 "is active");
331 ehca_info(&shca->ib_device, 363 } else
332 "port %x is active.", port); 364 notify_port_conf_change(shca, port);
333 event.device = &shca->ib_device;
334 event.event = IB_EVENT_PORT_ACTIVE;
335 event.element.port_num = port;
336 shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
337 ib_dispatch_event(&event);
338 break; 365 break;
339 case 0x32: /* adapter malfunction */ 366 case 0x32: /* adapter malfunction */
340 ehca_err(&shca->ib_device, "Adapter malfunction."); 367 ehca_err(&shca->ib_device, "Adapter malfunction.");
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index fd84a804814c..77aeca6a2c2f 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -49,6 +49,9 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props);
49int ehca_query_port(struct ib_device *ibdev, u8 port, 49int ehca_query_port(struct ib_device *ibdev, u8 port,
50 struct ib_port_attr *props); 50 struct ib_port_attr *props);
51 51
52int ehca_query_sma_attr(struct ehca_shca *shca, u8 port,
53 struct ehca_sma_attr *attr);
54
52int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 * pkey); 55int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 * pkey);
53 56
54int ehca_query_gid(struct ib_device *ibdev, u8 port, int index, 57int ehca_query_gid(struct ib_device *ibdev, u8 port, int index,