diff options
Diffstat (limited to 'drivers/target/tcm_fc/tfc_io.c')
| -rw-r--r-- | drivers/target/tcm_fc/tfc_io.c | 59 |
1 files changed, 26 insertions, 33 deletions
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c index e415af32115a..45329284f52f 100644 --- a/drivers/target/tcm_fc/tfc_io.c +++ b/drivers/target/tcm_fc/tfc_io.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2010 Cisco Systems, Inc. * @@ -9,19 +10,6 @@ * Copyright (c) 2009 Rising Tide, Inc. * Copyright (c) 2009 Linux-iSCSI.org * Copyright (c) 2009 Nicholas A. Bellinger <nab@linux-iscsi.org> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ /* XXX TBD some includes may be extraneous */ @@ -38,18 +26,11 @@ #include <linux/ctype.h> #include <linux/hash.h> #include <linux/ratelimit.h> -#include <asm/unaligned.h> -#include <scsi/scsi.h> -#include <scsi/scsi_host.h> -#include <scsi/scsi_device.h> -#include <scsi/scsi_cmnd.h> +#include <linux/unaligned.h> #include <scsi/libfc.h> -#include <scsi/fc_encode.h> #include <target/target_core_base.h> #include <target/target_core_fabric.h> -#include <target/target_core_configfs.h> -#include <target/configfs_macros.h> #include "tcm_fc.h" @@ -82,9 +63,13 @@ int ft_queue_data_in(struct se_cmd *se_cmd) if (cmd->aborted) return 0; + + if (se_cmd->scsi_status == SAM_STAT_TASK_SET_FULL) + goto queue_status; + ep = fc_seq_exch(cmd->seq); lport = ep->lp; - cmd->seq = lport->tt.seq_start_next(cmd->seq); + cmd->seq = fc_seq_start_next(cmd->seq); remaining = se_cmd->data_length; @@ -150,15 +135,14 @@ int ft_queue_data_in(struct se_cmd *se_cmd) page, off_in_page, tlen); fr_len(fp) += tlen; fp_skb(fp)->data_len += tlen; - fp_skb(fp)->truesize += - PAGE_SIZE << compound_order(page); + fp_skb(fp)->truesize += page_size(page); } else { BUG_ON(!page); from = kmap_atomic(page + (mem_off >> PAGE_SHIFT)); page_addr = from; - from += mem_off & ~PAGE_MASK; + from += offset_in_page(mem_off); tlen = min(tlen, (size_t)(PAGE_SIZE - - (mem_off & ~PAGE_MASK))); + offset_in_page(mem_off))); memcpy(to, from, tlen); kunmap_atomic(page_addr); to += tlen; @@ -176,16 +160,25 @@ int ft_queue_data_in(struct se_cmd *se_cmd) f_ctl |= FC_FC_END_SEQ; fc_fill_fc_hdr(fp, FC_RCTL_DD_SOL_DATA, ep->did, ep->sid, FC_TYPE_FCP, f_ctl, fh_off); - error = lport->tt.seq_send(lport, seq, fp); + error = fc_seq_send(lport, seq, fp); if (error) { - /* XXX For now, initiator will retry */ - pr_err_ratelimited("%s: Failed to send frame %p, " + pr_info_ratelimited("%s: Failed to send frame %p, " "xid <0x%x>, remaining %zu, " "lso_max <0x%x>\n", __func__, fp, ep->xid, remaining, lport->lso_max); + /* + * Go ahead and set TASK_SET_FULL status ignoring the + * rest of the DataIN, and immediately attempt to + * send the response via ft_queue_status() in order + * to notify the initiator that it should reduce it's + * per LUN queue_depth. + */ + se_cmd->scsi_status = SAM_STAT_TASK_SET_FULL; + break; } } +queue_status: return ft_queue_status(se_cmd); } @@ -227,7 +220,6 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp) ep = fc_seq_exch(seq); lport = ep->lp; if (cmd->was_ddp_setup) { - BUG_ON(!ep); BUG_ON(!lport); /* * Since DDP (Large Rx offload) was setup for this request, @@ -307,9 +299,9 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp) to = kmap_atomic(page + (mem_off >> PAGE_SHIFT)); page_addr = to; - to += mem_off & ~PAGE_MASK; + to += offset_in_page(mem_off); tlen = min(tlen, (size_t)(PAGE_SIZE - - (mem_off & ~PAGE_MASK))); + offset_in_page(mem_off))); memcpy(to, from, tlen); kunmap_atomic(page_addr); @@ -346,7 +338,7 @@ void ft_invl_hw_context(struct ft_cmd *cmd) ep = fc_seq_exch(seq); if (ep) { lport = ep->lp; - if (lport && (ep->xid <= lport->lro_xid)) + if (lport && (ep->xid <= lport->lro_xid)) { /* * "ddp_done" trigger invalidation of HW * specific DDP context @@ -361,6 +353,7 @@ void ft_invl_hw_context(struct ft_cmd *cmd) * identified using ep->xid) */ cmd->was_ddp_setup = 0; + } } } } |
