Skip to content

Commit

Permalink
RDMA/cxgb4: Add support for iWARP Port Mapper user space service
Browse files Browse the repository at this point in the history
Based on original work by Vipul Pandya.

Signed-off-by: Steve Wise <swise@opengridcomputing.com>

[ Fix htons -> ntohs to make sparse happy.  - Roland ]

Signed-off-by: Roland Dreier <roland@purestorage.com>
  • Loading branch information
Steve Wise authored and Roland Dreier committed Jun 10, 2014
1 parent 5647263 commit 9eccfe1
Show file tree
Hide file tree
Showing 3 changed files with 262 additions and 43 deletions.
180 changes: 149 additions & 31 deletions drivers/infiniband/hw/cxgb4/cm.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2010 Chelsio, Inc. All rights reserved.
* Copyright (c) 2009-2014 Chelsio, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
Expand Down Expand Up @@ -294,6 +294,12 @@ void _c4iw_free_ep(struct kref *kref)
dst_release(ep->dst);
cxgb4_l2t_release(ep->l2t);
}
if (test_bit(RELEASE_MAPINFO, &ep->com.flags)) {
print_addr(&ep->com, __func__, "remove_mapinfo/mapping");
iwpm_remove_mapinfo(&ep->com.local_addr,
&ep->com.mapped_local_addr);
iwpm_remove_mapping(&ep->com.local_addr, RDMA_NL_C4IW);
}
kfree(ep);
}

Expand Down Expand Up @@ -528,6 +534,38 @@ static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
}

/*
* c4iw_form_pm_msg - Form a port mapper message with mapping info
*/
static void c4iw_form_pm_msg(struct c4iw_ep *ep,
struct iwpm_sa_data *pm_msg)
{
memcpy(&pm_msg->loc_addr, &ep->com.local_addr,
sizeof(ep->com.local_addr));
memcpy(&pm_msg->rem_addr, &ep->com.remote_addr,
sizeof(ep->com.remote_addr));
}

/*
* c4iw_form_reg_msg - Form a port mapper message with dev info
*/
static void c4iw_form_reg_msg(struct c4iw_dev *dev,
struct iwpm_dev_data *pm_msg)
{
memcpy(pm_msg->dev_name, dev->ibdev.name, IWPM_DEVNAME_SIZE);
memcpy(pm_msg->if_name, dev->rdev.lldi.ports[0]->name,
IWPM_IFNAME_SIZE);
}

static void c4iw_record_pm_msg(struct c4iw_ep *ep,
struct iwpm_sa_data *pm_msg)
{
memcpy(&ep->com.mapped_local_addr, &pm_msg->mapped_loc_addr,
sizeof(ep->com.mapped_local_addr));
memcpy(&ep->com.mapped_remote_addr, &pm_msg->mapped_rem_addr,
sizeof(ep->com.mapped_remote_addr));
}

static int send_connect(struct c4iw_ep *ep)
{
struct cpl_act_open_req *req;
Expand All @@ -546,10 +584,14 @@ static int send_connect(struct c4iw_ep *ep)
int sizev6 = is_t4(ep->com.dev->rdev.lldi.adapter_type) ?
sizeof(struct cpl_act_open_req6) :
sizeof(struct cpl_t5_act_open_req6);
struct sockaddr_in *la = (struct sockaddr_in *)&ep->com.local_addr;
struct sockaddr_in *ra = (struct sockaddr_in *)&ep->com.remote_addr;
struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&ep->com.local_addr;
struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&ep->com.remote_addr;
struct sockaddr_in *la = (struct sockaddr_in *)
&ep->com.mapped_local_addr;
struct sockaddr_in *ra = (struct sockaddr_in *)
&ep->com.mapped_remote_addr;
struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)
&ep->com.mapped_local_addr;
struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)
&ep->com.mapped_remote_addr;

wrlen = (ep->com.remote_addr.ss_family == AF_INET) ?
roundup(sizev4, 16) :
Expand Down Expand Up @@ -1627,10 +1669,10 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
req->le.filter = cpu_to_be32(cxgb4_select_ntuple(
ep->com.dev->rdev.lldi.ports[0],
ep->l2t));
sin = (struct sockaddr_in *)&ep->com.local_addr;
sin = (struct sockaddr_in *)&ep->com.mapped_local_addr;
req->le.lport = sin->sin_port;
req->le.u.ipv4.lip = sin->sin_addr.s_addr;
sin = (struct sockaddr_in *)&ep->com.remote_addr;
sin = (struct sockaddr_in *)&ep->com.mapped_remote_addr;
req->le.pport = sin->sin_port;
req->le.u.ipv4.pip = sin->sin_addr.s_addr;
req->tcb.t_state_to_astid =
Expand Down Expand Up @@ -1870,10 +1912,10 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
struct sockaddr_in6 *ra6;

ep = lookup_atid(t, atid);
la = (struct sockaddr_in *)&ep->com.local_addr;
ra = (struct sockaddr_in *)&ep->com.remote_addr;
la6 = (struct sockaddr_in6 *)&ep->com.local_addr;
ra6 = (struct sockaddr_in6 *)&ep->com.remote_addr;
la = (struct sockaddr_in *)&ep->com.mapped_local_addr;
ra = (struct sockaddr_in *)&ep->com.mapped_remote_addr;
la6 = (struct sockaddr_in6 *)&ep->com.mapped_local_addr;
ra6 = (struct sockaddr_in6 *)&ep->com.mapped_remote_addr;

PDBG("%s ep %p atid %u status %u errno %d\n", __func__, ep, atid,
status, status2errno(status));
Expand Down Expand Up @@ -2730,13 +2772,15 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
struct c4iw_dev *dev = to_c4iw_dev(cm_id->device);
struct c4iw_ep *ep;
int err = 0;
struct sockaddr_in *laddr = (struct sockaddr_in *)&cm_id->local_addr;
struct sockaddr_in *raddr = (struct sockaddr_in *)&cm_id->remote_addr;
struct sockaddr_in6 *laddr6 = (struct sockaddr_in6 *)&cm_id->local_addr;
struct sockaddr_in6 *raddr6 = (struct sockaddr_in6 *)
&cm_id->remote_addr;
struct sockaddr_in *laddr;
struct sockaddr_in *raddr;
struct sockaddr_in6 *laddr6;
struct sockaddr_in6 *raddr6;
struct iwpm_dev_data pm_reg_msg;
struct iwpm_sa_data pm_msg;
__u8 *ra;
int iptype;
int iwpm_err = 0;

if ((conn_param->ord > c4iw_max_read_depth) ||
(conn_param->ird > c4iw_max_read_depth)) {
Expand Down Expand Up @@ -2767,7 +2811,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (!ep->com.qp) {
PDBG("%s qpn 0x%x not found!\n", __func__, conn_param->qpn);
err = -EINVAL;
goto fail2;
goto fail1;
}
ref_qp(ep);
PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn,
Expand All @@ -2780,10 +2824,50 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (ep->atid == -1) {
printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
err = -ENOMEM;
goto fail2;
goto fail1;
}
insert_handle(dev, &dev->atid_idr, ep, ep->atid);

memcpy(&ep->com.local_addr, &cm_id->local_addr,
sizeof(ep->com.local_addr));
memcpy(&ep->com.remote_addr, &cm_id->remote_addr,
sizeof(ep->com.remote_addr));

/* No port mapper available, go with the specified peer information */
memcpy(&ep->com.mapped_local_addr, &cm_id->local_addr,
sizeof(ep->com.mapped_local_addr));
memcpy(&ep->com.mapped_remote_addr, &cm_id->remote_addr,
sizeof(ep->com.mapped_remote_addr));

c4iw_form_reg_msg(dev, &pm_reg_msg);
iwpm_err = iwpm_register_pid(&pm_reg_msg, RDMA_NL_C4IW);
if (iwpm_err) {
PDBG("%s: Port Mapper reg pid fail (err = %d).\n",
__func__, iwpm_err);
}
if (iwpm_valid_pid() && !iwpm_err) {
c4iw_form_pm_msg(ep, &pm_msg);
iwpm_err = iwpm_add_and_query_mapping(&pm_msg, RDMA_NL_C4IW);
if (iwpm_err)
PDBG("%s: Port Mapper query fail (err = %d).\n",
__func__, iwpm_err);
else
c4iw_record_pm_msg(ep, &pm_msg);
}
if (iwpm_create_mapinfo(&ep->com.local_addr,
&ep->com.mapped_local_addr, RDMA_NL_C4IW)) {
iwpm_remove_mapping(&ep->com.local_addr, RDMA_NL_C4IW);
err = -ENOMEM;
goto fail1;
}
print_addr(&ep->com, __func__, "add_query/create_mapinfo");
set_bit(RELEASE_MAPINFO, &ep->com.flags);

laddr = (struct sockaddr_in *)&ep->com.mapped_local_addr;
raddr = (struct sockaddr_in *)&ep->com.mapped_remote_addr;
laddr6 = (struct sockaddr_in6 *)&ep->com.mapped_local_addr;
raddr6 = (struct sockaddr_in6 *) &ep->com.mapped_remote_addr;

if (cm_id->remote_addr.ss_family == AF_INET) {
iptype = 4;
ra = (__u8 *)&raddr->sin_addr;
Expand All @@ -2794,7 +2878,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if ((__force int)raddr->sin_addr.s_addr == INADDR_ANY) {
err = pick_local_ipaddrs(dev, cm_id);
if (err)
goto fail2;
goto fail1;
}

/* find a route */
Expand All @@ -2814,7 +2898,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (ipv6_addr_type(&raddr6->sin6_addr) == IPV6_ADDR_ANY) {
err = pick_local_ip6addrs(dev, cm_id);
if (err)
goto fail2;
goto fail1;
}

/* find a route */
Expand All @@ -2830,13 +2914,13 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (!ep->dst) {
printk(KERN_ERR MOD "%s - cannot find route.\n", __func__);
err = -EHOSTUNREACH;
goto fail3;
goto fail2;
}

err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true);
if (err) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
goto fail4;
goto fail3;
}

PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n",
Expand All @@ -2845,23 +2929,19 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)

state_set(&ep->com, CONNECTING);
ep->tos = 0;
memcpy(&ep->com.local_addr, &cm_id->local_addr,
sizeof(ep->com.local_addr));
memcpy(&ep->com.remote_addr, &cm_id->remote_addr,
sizeof(ep->com.remote_addr));

/* send connect request to rnic */
err = send_connect(ep);
if (!err)
goto out;

cxgb4_l2t_release(ep->l2t);
fail4:
dst_release(ep->dst);
fail3:
dst_release(ep->dst);
fail2:
remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid);
cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
fail2:
fail1:
cm_id->rem_ref(cm_id);
c4iw_put_ep(&ep->com);
out:
Expand All @@ -2871,7 +2951,8 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
static int create_server6(struct c4iw_dev *dev, struct c4iw_listen_ep *ep)
{
int err;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ep->com.local_addr;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)
&ep->com.mapped_local_addr;

c4iw_init_wr_wait(&ep->com.wr_wait);
err = cxgb4_create_server6(ep->com.dev->rdev.lldi.ports[0],
Expand All @@ -2892,7 +2973,8 @@ static int create_server6(struct c4iw_dev *dev, struct c4iw_listen_ep *ep)
static int create_server4(struct c4iw_dev *dev, struct c4iw_listen_ep *ep)
{
int err;
struct sockaddr_in *sin = (struct sockaddr_in *)&ep->com.local_addr;
struct sockaddr_in *sin = (struct sockaddr_in *)
&ep->com.mapped_local_addr;

if (dev->rdev.lldi.enable_fw_ofld_conn) {
do {
Expand Down Expand Up @@ -2927,6 +3009,9 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
int err = 0;
struct c4iw_dev *dev = to_c4iw_dev(cm_id->device);
struct c4iw_listen_ep *ep;
struct iwpm_dev_data pm_reg_msg;
struct iwpm_sa_data pm_msg;
int iwpm_err = 0;

might_sleep();

Expand Down Expand Up @@ -2961,6 +3046,37 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
goto fail2;
}
insert_handle(dev, &dev->stid_idr, ep, ep->stid);

/* No port mapper available, go with the specified info */
memcpy(&ep->com.mapped_local_addr, &cm_id->local_addr,
sizeof(ep->com.mapped_local_addr));

c4iw_form_reg_msg(dev, &pm_reg_msg);
iwpm_err = iwpm_register_pid(&pm_reg_msg, RDMA_NL_C4IW);
if (iwpm_err) {
PDBG("%s: Port Mapper reg pid fail (err = %d).\n",
__func__, iwpm_err);
}
if (iwpm_valid_pid() && !iwpm_err) {
memcpy(&pm_msg.loc_addr, &ep->com.local_addr,
sizeof(ep->com.local_addr));
iwpm_err = iwpm_add_mapping(&pm_msg, RDMA_NL_C4IW);
if (iwpm_err)
PDBG("%s: Port Mapper query fail (err = %d).\n",
__func__, iwpm_err);
else
memcpy(&ep->com.mapped_local_addr,
&pm_msg.mapped_loc_addr,
sizeof(ep->com.mapped_local_addr));
}
if (iwpm_create_mapinfo(&ep->com.local_addr,
&ep->com.mapped_local_addr, RDMA_NL_C4IW)) {
err = -ENOMEM;
goto fail3;
}
print_addr(&ep->com, __func__, "add_mapping/create_mapinfo");

set_bit(RELEASE_MAPINFO, &ep->com.flags);
state_set(&ep->com, LISTEN);
if (ep->com.local_addr.ss_family == AF_INET)
err = create_server4(dev, ep);
Expand All @@ -2970,6 +3086,8 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
cm_id->provider_data = ep;
goto out;
}

fail3:
cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid,
ep->com.local_addr.ss_family);
fail2:
Expand Down
Loading

0 comments on commit 9eccfe1

Please sign in to comment.