diff options
-rw-r--r-- | drivers/scsi/sg.c | 203 |
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 | ||
21 | static int sg_version_num = 30532; /* 2 digits for each component */ | 21 | static 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> |
63 | static char *sg_version_date = "20050117"; | 63 | static char *sg_version_date = "20050328"; |
64 | 64 | ||
65 | static int sg_proc_init(void); | 65 | static int sg_proc_init(void); |
66 | static void sg_proc_cleanup(void); | 66 | static void sg_proc_cleanup(void); |
@@ -330,14 +330,13 @@ sg_release(struct inode *inode, struct file *filp) | |||
330 | static ssize_t | 330 | static ssize_t |
331 | sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) | 331 | sg_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; |
476 | free_old_hdr: | ||
477 | if (old_hdr) | ||
478 | kfree(old_hdr); | ||
479 | return retval; | ||
441 | } | 480 | } |
442 | 481 | ||
443 | static ssize_t | 482 | static 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 | |||
1208 | sg_mmap(struct file *filp, struct vm_area_struct *vma) | 1263 | sg_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 | } |