/** * iscsi_iser_conn_bind() - bind iscsi and iser connection structures * @cls_session: iscsi class session * @cls_conn: iscsi class connection * @transport_eph: transport end-point handle * @is_leading: indicate if this is the session leading connection (MCS) * * Return: zero on success, $error if iscsi_conn_bind fails and * -EINVAL in case end-point doesn't exsits anymore or iser connection * state is not UP (teardown already started). */ static int iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session, struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, int is_leading) { struct iscsi_conn *conn = cls_conn->dd_data; struct iser_conn *iser_conn; struct iscsi_endpoint *ep; int error; error = iscsi_conn_bind(cls_session, cls_conn, is_leading); if (error) return error; /* the transport ep handle comes from user space so it must be * verified against the global ib connections list */ ep = iscsi_lookup_endpoint(transport_eph); if (!ep) { iser_err("can't bind eph %llx\n", (unsigned long long)transport_eph); return -EINVAL; } iser_conn = ep->dd_data; mutex_lock(&iser_conn->state_mutex); if (iser_conn->state != ISER_CONN_UP) { error = -EINVAL; iser_err("iser_conn %p state is %d, teardown started\n", iser_conn, iser_conn->state); goto out; } error = iser_alloc_rx_descriptors(iser_conn, conn->session); if (error) goto out; /* binds the iSER connection retrieved from the previously * connected ep_handle to the iSCSI layer connection. exchanges * connection pointers */ iser_info("binding iscsi conn %p to iser_conn %p\n", conn, iser_conn); conn->dd_data = iser_conn; iser_conn->iscsi_conn = conn; out: mutex_unlock(&iser_conn->state_mutex); return error; }
/** * iser_conn_set_full_featured_mode - (iSER API) */ int iser_conn_set_full_featured_mode(struct iscsi_conn *conn) { struct iscsi_iser_conn *iser_conn = conn->dd_data; iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX); /* Check that there is no posted recv or send buffers left - */ /* they must be consumed during the login phase */ BUG_ON(iser_conn->ib_conn->post_recv_buf_count != 0); BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0); if (iser_alloc_rx_descriptors(iser_conn->ib_conn)) return -ENOMEM; /* Initial post receive buffers */ if (iser_post_recvm(iser_conn->ib_conn, ISER_MIN_POSTED_RX)) return -ENOMEM; return 0; }
static int iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session, struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, int is_leading) { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_session *session; struct iser_conn *ib_conn; struct iscsi_endpoint *ep; int error; error = iscsi_conn_bind(cls_session, cls_conn, is_leading); if (error) return error; /* the transport ep handle comes from user space so it must be * verified against the global ib connections list */ ep = iscsi_lookup_endpoint(transport_eph); if (!ep) { iser_err("can't bind eph %llx\n", (unsigned long long)transport_eph); return -EINVAL; } ib_conn = ep->dd_data; session = conn->session; if (iser_alloc_rx_descriptors(ib_conn, session)) return -ENOMEM; /* binds the iSER connection retrieved from the previously * connected ep_handle to the iSCSI layer connection. exchanges * connection pointers */ iser_info("binding iscsi conn %p to ib_conn %p\n", conn, ib_conn); conn->dd_data = ib_conn; ib_conn->iscsi_conn = conn; iser_conn_get(ib_conn); /* ref iscsi/ib conn binding */ return 0; }