[PATCH] Performance improvement, combine received data copy with CRC.
Signed-off-by: Joe Eykholt [EMAIL PROTECTED]
---
drivers/scsi/ofc/openfc/openfc_scsi.c | 130 +++--
1 files changed, 90 insertions(+), 40 deletions(-)
diff --git a/drivers/scsi/ofc/openfc/openfc_scsi.c
b/drivers/scsi/ofc/openfc/openfc_scsi.c
index 5fa0ad6..b5fc393 100644
--- a/drivers/scsi/ofc/openfc/openfc_scsi.c
+++ b/drivers/scsi/ofc/openfc/openfc_scsi.c
@@ -62,7 +62,6 @@ static void openfc_tm_done(struct fc_seq *, struct fc_frame
*, void *);
static void openfc_scsi_error(enum fc_event, void *);
static int openfc_abort_internal(struct fcdev *, struct fc_scsi_pkt *,
struct fc_frame *);
-int openfc_cp_to_user(struct fc_scsi_pkt *, uint, void *, int);
void openfc_scsi_cleanup(struct fc_scsi_pkt *);
static void openfc_timeout_error(struct fc_scsi_pkt *);
void openfc_scsi_rec_rcv(struct fc_seq *, struct fc_frame *, void *);
@@ -102,9 +101,13 @@ static void openfc_scsi_recv_data(struct fc_scsi_pkt *fsp,
struct fc_frame *fp)
struct fcoe_dev_stats *sp;
struct fc_frame_header *fh;
size_t offset;
+ u32 crc;
+ u32 copy_len = 0;
size_t len;
void *buf;
+ if (!sc-request_buffer)
+ return; /* XXX possible? */
fh = fc_frame_header_get(fp);
offset = net32_get(fh-fh_parm_offset);
len = fp-fr_len - sizeof(*fh);
@@ -115,13 +118,8 @@ static void openfc_scsi_recv_data(struct fc_scsi_pkt *fsp,
struct fc_frame *fp)
* this should never happen
*/
if ((fp-fr_flags FCPHF_CRC_UNCHECKED)
- fc_frame_crc_check(fp)) {
- sp = openfcp-fd.dev_stats[smp_processor_id()];
- sp-ErrorFrames++;
- if (sp-InvalidCRCCount++ 5)
- SA_LOG(CRC error on data frame);
- return; /* just ignore the frame */
- }
+ fc_frame_crc_check(fp))
+ goto crc_err;
if (openfc_debug) {
SA_LOG(data received past end.
len %zx offset %zx
@@ -130,42 +128,95 @@ static void openfc_scsi_recv_data(struct fc_scsi_pkt
*fsp, struct fc_frame *fp)
openfc_scsi_retry(fsp);
return;
}
-
- /*
-* Eventually, do scatter/gather buffer system to avoid
-* this copy. A NULL buffer means we discard the data.
-*/
+ crc = 0;
if (sc-use_sg) {
- len = openfc_cp_to_user(fsp, offset, buf, len);
- ASSERT_NOTIMPL(len 0);
- } else if (sc-request_buffer != NULL) {
- __memcpy((void *)sc-request_buffer + offset, buf, len);
- }
+ struct scatterlist *sg;
+ struct scatterlist *sg_limit;
+ size_t remaining, sg_bytes;
+ size_t off;
+ void *page_addr;
- /*
-* If the lower layer didn't do the CRC check, do it here.
-* This is the only type of frame the transport might not check.
-* Eventually we could do the CRC calculation during the copy above.
-*/
- if ((fp-fr_flags FCPHF_CRC_UNCHECKED) fc_frame_crc_check(fp)) {
- sp = openfcp-fd.dev_stats[smp_processor_id()];
- sp-ErrorFrames++;
- if (sp-InvalidCRCCount++ 5)
- SA_LOG(CRC error on data frame);
+ if (fp-fr_flags FCPHF_CRC_UNCHECKED)
+ crc = crc32_sb8_64_bit(~0, (u8 *) fh, sizeof(*fh));
- /*
-* Assume the frame is total garbage.
-* We may have copied it over the good part of the buffer.
-* If so, we need to retry the entire operation.
-* Otherwise, ignore it.
-*/
- if (offset fsp-xfer_len)
- openfc_scsi_retry(fsp);
- return;
- }
+ sg = (struct scatterlist *)sc-request_buffer;
+ sg_limit = sg + sc-use_sg;
+ remaining = len;
- fsp-xfer_len += len;
+ while (remaining 0 sg sg_limit) {
+ if (offset = sg-length) {
+ offset -= sg-length;
+ sg++;
+ continue;
+ }
+ sg_bytes = min(remaining, sg-length - offset);
+ /*
+* The scatterlist item may be bigger than PAGE_SIZE,
+* but we are limited to mapping PAGE_SIZE at a time.
+*/
+ off = offset + sg-offset;
+ sg_bytes = min(sg_bytes,
+ (PAGE_SIZE - (off