summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-12-02 00:32:16 -0600
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-12-29 11:24:23 -0600
commit6df19a791bdd5d820cccd8c7a12679888ae62099 (patch)
tree5afebc101c362d0a41275337dced617fb06f8a89 /drivers/scsi
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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/iscsi_tcp.c9
-rw-r--r--drivers/scsi/libiscsi_tcp.c37
2 files changed, 25 insertions, 21 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index de5c9b3e51f..23808dfe22b 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)
/**
* 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
*
* 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)
* hash as it goes. When the entire segment has been transmitted,
* 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_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
struct socket *sk = tcp_sw_conn->sock;
unsigned int copied = 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;
unsigned int offset, copy;
int flags = 0;
@@ -263,7 +264,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn)
int rc = 0;
while (1) {
- rc = iscsi_sw_tcp_xmit_segment(tcp_sw_conn, segment);
+ rc = iscsi_sw_tcp_xmit_segment(tcp_conn, segment);
if (rc < 0) {
rc = ISCSI_ERR_XMIT_FAILED;
goto error;
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index 9df6b3436e4..a745f91d292 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)
/**
* iscsi_tcp_segment_done - check whether the segment is complete
+ * @tcp_conn: iscsi tcp connection
* @segment: iscsi segment to check
* @recv: set to one of this is called from the recv path
* @copied: number of bytes copied
@@ -172,7 +173,8 @@ iscsi_tcp_segment_splice_digest(struct iscsi_segment *segment, void *digest)
*
* 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)
{
static unsigned char padbuf[ISCSI_PAD_LEN];
@@ -225,13 +227,15 @@ int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv,
}
/* Do we need to handle padding? */
- pad = iscsi_padding(segment->total_copied);
- if (pad != 0) {
- debug_tcp("consume %d pad bytes\n", pad);
- segment->total_size += pad;
- segment->size = pad;
- segment->data = padbuf;
- return 0;
+ if (!(tcp_conn->iscsi_conn->session->tt->caps & CAP_PADDING_OFFLOAD)) {
+ pad = iscsi_padding(segment->total_copied);
+ if (pad != 0) {
+ debug_tcp("consume %d pad bytes\n", pad);
+ segment->total_size += pad;
+ segment->size = pad;
+ segment->data = padbuf;
+ return 0;
+ }
}
/*
@@ -273,7 +277,7 @@ iscsi_tcp_segment_recv(struct iscsi_tcp_conn *tcp_conn,
{
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) {
debug_tcp("iscsi_tcp_segment_recv copied %d bytes\n",
len);
@@ -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
* header digests; if so, set up the recv_digest buffer
* 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) {
/*
* Even if we offload the digest processing we
@@ -806,14 +811,12 @@ iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
return 0;
}
- if (!(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) {
- iscsi_tcp_dgst_header(tcp_conn->rx_hash, hdr,
- segment->total_copied - ISCSI_DIGEST_SIZE,
- segment->digest);
+ iscsi_tcp_dgst_header(tcp_conn->rx_hash, hdr,
+ segment->total_copied - ISCSI_DIGEST_SIZE,
+ segment->digest);
- if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
- return ISCSI_ERR_HDR_DGST;
- }
+ if (!iscsi_tcp_dgst_verify(tcp_conn, segment))
+ return ISCSI_ERR_HDR_DGST;
}
tcp_conn->in.hdr = hdr;