Commit 6df19a79 authored by Mike Christie's avatar Mike Christie Committed by James Bottomley

[SCSI] libiscsi_tcp: support padding offload

cxgb3i does not offload the processing of the header,
but it will always process the padding. This patch
adds a padding offload flag to detect when the LLD
supports this.

The patch also modifies the header processing so that
we do not try to read/bypass the header dugest in the
skb. cxgb3i will not include it with the header like
with other offload cards.
Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent ae15f801
...@@ -194,7 +194,7 @@ iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_sw_tcp_conn *tcp_sw_conn) ...@@ -194,7 +194,7 @@ iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_sw_tcp_conn *tcp_sw_conn)
/** /**
* iscsi_sw_tcp_xmit_segment - transmit segment * iscsi_sw_tcp_xmit_segment - transmit segment
* @tcp_sw_conn: the iSCSI TCP connection * @tcp_conn: the iSCSI TCP connection
* @segment: the buffer to transmnit * @segment: the buffer to transmnit
* *
* This function transmits as much of the buffer as * This function transmits as much of the buffer as
...@@ -205,14 +205,15 @@ iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_sw_tcp_conn *tcp_sw_conn) ...@@ -205,14 +205,15 @@ iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_sw_tcp_conn *tcp_sw_conn)
* hash as it goes. When the entire segment has been transmitted, * hash as it goes. When the entire segment has been transmitted,
* it will retrieve the hash value and send it as well. * it will retrieve the hash value and send it as well.
*/ */
static int iscsi_sw_tcp_xmit_segment(struct iscsi_sw_tcp_conn *tcp_sw_conn, static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn,
struct iscsi_segment *segment) struct iscsi_segment *segment)
{ {
struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
struct socket *sk = tcp_sw_conn->sock; struct socket *sk = tcp_sw_conn->sock;
unsigned int copied = 0; unsigned int copied = 0;
int r = 0; int r = 0;
while (!iscsi_tcp_segment_done(segment, 0, r)) { while (!iscsi_tcp_segment_done(tcp_conn, segment, 0, r)) {
struct scatterlist *sg; struct scatterlist *sg;
unsigned int offset, copy; unsigned int offset, copy;
int flags = 0; int flags = 0;
...@@ -263,7 +264,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn) ...@@ -263,7 +264,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn)
int rc = 0; int rc = 0;
while (1) { while (1) {
rc = iscsi_sw_tcp_xmit_segment(tcp_sw_conn, segment); rc = iscsi_sw_tcp_xmit_segment(tcp_conn, segment);
if (rc < 0) { if (rc < 0) {
rc = ISCSI_ERR_XMIT_FAILED; rc = ISCSI_ERR_XMIT_FAILED;
goto error; goto error;
......
...@@ -159,6 +159,7 @@ iscsi_tcp_segment_splice_digest(struct iscsi_segment *segment, void *digest) ...@@ -159,6 +159,7 @@ iscsi_tcp_segment_splice_digest(struct iscsi_segment *segment, void *digest)
/** /**
* iscsi_tcp_segment_done - check whether the segment is complete * iscsi_tcp_segment_done - check whether the segment is complete
* @tcp_conn: iscsi tcp connection
* @segment: iscsi segment to check * @segment: iscsi segment to check
* @recv: set to one of this is called from the recv path * @recv: set to one of this is called from the recv path
* @copied: number of bytes copied * @copied: number of bytes copied
...@@ -172,7 +173,8 @@ iscsi_tcp_segment_splice_digest(struct iscsi_segment *segment, void *digest) ...@@ -172,7 +173,8 @@ iscsi_tcp_segment_splice_digest(struct iscsi_segment *segment, void *digest)
* *
* This function must be re-entrant. * This function must be re-entrant.
*/ */
int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv, int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
struct iscsi_segment *segment, int recv,
unsigned copied) unsigned copied)
{ {
static unsigned char padbuf[ISCSI_PAD_LEN]; static unsigned char padbuf[ISCSI_PAD_LEN];
...@@ -225,6 +227,7 @@ int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv, ...@@ -225,6 +227,7 @@ int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv,
} }
/* Do we need to handle padding? */ /* Do we need to handle padding? */
if (!(tcp_conn->iscsi_conn->session->tt->caps & CAP_PADDING_OFFLOAD)) {
pad = iscsi_padding(segment->total_copied); pad = iscsi_padding(segment->total_copied);
if (pad != 0) { if (pad != 0) {
debug_tcp("consume %d pad bytes\n", pad); debug_tcp("consume %d pad bytes\n", pad);
...@@ -233,6 +236,7 @@ int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv, ...@@ -233,6 +236,7 @@ int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv,
segment->data = padbuf; segment->data = padbuf;
return 0; return 0;
} }
}
/* /*
* Set us up for transferring the data digest. hdr digest * Set us up for transferring the data digest. hdr digest
...@@ -273,7 +277,7 @@ iscsi_tcp_segment_recv(struct iscsi_tcp_conn *tcp_conn, ...@@ -273,7 +277,7 @@ iscsi_tcp_segment_recv(struct iscsi_tcp_conn *tcp_conn,
{ {
unsigned int copy = 0, copied = 0; unsigned int copy = 0, copied = 0;
while (!iscsi_tcp_segment_done(segment, 1, copy)) { while (!iscsi_tcp_segment_done(tcp_conn, segment, 1, copy)) {
if (copied == len) { if (copied == len) {
debug_tcp("iscsi_tcp_segment_recv copied %d bytes\n", debug_tcp("iscsi_tcp_segment_recv copied %d bytes\n",
len); len);
...@@ -794,7 +798,8 @@ iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn, ...@@ -794,7 +798,8 @@ iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
/* We're done processing the header. See if we're doing /* We're done processing the header. See if we're doing
* header digests; if so, set up the recv_digest buffer * header digests; if so, set up the recv_digest buffer
* and go back for more. */ * and go back for more. */
if (conn->hdrdgst_en) { if (conn->hdrdgst_en &&
!(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) {
if (segment->digest_len == 0) { if (segment->digest_len == 0) {
/* /*
* Even if we offload the digest processing we * Even if we offload the digest processing we
...@@ -806,7 +811,6 @@ iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn, ...@@ -806,7 +811,6 @@ iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
return 0; return 0;
} }
if (!(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) {
iscsi_tcp_dgst_header(tcp_conn->rx_hash, hdr, iscsi_tcp_dgst_header(tcp_conn->rx_hash, hdr,
segment->total_copied - ISCSI_DIGEST_SIZE, segment->total_copied - ISCSI_DIGEST_SIZE,
segment->digest); segment->digest);
...@@ -814,7 +818,6 @@ iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn, ...@@ -814,7 +818,6 @@ iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
if (!iscsi_tcp_dgst_verify(tcp_conn, segment)) if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
return ISCSI_ERR_HDR_DGST; return ISCSI_ERR_HDR_DGST;
} }
}
tcp_conn->in.hdr = hdr; tcp_conn->in.hdr = hdr;
return iscsi_tcp_hdr_dissect(conn, hdr); return iscsi_tcp_hdr_dissect(conn, hdr);
......
...@@ -336,6 +336,8 @@ enum iscsi_host_param { ...@@ -336,6 +336,8 @@ enum iscsi_host_param {
#define CAP_SENDTARGETS_OFFLOAD 0x400 /* offload discovery process */ #define CAP_SENDTARGETS_OFFLOAD 0x400 /* offload discovery process */
#define CAP_DATA_PATH_OFFLOAD 0x800 /* offload entire IO path */ #define CAP_DATA_PATH_OFFLOAD 0x800 /* offload entire IO path */
#define CAP_DIGEST_OFFLOAD 0x1000 /* offload hdr and data digests */ #define CAP_DIGEST_OFFLOAD 0x1000 /* offload hdr and data digests */
#define CAP_PADDING_OFFLOAD 0x2000 /* offload padding insertion, removal,
and verification */
/* /*
* These flags describes reason of stop_conn() call * These flags describes reason of stop_conn() call
......
...@@ -99,7 +99,8 @@ extern int iscsi_tcp_task_xmit(struct iscsi_task *task); ...@@ -99,7 +99,8 @@ extern int iscsi_tcp_task_xmit(struct iscsi_task *task);
/* segment helpers */ /* segment helpers */
extern int iscsi_tcp_recv_segment_is_hdr(struct iscsi_tcp_conn *tcp_conn); extern int iscsi_tcp_recv_segment_is_hdr(struct iscsi_tcp_conn *tcp_conn);
extern int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv, extern int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
struct iscsi_segment *segment, int recv,
unsigned copied); unsigned copied);
extern void iscsi_tcp_segment_unmap(struct iscsi_segment *segment); extern void iscsi_tcp_segment_unmap(struct iscsi_segment *segment);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment