- if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_INIT) {
- tcp_ctask->sent = 0;
- tcp_ctask->sg_count = 0;
- tcp_ctask->exp_datasn = 0;
-
- if (sc->sc_data_direction == DMA_TO_DEVICE) {
- struct scatterlist *sg = scsi_sglist(sc);
-
- iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg);
- tcp_ctask->sg = sg + 1;
- tcp_ctask->bad_sg = sg + scsi_sg_count(sc);
-
- debug_scsi("cmd [itt 0x%x total %d imm_data %d "
- "unsol count %d, unsol offset %d]\n",
- ctask->itt, scsi_bufflen(sc),
- ctask->imm_count, ctask->unsol_count,
- ctask->unsol_offset);
- }
-
- iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
- sizeof(struct iscsi_hdr));
-
- if (conn->hdrdgst_en)
- iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
- (u8*)tcp_ctask->hdrext);
- tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT;
- tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT;
- }
-
- if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_XMIT) {
- rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
- if (rc)
- return rc;
- tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_XMIT;
-
- if (sc->sc_data_direction != DMA_TO_DEVICE)
- return 0;
-
- if (ctask->imm_count) {
- tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
- iscsi_set_padding(tcp_ctask, ctask->imm_count);
-
- if (ctask->conn->datadgst_en) {
- iscsi_data_digest_init(ctask->conn->dd_data,
- tcp_ctask);
- tcp_ctask->immdigest = 0;
- }
- }
-
- if (ctask->unsol_count)
- tcp_ctask->xmstate |=
- XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
- }
- return rc;
-}
-
-static int
-iscsi_send_padding(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;
- int sent = 0, rc;
-
- if (tcp_ctask->xmstate & XMSTATE_W_PAD) {
- iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
- tcp_ctask->pad_count);
- if (conn->datadgst_en)
- crypto_hash_update(&tcp_conn->tx_hash,
- &tcp_ctask->sendbuf.sg,
- tcp_ctask->sendbuf.sg.length);
- } else if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_PAD))
- return 0;
-
- tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
- tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_PAD;
- debug_scsi("sending %d pad bytes for itt 0x%x\n",
- tcp_ctask->pad_count, ctask->itt);
- rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count,
- &sent);
- if (rc) {
- debug_scsi("padding send failed %d\n", rc);
- tcp_ctask->xmstate |= XMSTATE_W_RESEND_PAD;
- }
- return rc;
-}
-
-static int
-iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
- struct iscsi_buf *buf, uint32_t *digest)
-{
- struct iscsi_tcp_cmd_task *tcp_ctask;
- struct iscsi_tcp_conn *tcp_conn;
- int rc, sent = 0;
-
- if (!conn->datadgst_en)
- return 0;
-
- tcp_ctask = ctask->dd_data;
- tcp_conn = conn->dd_data;
-
- if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_DATA_DIGEST)) {
- crypto_hash_final(&tcp_conn->tx_hash, (u8*)digest);
- iscsi_buf_init_iov(buf, (char*)digest, 4);
- }
- tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_DATA_DIGEST;
-
- rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent);
- if (!rc)
- debug_scsi("sent digest 0x%x for itt 0x%x\n", *digest,
- ctask->itt);
- else {
- debug_scsi("sending digest 0x%x failed for itt 0x%x!\n",
- *digest, ctask->itt);
- tcp_ctask->xmstate |= XMSTATE_W_RESEND_DATA_DIGEST;
- }
- return rc;
-}
-
-static int
-iscsi_send_data(struct iscsi_cmd_task *ctask, struct iscsi_buf *sendbuf,
- struct scatterlist **sg, int *sent, int *count,
- struct iscsi_buf *digestbuf, uint32_t *digest)
-{
- struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
- struct iscsi_conn *conn = ctask->conn;
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- int rc, buf_sent, offset;
-
- while (*count) {
- buf_sent = 0;
- offset = sendbuf->sent;
-
- rc = iscsi_sendpage(conn, sendbuf, count, &buf_sent);
- *sent = *sent + buf_sent;
- if (buf_sent && conn->datadgst_en)
- partial_sg_digest_update(&tcp_conn->tx_hash,
- &sendbuf->sg, sendbuf->sg.offset + offset,
- buf_sent);
- if (!iscsi_buf_left(sendbuf) && *sg != tcp_ctask->bad_sg) {
- iscsi_buf_init_sg(sendbuf, *sg);
- *sg = *sg + 1;
- }
-
- if (rc)
- return rc;
- }
-
- rc = iscsi_send_padding(conn, ctask);
- if (rc)