aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-12-02 01:32:16 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-12-29 12:24:23 -0500
commit6df19a791bdd5d820cccd8c7a12679888ae62099 (patch)
tree5afebc101c362d0a41275337dced617fb06f8a89
parentae15f80172d95f978b60d40408353943d5bc099b (diff)
[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: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/scsi/iscsi_tcp.c9
-rw-r--r--drivers/scsi/libiscsi_tcp.c37
-rw-r--r--include/scsi/iscsi_if.h2
-rw-r--r--include/scsi/libiscsi_tcp.h3
4 files changed, 29 insertions, 22 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index de5c9b3e51fb..23808dfe22ba 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -194,7 +194,7 @@ iscsi_sw_tcp_conn_restore_callbacks(struct iscsi_sw_tcp_conn *tcp_sw_conn)
194 194
195/** 195/**
196 * iscsi_sw_tcp_xmit_segment - transmit segment 196 * iscsi_sw_tcp_xmit_segment - transmit segment
197 * @tcp_sw_conn: the iSCSI TCP connection 197 * @tcp_conn: the iSCSI TCP connection
198 * @segment: the buffer to transmnit 198 * @segment: the buffer to transmnit
199 * 199 *
200 * This function transmits as much of the buffer as 200 * 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 * hash as it goes. When the entire segment has been transmitted, 205 * hash as it goes. When the entire segment has been transmitted,
206 * it will retrieve the hash value and send it as well. 206 * it will retrieve the hash value and send it as well.
207 */ 207 */
208static int iscsi_sw_tcp_xmit_segment(struct iscsi_sw_tcp_conn *tcp_sw_conn, 208static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn,
209 struct iscsi_segment *segment) 209 struct iscsi_segment *segment)
210{ 210{
211 struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
211 struct socket *sk = tcp_sw_conn->sock; 212 struct socket *sk = tcp_sw_conn->sock;
212 unsigned int copied = 0; 213 unsigned int copied = 0;
213 int r = 0; 214 int r = 0;
214 215
215 while (!iscsi_tcp_segment_done(segment, 0, r)) { 216 while (!iscsi_tcp_segment_done(tcp_conn, segment, 0, r)) {
216 struct scatterlist *sg; 217 struct scatterlist *sg;
217 unsigned int offset, copy; 218 unsigned int offset, copy;
218 int flags = 0; 219 int flags = 0;
@@ -263,7 +264,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn)
263 int rc = 0; 264 int rc = 0;
264 265
265 while (1) { 266 while (1) {
266 rc = iscsi_sw_tcp_xmit_segment(tcp_sw_conn, segment); 267 rc = iscsi_sw_tcp_xmit_segment(tcp_conn, segment);
267 if (rc < 0) { 268 if (rc < 0) {
268 rc = ISCSI_ERR_XMIT_FAILED; 269 rc = ISCSI_ERR_XMIT_FAILED;
269 goto error; 270 goto error;
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index 9df6b3436e4a..a745f91d2928 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -159,6 +159,7 @@ iscsi_tcp_segment_splice_digest(struct iscsi_segment *segment, void *digest)
159 159
160/** 160/**
161 * iscsi_tcp_segment_done - check whether the segment is complete 161 * iscsi_tcp_segment_done - check whether the segment is complete
162 * @tcp_conn: iscsi tcp connection
162 * @segment: iscsi segment to check 163 * @segment: iscsi segment to check
163 * @recv: set to one of this is called from the recv path 164 * @recv: set to one of this is called from the recv path
164 * @copied: number of bytes copied 165 * @copied: number of bytes copied
@@ -172,7 +173,8 @@ iscsi_tcp_segment_splice_digest(struct iscsi_segment *segment, void *digest)
172 * 173 *
173 * This function must be re-entrant. 174 * This function must be re-entrant.
174 */ 175 */
175int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv, 176int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
177 struct iscsi_segment *segment, int recv,
176 unsigned copied) 178 unsigned copied)
177{ 179{
178 static unsigned char padbuf[ISCSI_PAD_LEN]; 180 static unsigned char padbuf[ISCSI_PAD_LEN];
@@ -225,13 +227,15 @@ int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv,
225 } 227 }
226 228
227 /* Do we need to handle padding? */ 229 /* Do we need to handle padding? */
228 pad = iscsi_padding(segment->total_copied); 230 if (!(tcp_conn->iscsi_conn->session->tt->caps & CAP_PADDING_OFFLOAD)) {
229 if (pad != 0) { 231 pad = iscsi_padding(segment->total_copied);
230 debug_tcp("consume %d pad bytes\n", pad); 232 if (pad != 0) {
231 segment->total_size += pad; 233 debug_tcp("consume %d pad bytes\n", pad);
232 segment->size = pad; 234 segment->total_size += pad;
233 segment->data = padbuf; 235 segment->size = pad;
234 return 0; 236 segment->data = padbuf;
237 return 0;
238 }
235 } 239 }
236 240
237 /* 241 /*
@@ -273,7 +277,7 @@ iscsi_tcp_segment_recv(struct iscsi_tcp_conn *tcp_conn,
273{ 277{
274 unsigned int copy = 0, copied = 0; 278 unsigned int copy = 0, copied = 0;
275 279
276 while (!iscsi_tcp_segment_done(segment, 1, copy)) { 280 while (!iscsi_tcp_segment_done(tcp_conn, segment, 1, copy)) {
277 if (copied == len) { 281 if (copied == len) {
278 debug_tcp("iscsi_tcp_segment_recv copied %d bytes\n", 282 debug_tcp("iscsi_tcp_segment_recv copied %d bytes\n",
279 len); 283 len);
@@ -794,7 +798,8 @@ iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
794 /* We're done processing the header. See if we're doing 798 /* We're done processing the header. See if we're doing
795 * header digests; if so, set up the recv_digest buffer 799 * header digests; if so, set up the recv_digest buffer
796 * and go back for more. */ 800 * and go back for more. */
797 if (conn->hdrdgst_en) { 801 if (conn->hdrdgst_en &&
802 !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) {
798 if (segment->digest_len == 0) { 803 if (segment->digest_len == 0) {
799 /* 804 /*
800 * Even if we offload the digest processing we 805 * Even if we offload the digest processing we
@@ -806,14 +811,12 @@ iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
806 return 0; 811 return 0;
807 } 812 }
808 813
809 if (!(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) { 814 iscsi_tcp_dgst_header(tcp_conn->rx_hash, hdr,
810 iscsi_tcp_dgst_header(tcp_conn->rx_hash, hdr, 815 segment->total_copied - ISCSI_DIGEST_SIZE,
811 segment->total_copied - ISCSI_DIGEST_SIZE, 816 segment->digest);
812 segment->digest);
813 817
814 if (!iscsi_tcp_dgst_verify(tcp_conn, segment)) 818 if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
815 return ISCSI_ERR_HDR_DGST; 819 return ISCSI_ERR_HDR_DGST;
816 }
817 } 820 }
818 821
819 tcp_conn->in.hdr = hdr; 822 tcp_conn->in.hdr = hdr;
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index 8e008c96e795..d0ed5226f8c4 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -336,6 +336,8 @@ enum iscsi_host_param {
336#define CAP_SENDTARGETS_OFFLOAD 0x400 /* offload discovery process */ 336#define CAP_SENDTARGETS_OFFLOAD 0x400 /* offload discovery process */
337#define CAP_DATA_PATH_OFFLOAD 0x800 /* offload entire IO path */ 337#define CAP_DATA_PATH_OFFLOAD 0x800 /* offload entire IO path */
338#define CAP_DIGEST_OFFLOAD 0x1000 /* offload hdr and data digests */ 338#define CAP_DIGEST_OFFLOAD 0x1000 /* offload hdr and data digests */
339#define CAP_PADDING_OFFLOAD 0x2000 /* offload padding insertion, removal,
340 and verification */
339 341
340/* 342/*
341 * These flags describes reason of stop_conn() call 343 * These flags describes reason of stop_conn() call
diff --git a/include/scsi/libiscsi_tcp.h b/include/scsi/libiscsi_tcp.h
index e6bf8ef276bb..83e32f6d7859 100644
--- a/include/scsi/libiscsi_tcp.h
+++ b/include/scsi/libiscsi_tcp.h
@@ -99,7 +99,8 @@ extern int iscsi_tcp_task_xmit(struct iscsi_task *task);
99 99
100/* segment helpers */ 100/* segment helpers */
101extern int iscsi_tcp_recv_segment_is_hdr(struct iscsi_tcp_conn *tcp_conn); 101extern int iscsi_tcp_recv_segment_is_hdr(struct iscsi_tcp_conn *tcp_conn);
102extern int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv, 102extern int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
103 struct iscsi_segment *segment, int recv,
103 unsigned copied); 104 unsigned copied);
104extern void iscsi_tcp_segment_unmap(struct iscsi_segment *segment); 105extern void iscsi_tcp_segment_unmap(struct iscsi_segment *segment);
105 106