aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-05-07 09:24:37 -0400
committerJens Axboe <jens.axboe@oracle.com>2009-05-11 03:50:53 -0400
commitc3a4d78c580de4edc9ef0f7c59812fb02ceb037f (patch)
tree916ca44287100707508678e2cc0eff0c43b9ca39 /drivers/scsi
parent9720aef2539c10e3a872e9a92beec225030d99db (diff)
block: add rq->resid_len
rq->data_len served two purposes - the length of data buffer on issue and the residual count on completion. This duality creates some headaches. First of all, block layer and low level drivers can't really determine what rq->data_len contains while a request is executing. It could be the total request length or it coulde be anything else one of the lower layers is using to keep track of residual count. This complicates things because blk_rq_bytes() and thus [__]blk_end_request_all() relies on rq->data_len for PC commands. Drivers which want to report residual count should first cache the total request length, update rq->data_len and then complete the request with the cached data length. Secondly, it makes requests default to reporting full residual count, ie. reporting that no data transfer occurred. The residual count is an exception not the norm; however, the driver should clear rq->data_len to zero to signify the normal cases while leaving it alone means no data transfer occurred at all. This reverse default behavior complicates code unnecessarily and renders block PC on some drivers (ide-tape/floppy) unuseable. This patch adds rq->resid_len which is used only for residual count. While at it, remove now unnecessasry blk_rq_bytes() caching in ide_pc_intr() as rq->data_len is not changed anymore. Boaz : spotted missing conversion in osd Sergei : spotted too early conversion to blk_rq_bytes() in ide-tape [ Impact: cleanup residual count handling, report 0 resid by default ] Signed-off-by: Tejun Heo <tj@kernel.org> Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Cc: Borislav Petkov <petkovbb@googlemail.com> Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com> Cc: Mike Miller <mike.miller@hp.com> Cc: Eric Moore <Eric.Moore@lsi.com> Cc: Alan Stern <stern@rowland.harvard.edu> Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Cc: Doug Gilbert <dgilbert@interlog.com> Cc: Mike Miller <mike.miller@hp.com> Cc: Eric Moore <Eric.Moore@lsi.com> Cc: Darrick J. Wong <djwong@us.ibm.com> Cc: Pete Zaitcev <zaitcev@redhat.com> Cc: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libsas/sas_expander.c6
-rw-r--r--drivers/scsi/libsas/sas_host_smp.c38
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c4
-rw-r--r--drivers/scsi/scsi_lib.c24
-rw-r--r--drivers/scsi/sg.c2
-rw-r--r--drivers/scsi/st.c2
6 files changed, 36 insertions, 40 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 3da02e436788..6605ec905cc0 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -1936,12 +1936,8 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1936 bio_data(rsp->bio), rsp->data_len); 1936 bio_data(rsp->bio), rsp->data_len);
1937 if (ret > 0) { 1937 if (ret > 0) {
1938 /* positive number is the untransferred residual */ 1938 /* positive number is the untransferred residual */
1939 rsp->data_len = ret; 1939 rsp->resid_len = ret;
1940 req->data_len = 0;
1941 ret = 0; 1940 ret = 0;
1942 } else if (ret == 0) {
1943 rsp->data_len = 0;
1944 req->data_len = 0;
1945 } 1941 }
1946 1942
1947 return ret; 1943 return ret;
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c
index d110a366c48a..89952edd0be3 100644
--- a/drivers/scsi/libsas/sas_host_smp.c
+++ b/drivers/scsi/libsas/sas_host_smp.c
@@ -134,7 +134,7 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
134{ 134{
135 u8 *req_data = NULL, *resp_data = NULL, *buf; 135 u8 *req_data = NULL, *resp_data = NULL, *buf;
136 struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); 136 struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
137 int error = -EINVAL, resp_data_len = rsp->data_len; 137 int error = -EINVAL;
138 138
139 /* eight is the minimum size for request and response frames */ 139 /* eight is the minimum size for request and response frames */
140 if (req->data_len < 8 || rsp->data_len < 8) 140 if (req->data_len < 8 || rsp->data_len < 8)
@@ -176,17 +176,20 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
176 resp_data[1] = req_data[1]; 176 resp_data[1] = req_data[1];
177 resp_data[2] = SMP_RESP_FUNC_UNK; 177 resp_data[2] = SMP_RESP_FUNC_UNK;
178 178
179 req->resid_len = req->data_len;
180 rsp->resid_len = rsp->data_len;
181
179 switch (req_data[1]) { 182 switch (req_data[1]) {
180 case SMP_REPORT_GENERAL: 183 case SMP_REPORT_GENERAL:
181 req->data_len -= 8; 184 req->resid_len -= 8;
182 resp_data_len -= 32; 185 rsp->resid_len -= 32;
183 resp_data[2] = SMP_RESP_FUNC_ACC; 186 resp_data[2] = SMP_RESP_FUNC_ACC;
184 resp_data[9] = sas_ha->num_phys; 187 resp_data[9] = sas_ha->num_phys;
185 break; 188 break;
186 189
187 case SMP_REPORT_MANUF_INFO: 190 case SMP_REPORT_MANUF_INFO:
188 req->data_len -= 8; 191 req->resid_len -= 8;
189 resp_data_len -= 64; 192 rsp->resid_len -= 64;
190 resp_data[2] = SMP_RESP_FUNC_ACC; 193 resp_data[2] = SMP_RESP_FUNC_ACC;
191 memcpy(resp_data + 12, shost->hostt->name, 194 memcpy(resp_data + 12, shost->hostt->name,
192 SAS_EXPANDER_VENDOR_ID_LEN); 195 SAS_EXPANDER_VENDOR_ID_LEN);
@@ -199,13 +202,13 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
199 break; 202 break;
200 203
201 case SMP_DISCOVER: 204 case SMP_DISCOVER:
202 req->data_len -= 16; 205 req->resid_len -= 16;
203 if ((int)req->data_len < 0) { 206 if ((int)req->resid_len < 0) {
204 req->data_len = 0; 207 req->resid_len = 0;
205 error = -EINVAL; 208 error = -EINVAL;
206 goto out; 209 goto out;
207 } 210 }
208 resp_data_len -= 56; 211 rsp->resid_len -= 56;
209 sas_host_smp_discover(sas_ha, resp_data, req_data[9]); 212 sas_host_smp_discover(sas_ha, resp_data, req_data[9]);
210 break; 213 break;
211 214
@@ -215,13 +218,13 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
215 break; 218 break;
216 219
217 case SMP_REPORT_PHY_SATA: 220 case SMP_REPORT_PHY_SATA:
218 req->data_len -= 16; 221 req->resid_len -= 16;
219 if ((int)req->data_len < 0) { 222 if ((int)req->resid_len < 0) {
220 req->data_len = 0; 223 req->resid_len = 0;
221 error = -EINVAL; 224 error = -EINVAL;
222 goto out; 225 goto out;
223 } 226 }
224 resp_data_len -= 60; 227 rsp->resid_len -= 60;
225 sas_report_phy_sata(sas_ha, resp_data, req_data[9]); 228 sas_report_phy_sata(sas_ha, resp_data, req_data[9]);
226 break; 229 break;
227 230
@@ -238,13 +241,13 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
238 break; 241 break;
239 242
240 case SMP_PHY_CONTROL: 243 case SMP_PHY_CONTROL:
241 req->data_len -= 44; 244 req->resid_len -= 44;
242 if ((int)req->data_len < 0) { 245 if ((int)req->resid_len < 0) {
243 req->data_len = 0; 246 req->resid_len = 0;
244 error = -EINVAL; 247 error = -EINVAL;
245 goto out; 248 goto out;
246 } 249 }
247 resp_data_len -= 8; 250 rsp->resid_len -= 8;
248 sas_phy_control(sas_ha, req_data[9], req_data[10], 251 sas_phy_control(sas_ha, req_data[9], req_data[10],
249 req_data[32] >> 4, req_data[33] >> 4, 252 req_data[32] >> 4, req_data[33] >> 4,
250 resp_data); 253 resp_data);
@@ -265,7 +268,6 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
265 flush_kernel_dcache_page(bio_page(rsp->bio)); 268 flush_kernel_dcache_page(bio_page(rsp->bio));
266 kunmap_atomic(buf - bio_offset(rsp->bio), KM_USER0); 269 kunmap_atomic(buf - bio_offset(rsp->bio), KM_USER0);
267 local_irq_enable(); 270 local_irq_enable();
268 rsp->data_len = resp_data_len;
269 271
270 out: 272 out:
271 kfree(req_data); 273 kfree(req_data);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index e03dc0b1e1a0..53759c566bfe 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -1170,9 +1170,7 @@ transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1170 1170
1171 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply)); 1171 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
1172 req->sense_len = sizeof(*mpi_reply); 1172 req->sense_len = sizeof(*mpi_reply);
1173 req->data_len = 0; 1173 rsp->resid_len = rsp->data_len - mpi_reply->ResponseDataLength;
1174 rsp->data_len -= mpi_reply->ResponseDataLength;
1175
1176 } else { 1174 } else {
1177 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT 1175 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
1178 "%s - no reply\n", ioc->name, __func__)); 1176 "%s - no reply\n", ioc->name, __func__));
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index aa9fc572e45f..7d49ef589f33 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -240,11 +240,11 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
240 * is invalid. Prevent the garbage from being misinterpreted 240 * is invalid. Prevent the garbage from being misinterpreted
241 * and prevent security leaks by zeroing out the excess data. 241 * and prevent security leaks by zeroing out the excess data.
242 */ 242 */
243 if (unlikely(req->data_len > 0 && req->data_len <= bufflen)) 243 if (unlikely(req->resid_len > 0 && req->resid_len <= bufflen))
244 memset(buffer + (bufflen - req->data_len), 0, req->data_len); 244 memset(buffer + (bufflen - req->resid_len), 0, req->resid_len);
245 245
246 if (resid) 246 if (resid)
247 *resid = req->data_len; 247 *resid = req->resid_len;
248 ret = req->errors; 248 ret = req->errors;
249 out: 249 out:
250 blk_put_request(req); 250 blk_put_request(req);
@@ -549,7 +549,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,
549 int leftover = (req->hard_nr_sectors << 9); 549 int leftover = (req->hard_nr_sectors << 9);
550 550
551 if (blk_pc_request(req)) 551 if (blk_pc_request(req))
552 leftover = req->data_len; 552 leftover = req->resid_len;
553 553
554 /* kill remainder if no retrys */ 554 /* kill remainder if no retrys */
555 if (error && scsi_noretry_cmd(cmd)) 555 if (error && scsi_noretry_cmd(cmd))
@@ -673,11 +673,11 @@ void scsi_release_buffers(struct scsi_cmnd *cmd)
673EXPORT_SYMBOL(scsi_release_buffers); 673EXPORT_SYMBOL(scsi_release_buffers);
674 674
675/* 675/*
676 * Bidi commands Must be complete as a whole, both sides at once. 676 * Bidi commands Must be complete as a whole, both sides at once. If
677 * If part of the bytes were written and lld returned 677 * part of the bytes were written and lld returned scsi_in()->resid
678 * scsi_in()->resid and/or scsi_out()->resid this information will be left 678 * and/or scsi_out()->resid this information will be left in
679 * in req->data_len and req->next_rq->data_len. The upper-layer driver can 679 * req->resid_len and req->next_rq->resid_len. The upper-layer driver
680 * decide what to do with this information. 680 * can decide what to do with this information.
681 */ 681 */
682static void scsi_end_bidi_request(struct scsi_cmnd *cmd) 682static void scsi_end_bidi_request(struct scsi_cmnd *cmd)
683{ 683{
@@ -685,8 +685,8 @@ static void scsi_end_bidi_request(struct scsi_cmnd *cmd)
685 unsigned int dlen = req->data_len; 685 unsigned int dlen = req->data_len;
686 unsigned int next_dlen = req->next_rq->data_len; 686 unsigned int next_dlen = req->next_rq->data_len;
687 687
688 req->data_len = scsi_out(cmd)->resid; 688 req->resid_len = scsi_out(cmd)->resid;
689 req->next_rq->data_len = scsi_in(cmd)->resid; 689 req->next_rq->resid_len = scsi_in(cmd)->resid;
690 690
691 /* The req and req->next_rq have not been completed */ 691 /* The req and req->next_rq have not been completed */
692 BUG_ON(blk_end_bidi_request(req, 0, dlen, next_dlen)); 692 BUG_ON(blk_end_bidi_request(req, 0, dlen, next_dlen));
@@ -778,7 +778,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
778 scsi_end_bidi_request(cmd); 778 scsi_end_bidi_request(cmd);
779 return; 779 return;
780 } 780 }
781 req->data_len = scsi_get_resid(cmd); 781 req->resid_len = scsi_get_resid(cmd);
782 } 782 }
783 783
784 BUG_ON(blk_bidi_rq(req)); /* bidi not support for !blk_pc_request yet */ 784 BUG_ON(blk_bidi_rq(req)); /* bidi not support for !blk_pc_request yet */
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 82312df9b0bf..dec4c70677de 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1260,7 +1260,7 @@ static void sg_rq_end_io(struct request *rq, int uptodate)
1260 1260
1261 sense = rq->sense; 1261 sense = rq->sense;
1262 result = rq->errors; 1262 result = rq->errors;
1263 resid = rq->data_len; 1263 resid = rq->resid_len;
1264 1264
1265 SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n", 1265 SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n",
1266 sdp->disk->disk_name, srp->header.pack_id, result)); 1266 sdp->disk->disk_name, srp->header.pack_id, result));
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index eb24efea8f14..8681b708344f 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -463,7 +463,7 @@ static void st_scsi_execute_end(struct request *req, int uptodate)
463 struct scsi_tape *STp = SRpnt->stp; 463 struct scsi_tape *STp = SRpnt->stp;
464 464
465 STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors; 465 STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
466 STp->buffer->cmdstat.residual = req->data_len; 466 STp->buffer->cmdstat.residual = req->resid_len;
467 467
468 if (SRpnt->waiting) 468 if (SRpnt->waiting)
469 complete(SRpnt->waiting); 469 complete(SRpnt->waiting);