[PATCH] 2.4 sym53c8xx driver residual problem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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). 



--- 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;
 		}
 	}

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux