diff options
Diffstat (limited to 'drivers/infiniband/hw/ehca/ehca_qp.c')
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_qp.c | 159 |
1 files changed, 154 insertions, 5 deletions
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; |