-iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
-{
- struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
-
- debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n",
- conn->id, tcp_mtask->xmstate, mtask->itt);
-
- if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) {
- tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR;
- if (mtask->data_count)
- tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
- if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
- conn->stop_stage != STOP_CONN_RECOVER &&
- conn->hdrdgst_en)
- iscsi_hdr_digest(conn, &tcp_mtask->headbuf,
- (u8*)tcp_mtask->hdrext);
- if (iscsi_sendhdr(conn, &tcp_mtask->headbuf,
- mtask->data_count)) {
- tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
- if (mtask->data_count)
- tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
- return -EAGAIN;
- }
- }
-
- if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) {
- BUG_ON(!mtask->data_count);
- tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
- /* FIXME: implement.
- * Virtual buffer could be spreaded across multiple pages...
- */
- do {
- if (iscsi_sendpage(conn, &tcp_mtask->sendbuf,
- &mtask->data_count, &tcp_mtask->sent)) {
- tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
- return -EAGAIN;
- }
- } while (mtask->data_count);
- }
-
- BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE);
- if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) {
- struct iscsi_session *session = conn->session;
-
- spin_lock_bh(&session->lock);
- list_del(&conn->mtask->running);
- __kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask,
- sizeof(void*));
- spin_unlock_bh(&session->lock);
- }
- return 0;
-}
-
-static inline int
-handle_xmstate_r_hdr(struct iscsi_conn *conn,
- struct iscsi_tcp_cmd_task *tcp_ctask)
-{
- tcp_ctask->xmstate &= ~XMSTATE_R_HDR;
- if (conn->hdrdgst_en)
- iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
- (u8*)tcp_ctask->hdrext);
- if (!iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0)) {
- BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE);
- return 0; /* wait for Data-In */
- }
- tcp_ctask->xmstate |= XMSTATE_R_HDR;
- return -EAGAIN;
-}
-
-static inline int
-handle_xmstate_w_hdr(struct iscsi_conn *conn,
- struct iscsi_cmd_task *ctask)
-{
- struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
-
- tcp_ctask->xmstate &= ~XMSTATE_W_HDR;
- if (conn->hdrdgst_en)
- iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
- (u8*)tcp_ctask->hdrext);
- if (iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count)) {
- tcp_ctask->xmstate |= XMSTATE_W_HDR;
- return -EAGAIN;
- }
- return 0;
-}
-
-static inline int
-handle_xmstate_data_digest(struct iscsi_conn *conn,
- struct iscsi_cmd_task *ctask)
-{
- struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
-
- tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST;
- debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest);
- if (iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
- &tcp_ctask->datadigest, 0)) {
- tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST;
- debug_tcp("resent data digest 0x%x fail!\n",
- tcp_ctask->datadigest);
- return -EAGAIN;
- }
- return 0;
-}
-
-static inline int
-handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
-{
- struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-
- BUG_ON(!ctask->imm_count);
- tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA;
-
- if (conn->datadgst_en) {
- iscsi_data_digest_init(tcp_conn, ctask);
- tcp_ctask->immdigest = 0;
- }
-
- for (;;) {
- if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, &ctask->imm_count,
- &tcp_ctask->sent)) {
- tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
- if (conn->datadgst_en) {
- crypto_digest_final(tcp_conn->data_tx_tfm,
- (u8*)&tcp_ctask->immdigest);
- debug_tcp("tx imm sendpage fail 0x%x\n",
- tcp_ctask->datadigest);
- }
- return -EAGAIN;
- }
- if (conn->datadgst_en)
- crypto_digest_update(tcp_conn->data_tx_tfm,
- &tcp_ctask->sendbuf.sg, 1);
-
- if (!ctask->imm_count)
- break;
- iscsi_buf_init_sg(&tcp_ctask->sendbuf,
- &tcp_ctask->sg[tcp_ctask->sg_count++]);
- }
-
- if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
- if (iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
- &tcp_ctask->immdigest, 1)) {
- debug_tcp("sending imm digest 0x%x fail!\n",
- tcp_ctask->immdigest);
- return -EAGAIN;
- }
- debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest);
- }
-
- return 0;
-}
-
-static inline int
-handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
-{
- struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
- struct iscsi_data_task *dtask;
-
- tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
- if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) {
- iscsi_unsolicit_data_init(conn, ctask);
- dtask = tcp_ctask->dtask;
- if (conn->hdrdgst_en)
- iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
- (u8*)dtask->hdrext);
- tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT;
- }
- if (iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count)) {
- tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
- tcp_ctask->xmstate |= XMSTATE_UNS_HDR;
- return -EAGAIN;
- }
-
- debug_scsi("uns dout [itt 0x%x dlen %d sent %d]\n",
- ctask->itt, ctask->unsol_count, tcp_ctask->sent);
- return 0;
-}
-
-static inline int
-handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
-{
- struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
- struct iscsi_data_task *dtask = tcp_ctask->dtask;
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-
- BUG_ON(!ctask->data_count);
- tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
-
- if (conn->datadgst_en) {
- iscsi_data_digest_init(tcp_conn, ctask);
- dtask->digest = 0;
- }
-
- for (;;) {
- int start = tcp_ctask->sent;
-
- if (iscsi_sendpage(conn, &tcp_ctask->sendbuf,
- &ctask->data_count, &tcp_ctask->sent)) {
- ctask->unsol_count -= tcp_ctask->sent - start;
- tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
- /* will continue with this ctask later.. */
- if (conn->datadgst_en) {
- crypto_digest_final(tcp_conn->data_tx_tfm,
- (u8 *)&dtask->digest);
- debug_tcp("tx uns data fail 0x%x\n",
- dtask->digest);
- }
- return -EAGAIN;
- }
-
- BUG_ON(tcp_ctask->sent > ctask->total_length);
- ctask->unsol_count -= tcp_ctask->sent - start;
-
- /*
- * XXX:we may run here with un-initial sendbuf.
- * so pass it
- */
- if (conn->datadgst_en && tcp_ctask->sent - start > 0)
- crypto_digest_update(tcp_conn->data_tx_tfm,
- &tcp_ctask->sendbuf.sg, 1);
-
- if (!ctask->data_count)
- break;
- iscsi_buf_init_sg(&tcp_ctask->sendbuf,
- &tcp_ctask->sg[tcp_ctask->sg_count++]);
- }
- BUG_ON(ctask->unsol_count < 0);
-
- /*
- * Done with the Data-Out. Next, check if we need
- * to send another unsolicited Data-Out.
- */
- if (ctask->unsol_count) {
- if (conn->datadgst_en) {
- if (iscsi_digest_final_send(conn, ctask,
- &dtask->digestbuf,
- &dtask->digest, 1)) {
- debug_tcp("send uns digest 0x%x fail\n",
- dtask->digest);
- return -EAGAIN;
- }
- debug_tcp("sending uns digest 0x%x, more uns\n",
- dtask->digest);
- }
- tcp_ctask->xmstate |= XMSTATE_UNS_INIT;
- return 1;
- }
-
- if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
- if (iscsi_digest_final_send(conn, ctask,
- &dtask->digestbuf,
- &dtask->digest, 1)) {
- debug_tcp("send last uns digest 0x%x fail\n",
- dtask->digest);
- return -EAGAIN;
- }
- debug_tcp("sending uns digest 0x%x\n",dtask->digest);
- }
-
- return 0;
-}
-
-static inline int
-handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
-{
- struct iscsi_session *session = conn->session;
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
- struct iscsi_r2t_info *r2t = tcp_ctask->r2t;
- struct iscsi_data_task *dtask = &r2t->dtask;
- int left;
-
- tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
- tcp_ctask->dtask = dtask;
-
- if (conn->datadgst_en) {
- iscsi_data_digest_init(tcp_conn, ctask);
- dtask->digest = 0;
- }
-solicit_again:
- /*
- * send Data-Out whitnin this R2T sequence.
- */
- if (!r2t->data_count)
- goto data_out_done;
-
- if (iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent)) {
- tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
- /* will continue with this ctask later.. */
- if (conn->datadgst_en) {
- crypto_digest_final(tcp_conn->data_tx_tfm,
- (u8 *)&dtask->digest);
- debug_tcp("r2t data send fail 0x%x\n", dtask->digest);
- }
- return -EAGAIN;
- }
-
- BUG_ON(r2t->data_count < 0);
- if (conn->datadgst_en)
- crypto_digest_update(tcp_conn->data_tx_tfm, &r2t->sendbuf.sg,
- 1);
-
- if (r2t->data_count) {
- BUG_ON(ctask->sc->use_sg == 0);
- if (!iscsi_buf_left(&r2t->sendbuf)) {
- BUG_ON(tcp_ctask->bad_sg == r2t->sg);
- iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
- r2t->sg += 1;
- }
- goto solicit_again;
- }
-
-data_out_done:
- /*
- * Done with this Data-Out. Next, check if we have
- * to send another Data-Out for this R2T.
- */
- BUG_ON(r2t->data_length - r2t->sent < 0);
- left = r2t->data_length - r2t->sent;
- if (left) {
- if (conn->datadgst_en) {
- if (iscsi_digest_final_send(conn, ctask,
- &dtask->digestbuf,
- &dtask->digest, 1)) {
- debug_tcp("send r2t data digest 0x%x"
- "fail\n", dtask->digest);
- return -EAGAIN;
- }
- debug_tcp("r2t data send digest 0x%x\n",
- dtask->digest);
- }
- iscsi_solicit_data_cont(conn, ctask, r2t, left);
- tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
- tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
- return 1;
- }