aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/st.c150
-rw-r--r--drivers/scsi/st.h3
2 files changed, 123 insertions, 30 deletions
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 0291a8fb654d..47a5698a712a 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -17,7 +17,7 @@
17 Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support 17 Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
18 */ 18 */
19 19
20static char *verstr = "20050501"; 20static char *verstr = "20050802";
21 21
22#include <linux/module.h> 22#include <linux/module.h>
23 23
@@ -219,6 +219,12 @@ static int switch_partition(struct scsi_tape *);
219 219
220static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long); 220static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);
221 221
222static void scsi_tape_release(struct kref *);
223
224#define to_scsi_tape(obj) container_of(obj, struct scsi_tape, kref)
225
226static DECLARE_MUTEX(st_ref_sem);
227
222 228
223#include "osst_detect.h" 229#include "osst_detect.h"
224#ifndef SIGS_FROM_OSST 230#ifndef SIGS_FROM_OSST
@@ -230,6 +236,46 @@ static int st_int_ioctl(struct scsi_tape *, unsigned int, unsigned long);
230 {"OnStream", "FW-", "", "osst"} 236 {"OnStream", "FW-", "", "osst"}
231#endif 237#endif
232 238
239static struct scsi_tape *scsi_tape_get(int dev)
240{
241 struct scsi_tape *STp = NULL;
242
243 down(&st_ref_sem);
244 write_lock(&st_dev_arr_lock);
245
246 if (dev < st_dev_max && scsi_tapes != NULL)
247 STp = scsi_tapes[dev];
248 if (!STp) goto out;
249
250 kref_get(&STp->kref);
251
252 if (!STp->device)
253 goto out_put;
254
255 if (scsi_device_get(STp->device))
256 goto out_put;
257
258 goto out;
259
260out_put:
261 kref_put(&STp->kref, scsi_tape_release);
262 STp = NULL;
263out:
264 write_unlock(&st_dev_arr_lock);
265 up(&st_ref_sem);
266 return STp;
267}
268
269static void scsi_tape_put(struct scsi_tape *STp)
270{
271 struct scsi_device *sdev = STp->device;
272
273 down(&st_ref_sem);
274 kref_put(&STp->kref, scsi_tape_release);
275 scsi_device_put(sdev);
276 up(&st_ref_sem);
277}
278
233struct st_reject_data { 279struct st_reject_data {
234 char *vendor; 280 char *vendor;
235 char *model; 281 char *model;
@@ -311,7 +357,7 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
311 return 0; 357 return 0;
312 358
313 cmdstatp = &STp->buffer->cmdstat; 359 cmdstatp = &STp->buffer->cmdstat;
314 st_analyze_sense(STp->buffer->last_SRpnt, cmdstatp); 360 st_analyze_sense(SRpnt, cmdstatp);
315 361
316 if (cmdstatp->have_sense) 362 if (cmdstatp->have_sense)
317 scode = STp->buffer->cmdstat.sense_hdr.sense_key; 363 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
@@ -399,10 +445,10 @@ static void st_sleep_done(struct scsi_cmnd * SCpnt)
399 445
400 (STp->buffer)->cmdstat.midlevel_result = SCpnt->result; 446 (STp->buffer)->cmdstat.midlevel_result = SCpnt->result;
401 SCpnt->request->rq_status = RQ_SCSI_DONE; 447 SCpnt->request->rq_status = RQ_SCSI_DONE;
402 (STp->buffer)->last_SRpnt = SCpnt->sc_request;
403 DEB( STp->write_pending = 0; ) 448 DEB( STp->write_pending = 0; )
404 449
405 complete(SCpnt->request->waiting); 450 if (SCpnt->request->waiting)
451 complete(SCpnt->request->waiting);
406} 452}
407 453
408/* Do the scsi command. Waits until command performed if do_wait is true. 454/* Do the scsi command. Waits until command performed if do_wait is true.
@@ -412,8 +458,20 @@ static struct scsi_request *
412st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd, 458st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
413 int bytes, int direction, int timeout, int retries, int do_wait) 459 int bytes, int direction, int timeout, int retries, int do_wait)
414{ 460{
461 struct completion *waiting;
415 unsigned char *bp; 462 unsigned char *bp;
416 463
464 /* if async, make sure there's no command outstanding */
465 if (!do_wait && ((STp->buffer)->last_SRpnt)) {
466 printk(KERN_ERR "%s: Async command already active.\n",
467 tape_name(STp));
468 if (signal_pending(current))
469 (STp->buffer)->syscall_result = (-EINTR);
470 else
471 (STp->buffer)->syscall_result = (-EBUSY);
472 return NULL;
473 }
474
417 if (SRpnt == NULL) { 475 if (SRpnt == NULL) {
418 SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC); 476 SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC);
419 if (SRpnt == NULL) { 477 if (SRpnt == NULL) {
@@ -427,7 +485,13 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
427 } 485 }
428 } 486 }
429 487
430 init_completion(&STp->wait); 488 /* If async IO, set last_SRpnt. This ptr tells write_behind_check
489 which IO is outstanding. It's nulled out when the IO completes. */
490 if (!do_wait)
491 (STp->buffer)->last_SRpnt = SRpnt;
492
493 waiting = &STp->wait;
494 init_completion(waiting);
431 SRpnt->sr_use_sg = STp->buffer->do_dio || (bytes > (STp->buffer)->frp[0].length); 495 SRpnt->sr_use_sg = STp->buffer->do_dio || (bytes > (STp->buffer)->frp[0].length);
432 if (SRpnt->sr_use_sg) { 496 if (SRpnt->sr_use_sg) {
433 if (!STp->buffer->do_dio) 497 if (!STp->buffer->do_dio)
@@ -438,17 +502,20 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
438 bp = (STp->buffer)->b_data; 502 bp = (STp->buffer)->b_data;
439 SRpnt->sr_data_direction = direction; 503 SRpnt->sr_data_direction = direction;
440 SRpnt->sr_cmd_len = 0; 504 SRpnt->sr_cmd_len = 0;
441 SRpnt->sr_request->waiting = &(STp->wait); 505 SRpnt->sr_request->waiting = waiting;
442 SRpnt->sr_request->rq_status = RQ_SCSI_BUSY; 506 SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
443 SRpnt->sr_request->rq_disk = STp->disk; 507 SRpnt->sr_request->rq_disk = STp->disk;
508 SRpnt->sr_request->end_io = blk_end_sync_rq;
444 STp->buffer->cmdstat.have_sense = 0; 509 STp->buffer->cmdstat.have_sense = 0;
445 510
446 scsi_do_req(SRpnt, (void *) cmd, bp, bytes, 511 scsi_do_req(SRpnt, (void *) cmd, bp, bytes,
447 st_sleep_done, timeout, retries); 512 st_sleep_done, timeout, retries);
448 513
449 if (do_wait) { 514 if (do_wait) {
450 wait_for_completion(SRpnt->sr_request->waiting); 515 wait_for_completion(waiting);
451 SRpnt->sr_request->waiting = NULL; 516 SRpnt->sr_request->waiting = NULL;
517 if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
518 SRpnt->sr_result |= (DRIVER_ERROR << 24);
452 (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt); 519 (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
453 } 520 }
454 return SRpnt; 521 return SRpnt;
@@ -465,6 +532,7 @@ static int write_behind_check(struct scsi_tape * STp)
465 struct st_buffer *STbuffer; 532 struct st_buffer *STbuffer;
466 struct st_partstat *STps; 533 struct st_partstat *STps;
467 struct st_cmdstatus *cmdstatp; 534 struct st_cmdstatus *cmdstatp;
535 struct scsi_request *SRpnt;
468 536
469 STbuffer = STp->buffer; 537 STbuffer = STp->buffer;
470 if (!STbuffer->writing) 538 if (!STbuffer->writing)
@@ -478,10 +546,14 @@ static int write_behind_check(struct scsi_tape * STp)
478 ) /* end DEB */ 546 ) /* end DEB */
479 547
480 wait_for_completion(&(STp->wait)); 548 wait_for_completion(&(STp->wait));
481 (STp->buffer)->last_SRpnt->sr_request->waiting = NULL; 549 SRpnt = STbuffer->last_SRpnt;
550 STbuffer->last_SRpnt = NULL;
551 SRpnt->sr_request->waiting = NULL;
552 if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
553 SRpnt->sr_result |= (DRIVER_ERROR << 24);
482 554
483 (STp->buffer)->syscall_result = st_chk_result(STp, (STp->buffer)->last_SRpnt); 555 (STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
484 scsi_release_request((STp->buffer)->last_SRpnt); 556 scsi_release_request(SRpnt);
485 557
486 STbuffer->buffer_bytes -= STbuffer->writing; 558 STbuffer->buffer_bytes -= STbuffer->writing;
487 STps = &(STp->ps[STp->partition]); 559 STps = &(STp->ps[STp->partition]);
@@ -1055,25 +1127,20 @@ static int st_open(struct inode *inode, struct file *filp)
1055 */ 1127 */
1056 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE); 1128 filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
1057 1129
1130 if (!(STp = scsi_tape_get(dev)))
1131 return -ENXIO;
1132
1058 write_lock(&st_dev_arr_lock); 1133 write_lock(&st_dev_arr_lock);
1059 if (dev >= st_dev_max || scsi_tapes == NULL ||
1060 ((STp = scsi_tapes[dev]) == NULL)) {
1061 write_unlock(&st_dev_arr_lock);
1062 return (-ENXIO);
1063 }
1064 filp->private_data = STp; 1134 filp->private_data = STp;
1065 name = tape_name(STp); 1135 name = tape_name(STp);
1066 1136
1067 if (STp->in_use) { 1137 if (STp->in_use) {
1068 write_unlock(&st_dev_arr_lock); 1138 write_unlock(&st_dev_arr_lock);
1139 scsi_tape_put(STp);
1069 DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); ) 1140 DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); )
1070 return (-EBUSY); 1141 return (-EBUSY);
1071 } 1142 }
1072 1143
1073 if(scsi_device_get(STp->device)) {
1074 write_unlock(&st_dev_arr_lock);
1075 return (-ENXIO);
1076 }
1077 STp->in_use = 1; 1144 STp->in_use = 1;
1078 write_unlock(&st_dev_arr_lock); 1145 write_unlock(&st_dev_arr_lock);
1079 STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0; 1146 STp->rew_at_close = STp->autorew_dev = (iminor(inode) & 0x80) == 0;
@@ -1118,7 +1185,7 @@ static int st_open(struct inode *inode, struct file *filp)
1118 err_out: 1185 err_out:
1119 normalize_buffer(STp->buffer); 1186 normalize_buffer(STp->buffer);
1120 STp->in_use = 0; 1187 STp->in_use = 0;
1121 scsi_device_put(STp->device); 1188 scsi_tape_put(STp);
1122 return retval; 1189 return retval;
1123 1190
1124} 1191}
@@ -1250,7 +1317,7 @@ static int st_release(struct inode *inode, struct file *filp)
1250 write_lock(&st_dev_arr_lock); 1317 write_lock(&st_dev_arr_lock);
1251 STp->in_use = 0; 1318 STp->in_use = 0;
1252 write_unlock(&st_dev_arr_lock); 1319 write_unlock(&st_dev_arr_lock);
1253 scsi_device_put(STp->device); 1320 scsi_tape_put(STp);
1254 1321
1255 return result; 1322 return result;
1256} 1323}
@@ -3887,6 +3954,7 @@ static int st_probe(struct device *dev)
3887 goto out_put_disk; 3954 goto out_put_disk;
3888 } 3955 }
3889 memset(tpnt, 0, sizeof(struct scsi_tape)); 3956 memset(tpnt, 0, sizeof(struct scsi_tape));
3957 kref_init(&tpnt->kref);
3890 tpnt->disk = disk; 3958 tpnt->disk = disk;
3891 sprintf(disk->disk_name, "st%d", i); 3959 sprintf(disk->disk_name, "st%d", i);
3892 disk->private_data = &tpnt->driver; 3960 disk->private_data = &tpnt->driver;
@@ -3902,6 +3970,7 @@ static int st_probe(struct device *dev)
3902 tpnt->tape_type = MT_ISSCSI2; 3970 tpnt->tape_type = MT_ISSCSI2;
3903 3971
3904 tpnt->buffer = buffer; 3972 tpnt->buffer = buffer;
3973 tpnt->buffer->last_SRpnt = NULL;
3905 3974
3906 tpnt->inited = 0; 3975 tpnt->inited = 0;
3907 tpnt->dirty = 0; 3976 tpnt->dirty = 0;
@@ -4076,15 +4145,10 @@ static int st_remove(struct device *dev)
4076 tpnt->modes[mode].cdevs[j] = NULL; 4145 tpnt->modes[mode].cdevs[j] = NULL;
4077 } 4146 }
4078 } 4147 }
4079 tpnt->device = NULL;
4080 4148
4081 if (tpnt->buffer) { 4149 down(&st_ref_sem);
4082 tpnt->buffer->orig_frp_segs = 0; 4150 kref_put(&tpnt->kref, scsi_tape_release);
4083 normalize_buffer(tpnt->buffer); 4151 up(&st_ref_sem);
4084 kfree(tpnt->buffer);
4085 }
4086 put_disk(tpnt->disk);
4087 kfree(tpnt);
4088 return 0; 4152 return 0;
4089 } 4153 }
4090 } 4154 }
@@ -4093,6 +4157,34 @@ static int st_remove(struct device *dev)
4093 return 0; 4157 return 0;
4094} 4158}
4095 4159
4160/**
4161 * scsi_tape_release - Called to free the Scsi_Tape structure
4162 * @kref: pointer to embedded kref
4163 *
4164 * st_ref_sem must be held entering this routine. Because it is
4165 * called on last put, you should always use the scsi_tape_get()
4166 * scsi_tape_put() helpers which manipulate the semaphore directly
4167 * and never do a direct kref_put().
4168 **/
4169static void scsi_tape_release(struct kref *kref)
4170{
4171 struct scsi_tape *tpnt = to_scsi_tape(kref);
4172 struct gendisk *disk = tpnt->disk;
4173
4174 tpnt->device = NULL;
4175
4176 if (tpnt->buffer) {
4177 tpnt->buffer->orig_frp_segs = 0;
4178 normalize_buffer(tpnt->buffer);
4179 kfree(tpnt->buffer);
4180 }
4181
4182 disk->private_data = NULL;
4183 put_disk(disk);
4184 kfree(tpnt);
4185 return;
4186}
4187
4096static void st_intr(struct scsi_cmnd *SCpnt) 4188static void st_intr(struct scsi_cmnd *SCpnt)
4097{ 4189{
4098 scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen), 1); 4190 scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen), 1);
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 061da111398e..790acac160bc 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -3,7 +3,7 @@
3#define _ST_H 3#define _ST_H
4 4
5#include <linux/completion.h> 5#include <linux/completion.h>
6 6#include <linux/kref.h>
7 7
8/* Descriptor for analyzed sense data */ 8/* Descriptor for analyzed sense data */
9struct st_cmdstatus { 9struct st_cmdstatus {
@@ -156,6 +156,7 @@ struct scsi_tape {
156 unsigned char last_sense[16]; 156 unsigned char last_sense[16];
157#endif 157#endif
158 struct gendisk *disk; 158 struct gendisk *disk;
159 struct kref kref;
159}; 160};
160 161
161/* Bit masks for use_pf */ 162/* Bit masks for use_pf */