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