in rio_cm.c [942:1019]
static int riocm_ch_connect(u16 loc_ch, struct cm_dev *cm,
struct cm_peer *peer, u16 rem_ch)
{
struct rio_channel *ch = NULL;
struct rio_ch_chan_hdr *hdr;
int ret;
long wret;
ch = riocm_get_channel(loc_ch);
if (!ch)
return -ENODEV;
if (!riocm_cmp_exch(ch, RIO_CM_IDLE, RIO_CM_CONNECT)) {
ret = -EINVAL;
goto conn_done;
}
ch->cmdev = cm;
ch->rdev = peer->rdev;
ch->context = NULL;
ch->loc_destid = cm->mport->host_deviceid;
ch->rem_channel = rem_ch;
/*
* Send connect request to the remote RapidIO device
*/
hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
if (hdr == NULL) {
ret = -ENOMEM;
goto conn_done;
}
hdr->bhdr.src_id = htonl(ch->loc_destid);
hdr->bhdr.dst_id = htonl(peer->rdev->destid);
hdr->bhdr.src_mbox = cmbox;
hdr->bhdr.dst_mbox = cmbox;
hdr->bhdr.type = RIO_CM_CHAN;
hdr->ch_op = CM_CONN_REQ;
hdr->dst_ch = htons(rem_ch);
hdr->src_ch = htons(loc_ch);
/* ATTN: the function call below relies on the fact that underlying
* HW-specific add_outb_message() routine copies TX data into its
* internal transfer buffer. Must be reviewed if mport driver uses
* this buffer directly.
*/
ret = riocm_post_send(cm, peer->rdev, hdr, sizeof(*hdr));
if (ret != -EBUSY) {
kfree(hdr);
} else {
ret = riocm_queue_req(cm, peer->rdev, hdr, sizeof(*hdr));
if (ret)
kfree(hdr);
}
if (ret) {
riocm_cmp_exch(ch, RIO_CM_CONNECT, RIO_CM_IDLE);
goto conn_done;
}
/* Wait for connect response from the remote device */
wret = wait_for_completion_interruptible_timeout(&ch->comp,
RIOCM_CONNECT_TO * HZ);
riocm_debug(WAIT, "wait on %d returns %ld", ch->id, wret);
if (!wret)
ret = -ETIME;
else if (wret == -ERESTARTSYS)
ret = -EINTR;
else
ret = riocm_cmp(ch, RIO_CM_CONNECTED) ? 0 : -1;
conn_done:
riocm_put_channel(ch);
return ret;
}