Changeset View
Changeset View
Standalone View
Standalone View
head/sys/ofed/drivers/infiniband/core/iwcm.c
Show First 20 Lines • Show All 410 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
EXPORT_SYMBOL(iw_cm_disconnect); | EXPORT_SYMBOL(iw_cm_disconnect); | ||||
static struct socket * | static struct socket * | ||||
dequeue_socket(struct socket *head) | dequeue_socket(struct socket *head) | ||||
{ | { | ||||
struct socket *so; | struct socket *so; | ||||
struct sockaddr_in *remote; | struct sockaddr_in *remote; | ||||
int error; | |||||
ACCEPT_LOCK(); | SOLISTEN_LOCK(head); | ||||
so = TAILQ_FIRST(&head->so_comp); | error = solisten_dequeue(head, &so, SOCK_NONBLOCK); | ||||
if (!so) { | if (error == EWOULDBLOCK) | ||||
ACCEPT_UNLOCK(); | return (NULL); | ||||
return NULL; | |||||
} | |||||
SOCK_LOCK(so); | |||||
/* | |||||
* Before changing the flags on the socket, we have to bump the | |||||
* reference count. Otherwise, if the protocol calls sofree(), | |||||
* the socket will be released due to a zero refcount. | |||||
*/ | |||||
soref(so); | |||||
TAILQ_REMOVE(&head->so_comp, so, so_list); | |||||
head->so_qlen--; | |||||
so->so_qstate &= ~SQ_COMP; | |||||
so->so_head = NULL; | |||||
so->so_state |= SS_NBIO; | |||||
SOCK_UNLOCK(so); | |||||
ACCEPT_UNLOCK(); | |||||
remote = NULL; | remote = NULL; | ||||
soaccept(so, (struct sockaddr **)&remote); | soaccept(so, (struct sockaddr **)&remote); | ||||
free(remote, M_SONAME); | free(remote, M_SONAME); | ||||
return so; | return so; | ||||
} | } | ||||
static void | static void | ||||
iw_so_event_handler(struct work_struct *_work) | iw_so_event_handler(struct work_struct *_work) | ||||
{ | { | ||||
#ifdef INET | #ifdef INET | ||||
struct iwcm_listen_work *work = container_of(_work, | struct iwcm_listen_work *work = container_of(_work, | ||||
struct iwcm_listen_work, work); | struct iwcm_listen_work, work); | ||||
struct iw_cm_id *listen_cm_id = work->cm_id; | struct iw_cm_id *listen_cm_id = work->cm_id; | ||||
struct iwcm_id_private *cm_id_priv; | struct iwcm_id_private *cm_id_priv; | ||||
Show All 25 Lines | if (rdma_cma_any_addr((struct sockaddr *) | ||||
listen_cm_id->device->iwcm->newconn(listen_cm_id, so); | listen_cm_id->device->iwcm->newconn(listen_cm_id, so); | ||||
} | } | ||||
} | } | ||||
err: | err: | ||||
kfree(work); | kfree(work); | ||||
#endif | #endif | ||||
return; | return; | ||||
} | } | ||||
static int | static int | ||||
iw_so_upcall(struct socket *parent_so, void *arg, int waitflag) | iw_so_upcall(struct socket *parent_so, void *arg, int waitflag) | ||||
{ | { | ||||
struct iwcm_listen_work *work; | struct iwcm_listen_work *work; | ||||
struct socket *so; | |||||
struct iw_cm_id *cm_id = arg; | struct iw_cm_id *cm_id = arg; | ||||
/* check whether iw_so_event_handler() already dequeued this 'so' */ | /* check whether iw_so_event_handler() already dequeued this 'so' */ | ||||
so = TAILQ_FIRST(&parent_so->so_comp); | if (TAILQ_EMPTY(&parent_so->sol_comp)) | ||||
if (!so) | |||||
return SU_OK; | return SU_OK; | ||||
work = kzalloc(sizeof(*work), M_NOWAIT); | work = kzalloc(sizeof(*work), waitflag); | ||||
if (!work) | if (!work) | ||||
return -ENOMEM; | return -ENOMEM; | ||||
work->cm_id = cm_id; | work->cm_id = cm_id; | ||||
INIT_WORK(&work->work, iw_so_event_handler); | INIT_WORK(&work->work, iw_so_event_handler); | ||||
queue_work(iwcm_wq, &work->work); | queue_work(iwcm_wq, &work->work); | ||||
return SU_OK; | return SU_OK; | ||||
} | } | ||||
static void | static int | ||||
iw_init_sock(struct iw_cm_id *cm_id) | iw_create_listen(struct iw_cm_id *cm_id, int backlog) | ||||
{ | { | ||||
struct sockopt sopt; | struct sockopt sopt; | ||||
struct socket *so = cm_id->so; | struct socket *so = cm_id->so; | ||||
int on = 1; | int on = 1; | ||||
int rc; | |||||
SOCK_LOCK(so); | rc = -solisten(cm_id->so, backlog, curthread); | ||||
soupcall_set(so, SO_RCV, iw_so_upcall, cm_id); | if (rc != 0) | ||||
return (rc); | |||||
SOLISTEN_LOCK(so); | |||||
solisten_upcall_set(so, iw_so_upcall, cm_id); | |||||
so->so_state |= SS_NBIO; | so->so_state |= SS_NBIO; | ||||
SOCK_UNLOCK(so); | SOLISTEN_UNLOCK(so); | ||||
sopt.sopt_dir = SOPT_SET; | sopt.sopt_dir = SOPT_SET; | ||||
sopt.sopt_level = IPPROTO_TCP; | sopt.sopt_level = IPPROTO_TCP; | ||||
sopt.sopt_name = TCP_NODELAY; | sopt.sopt_name = TCP_NODELAY; | ||||
sopt.sopt_val = (caddr_t)&on; | sopt.sopt_val = (caddr_t)&on; | ||||
sopt.sopt_valsize = sizeof(on); | sopt.sopt_valsize = sizeof(on); | ||||
sopt.sopt_td = NULL; | sopt.sopt_td = NULL; | ||||
sosetopt(so, &sopt); | sosetopt(so, &sopt); | ||||
} | |||||
static int | |||||
iw_uninit_socket(struct iw_cm_id *cm_id) | |||||
{ | |||||
struct socket *so = cm_id->so; | |||||
SOCK_LOCK(so); | |||||
soupcall_clear(so, SO_RCV); | |||||
SOCK_UNLOCK(so); | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
iw_create_listen(struct iw_cm_id *cm_id, int backlog) | |||||
{ | |||||
int rc; | |||||
iw_init_sock(cm_id); | |||||
rc = -solisten(cm_id->so, backlog, curthread); | |||||
if (rc != 0) | |||||
iw_uninit_socket(cm_id); | |||||
return (rc); | |||||
} | |||||
static int | |||||
iw_destroy_listen(struct iw_cm_id *cm_id) | iw_destroy_listen(struct iw_cm_id *cm_id) | ||||
{ | { | ||||
struct socket *so = cm_id->so; | |||||
return (iw_uninit_socket(cm_id)); | SOLISTEN_LOCK(so); | ||||
solisten_upcall_set(so, NULL, NULL); | |||||
SOLISTEN_UNLOCK(so); | |||||
return (0); | |||||
} | } | ||||
/* | /* | ||||
* CM_ID <-- DESTROYING | * CM_ID <-- DESTROYING | ||||
* | * | ||||
* Clean up all resources associated with the connection and release | * Clean up all resources associated with the connection and release | ||||
* the initial reference taken by iw_create_cm_id. | * the initial reference taken by iw_create_cm_id. | ||||
▲ Show 20 Lines • Show All 750 Lines • Show Last 20 Lines |