* [PATCH] 2.4 sym53c8xx driver residual problem
@ 2006-10-05 19:50 Jeremy Linton
0 siblings, 0 replies; only message in thread
From: Jeremy Linton @ 2006-10-05 19:50 UTC (permalink / raw)
To: linux-scsi; +Cc: groudier
[-- Attachment #1: Type: text/plain, Size: 1229 bytes --]
Hello all,
I've got an application that depends on the residual data information in
order to send it to another application. The basic problem is that if a
single SCSI transfer size is greater than a single scatter gather region
(generally ~32k), then the residual length is based on the size of the
scatter gather regions and not the request size. When the two differ, and
there is a residual data condition the application computes the transfer size
incorrectly.
The attached patch is against the sym53c8xx.c driver in the 2.4 tree, I
haven't tested the 2.6 sym53c8xx_2 driver, but a quick glance at the code
seems to indicate it has the same problem. When I get a chance, I will test
the 2.6 driver as well, for the same problem. The patch basically saves the
original request length into a new member in the ccb structure called
orig_data_len. Then, when the residual len is being computed, it adjusts it
for the original data request size.
BTW: We are using the old sym53c8xx driver instead of the new one, because it
passes more of our validation tests in 2.4 than the sym53c8xx_2 driver does.
Our tests use the sg interface exclusively, so I'm not sure about behavior
with other drivers (st,sd).
[-- Attachment #2: sym53c.patch --]
[-- Type: text/x-diff, Size: 2431 bytes --]
--- sym53c8xx.c.orig 2006-10-04 18:40:39.132184101 -0500
+++ sym53c8xx.c 2006-10-05 12:20:48.252759592 -0500
@@ -1990,6 +1990,9 @@
int ext_sg; /* Extreme data pointer, used */
int ext_ofs; /* to calculate the residual. */
int resid;
+ int orig_data_len; /* used to calculate the correct*/
+ /* resid based on the original */
+ /* data len, not the scatter len*/
};
#define CCB_PHYS(cp,lbl) (cp->p_ccb + offsetof(struct ccb, lbl))
@@ -10666,8 +10669,8 @@
** unknown), then no data transfer should have
** taken place.
*/
- if (cp->phys.header.lastp == NCB_SCRIPTH_PHYS (np, data_io))
- return cp->data_len;
+ if (cp->phys.header.lastp == NCB_SCRIPTH_PHYS (np, data_io))
+ return cp->orig_data_len;
/*
** If no data transfer occurs, or if the data
@@ -10676,7 +10679,7 @@
if (cp->startp == cp->phys.header.lastp ||
ncr_evaluate_dp(np, cp, scr_to_cpu(cp->phys.header.lastp),
&dp_ofs) < 0) {
- return cp->data_len;
+ return cp->orig_data_len;
}
/*
@@ -10685,14 +10688,13 @@
*/
dp_sgmin = MAX_SCATTER - cp->segments;
resid = -cp->ext_ofs;
- for (dp_sg = cp->ext_sg; dp_sg < MAX_SCATTER; ++dp_sg) {
+ for (dp_sg = cp->ext_sg; dp_sg < MAX_SCATTER; ++dp_sg) {
tmp = scr_to_cpu(cp->phys.data[dp_sg].size);
resid += (tmp & 0xffffff);
}
-
- /*
- ** Hopefully, the result is not too wrong.
- */
+
+ /* adjust based on original data length */
+ resid=cp->orig_data_len-(cp->data_len-resid);
return resid;
}
@@ -12096,6 +12098,7 @@
int segment;
cp->data_len = cmd->request_bufflen;
+ cp->orig_data_len = cmd->request_bufflen;
if (cmd->request_bufflen) {
dma_addr_t baddr = map_scsi_single_data(np, cmd);
@@ -12136,6 +12139,7 @@
int use_sg = (int) cmd->use_sg;
cp->data_len = 0;
+ cp->orig_data_len = cmd->request_bufflen;
if (!use_sg)
segn = ncr_scatter_no_sglist(np, cp, cmd);
@@ -12175,6 +12179,7 @@
int use_sg = (int) cmd->use_sg;
cp->data_len = 0;
+ cp->orig_data_len = cmd->request_bufflen;
if (!use_sg)
segment = ncr_scatter_no_sglist(np, cp, cmd);
@@ -12191,9 +12196,7 @@
dma_addr_t baddr = scsi_sg_dma_address(&scatter[segment]);
unsigned int len = scsi_sg_dma_len(&scatter[segment]);
- SCATTER_ONE(&data[segment],
- baddr,
- len);
+ SCATTER_ONE(&data[segment], baddr, len);
cp->data_len += len;
}
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2006-10-05 19:51 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-05 19:50 [PATCH] 2.4 sym53c8xx driver residual problem Jeremy Linton
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.