aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/sg.c')
-rw-r--r--drivers/scsi/sg.c203
1 files changed, 132 insertions, 71 deletions
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index cf6b1f0fb124..ce8332297dfa 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -18,8 +18,8 @@
18 * 18 *
19 */ 19 */
20 20
21static int sg_version_num = 30532; /* 2 digits for each component */ 21static int sg_version_num = 30533; /* 2 digits for each component */
22#define SG_VERSION_STR "3.5.32" 22#define SG_VERSION_STR "3.5.33"
23 23
24/* 24/*
25 * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: 25 * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes:
@@ -61,7 +61,7 @@ static int sg_version_num = 30532; /* 2 digits for each component */
61 61
62#ifdef CONFIG_SCSI_PROC_FS 62#ifdef CONFIG_SCSI_PROC_FS
63#include <linux/proc_fs.h> 63#include <linux/proc_fs.h>
64static char *sg_version_date = "20050117"; 64static char *sg_version_date = "20050328";
65 65
66static int sg_proc_init(void); 66static int sg_proc_init(void);
67static void sg_proc_cleanup(void); 67static void sg_proc_cleanup(void);
@@ -331,14 +331,13 @@ sg_release(struct inode *inode, struct file *filp)
331static ssize_t 331static ssize_t
332sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) 332sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
333{ 333{
334 int res;
335 Sg_device *sdp; 334 Sg_device *sdp;
336 Sg_fd *sfp; 335 Sg_fd *sfp;
337 Sg_request *srp; 336 Sg_request *srp;
338 int req_pack_id = -1; 337 int req_pack_id = -1;
339 struct sg_header old_hdr;
340 sg_io_hdr_t new_hdr;
341 sg_io_hdr_t *hp; 338 sg_io_hdr_t *hp;
339 struct sg_header *old_hdr = NULL;
340 int retval = 0;
342 341
343 if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) 342 if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
344 return -ENXIO; 343 return -ENXIO;
@@ -347,98 +346,138 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
347 if (!access_ok(VERIFY_WRITE, buf, count)) 346 if (!access_ok(VERIFY_WRITE, buf, count))
348 return -EFAULT; 347 return -EFAULT;
349 if (sfp->force_packid && (count >= SZ_SG_HEADER)) { 348 if (sfp->force_packid && (count >= SZ_SG_HEADER)) {
350 if (__copy_from_user(&old_hdr, buf, SZ_SG_HEADER)) 349 old_hdr = kmalloc(SZ_SG_HEADER, GFP_KERNEL);
351 return -EFAULT; 350 if (!old_hdr)
352 if (old_hdr.reply_len < 0) { 351 return -ENOMEM;
352 if (__copy_from_user(old_hdr, buf, SZ_SG_HEADER)) {
353 retval = -EFAULT;
354 goto free_old_hdr;
355 }
356 if (old_hdr->reply_len < 0) {
353 if (count >= SZ_SG_IO_HDR) { 357 if (count >= SZ_SG_IO_HDR) {
354 if (__copy_from_user 358 sg_io_hdr_t *new_hdr;
355 (&new_hdr, buf, SZ_SG_IO_HDR)) 359 new_hdr = kmalloc(SZ_SG_IO_HDR, GFP_KERNEL);
356 return -EFAULT; 360 if (!new_hdr) {
357 req_pack_id = new_hdr.pack_id; 361 retval = -ENOMEM;
362 goto free_old_hdr;
363 }
364 retval =__copy_from_user
365 (new_hdr, buf, SZ_SG_IO_HDR);
366 req_pack_id = new_hdr->pack_id;
367 kfree(new_hdr);
368 if (retval) {
369 retval = -EFAULT;
370 goto free_old_hdr;
371 }
358 } 372 }
359 } else 373 } else
360 req_pack_id = old_hdr.pack_id; 374 req_pack_id = old_hdr->pack_id;
361 } 375 }
362 srp = sg_get_rq_mark(sfp, req_pack_id); 376 srp = sg_get_rq_mark(sfp, req_pack_id);
363 if (!srp) { /* now wait on packet to arrive */ 377 if (!srp) { /* now wait on packet to arrive */
364 if (sdp->detached) 378 if (sdp->detached) {
365 return -ENODEV; 379 retval = -ENODEV;
366 if (filp->f_flags & O_NONBLOCK) 380 goto free_old_hdr;
367 return -EAGAIN; 381 }
382 if (filp->f_flags & O_NONBLOCK) {
383 retval = -EAGAIN;
384 goto free_old_hdr;
385 }
368 while (1) { 386 while (1) {
369 res = 0; /* following is a macro that beats race condition */ 387 retval = 0; /* following macro beats race condition */
370 __wait_event_interruptible(sfp->read_wait, 388 __wait_event_interruptible(sfp->read_wait,
371 (sdp->detached || (srp = sg_get_rq_mark(sfp, req_pack_id))), 389 (sdp->detached ||
372 res); 390 (srp = sg_get_rq_mark(sfp, req_pack_id))),
373 if (sdp->detached) 391 retval);
374 return -ENODEV; 392 if (sdp->detached) {
375 if (0 == res) 393 retval = -ENODEV;
394 goto free_old_hdr;
395 }
396 if (0 == retval)
376 break; 397 break;
377 return res; /* -ERESTARTSYS because signal hit process */ 398
399 /* -ERESTARTSYS as signal hit process */
400 goto free_old_hdr;
378 } 401 }
379 } 402 }
380 if (srp->header.interface_id != '\0') 403 if (srp->header.interface_id != '\0') {
381 return sg_new_read(sfp, buf, count, srp); 404 retval = sg_new_read(sfp, buf, count, srp);
405 goto free_old_hdr;
406 }
382 407
383 hp = &srp->header; 408 hp = &srp->header;
384 memset(&old_hdr, 0, SZ_SG_HEADER); 409 if (old_hdr == NULL) {
385 old_hdr.reply_len = (int) hp->timeout; 410 old_hdr = kmalloc(SZ_SG_HEADER, GFP_KERNEL);
386 old_hdr.pack_len = old_hdr.reply_len; /* very old, strange behaviour */ 411 if (! old_hdr) {
387 old_hdr.pack_id = hp->pack_id; 412 retval = -ENOMEM;
388 old_hdr.twelve_byte = 413 goto free_old_hdr;
414 }
415 }
416 memset(old_hdr, 0, SZ_SG_HEADER);
417 old_hdr->reply_len = (int) hp->timeout;
418 old_hdr->pack_len = old_hdr->reply_len; /* old, strange behaviour */
419 old_hdr->pack_id = hp->pack_id;
420 old_hdr->twelve_byte =
389 ((srp->data.cmd_opcode >= 0xc0) && (12 == hp->cmd_len)) ? 1 : 0; 421 ((srp->data.cmd_opcode >= 0xc0) && (12 == hp->cmd_len)) ? 1 : 0;
390 old_hdr.target_status = hp->masked_status; 422 old_hdr->target_status = hp->masked_status;
391 old_hdr.host_status = hp->host_status; 423 old_hdr->host_status = hp->host_status;
392 old_hdr.driver_status = hp->driver_status; 424 old_hdr->driver_status = hp->driver_status;
393 if ((CHECK_CONDITION & hp->masked_status) || 425 if ((CHECK_CONDITION & hp->masked_status) ||
394 (DRIVER_SENSE & hp->driver_status)) 426 (DRIVER_SENSE & hp->driver_status))
395 memcpy(old_hdr.sense_buffer, srp->sense_b, 427 memcpy(old_hdr->sense_buffer, srp->sense_b,
396 sizeof (old_hdr.sense_buffer)); 428 sizeof (old_hdr->sense_buffer));
397 switch (hp->host_status) { 429 switch (hp->host_status) {
398 /* This setup of 'result' is for backward compatibility and is best 430 /* This setup of 'result' is for backward compatibility and is best
399 ignored by the user who should use target, host + driver status */ 431 ignored by the user who should use target, host + driver status */
400 case DID_OK: 432 case DID_OK:
401 case DID_PASSTHROUGH: 433 case DID_PASSTHROUGH:
402 case DID_SOFT_ERROR: 434 case DID_SOFT_ERROR:
403 old_hdr.result = 0; 435 old_hdr->result = 0;
404 break; 436 break;
405 case DID_NO_CONNECT: 437 case DID_NO_CONNECT:
406 case DID_BUS_BUSY: 438 case DID_BUS_BUSY:
407 case DID_TIME_OUT: 439 case DID_TIME_OUT:
408 old_hdr.result = EBUSY; 440 old_hdr->result = EBUSY;
409 break; 441 break;
410 case DID_BAD_TARGET: 442 case DID_BAD_TARGET:
411 case DID_ABORT: 443 case DID_ABORT:
412 case DID_PARITY: 444 case DID_PARITY:
413 case DID_RESET: 445 case DID_RESET:
414 case DID_BAD_INTR: 446 case DID_BAD_INTR:
415 old_hdr.result = EIO; 447 old_hdr->result = EIO;
416 break; 448 break;
417 case DID_ERROR: 449 case DID_ERROR:
418 old_hdr.result = (srp->sense_b[0] == 0 && 450 old_hdr->result = (srp->sense_b[0] == 0 &&
419 hp->masked_status == GOOD) ? 0 : EIO; 451 hp->masked_status == GOOD) ? 0 : EIO;
420 break; 452 break;
421 default: 453 default:
422 old_hdr.result = EIO; 454 old_hdr->result = EIO;
423 break; 455 break;
424 } 456 }
425 457
426 /* Now copy the result back to the user buffer. */ 458 /* Now copy the result back to the user buffer. */
427 if (count >= SZ_SG_HEADER) { 459 if (count >= SZ_SG_HEADER) {
428 if (__copy_to_user(buf, &old_hdr, SZ_SG_HEADER)) 460 if (__copy_to_user(buf, old_hdr, SZ_SG_HEADER)) {
429 return -EFAULT; 461 retval = -EFAULT;
462 goto free_old_hdr;
463 }
430 buf += SZ_SG_HEADER; 464 buf += SZ_SG_HEADER;
431 if (count > old_hdr.reply_len) 465 if (count > old_hdr->reply_len)
432 count = old_hdr.reply_len; 466 count = old_hdr->reply_len;
433 if (count > SZ_SG_HEADER) { 467 if (count > SZ_SG_HEADER) {
434 if ((res = 468 if (sg_read_oxfer(srp, buf, count - SZ_SG_HEADER)) {
435 sg_read_oxfer(srp, buf, count - SZ_SG_HEADER))) 469 retval = -EFAULT;
436 return -EFAULT; 470 goto free_old_hdr;
471 }
437 } 472 }
438 } else 473 } else
439 count = (old_hdr.result == 0) ? 0 : -EIO; 474 count = (old_hdr->result == 0) ? 0 : -EIO;
440 sg_finish_rem_req(srp); 475 sg_finish_rem_req(srp);
441 return count; 476 retval = count;
477free_old_hdr:
478 if (old_hdr)
479 kfree(old_hdr);
480 return retval;
442} 481}
443 482
444static ssize_t 483static ssize_t
@@ -725,7 +764,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
725 srp->data.sglist_len = 0; 764 srp->data.sglist_len = 0;
726 srp->data.bufflen = 0; 765 srp->data.bufflen = 0;
727 srp->data.buffer = NULL; 766 srp->data.buffer = NULL;
728 hp->duration = jiffies; /* unit jiffies now, millisecs after done */ 767 hp->duration = jiffies_to_msecs(jiffies);
729/* Now send everything of to mid-level. The next time we hear about this 768/* Now send everything of to mid-level. The next time we hear about this
730 packet is when sg_cmd_done() is called (i.e. a callback). */ 769 packet is when sg_cmd_done() is called (i.e. a callback). */
731 scsi_do_req(SRpnt, (void *) cmnd, 770 scsi_do_req(SRpnt, (void *) cmnd,
@@ -938,8 +977,13 @@ sg_ioctl(struct inode *inode, struct file *filp,
938 if (!access_ok(VERIFY_WRITE, p, SZ_SG_REQ_INFO * SG_MAX_QUEUE)) 977 if (!access_ok(VERIFY_WRITE, p, SZ_SG_REQ_INFO * SG_MAX_QUEUE))
939 return -EFAULT; 978 return -EFAULT;
940 else { 979 else {
941 sg_req_info_t rinfo[SG_MAX_QUEUE]; 980 sg_req_info_t *rinfo;
942 Sg_request *srp; 981 unsigned int ms;
982
983 rinfo = kmalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE,
984 GFP_KERNEL);
985 if (!rinfo)
986 return -ENOMEM;
943 read_lock_irqsave(&sfp->rq_list_lock, iflags); 987 read_lock_irqsave(&sfp->rq_list_lock, iflags);
944 for (srp = sfp->headrp, val = 0; val < SG_MAX_QUEUE; 988 for (srp = sfp->headrp, val = 0; val < SG_MAX_QUEUE;
945 ++val, srp = srp ? srp->nextrp : srp) { 989 ++val, srp = srp ? srp->nextrp : srp) {
@@ -950,19 +994,30 @@ sg_ioctl(struct inode *inode, struct file *filp,
950 srp->header.masked_status & 994 srp->header.masked_status &
951 srp->header.host_status & 995 srp->header.host_status &
952 srp->header.driver_status; 996 srp->header.driver_status;
953 rinfo[val].duration = 997 if (srp->done)
954 srp->done ? srp->header.duration : 998 rinfo[val].duration =
955 jiffies_to_msecs( 999 srp->header.duration;
956 jiffies - srp->header.duration); 1000 else {
1001 ms = jiffies_to_msecs(jiffies);
1002 rinfo[val].duration =
1003 (ms > srp->header.duration) ?
1004 (ms - srp->header.duration) : 0;
1005 }
957 rinfo[val].orphan = srp->orphan; 1006 rinfo[val].orphan = srp->orphan;
958 rinfo[val].sg_io_owned = srp->sg_io_owned; 1007 rinfo[val].sg_io_owned =
959 rinfo[val].pack_id = srp->header.pack_id; 1008 srp->sg_io_owned;
960 rinfo[val].usr_ptr = srp->header.usr_ptr; 1009 rinfo[val].pack_id =
1010 srp->header.pack_id;
1011 rinfo[val].usr_ptr =
1012 srp->header.usr_ptr;
961 } 1013 }
962 } 1014 }
963 read_unlock_irqrestore(&sfp->rq_list_lock, iflags); 1015 read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
964 return (__copy_to_user(p, rinfo, 1016 result = __copy_to_user(p, rinfo,
965 SZ_SG_REQ_INFO * SG_MAX_QUEUE) ? -EFAULT : 0); 1017 SZ_SG_REQ_INFO * SG_MAX_QUEUE);
1018 result = result ? -EFAULT : 0;
1019 kfree(rinfo);
1020 return result;
966 } 1021 }
967 case SG_EMULATED_HOST: 1022 case SG_EMULATED_HOST:
968 if (sdp->detached) 1023 if (sdp->detached)
@@ -1209,11 +1264,12 @@ static int
1209sg_mmap(struct file *filp, struct vm_area_struct *vma) 1264sg_mmap(struct file *filp, struct vm_area_struct *vma)
1210{ 1265{
1211 Sg_fd *sfp; 1266 Sg_fd *sfp;
1212 unsigned long req_sz = vma->vm_end - vma->vm_start; 1267 unsigned long req_sz;
1213 Sg_scatter_hold *rsv_schp; 1268 Sg_scatter_hold *rsv_schp;
1214 1269
1215 if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data))) 1270 if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data)))
1216 return -ENXIO; 1271 return -ENXIO;
1272 req_sz = vma->vm_end - vma->vm_start;
1217 SCSI_LOG_TIMEOUT(3, printk("sg_mmap starting, vm_start=%p, len=%d\n", 1273 SCSI_LOG_TIMEOUT(3, printk("sg_mmap starting, vm_start=%p, len=%d\n",
1218 (void *) vma->vm_start, (int) req_sz)); 1274 (void *) vma->vm_start, (int) req_sz));
1219 if (vma->vm_pgoff) 1275 if (vma->vm_pgoff)
@@ -1260,6 +1316,7 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
1260 Sg_fd *sfp; 1316 Sg_fd *sfp;
1261 Sg_request *srp = NULL; 1317 Sg_request *srp = NULL;
1262 unsigned long iflags; 1318 unsigned long iflags;
1319 unsigned int ms;
1263 1320
1264 if (SCpnt && (SRpnt = SCpnt->sc_request)) 1321 if (SCpnt && (SRpnt = SCpnt->sc_request))
1265 srp = (Sg_request *) SRpnt->upper_private_data; 1322 srp = (Sg_request *) SRpnt->upper_private_data;
@@ -1296,9 +1353,9 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
1296 SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n", 1353 SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n",
1297 sdp->disk->disk_name, srp->header.pack_id, (int) SRpnt->sr_result)); 1354 sdp->disk->disk_name, srp->header.pack_id, (int) SRpnt->sr_result));
1298 srp->header.resid = SCpnt->resid; 1355 srp->header.resid = SCpnt->resid;
1299 /* N.B. unit of duration changes here from jiffies to millisecs */ 1356 ms = jiffies_to_msecs(jiffies);
1300 srp->header.duration = 1357 srp->header.duration = (ms > srp->header.duration) ?
1301 jiffies_to_msecs(jiffies - srp->header.duration); 1358 (ms - srp->header.duration) : 0;
1302 if (0 != SRpnt->sr_result) { 1359 if (0 != SRpnt->sr_result) {
1303 struct scsi_sense_hdr sshdr; 1360 struct scsi_sense_hdr sshdr;
1304 1361
@@ -2396,7 +2453,7 @@ sg_add_request(Sg_fd * sfp)
2396 } 2453 }
2397 if (resp) { 2454 if (resp) {
2398 resp->nextrp = NULL; 2455 resp->nextrp = NULL;
2399 resp->header.duration = jiffies; 2456 resp->header.duration = jiffies_to_msecs(jiffies);
2400 resp->my_cmdp = NULL; 2457 resp->my_cmdp = NULL;
2401 } 2458 }
2402 write_unlock_irqrestore(&sfp->rq_list_lock, iflags); 2459 write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
@@ -2991,6 +3048,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
2991 Sg_fd *fp; 3048 Sg_fd *fp;
2992 const sg_io_hdr_t *hp; 3049 const sg_io_hdr_t *hp;
2993 const char * cp; 3050 const char * cp;
3051 unsigned int ms;
2994 3052
2995 for (k = 0; (fp = sg_get_nth_sfp(sdp, k)); ++k) { 3053 for (k = 0; (fp = sg_get_nth_sfp(sdp, k)); ++k) {
2996 seq_printf(s, " FD(%d): timeout=%dms bufflen=%d " 3054 seq_printf(s, " FD(%d): timeout=%dms bufflen=%d "
@@ -3029,10 +3087,13 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
3029 srp->header.pack_id, blen); 3087 srp->header.pack_id, blen);
3030 if (srp->done) 3088 if (srp->done)
3031 seq_printf(s, " dur=%d", hp->duration); 3089 seq_printf(s, " dur=%d", hp->duration);
3032 else 3090 else {
3091 ms = jiffies_to_msecs(jiffies);
3033 seq_printf(s, " t_o/elap=%d/%d", 3092 seq_printf(s, " t_o/elap=%d/%d",
3034 new_interface ? hp->timeout : jiffies_to_msecs(fp->timeout), 3093 (new_interface ? hp->timeout :
3035 jiffies_to_msecs(hp->duration ? (jiffies - hp->duration) : 0)); 3094 jiffies_to_msecs(fp->timeout)),
3095 (ms > hp->duration ? ms - hp->duration : 0));
3096 }
3036 seq_printf(s, "ms sgat=%d op=0x%02x\n", usg, 3097 seq_printf(s, "ms sgat=%d op=0x%02x\n", usg,
3037 (int) srp->data.cmd_opcode); 3098 (int) srp->data.cmd_opcode);
3038 } 3099 }