ALSA: usb-audio: parse more format descriptors with structs
[safe/jmp/linux-2.6] / drivers / scsi / libiscsi_tcp.c
index e865089..5c92620 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/inet.h>
+#include <linux/slab.h>
 #include <linux/file.h>
 #include <linux/blkdev.h>
 #include <linux/crypto.h>
@@ -49,13 +50,21 @@ MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
              "Alex Aizman <itn780@yahoo.com>");
 MODULE_DESCRIPTION("iSCSI/TCP data-path");
 MODULE_LICENSE("GPL");
-#undef DEBUG_TCP
 
-#ifdef DEBUG_TCP
-#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt)
-#else
-#define debug_tcp(fmt...)
-#endif
+static int iscsi_dbg_libtcp;
+module_param_named(debug_libiscsi_tcp, iscsi_dbg_libtcp, int,
+                  S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug_libiscsi_tcp, "Turn on debugging for libiscsi_tcp "
+                "module. Set to 1 to turn on, and zero to turn off. Default "
+                "is off.");
+
+#define ISCSI_DBG_TCP(_conn, dbg_fmt, arg...)                  \
+       do {                                                    \
+               if (iscsi_dbg_libtcp)                           \
+                       iscsi_conn_printk(KERN_INFO, _conn,     \
+                                            "%s " dbg_fmt,     \
+                                            __func__, ##arg);  \
+       } while (0);
 
 static int iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
                                   struct iscsi_segment *segment);
@@ -123,18 +132,13 @@ static void iscsi_tcp_segment_map(struct iscsi_segment *segment, int recv)
        if (page_count(sg_page(sg)) >= 1 && !recv)
                return;
 
-       debug_tcp("iscsi_tcp_segment_map %s %p\n", recv ? "recv" : "xmit",
-                 segment);
        segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
        segment->data = segment->sg_mapped + sg->offset + segment->sg_offset;
 }
 
 void iscsi_tcp_segment_unmap(struct iscsi_segment *segment)
 {
-       debug_tcp("iscsi_tcp_segment_unmap %p\n", segment);
-
        if (segment->sg_mapped) {
-               debug_tcp("iscsi_tcp_segment_unmap valid\n");
                kunmap_atomic(segment->sg_mapped, KM_SOFTIRQ0);
                segment->sg_mapped = NULL;
                segment->data = NULL;
@@ -159,6 +163,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,15 +177,16 @@ 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];
        struct scatterlist sg;
        unsigned int pad;
 
-       debug_tcp("copied %u %u size %u %s\n", segment->copied, copied,
-                 segment->size, recv ? "recv" : "xmit");
+       ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "copied %u %u size %u %s\n",
+                     segment->copied, copied, segment->size,
+                     recv ? "recv" : "xmit");
        if (segment->hash && copied) {
                /*
                 * If a segment is kmapd we must unmap it before sending
@@ -213,8 +219,8 @@ int iscsi_tcp_segment_done(struct iscsi_segment *segment, int recv,
        iscsi_tcp_segment_unmap(segment);
 
        /* Do we have more scatterlist entries? */
-       debug_tcp("total copied %u total size %u\n", segment->total_copied,
-                  segment->total_size);
+       ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "total copied %u total size %u\n",
+                     segment->total_copied, segment->total_size);
        if (segment->total_copied < segment->total_size) {
                /* Proceed to the next entry in the scatterlist. */
                iscsi_tcp_segment_init_sg(segment, sg_next(segment->sg),
@@ -225,13 +231,16 @@ 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) {
+                       ISCSI_DBG_TCP(tcp_conn->iscsi_conn,
+                                     "consume %d pad bytes\n", pad);
+                       segment->total_size += pad;
+                       segment->size = pad;
+                       segment->data = segment->padbuf;
+                       return 0;
+               }
        }
 
        /*
@@ -273,15 +282,15 @@ 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);
+                       ISCSI_DBG_TCP(tcp_conn->iscsi_conn,
+                                     "copied %d bytes\n", len);
                        break;
                }
 
                copy = min(len - copied, segment->size - segment->copied);
-               debug_tcp("iscsi_tcp_segment_recv copying %d\n", copy);
+               ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "copying %d\n", copy);
                memcpy(segment->data + segment->copied, ptr + copied, copy);
                copied += copy;
        }
@@ -308,7 +317,7 @@ iscsi_tcp_dgst_verify(struct iscsi_tcp_conn *tcp_conn,
 
        if (memcmp(segment->recv_digest, segment->digest,
                   segment->digest_len)) {
-               debug_scsi("digest mismatch\n");
+               ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "digest mismatch\n");
                return 0;
        }
 
@@ -352,12 +361,8 @@ iscsi_segment_seek_sg(struct iscsi_segment *segment,
        struct scatterlist *sg;
        unsigned int i;
 
-       debug_scsi("iscsi_segment_seek_sg offset %u size %llu\n",
-                 offset, size);
        __iscsi_segment_init(segment, size, done, hash);
        for_each_sg(sg_list, sg, sg_count, i) {
-               debug_scsi("sg %d, len %u offset %u\n", i, sg->length,
-                          sg->offset);
                if (offset < sg->length) {
                        iscsi_tcp_segment_init_sg(segment, sg, offset);
                        return 0;
@@ -379,8 +384,9 @@ EXPORT_SYMBOL_GPL(iscsi_segment_seek_sg);
  */
 void iscsi_tcp_hdr_recv_prep(struct iscsi_tcp_conn *tcp_conn)
 {
-       debug_tcp("iscsi_tcp_hdr_recv_prep(%p%s)\n", tcp_conn,
-                 tcp_conn->iscsi_conn->hdrdgst_en ? ", digest enabled" : "");
+       ISCSI_DBG_TCP(tcp_conn->iscsi_conn,
+                     "(%s)\n", tcp_conn->iscsi_conn->hdrdgst_en ?
+                     "digest enabled" : "digest disabled");
        iscsi_segment_init_linear(&tcp_conn->in.segment,
                                tcp_conn->in.hdr_buf, sizeof(struct iscsi_hdr),
                                iscsi_tcp_hdr_recv_done, NULL);
@@ -435,20 +441,20 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task)
        struct iscsi_tcp_task *tcp_task = task->dd_data;
        struct iscsi_r2t_info *r2t;
 
-       /* nothing to do for mgmt or pending tasks */
-       if (!task->sc || task->state == ISCSI_TASK_PENDING)
+       /* nothing to do for mgmt */
+       if (!task->sc)
                return;
 
        /* flush task's r2t queues */
-       while (__kfifo_get(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) {
-               __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+       while (kfifo_out(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) {
+               kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t,
                            sizeof(void*));
-               debug_scsi("iscsi_tcp_cleanup_task pending r2t dropped\n");
+               ISCSI_DBG_TCP(task->conn, "pending r2t dropped\n");
        }
 
        r2t = tcp_task->r2t;
        if (r2t != NULL) {
-               __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+               kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t,
                            sizeof(void*));
                tcp_task->r2t = NULL;
        }
@@ -468,13 +474,19 @@ static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
        int datasn = be32_to_cpu(rhdr->datasn);
        unsigned total_in_length = scsi_in(task->sc)->length;
 
-       iscsi_update_cmdsn(conn->session, (struct iscsi_nopin*)rhdr);
+       /*
+        * lib iscsi will update this in the completion handling if there
+        * is status.
+        */
+       if (!(rhdr->flags & ISCSI_FLAG_DATA_STATUS))
+               iscsi_update_cmdsn(conn->session, (struct iscsi_nopin*)rhdr);
+
        if (tcp_conn->in.datalen == 0)
                return 0;
 
        if (tcp_task->exp_datasn != datasn) {
-               debug_tcp("%s: task->exp_datasn(%d) != rhdr->datasn(%d)\n",
-                         __func__, tcp_task->exp_datasn, datasn);
+               ISCSI_DBG_TCP(conn, "task->exp_datasn(%d) != rhdr->datasn(%d)"
+                             "\n", tcp_task->exp_datasn, datasn);
                return ISCSI_ERR_DATASN;
        }
 
@@ -482,9 +494,9 @@ static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
 
        tcp_task->data_offset = be32_to_cpu(rhdr->offset);
        if (tcp_task->data_offset + tcp_conn->in.datalen > total_in_length) {
-               debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
-                         __func__, tcp_task->data_offset,
-                         tcp_conn->in.datalen, total_in_length);
+               ISCSI_DBG_TCP(conn, "data_offset(%d) + data_len(%d) > "
+                             "total_length_in(%d)\n", tcp_task->data_offset,
+                             tcp_conn->in.datalen, total_in_length);
                return ISCSI_ERR_DATA_OFFSET;
        }
 
@@ -515,8 +527,8 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
        }
 
        if (tcp_task->exp_datasn != r2tsn){
-               debug_tcp("%s: task->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
-                         __func__, tcp_task->exp_datasn, r2tsn);
+               ISCSI_DBG_TCP(conn, "task->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
+                             tcp_task->exp_datasn, r2tsn);
                return ISCSI_ERR_R2TSN;
        }
 
@@ -530,7 +542,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
                return 0;
        }
 
-       rc = __kfifo_get(tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));
+       rc = kfifo_out(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));
        if (!rc) {
                iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. "
                                  "Target has sent more R2Ts than it "
@@ -543,15 +555,15 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
        if (r2t->data_length == 0) {
                iscsi_conn_printk(KERN_ERR, conn,
                                  "invalid R2T with zero data len\n");
-               __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+               kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t,
                            sizeof(void*));
                return ISCSI_ERR_DATALEN;
        }
 
        if (r2t->data_length > session->max_burst)
-               debug_scsi("invalid R2T with data len %u and max burst %u."
-                          "Attempting to execute request.\n",
-                           r2t->data_length, session->max_burst);
+               ISCSI_DBG_TCP(conn, "invalid R2T with data len %u and max "
+                             "burst %u. Attempting to execute request.\n",
+                             r2t->data_length, session->max_burst);
 
        r2t->data_offset = be32_to_cpu(rhdr->data_offset);
        if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) {
@@ -559,7 +571,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
                                  "invalid R2T with data len %u at offset %u "
                                  "and total length %d\n", r2t->data_length,
                                  r2t->data_offset, scsi_out(task->sc)->length);
-               __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+               kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t,
                            sizeof(void*));
                return ISCSI_ERR_DATALEN;
        }
@@ -569,7 +581,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
        r2t->sent = 0;
 
        tcp_task->exp_datasn = r2tsn + 1;
-       __kfifo_put(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*));
+       kfifo_in(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*));
        conn->r2t_pdus_cnt++;
 
        iscsi_requeue_task(task);
@@ -638,8 +650,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
        if (rc)
                return rc;
 
-       debug_tcp("opcode 0x%x ahslen %d datalen %d\n",
-                 opcode, ahslen, tcp_conn->in.datalen);
+       ISCSI_DBG_TCP(conn, "opcode 0x%x ahslen %d datalen %d\n",
+                     opcode, ahslen, tcp_conn->in.datalen);
 
        switch(opcode) {
        case ISCSI_OP_SCSI_DATA_IN:
@@ -671,10 +683,11 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
                            !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD))
                                rx_hash = tcp_conn->rx_hash;
 
-                       debug_tcp("iscsi_tcp_begin_data_in(%p, offset=%d, "
-                                 "datalen=%d)\n", tcp_conn,
-                                 tcp_task->data_offset,
-                                 tcp_conn->in.datalen);
+                       ISCSI_DBG_TCP(conn, "iscsi_tcp_begin_data_in( "
+                                    "offset=%d, datalen=%d)\n",
+                                     tcp_task->data_offset,
+                                     tcp_conn->in.datalen);
+                       task->last_xfer = jiffies;
                        rc = iscsi_segment_seek_sg(&tcp_conn->in.segment,
                                                   sdb->table.sgl,
                                                   sdb->table.nents,
@@ -702,9 +715,10 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
                        rc = ISCSI_ERR_BAD_ITT;
                else if (ahslen)
                        rc = ISCSI_ERR_AHSLEN;
-               else if (task->sc->sc_data_direction == DMA_TO_DEVICE)
+               else if (task->sc->sc_data_direction == DMA_TO_DEVICE) {
+                       task->last_xfer = jiffies;
                        rc = iscsi_tcp_r2t_rsp(conn, task);
-               else
+               else
                        rc = ISCSI_ERR_PROTO;
                spin_unlock(&conn->session->lock);
                break;
@@ -794,7 +808,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 +821,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;
@@ -852,10 +865,16 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
        unsigned int consumed = 0;
        int rc = 0;
 
-       debug_tcp("in %d bytes\n", skb->len - offset);
+       ISCSI_DBG_TCP(conn, "in %d bytes\n", skb->len - offset);
+       /*
+        * Update for each skb instead of pdu, because over slow networks a
+        * data_in's data could take a while to read in. We also want to
+        * account for r2ts.
+        */
+       conn->last_recv = jiffies;
 
        if (unlikely(conn->suspend_rx)) {
-               debug_tcp("conn %d Rx suspended!\n", conn->id);
+               ISCSI_DBG_TCP(conn, "Rx suspended!\n");
                *status = ISCSI_TCP_SUSPENDED;
                return 0;
        }
@@ -872,15 +891,16 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
 
                avail = skb_seq_read(consumed, &ptr, &seq);
                if (avail == 0) {
-                       debug_tcp("no more data avail. Consumed %d\n",
-                                 consumed);
+                       ISCSI_DBG_TCP(conn, "no more data avail. Consumed %d\n",
+                                     consumed);
                        *status = ISCSI_TCP_SKB_DONE;
                        skb_abort_seq_read(&seq);
                        goto skb_done;
                }
                BUG_ON(segment->copied >= segment->size);
 
-               debug_tcp("skb %p ptr=%p avail=%u\n", skb, ptr, avail);
+               ISCSI_DBG_TCP(conn, "skb %p ptr=%p avail=%u\n", skb, ptr,
+                             avail);
                rc = iscsi_tcp_segment_recv(tcp_conn, segment, ptr, avail);
                BUG_ON(rc == 0);
                consumed += rc;
@@ -893,11 +913,11 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
 
 segment_done:
        *status = ISCSI_TCP_SEGMENT_DONE;
-       debug_tcp("segment done\n");
+       ISCSI_DBG_TCP(conn, "segment done\n");
        rc = segment->done(tcp_conn, segment);
        if (rc != 0) {
                *status = ISCSI_TCP_CONN_ERR;
-               debug_tcp("Error receiving PDU, errno=%d\n", rc);
+               ISCSI_DBG_TCP(conn, "Error receiving PDU, errno=%d\n", rc);
                iscsi_conn_failure(conn, rc);
                return 0;
        }
@@ -927,19 +947,17 @@ int iscsi_tcp_task_init(struct iscsi_task *task)
                 * mgmt tasks do not have a scatterlist since they come
                 * in from the iscsi interface.
                 */
-               debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id,
-                          task->itt);
+               ISCSI_DBG_TCP(conn, "mtask deq [itt 0x%x]\n", task->itt);
 
                return conn->session->tt->init_pdu(task, 0, task->data_count);
        }
 
-       BUG_ON(__kfifo_len(tcp_task->r2tqueue));
+       BUG_ON(kfifo_len(&tcp_task->r2tqueue));
        tcp_task->exp_datasn = 0;
 
        /* Prepare PDU, optionally w/ immediate data */
-       debug_scsi("task deq [cid %d itt 0x%x imm %d unsol %d]\n",
-                   conn->id, task->itt, task->imm_count,
-                   task->unsol_r2t.data_length);
+       ISCSI_DBG_TCP(conn, "task deq [itt 0x%x imm %d unsol %d]\n",
+                     task->itt, task->imm_count, task->unsol_r2t.data_length);
 
        err = conn->session->tt->init_pdu(task, 0, task->imm_count);
        if (err)
@@ -963,8 +981,9 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)
                        r2t = tcp_task->r2t;
                        /* Continue with this R2T? */
                        if (r2t->data_length <= r2t->sent) {
-                               debug_scsi("  done with r2t %p\n", r2t);
-                               __kfifo_put(tcp_task->r2tpool.queue,
+                               ISCSI_DBG_TCP(task->conn,
+                                             "  done with r2t %p\n", r2t);
+                               kfifo_in(&tcp_task->r2tpool.queue,
                                            (void *)&tcp_task->r2t,
                                            sizeof(void *));
                                tcp_task->r2t = r2t = NULL;
@@ -972,9 +991,12 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)
                }
 
                if (r2t == NULL) {
-                       __kfifo_get(tcp_task->r2tqueue,
-                                   (void *)&tcp_task->r2t, sizeof(void *));
-                       r2t = tcp_task->r2t;
+                       if (kfifo_out(&tcp_task->r2tqueue,
+                           (void *)&tcp_task->r2t, sizeof(void *)) !=
+                           sizeof(void *))
+                               r2t = NULL;
+                       else
+                               r2t = tcp_task->r2t;
                }
                spin_unlock_bh(&session->lock);
        }
@@ -986,7 +1008,7 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)
  * iscsi_tcp_task_xmit - xmit normal PDU task
  * @task: iscsi command task
  *
- * We're expected to return 0 when everything was transmitted succesfully,
+ * We're expected to return 0 when everything was transmitted successfully,
  * -EAGAIN if there's still data in the queue, or != 0 for any other kind
  * of error.
  */
@@ -1017,23 +1039,26 @@ flush:
        r2t = iscsi_tcp_get_curr_r2t(task);
        if (r2t == NULL) {
                /* Waiting for more R2Ts to arrive. */
-               debug_tcp("no R2Ts yet\n");
+               ISCSI_DBG_TCP(conn, "no R2Ts yet\n");
                return 0;
        }
 
-       rc = conn->session->tt->alloc_pdu(task);
+       rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_DATA_OUT);
        if (rc)
                return rc;
        iscsi_prep_data_out_pdu(task, r2t, (struct iscsi_data *) task->hdr);
 
-       debug_scsi("sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n",
-                  r2t, r2t->datasn - 1, task->hdr->itt,
-                  r2t->data_offset + r2t->sent, r2t->data_count);
+       ISCSI_DBG_TCP(conn, "sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n",
+                     r2t, r2t->datasn - 1, task->hdr->itt,
+                     r2t->data_offset + r2t->sent, r2t->data_count);
 
        rc = conn->session->tt->init_pdu(task, r2t->data_offset + r2t->sent,
                                         r2t->data_count);
-       if (rc)
+       if (rc) {
+               iscsi_conn_failure(conn, ISCSI_ERR_XMIT_FAILED);
                return rc;
+       }
+
        r2t->sent += r2t->data_count;
        goto flush;
 }
@@ -1106,9 +1131,8 @@ int iscsi_tcp_r2tpool_alloc(struct iscsi_session *session)
                }
 
                /* R2T xmit queue */
-               tcp_task->r2tqueue = kfifo_alloc(
-                     session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL);
-               if (tcp_task->r2tqueue == ERR_PTR(-ENOMEM)) {
+               if (kfifo_alloc(&tcp_task->r2tqueue,
+                     session->max_r2t * 4 * sizeof(void*), GFP_KERNEL)) {
                        iscsi_pool_free(&tcp_task->r2tpool);
                        goto r2t_alloc_fail;
                }
@@ -1121,7 +1145,7 @@ r2t_alloc_fail:
                struct iscsi_task *task = session->cmds[i];
                struct iscsi_tcp_task *tcp_task = task->dd_data;
 
-               kfifo_free(tcp_task->r2tqueue);
+               kfifo_free(&tcp_task->r2tqueue);
                iscsi_pool_free(&tcp_task->r2tpool);
        }
        return -ENOMEM;
@@ -1136,7 +1160,7 @@ void iscsi_tcp_r2tpool_free(struct iscsi_session *session)
                struct iscsi_task *task = session->cmds[i];
                struct iscsi_tcp_task *tcp_task = task->dd_data;
 
-               kfifo_free(tcp_task->r2tqueue);
+               kfifo_free(&tcp_task->r2tqueue);
                iscsi_pool_free(&tcp_task->r2tpool);
        }
 }