diff options
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_classes.h | 16 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_irq.c | 26 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_iverbs.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_main.c | 7 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_qp.c | 159 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_sqp.c | 6 |
6 files changed, 201 insertions, 15 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 936580d86ad3..2502366e845f 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h | |||
@@ -95,6 +95,10 @@ struct ehca_sma_attr { | |||
95 | struct ehca_sport { | 95 | struct ehca_sport { |
96 | struct ib_cq *ibcq_aqp1; | 96 | struct ib_cq *ibcq_aqp1; |
97 | struct ib_qp *ibqp_sqp[2]; | 97 | struct ib_qp *ibqp_sqp[2]; |
98 | /* lock to serialze modify_qp() calls for sqp in normal | ||
99 | * and irq path (when event PORT_ACTIVE is received first time) | ||
100 | */ | ||
101 | spinlock_t mod_sqp_lock; | ||
98 | enum ib_port_state port_state; | 102 | enum ib_port_state port_state; |
99 | struct ehca_sma_attr saved_attr; | 103 | struct ehca_sma_attr saved_attr; |
100 | }; | 104 | }; |
@@ -141,6 +145,14 @@ enum ehca_ext_qp_type { | |||
141 | EQPT_SRQ = 3, | 145 | EQPT_SRQ = 3, |
142 | }; | 146 | }; |
143 | 147 | ||
148 | /* struct to cache modify_qp()'s parms for GSI/SMI qp */ | ||
149 | struct ehca_mod_qp_parm { | ||
150 | int mask; | ||
151 | struct ib_qp_attr attr; | ||
152 | }; | ||
153 | |||
154 | #define EHCA_MOD_QP_PARM_MAX 4 | ||
155 | |||
144 | struct ehca_qp { | 156 | struct ehca_qp { |
145 | union { | 157 | union { |
146 | struct ib_qp ib_qp; | 158 | struct ib_qp ib_qp; |
@@ -164,6 +176,9 @@ struct ehca_qp { | |||
164 | struct ehca_cq *recv_cq; | 176 | struct ehca_cq *recv_cq; |
165 | unsigned int sqerr_purgeflag; | 177 | unsigned int sqerr_purgeflag; |
166 | struct hlist_node list_entries; | 178 | struct hlist_node list_entries; |
179 | /* array to cache modify_qp()'s parms for GSI/SMI qp */ | ||
180 | struct ehca_mod_qp_parm *mod_qp_parm; | ||
181 | int mod_qp_parm_idx; | ||
167 | /* mmap counter for resources mapped into user space */ | 182 | /* mmap counter for resources mapped into user space */ |
168 | u32 mm_count_squeue; | 183 | u32 mm_count_squeue; |
169 | u32 mm_count_rqueue; | 184 | u32 mm_count_rqueue; |
@@ -323,6 +338,7 @@ extern int ehca_port_act_time; | |||
323 | extern int ehca_use_hp_mr; | 338 | extern int ehca_use_hp_mr; |
324 | extern int ehca_scaling_code; | 339 | extern int ehca_scaling_code; |
325 | extern int ehca_lock_hcalls; | 340 | extern int ehca_lock_hcalls; |
341 | extern int ehca_nr_ports; | ||
326 | 342 | ||
327 | struct ipzu_queue_resp { | 343 | struct ipzu_queue_resp { |
328 | u32 qe_size; /* queue entry size */ | 344 | u32 qe_size; /* queue entry size */ |
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index 4c734ecef11d..863b34fa9ff9 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c | |||
@@ -356,17 +356,33 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe) | |||
356 | u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); | 356 | u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); |
357 | u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); | 357 | u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); |
358 | u8 spec_event; | 358 | u8 spec_event; |
359 | struct ehca_sport *sport = &shca->sport[port - 1]; | ||
360 | unsigned long flags; | ||
359 | 361 | ||
360 | switch (ec) { | 362 | switch (ec) { |
361 | case 0x30: /* port availability change */ | 363 | case 0x30: /* port availability change */ |
362 | if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { | 364 | if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { |
363 | shca->sport[port - 1].port_state = IB_PORT_ACTIVE; | 365 | int suppress_event; |
366 | /* replay modify_qp for sqps */ | ||
367 | spin_lock_irqsave(&sport->mod_sqp_lock, flags); | ||
368 | suppress_event = !sport->ibqp_sqp[IB_QPT_GSI]; | ||
369 | if (sport->ibqp_sqp[IB_QPT_SMI]) | ||
370 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]); | ||
371 | if (!suppress_event) | ||
372 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]); | ||
373 | spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); | ||
374 | |||
375 | /* AQP1 was destroyed, ignore this event */ | ||
376 | if (suppress_event) | ||
377 | break; | ||
378 | |||
379 | sport->port_state = IB_PORT_ACTIVE; | ||
364 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, | 380 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, |
365 | "is active"); | 381 | "is active"); |
366 | ehca_query_sma_attr(shca, port, | 382 | ehca_query_sma_attr(shca, port, |
367 | &shca->sport[port - 1].saved_attr); | 383 | &sport->saved_attr); |
368 | } else { | 384 | } else { |
369 | shca->sport[port - 1].port_state = IB_PORT_DOWN; | 385 | sport->port_state = IB_PORT_DOWN; |
370 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, | 386 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, |
371 | "is inactive"); | 387 | "is inactive"); |
372 | } | 388 | } |
@@ -380,11 +396,11 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe) | |||
380 | ehca_warn(&shca->ib_device, "disruptive port " | 396 | ehca_warn(&shca->ib_device, "disruptive port " |
381 | "%d configuration change", port); | 397 | "%d configuration change", port); |
382 | 398 | ||
383 | shca->sport[port - 1].port_state = IB_PORT_DOWN; | 399 | sport->port_state = IB_PORT_DOWN; |
384 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, | 400 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, |
385 | "is inactive"); | 401 | "is inactive"); |
386 | 402 | ||
387 | shca->sport[port - 1].port_state = IB_PORT_ACTIVE; | 403 | sport->port_state = IB_PORT_ACTIVE; |
388 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, | 404 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, |
389 | "is active"); | 405 | "is active"); |
390 | } else | 406 | } else |
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h index 5485799cdc8d..c469bfde2708 100644 --- a/drivers/infiniband/hw/ehca/ehca_iverbs.h +++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h | |||
@@ -200,4 +200,6 @@ void ehca_free_fw_ctrlblock(void *ptr); | |||
200 | #define ehca_free_fw_ctrlblock(ptr) free_page((unsigned long)(ptr)) | 200 | #define ehca_free_fw_ctrlblock(ptr) free_page((unsigned long)(ptr)) |
201 | #endif | 201 | #endif |
202 | 202 | ||
203 | void ehca_recover_sqp(struct ib_qp *sqp); | ||
204 | |||
203 | #endif | 205 | #endif |
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index 0a34083dac8a..84c9b7b8669b 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
@@ -90,7 +90,8 @@ MODULE_PARM_DESC(hw_level, | |||
90 | "hardware level" | 90 | "hardware level" |
91 | " (0: autosensing (default), 1: v. 0.20, 2: v. 0.21)"); | 91 | " (0: autosensing (default), 1: v. 0.20, 2: v. 0.21)"); |
92 | MODULE_PARM_DESC(nr_ports, | 92 | MODULE_PARM_DESC(nr_ports, |
93 | "number of connected ports (default: 2)"); | 93 | "number of connected ports (-1: autodetect, 1: port one only, " |
94 | "2: two ports (default)"); | ||
94 | MODULE_PARM_DESC(use_hp_mr, | 95 | MODULE_PARM_DESC(use_hp_mr, |
95 | "high performance MRs (0: no (default), 1: yes)"); | 96 | "high performance MRs (0: no (default), 1: yes)"); |
96 | MODULE_PARM_DESC(port_act_time, | 97 | MODULE_PARM_DESC(port_act_time, |
@@ -693,7 +694,7 @@ static int __devinit ehca_probe(struct of_device *dev, | |||
693 | struct ehca_shca *shca; | 694 | struct ehca_shca *shca; |
694 | const u64 *handle; | 695 | const u64 *handle; |
695 | struct ib_pd *ibpd; | 696 | struct ib_pd *ibpd; |
696 | int ret; | 697 | int ret, i; |
697 | 698 | ||
698 | handle = of_get_property(dev->node, "ibm,hca-handle", NULL); | 699 | handle = of_get_property(dev->node, "ibm,hca-handle", NULL); |
699 | if (!handle) { | 700 | if (!handle) { |
@@ -714,6 +715,8 @@ static int __devinit ehca_probe(struct of_device *dev, | |||
714 | return -ENOMEM; | 715 | return -ENOMEM; |
715 | } | 716 | } |
716 | mutex_init(&shca->modify_mutex); | 717 | mutex_init(&shca->modify_mutex); |
718 | for (i = 0; i < ARRAY_SIZE(shca->sport); i++) | ||
719 | spin_lock_init(&shca->sport[i].mod_sqp_lock); | ||
717 | 720 | ||
718 | shca->ofdev = dev; | 721 | shca->ofdev = dev; |
719 | shca->ipz_hca_handle.handle = *handle; | 722 | shca->ipz_hca_handle.handle = *handle; |
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index 26c6a945459f..8d3c35fa051b 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c | |||
@@ -729,12 +729,31 @@ static struct ehca_qp *internal_create_qp( | |||
729 | init_attr->cap.max_send_wr = parms.squeue.act_nr_wqes; | 729 | init_attr->cap.max_send_wr = parms.squeue.act_nr_wqes; |
730 | my_qp->init_attr = *init_attr; | 730 | my_qp->init_attr = *init_attr; |
731 | 731 | ||
732 | if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) { | ||
733 | shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] = | ||
734 | &my_qp->ib_qp; | ||
735 | if (ehca_nr_ports < 0) { | ||
736 | /* alloc array to cache subsequent modify qp parms | ||
737 | * for autodetect mode | ||
738 | */ | ||
739 | my_qp->mod_qp_parm = | ||
740 | kzalloc(EHCA_MOD_QP_PARM_MAX * | ||
741 | sizeof(*my_qp->mod_qp_parm), | ||
742 | GFP_KERNEL); | ||
743 | if (!my_qp->mod_qp_parm) { | ||
744 | ehca_err(pd->device, | ||
745 | "Could not alloc mod_qp_parm"); | ||
746 | goto create_qp_exit4; | ||
747 | } | ||
748 | } | ||
749 | } | ||
750 | |||
732 | /* NOTE: define_apq0() not supported yet */ | 751 | /* NOTE: define_apq0() not supported yet */ |
733 | if (qp_type == IB_QPT_GSI) { | 752 | if (qp_type == IB_QPT_GSI) { |
734 | h_ret = ehca_define_sqp(shca, my_qp, init_attr); | 753 | h_ret = ehca_define_sqp(shca, my_qp, init_attr); |
735 | if (h_ret != H_SUCCESS) { | 754 | if (h_ret != H_SUCCESS) { |
736 | ret = ehca2ib_return_code(h_ret); | 755 | ret = ehca2ib_return_code(h_ret); |
737 | goto create_qp_exit4; | 756 | goto create_qp_exit5; |
738 | } | 757 | } |
739 | } | 758 | } |
740 | 759 | ||
@@ -743,7 +762,7 @@ static struct ehca_qp *internal_create_qp( | |||
743 | if (ret) { | 762 | if (ret) { |
744 | ehca_err(pd->device, | 763 | ehca_err(pd->device, |
745 | "Couldn't assign qp to send_cq ret=%i", ret); | 764 | "Couldn't assign qp to send_cq ret=%i", ret); |
746 | goto create_qp_exit4; | 765 | goto create_qp_exit5; |
747 | } | 766 | } |
748 | } | 767 | } |
749 | 768 | ||
@@ -769,15 +788,18 @@ static struct ehca_qp *internal_create_qp( | |||
769 | if (ib_copy_to_udata(udata, &resp, sizeof resp)) { | 788 | if (ib_copy_to_udata(udata, &resp, sizeof resp)) { |
770 | ehca_err(pd->device, "Copy to udata failed"); | 789 | ehca_err(pd->device, "Copy to udata failed"); |
771 | ret = -EINVAL; | 790 | ret = -EINVAL; |
772 | goto create_qp_exit5; | 791 | goto create_qp_exit6; |
773 | } | 792 | } |
774 | } | 793 | } |
775 | 794 | ||
776 | return my_qp; | 795 | return my_qp; |
777 | 796 | ||
778 | create_qp_exit5: | 797 | create_qp_exit6: |
779 | ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num); | 798 | ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num); |
780 | 799 | ||
800 | create_qp_exit5: | ||
801 | kfree(my_qp->mod_qp_parm); | ||
802 | |||
781 | create_qp_exit4: | 803 | create_qp_exit4: |
782 | if (HAS_RQ(my_qp)) | 804 | if (HAS_RQ(my_qp)) |
783 | ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue); | 805 | ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue); |
@@ -995,7 +1017,7 @@ static int internal_modify_qp(struct ib_qp *ibqp, | |||
995 | unsigned long flags = 0; | 1017 | unsigned long flags = 0; |
996 | 1018 | ||
997 | /* do query_qp to obtain current attr values */ | 1019 | /* do query_qp to obtain current attr values */ |
998 | mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL); | 1020 | mqpcb = ehca_alloc_fw_ctrlblock(GFP_ATOMIC); |
999 | if (!mqpcb) { | 1021 | if (!mqpcb) { |
1000 | ehca_err(ibqp->device, "Could not get zeroed page for mqpcb " | 1022 | ehca_err(ibqp->device, "Could not get zeroed page for mqpcb " |
1001 | "ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num); | 1023 | "ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num); |
@@ -1183,6 +1205,8 @@ static int internal_modify_qp(struct ib_qp *ibqp, | |||
1183 | update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_P_KEY_IDX, 1); | 1205 | update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_P_KEY_IDX, 1); |
1184 | } | 1206 | } |
1185 | if (attr_mask & IB_QP_PORT) { | 1207 | if (attr_mask & IB_QP_PORT) { |
1208 | struct ehca_sport *sport; | ||
1209 | struct ehca_qp *aqp1; | ||
1186 | if (attr->port_num < 1 || attr->port_num > shca->num_ports) { | 1210 | if (attr->port_num < 1 || attr->port_num > shca->num_ports) { |
1187 | ret = -EINVAL; | 1211 | ret = -EINVAL; |
1188 | ehca_err(ibqp->device, "Invalid port=%x. " | 1212 | ehca_err(ibqp->device, "Invalid port=%x. " |
@@ -1191,6 +1215,29 @@ static int internal_modify_qp(struct ib_qp *ibqp, | |||
1191 | shca->num_ports); | 1215 | shca->num_ports); |
1192 | goto modify_qp_exit2; | 1216 | goto modify_qp_exit2; |
1193 | } | 1217 | } |
1218 | sport = &shca->sport[attr->port_num - 1]; | ||
1219 | if (!sport->ibqp_sqp[IB_QPT_GSI]) { | ||
1220 | /* should not occur */ | ||
1221 | ret = -EFAULT; | ||
1222 | ehca_err(ibqp->device, "AQP1 was not created for " | ||
1223 | "port=%x", attr->port_num); | ||
1224 | goto modify_qp_exit2; | ||
1225 | } | ||
1226 | aqp1 = container_of(sport->ibqp_sqp[IB_QPT_GSI], | ||
1227 | struct ehca_qp, ib_qp); | ||
1228 | if (ibqp->qp_type != IB_QPT_GSI && | ||
1229 | ibqp->qp_type != IB_QPT_SMI && | ||
1230 | aqp1->mod_qp_parm) { | ||
1231 | /* | ||
1232 | * firmware will reject this modify_qp() because | ||
1233 | * port is not activated/initialized fully | ||
1234 | */ | ||
1235 | ret = -EFAULT; | ||
1236 | ehca_warn(ibqp->device, "Couldn't modify qp port=%x: " | ||
1237 | "either port is being activated (try again) " | ||
1238 | "or cabling issue", attr->port_num); | ||
1239 | goto modify_qp_exit2; | ||
1240 | } | ||
1194 | mqpcb->prim_phys_port = attr->port_num; | 1241 | mqpcb->prim_phys_port = attr->port_num; |
1195 | update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_PHYS_PORT, 1); | 1242 | update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_PHYS_PORT, 1); |
1196 | } | 1243 | } |
@@ -1470,6 +1517,8 @@ modify_qp_exit1: | |||
1470 | int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, | 1517 | int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, |
1471 | struct ib_udata *udata) | 1518 | struct ib_udata *udata) |
1472 | { | 1519 | { |
1520 | struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca, | ||
1521 | ib_device); | ||
1473 | struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); | 1522 | struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); |
1474 | struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd, | 1523 | struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd, |
1475 | ib_pd); | 1524 | ib_pd); |
@@ -1482,9 +1531,100 @@ int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, | |||
1482 | return -EINVAL; | 1531 | return -EINVAL; |
1483 | } | 1532 | } |
1484 | 1533 | ||
1534 | /* The if-block below caches qp_attr to be modified for GSI and SMI | ||
1535 | * qps during the initialization by ib_mad. When the respective port | ||
1536 | * is activated, ie we got an event PORT_ACTIVE, we'll replay the | ||
1537 | * cached modify calls sequence, see ehca_recover_sqs() below. | ||
1538 | * Why that is required: | ||
1539 | * 1) If one port is connected, older code requires that port one | ||
1540 | * to be connected and module option nr_ports=1 to be given by | ||
1541 | * user, which is very inconvenient for end user. | ||
1542 | * 2) Firmware accepts modify_qp() only if respective port has become | ||
1543 | * active. Older code had a wait loop of 30sec create_qp()/ | ||
1544 | * define_aqp1(), which is not appropriate in practice. This | ||
1545 | * code now removes that wait loop, see define_aqp1(), and always | ||
1546 | * reports all ports to ib_mad resp. users. Only activated ports | ||
1547 | * will then usable for the users. | ||
1548 | */ | ||
1549 | if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI) { | ||
1550 | int port = my_qp->init_attr.port_num; | ||
1551 | struct ehca_sport *sport = &shca->sport[port - 1]; | ||
1552 | unsigned long flags; | ||
1553 | spin_lock_irqsave(&sport->mod_sqp_lock, flags); | ||
1554 | /* cache qp_attr only during init */ | ||
1555 | if (my_qp->mod_qp_parm) { | ||
1556 | struct ehca_mod_qp_parm *p; | ||
1557 | if (my_qp->mod_qp_parm_idx >= EHCA_MOD_QP_PARM_MAX) { | ||
1558 | ehca_err(&shca->ib_device, | ||
1559 | "mod_qp_parm overflow state=%x port=%x" | ||
1560 | " type=%x", attr->qp_state, | ||
1561 | my_qp->init_attr.port_num, | ||
1562 | ibqp->qp_type); | ||
1563 | spin_unlock_irqrestore(&sport->mod_sqp_lock, | ||
1564 | flags); | ||
1565 | return -EINVAL; | ||
1566 | } | ||
1567 | p = &my_qp->mod_qp_parm[my_qp->mod_qp_parm_idx]; | ||
1568 | p->mask = attr_mask; | ||
1569 | p->attr = *attr; | ||
1570 | my_qp->mod_qp_parm_idx++; | ||
1571 | ehca_dbg(&shca->ib_device, | ||
1572 | "Saved qp_attr for state=%x port=%x type=%x", | ||
1573 | attr->qp_state, my_qp->init_attr.port_num, | ||
1574 | ibqp->qp_type); | ||
1575 | spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); | ||
1576 | return 0; | ||
1577 | } | ||
1578 | spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); | ||
1579 | } | ||
1580 | |||
1485 | return internal_modify_qp(ibqp, attr, attr_mask, 0); | 1581 | return internal_modify_qp(ibqp, attr, attr_mask, 0); |
1486 | } | 1582 | } |
1487 | 1583 | ||
1584 | void ehca_recover_sqp(struct ib_qp *sqp) | ||
1585 | { | ||
1586 | struct ehca_qp *my_sqp = container_of(sqp, struct ehca_qp, ib_qp); | ||
1587 | int port = my_sqp->init_attr.port_num; | ||
1588 | struct ib_qp_attr attr; | ||
1589 | struct ehca_mod_qp_parm *qp_parm; | ||
1590 | int i, qp_parm_idx, ret; | ||
1591 | unsigned long flags, wr_cnt; | ||
1592 | |||
1593 | if (!my_sqp->mod_qp_parm) | ||
1594 | return; | ||
1595 | ehca_dbg(sqp->device, "SQP port=%x qp_num=%x", port, sqp->qp_num); | ||
1596 | |||
1597 | qp_parm = my_sqp->mod_qp_parm; | ||
1598 | qp_parm_idx = my_sqp->mod_qp_parm_idx; | ||
1599 | for (i = 0; i < qp_parm_idx; i++) { | ||
1600 | attr = qp_parm[i].attr; | ||
1601 | ret = internal_modify_qp(sqp, &attr, qp_parm[i].mask, 0); | ||
1602 | if (ret) { | ||
1603 | ehca_err(sqp->device, "Could not modify SQP port=%x " | ||
1604 | "qp_num=%x ret=%x", port, sqp->qp_num, ret); | ||
1605 | goto free_qp_parm; | ||
1606 | } | ||
1607 | ehca_dbg(sqp->device, "SQP port=%x qp_num=%x in state=%x", | ||
1608 | port, sqp->qp_num, attr.qp_state); | ||
1609 | } | ||
1610 | |||
1611 | /* re-trigger posted recv wrs */ | ||
1612 | wr_cnt = my_sqp->ipz_rqueue.current_q_offset / | ||
1613 | my_sqp->ipz_rqueue.qe_size; | ||
1614 | if (wr_cnt) { | ||
1615 | spin_lock_irqsave(&my_sqp->spinlock_r, flags); | ||
1616 | hipz_update_rqa(my_sqp, wr_cnt); | ||
1617 | spin_unlock_irqrestore(&my_sqp->spinlock_r, flags); | ||
1618 | ehca_dbg(sqp->device, "doorbell port=%x qp_num=%x wr_cnt=%lx", | ||
1619 | port, sqp->qp_num, wr_cnt); | ||
1620 | } | ||
1621 | |||
1622 | free_qp_parm: | ||
1623 | kfree(qp_parm); | ||
1624 | /* this prevents subsequent calls to modify_qp() to cache qp_attr */ | ||
1625 | my_sqp->mod_qp_parm = NULL; | ||
1626 | } | ||
1627 | |||
1488 | int ehca_query_qp(struct ib_qp *qp, | 1628 | int ehca_query_qp(struct ib_qp *qp, |
1489 | struct ib_qp_attr *qp_attr, | 1629 | struct ib_qp_attr *qp_attr, |
1490 | int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr) | 1630 | int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr) |
@@ -1772,6 +1912,7 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, | |||
1772 | struct ehca_shca *shca = container_of(dev, struct ehca_shca, ib_device); | 1912 | struct ehca_shca *shca = container_of(dev, struct ehca_shca, ib_device); |
1773 | struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd, | 1913 | struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd, |
1774 | ib_pd); | 1914 | ib_pd); |
1915 | struct ehca_sport *sport = &shca->sport[my_qp->init_attr.port_num - 1]; | ||
1775 | u32 cur_pid = current->tgid; | 1916 | u32 cur_pid = current->tgid; |
1776 | u32 qp_num = my_qp->real_qp_num; | 1917 | u32 qp_num = my_qp->real_qp_num; |
1777 | int ret; | 1918 | int ret; |
@@ -1818,6 +1959,14 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp, | |||
1818 | port_num = my_qp->init_attr.port_num; | 1959 | port_num = my_qp->init_attr.port_num; |
1819 | qp_type = my_qp->init_attr.qp_type; | 1960 | qp_type = my_qp->init_attr.qp_type; |
1820 | 1961 | ||
1962 | if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) { | ||
1963 | spin_lock_irqsave(&sport->mod_sqp_lock, flags); | ||
1964 | kfree(my_qp->mod_qp_parm); | ||
1965 | my_qp->mod_qp_parm = NULL; | ||
1966 | shca->sport[port_num - 1].ibqp_sqp[qp_type] = NULL; | ||
1967 | spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); | ||
1968 | } | ||
1969 | |||
1821 | /* no support for IB_QPT_SMI yet */ | 1970 | /* no support for IB_QPT_SMI yet */ |
1822 | if (qp_type == IB_QPT_GSI) { | 1971 | if (qp_type == IB_QPT_GSI) { |
1823 | struct ib_event event; | 1972 | struct ib_event event; |
diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c b/drivers/infiniband/hw/ehca/ehca_sqp.c index f0792e5fbd02..79e72b25b252 100644 --- a/drivers/infiniband/hw/ehca/ehca_sqp.c +++ b/drivers/infiniband/hw/ehca/ehca_sqp.c | |||
@@ -40,11 +40,8 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | 42 | ||
43 | #include <linux/module.h> | ||
44 | #include <linux/err.h> | ||
45 | #include "ehca_classes.h" | 43 | #include "ehca_classes.h" |
46 | #include "ehca_tools.h" | 44 | #include "ehca_tools.h" |
47 | #include "ehca_qes.h" | ||
48 | #include "ehca_iverbs.h" | 45 | #include "ehca_iverbs.h" |
49 | #include "hcp_if.h" | 46 | #include "hcp_if.h" |
50 | 47 | ||
@@ -93,6 +90,9 @@ u64 ehca_define_sqp(struct ehca_shca *shca, | |||
93 | return H_PARAMETER; | 90 | return H_PARAMETER; |
94 | } | 91 | } |
95 | 92 | ||
93 | if (ehca_nr_ports < 0) /* autodetect mode */ | ||
94 | return H_SUCCESS; | ||
95 | |||
96 | for (counter = 0; | 96 | for (counter = 0; |
97 | shca->sport[port - 1].port_state != IB_PORT_ACTIVE && | 97 | shca->sport[port - 1].port_state != IB_PORT_ACTIVE && |
98 | counter < ehca_port_act_time; | 98 | counter < ehca_port_act_time; |