From 21eb481926965ce8d0d602e9d98d4d967e08a5b4 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 12 Aug 2008 22:59:56 -0500 Subject: [PATCH 05/23] libfc: don't process frames when aborting commands. If I am reading fcp4 12.3.2 right then we are not supposed to process any device data frame when a abort is in flight. Currently, we only do not read in data, but we update the counters. If we got some data then status, while we were aborting the command then we could be retutning scsi-ml ok status, but no data. So this patch has use return DID_ABORT so scsi-ml can retry if possible. Signed-off-by: Mike Christie --- drivers/scsi/libfc/fc_fcp.c | 36 ++++++++++++++++++++++-------------- 1 files changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index cd77273..c34f67e 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -360,12 +360,11 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) if (!page_addr) break; /* XXX panic? */ - if (!(fsp->state & FC_SRB_ABORT_PENDING)) { - if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) - crc = crc32(crc, buf, sg_bytes); - memcpy((char *)page_addr + (off & ~PAGE_MASK), buf, - sg_bytes); - } + if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) + crc = crc32(crc, buf, sg_bytes); + memcpy((char *)page_addr + (off & ~PAGE_MASK), buf, + sg_bytes); + kunmap_atomic(page_addr, KM_SOFTIRQ0); buf += sg_bytes; offset += sg_bytes; @@ -615,6 +614,9 @@ static void fc_fcp_recv(struct fc_seq *sp, struct fc_frame *fp, void *arg) goto out; fsp->last_pkt_time = jiffies; + if (fsp->state & FC_SRB_ABORT_PENDING) + goto unlock; + if (r_ctl == FC_RCTL_DD_DATA_DESC) { /* * received XFER RDY from the target @@ -644,6 +646,7 @@ static void fc_fcp_recv(struct fc_seq *sp, struct fc_frame *fp, void *arg) } else { FC_DBG("unexpected frame. r_ctl %x\n", r_ctl); } +unlock: fc_fcp_unlock_pkt(fsp); out: fc_frame_free(fp); @@ -774,14 +777,19 @@ static void fc_fcp_complete(struct fc_fcp_pkt *fsp) struct fc_seq *sp; u32 f_ctl; - /* - * Test for transport underrun, independent of response underrun status. - */ - if (fsp->xfer_len < fsp->data_len && !fsp->io_status && - (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) || - fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) { - fsp->status_code = FC_DATA_UNDRUN; - fsp->io_status = SUGGEST_RETRY << 24; + if (fsp->state & (FC_SRB_ABORT_PENDING | FC_SRB_ABORTED)) + fsp->status_code = FC_CMD_ABORTED; + else { + /* + * Test for transport underrun, independent of response + * underrun status. + */ + if (fsp->xfer_len < fsp->data_len && !fsp->io_status && + (!(fsp->scsi_comp_flags & FCP_RESID_UNDER) || + fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) { + fsp->status_code = FC_DATA_UNDRUN; + fsp->io_status = SUGGEST_RETRY << 24; + } } sp = fsp->seq_ptr; -- 1.5.5.1