diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/sg.c | 253 |
1 files changed, 112 insertions, 141 deletions
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index fdc6618c1f61..f6f5fc7d0cee 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -43,6 +43,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */ | |||
43 | #include <linux/poll.h> | 43 | #include <linux/poll.h> |
44 | #include <linux/moduleparam.h> | 44 | #include <linux/moduleparam.h> |
45 | #include <linux/cdev.h> | 45 | #include <linux/cdev.h> |
46 | #include <linux/idr.h> | ||
46 | #include <linux/seq_file.h> | 47 | #include <linux/seq_file.h> |
47 | #include <linux/blkdev.h> | 48 | #include <linux/blkdev.h> |
48 | #include <linux/delay.h> | 49 | #include <linux/delay.h> |
@@ -99,12 +100,11 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ; | |||
99 | #define SG_SECTOR_SZ 512 | 100 | #define SG_SECTOR_SZ 512 |
100 | #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1) | 101 | #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1) |
101 | 102 | ||
102 | #define SG_DEV_ARR_LUMP 32 /* amount to over allocate sg_dev_arr by */ | ||
103 | |||
104 | static int sg_add(struct class_device *, struct class_interface *); | 103 | static int sg_add(struct class_device *, struct class_interface *); |
105 | static void sg_remove(struct class_device *, struct class_interface *); | 104 | static void sg_remove(struct class_device *, struct class_interface *); |
106 | 105 | ||
107 | static DEFINE_RWLOCK(sg_dev_arr_lock); /* Also used to lock | 106 | static DEFINE_IDR(sg_index_idr); |
107 | static DEFINE_RWLOCK(sg_index_lock); /* Also used to lock | ||
108 | file descriptor list for device */ | 108 | file descriptor list for device */ |
109 | 109 | ||
110 | static struct class_interface sg_interface = { | 110 | static struct class_interface sg_interface = { |
@@ -162,6 +162,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */ | |||
162 | struct scsi_device *device; | 162 | struct scsi_device *device; |
163 | wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */ | 163 | wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */ |
164 | int sg_tablesize; /* adapter's max scatter-gather table size */ | 164 | int sg_tablesize; /* adapter's max scatter-gather table size */ |
165 | u32 index; /* device index number */ | ||
165 | Sg_fd *headfp; /* first open fd belonging to this device */ | 166 | Sg_fd *headfp; /* first open fd belonging to this device */ |
166 | volatile char detached; /* 0->attached, 1->detached pending removal */ | 167 | volatile char detached; /* 0->attached, 1->detached pending removal */ |
167 | volatile char exclude; /* opened for exclusive access */ | 168 | volatile char exclude; /* opened for exclusive access */ |
@@ -209,10 +210,6 @@ static Sg_device *sg_get_dev(int dev); | |||
209 | static int sg_last_dev(void); | 210 | static int sg_last_dev(void); |
210 | #endif | 211 | #endif |
211 | 212 | ||
212 | static Sg_device **sg_dev_arr = NULL; | ||
213 | static int sg_dev_max; | ||
214 | static int sg_nr_dev; | ||
215 | |||
216 | #define SZ_SG_HEADER sizeof(struct sg_header) | 213 | #define SZ_SG_HEADER sizeof(struct sg_header) |
217 | #define SZ_SG_IO_HDR sizeof(sg_io_hdr_t) | 214 | #define SZ_SG_IO_HDR sizeof(sg_io_hdr_t) |
218 | #define SZ_SG_IOVEC sizeof(sg_iovec_t) | 215 | #define SZ_SG_IOVEC sizeof(sg_iovec_t) |
@@ -1331,40 +1328,35 @@ static struct class *sg_sysfs_class; | |||
1331 | 1328 | ||
1332 | static int sg_sysfs_valid = 0; | 1329 | static int sg_sysfs_valid = 0; |
1333 | 1330 | ||
1334 | static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) | 1331 | static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) |
1335 | { | 1332 | { |
1336 | struct request_queue *q = scsidp->request_queue; | 1333 | struct request_queue *q = scsidp->request_queue; |
1337 | Sg_device *sdp; | 1334 | Sg_device *sdp; |
1338 | unsigned long iflags; | 1335 | unsigned long iflags; |
1339 | void *old_sg_dev_arr = NULL; | 1336 | int error; |
1340 | int k, error; | 1337 | u32 k; |
1341 | 1338 | ||
1342 | sdp = kzalloc(sizeof(Sg_device), GFP_KERNEL); | 1339 | sdp = kzalloc(sizeof(Sg_device), GFP_KERNEL); |
1343 | if (!sdp) { | 1340 | if (!sdp) { |
1344 | printk(KERN_WARNING "kmalloc Sg_device failure\n"); | 1341 | printk(KERN_WARNING "kmalloc Sg_device failure\n"); |
1345 | return -ENOMEM; | 1342 | return ERR_PTR(-ENOMEM); |
1343 | } | ||
1344 | error = -ENOMEM; | ||
1345 | if (!idr_pre_get(&sg_index_idr, GFP_KERNEL)) { | ||
1346 | printk(KERN_WARNING "idr expansion Sg_device failure\n"); | ||
1347 | goto out; | ||
1346 | } | 1348 | } |
1347 | 1349 | ||
1348 | write_lock_irqsave(&sg_dev_arr_lock, iflags); | 1350 | write_lock_irqsave(&sg_index_lock, iflags); |
1349 | if (unlikely(sg_nr_dev >= sg_dev_max)) { /* try to resize */ | 1351 | error = idr_get_new(&sg_index_idr, sdp, &k); |
1350 | Sg_device **tmp_da; | 1352 | write_unlock_irqrestore(&sg_index_lock, iflags); |
1351 | int tmp_dev_max = sg_nr_dev + SG_DEV_ARR_LUMP; | ||
1352 | write_unlock_irqrestore(&sg_dev_arr_lock, iflags); | ||
1353 | |||
1354 | tmp_da = kzalloc(tmp_dev_max * sizeof(Sg_device *), GFP_KERNEL); | ||
1355 | if (unlikely(!tmp_da)) | ||
1356 | goto expand_failed; | ||
1357 | 1353 | ||
1358 | write_lock_irqsave(&sg_dev_arr_lock, iflags); | 1354 | if (error) { |
1359 | memcpy(tmp_da, sg_dev_arr, sg_dev_max * sizeof(Sg_device *)); | 1355 | printk(KERN_WARNING "idr allocation Sg_device failure: %d\n", |
1360 | old_sg_dev_arr = sg_dev_arr; | 1356 | error); |
1361 | sg_dev_arr = tmp_da; | 1357 | goto out; |
1362 | sg_dev_max = tmp_dev_max; | ||
1363 | } | 1358 | } |
1364 | 1359 | ||
1365 | for (k = 0; k < sg_dev_max; k++) | ||
1366 | if (!sg_dev_arr[k]) | ||
1367 | break; | ||
1368 | if (unlikely(k >= SG_MAX_DEVS)) | 1360 | if (unlikely(k >= SG_MAX_DEVS)) |
1369 | goto overflow; | 1361 | goto overflow; |
1370 | 1362 | ||
@@ -1375,25 +1367,17 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) | |||
1375 | sdp->device = scsidp; | 1367 | sdp->device = scsidp; |
1376 | init_waitqueue_head(&sdp->o_excl_wait); | 1368 | init_waitqueue_head(&sdp->o_excl_wait); |
1377 | sdp->sg_tablesize = min(q->max_hw_segments, q->max_phys_segments); | 1369 | sdp->sg_tablesize = min(q->max_hw_segments, q->max_phys_segments); |
1370 | sdp->index = k; | ||
1378 | 1371 | ||
1379 | sg_nr_dev++; | 1372 | error = 0; |
1380 | sg_dev_arr[k] = sdp; | ||
1381 | write_unlock_irqrestore(&sg_dev_arr_lock, iflags); | ||
1382 | error = k; | ||
1383 | |||
1384 | out: | 1373 | out: |
1385 | if (error < 0) | 1374 | if (error) { |
1386 | kfree(sdp); | 1375 | kfree(sdp); |
1387 | kfree(old_sg_dev_arr); | 1376 | return ERR_PTR(error); |
1388 | return error; | 1377 | } |
1389 | 1378 | return sdp; | |
1390 | expand_failed: | ||
1391 | printk(KERN_WARNING "sg_alloc: device array cannot be resized\n"); | ||
1392 | error = -ENOMEM; | ||
1393 | goto out; | ||
1394 | 1379 | ||
1395 | overflow: | 1380 | overflow: |
1396 | write_unlock_irqrestore(&sg_dev_arr_lock, iflags); | ||
1397 | sdev_printk(KERN_WARNING, scsidp, | 1381 | sdev_printk(KERN_WARNING, scsidp, |
1398 | "Unable to attach sg device type=%d, minor " | 1382 | "Unable to attach sg device type=%d, minor " |
1399 | "number exceeds %d\n", scsidp->type, SG_MAX_DEVS - 1); | 1383 | "number exceeds %d\n", scsidp->type, SG_MAX_DEVS - 1); |
@@ -1408,7 +1392,7 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) | |||
1408 | struct gendisk *disk; | 1392 | struct gendisk *disk; |
1409 | Sg_device *sdp = NULL; | 1393 | Sg_device *sdp = NULL; |
1410 | struct cdev * cdev = NULL; | 1394 | struct cdev * cdev = NULL; |
1411 | int error, k; | 1395 | int error; |
1412 | unsigned long iflags; | 1396 | unsigned long iflags; |
1413 | 1397 | ||
1414 | disk = alloc_disk(1); | 1398 | disk = alloc_disk(1); |
@@ -1427,15 +1411,15 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) | |||
1427 | cdev->owner = THIS_MODULE; | 1411 | cdev->owner = THIS_MODULE; |
1428 | cdev->ops = &sg_fops; | 1412 | cdev->ops = &sg_fops; |
1429 | 1413 | ||
1430 | error = sg_alloc(disk, scsidp); | 1414 | sdp = sg_alloc(disk, scsidp); |
1431 | if (error < 0) { | 1415 | if (IS_ERR(sdp)) { |
1432 | printk(KERN_WARNING "sg_alloc failed\n"); | 1416 | printk(KERN_WARNING "sg_alloc failed\n"); |
1417 | error = PTR_ERR(sdp); | ||
1433 | goto out; | 1418 | goto out; |
1434 | } | 1419 | } |
1435 | k = error; | ||
1436 | sdp = sg_dev_arr[k]; | ||
1437 | 1420 | ||
1438 | error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, k), 1); | 1421 | class_set_devdata(cl_dev, sdp); |
1422 | error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, sdp->index), 1); | ||
1439 | if (error) | 1423 | if (error) |
1440 | goto cdev_add_err; | 1424 | goto cdev_add_err; |
1441 | 1425 | ||
@@ -1444,8 +1428,8 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) | |||
1444 | struct class_device * sg_class_member; | 1428 | struct class_device * sg_class_member; |
1445 | 1429 | ||
1446 | sg_class_member = class_device_create(sg_sysfs_class, NULL, | 1430 | sg_class_member = class_device_create(sg_sysfs_class, NULL, |
1447 | MKDEV(SCSI_GENERIC_MAJOR, k), | 1431 | MKDEV(SCSI_GENERIC_MAJOR, sdp->index), |
1448 | cl_dev->dev, "%s", | 1432 | cl_dev->dev, "%s", |
1449 | disk->disk_name); | 1433 | disk->disk_name); |
1450 | if (IS_ERR(sg_class_member)) | 1434 | if (IS_ERR(sg_class_member)) |
1451 | printk(KERN_WARNING "sg_add: " | 1435 | printk(KERN_WARNING "sg_add: " |
@@ -1455,21 +1439,21 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) | |||
1455 | &sg_class_member->kobj, "generic"); | 1439 | &sg_class_member->kobj, "generic"); |
1456 | if (error) | 1440 | if (error) |
1457 | printk(KERN_ERR "sg_add: unable to make symlink " | 1441 | printk(KERN_ERR "sg_add: unable to make symlink " |
1458 | "'generic' back to sg%d\n", k); | 1442 | "'generic' back to sg%d\n", sdp->index); |
1459 | } else | 1443 | } else |
1460 | printk(KERN_WARNING "sg_add: sg_sys INvalid\n"); | 1444 | printk(KERN_WARNING "sg_add: sg_sys Invalid\n"); |
1461 | 1445 | ||
1462 | sdev_printk(KERN_NOTICE, scsidp, | 1446 | sdev_printk(KERN_NOTICE, scsidp, |
1463 | "Attached scsi generic sg%d type %d\n", k,scsidp->type); | 1447 | "Attached scsi generic sg%d type %d\n", sdp->index, |
1448 | scsidp->type); | ||
1464 | 1449 | ||
1465 | return 0; | 1450 | return 0; |
1466 | 1451 | ||
1467 | cdev_add_err: | 1452 | cdev_add_err: |
1468 | write_lock_irqsave(&sg_dev_arr_lock, iflags); | 1453 | write_lock_irqsave(&sg_index_lock, iflags); |
1469 | kfree(sg_dev_arr[k]); | 1454 | idr_remove(&sg_index_idr, sdp->index); |
1470 | sg_dev_arr[k] = NULL; | 1455 | write_unlock_irqrestore(&sg_index_lock, iflags); |
1471 | sg_nr_dev--; | 1456 | kfree(sdp); |
1472 | write_unlock_irqrestore(&sg_dev_arr_lock, iflags); | ||
1473 | 1457 | ||
1474 | out: | 1458 | out: |
1475 | put_disk(disk); | 1459 | put_disk(disk); |
@@ -1482,64 +1466,56 @@ static void | |||
1482 | sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf) | 1466 | sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf) |
1483 | { | 1467 | { |
1484 | struct scsi_device *scsidp = to_scsi_device(cl_dev->dev); | 1468 | struct scsi_device *scsidp = to_scsi_device(cl_dev->dev); |
1485 | Sg_device *sdp = NULL; | 1469 | Sg_device *sdp = class_get_devdata(cl_dev); |
1486 | unsigned long iflags; | 1470 | unsigned long iflags; |
1487 | Sg_fd *sfp; | 1471 | Sg_fd *sfp; |
1488 | Sg_fd *tsfp; | 1472 | Sg_fd *tsfp; |
1489 | Sg_request *srp; | 1473 | Sg_request *srp; |
1490 | Sg_request *tsrp; | 1474 | Sg_request *tsrp; |
1491 | int k, delay; | 1475 | int delay; |
1492 | 1476 | ||
1493 | if (NULL == sg_dev_arr) | 1477 | if (!sdp) |
1494 | return; | 1478 | return; |
1479 | |||
1495 | delay = 0; | 1480 | delay = 0; |
1496 | write_lock_irqsave(&sg_dev_arr_lock, iflags); | 1481 | write_lock_irqsave(&sg_index_lock, iflags); |
1497 | for (k = 0; k < sg_dev_max; k++) { | 1482 | if (sdp->headfp) { |
1498 | sdp = sg_dev_arr[k]; | 1483 | sdp->detached = 1; |
1499 | if ((NULL == sdp) || (sdp->device != scsidp)) | 1484 | for (sfp = sdp->headfp; sfp; sfp = tsfp) { |
1500 | continue; /* dirty but lowers nesting */ | 1485 | tsfp = sfp->nextfp; |
1501 | if (sdp->headfp) { | 1486 | for (srp = sfp->headrp; srp; srp = tsrp) { |
1502 | sdp->detached = 1; | 1487 | tsrp = srp->nextrp; |
1503 | for (sfp = sdp->headfp; sfp; sfp = tsfp) { | 1488 | if (sfp->closed || (0 == sg_srp_done(srp, sfp))) |
1504 | tsfp = sfp->nextfp; | 1489 | sg_finish_rem_req(srp); |
1505 | for (srp = sfp->headrp; srp; srp = tsrp) { | ||
1506 | tsrp = srp->nextrp; | ||
1507 | if (sfp->closed || (0 == sg_srp_done(srp, sfp))) | ||
1508 | sg_finish_rem_req(srp); | ||
1509 | } | ||
1510 | if (sfp->closed) { | ||
1511 | scsi_device_put(sdp->device); | ||
1512 | __sg_remove_sfp(sdp, sfp); | ||
1513 | } else { | ||
1514 | delay = 1; | ||
1515 | wake_up_interruptible(&sfp->read_wait); | ||
1516 | kill_fasync(&sfp->async_qp, SIGPOLL, | ||
1517 | POLL_HUP); | ||
1518 | } | ||
1519 | } | 1490 | } |
1520 | SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d, dirty\n", k)); | 1491 | if (sfp->closed) { |
1521 | if (NULL == sdp->headfp) { | 1492 | scsi_device_put(sdp->device); |
1522 | sg_dev_arr[k] = NULL; | 1493 | __sg_remove_sfp(sdp, sfp); |
1494 | } else { | ||
1495 | delay = 1; | ||
1496 | wake_up_interruptible(&sfp->read_wait); | ||
1497 | kill_fasync(&sfp->async_qp, SIGPOLL, | ||
1498 | POLL_HUP); | ||
1523 | } | 1499 | } |
1524 | } else { /* nothing active, simple case */ | ||
1525 | SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d\n", k)); | ||
1526 | sg_dev_arr[k] = NULL; | ||
1527 | } | 1500 | } |
1528 | sg_nr_dev--; | 1501 | SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d, dirty\n", sdp->index)); |
1529 | break; | 1502 | if (NULL == sdp->headfp) { |
1530 | } | 1503 | idr_remove(&sg_index_idr, sdp->index); |
1531 | write_unlock_irqrestore(&sg_dev_arr_lock, iflags); | 1504 | } |
1532 | 1505 | } else { /* nothing active, simple case */ | |
1533 | if (sdp) { | 1506 | SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d\n", sdp->index)); |
1534 | sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic"); | 1507 | idr_remove(&sg_index_idr, sdp->index); |
1535 | class_device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, k)); | 1508 | } |
1536 | cdev_del(sdp->cdev); | 1509 | write_unlock_irqrestore(&sg_index_lock, iflags); |
1537 | sdp->cdev = NULL; | 1510 | |
1538 | put_disk(sdp->disk); | 1511 | sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic"); |
1539 | sdp->disk = NULL; | 1512 | class_device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index)); |
1540 | if (NULL == sdp->headfp) | 1513 | cdev_del(sdp->cdev); |
1541 | kfree((char *) sdp); | 1514 | sdp->cdev = NULL; |
1542 | } | 1515 | put_disk(sdp->disk); |
1516 | sdp->disk = NULL; | ||
1517 | if (NULL == sdp->headfp) | ||
1518 | kfree(sdp); | ||
1543 | 1519 | ||
1544 | if (delay) | 1520 | if (delay) |
1545 | msleep(10); /* dirty detach so delay device destruction */ | 1521 | msleep(10); /* dirty detach so delay device destruction */ |
@@ -1609,9 +1585,7 @@ exit_sg(void) | |||
1609 | sg_sysfs_valid = 0; | 1585 | sg_sysfs_valid = 0; |
1610 | unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), | 1586 | unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), |
1611 | SG_MAX_DEVS); | 1587 | SG_MAX_DEVS); |
1612 | kfree((char *)sg_dev_arr); | 1588 | idr_destroy(&sg_index_idr); |
1613 | sg_dev_arr = NULL; | ||
1614 | sg_dev_max = 0; | ||
1615 | } | 1589 | } |
1616 | 1590 | ||
1617 | static int | 1591 | static int |
@@ -2331,10 +2305,10 @@ sg_get_nth_sfp(Sg_device * sdp, int nth) | |||
2331 | unsigned long iflags; | 2305 | unsigned long iflags; |
2332 | int k; | 2306 | int k; |
2333 | 2307 | ||
2334 | read_lock_irqsave(&sg_dev_arr_lock, iflags); | 2308 | read_lock_irqsave(&sg_index_lock, iflags); |
2335 | for (k = 0, resp = sdp->headfp; resp && (k < nth); | 2309 | for (k = 0, resp = sdp->headfp; resp && (k < nth); |
2336 | ++k, resp = resp->nextfp) ; | 2310 | ++k, resp = resp->nextfp) ; |
2337 | read_unlock_irqrestore(&sg_dev_arr_lock, iflags); | 2311 | read_unlock_irqrestore(&sg_index_lock, iflags); |
2338 | return resp; | 2312 | return resp; |
2339 | } | 2313 | } |
2340 | #endif | 2314 | #endif |
@@ -2361,7 +2335,7 @@ sg_add_sfp(Sg_device * sdp, int dev) | |||
2361 | sfp->cmd_q = SG_DEF_COMMAND_Q; | 2335 | sfp->cmd_q = SG_DEF_COMMAND_Q; |
2362 | sfp->keep_orphan = SG_DEF_KEEP_ORPHAN; | 2336 | sfp->keep_orphan = SG_DEF_KEEP_ORPHAN; |
2363 | sfp->parentdp = sdp; | 2337 | sfp->parentdp = sdp; |
2364 | write_lock_irqsave(&sg_dev_arr_lock, iflags); | 2338 | write_lock_irqsave(&sg_index_lock, iflags); |
2365 | if (!sdp->headfp) | 2339 | if (!sdp->headfp) |
2366 | sdp->headfp = sfp; | 2340 | sdp->headfp = sfp; |
2367 | else { /* add to tail of existing list */ | 2341 | else { /* add to tail of existing list */ |
@@ -2370,7 +2344,7 @@ sg_add_sfp(Sg_device * sdp, int dev) | |||
2370 | pfp = pfp->nextfp; | 2344 | pfp = pfp->nextfp; |
2371 | pfp->nextfp = sfp; | 2345 | pfp->nextfp = sfp; |
2372 | } | 2346 | } |
2373 | write_unlock_irqrestore(&sg_dev_arr_lock, iflags); | 2347 | write_unlock_irqrestore(&sg_index_lock, iflags); |
2374 | SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp)); | 2348 | SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp)); |
2375 | if (unlikely(sg_big_buff != def_reserved_size)) | 2349 | if (unlikely(sg_big_buff != def_reserved_size)) |
2376 | sg_big_buff = def_reserved_size; | 2350 | sg_big_buff = def_reserved_size; |
@@ -2431,22 +2405,14 @@ sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp) | |||
2431 | if (0 == dirty) { | 2405 | if (0 == dirty) { |
2432 | unsigned long iflags; | 2406 | unsigned long iflags; |
2433 | 2407 | ||
2434 | write_lock_irqsave(&sg_dev_arr_lock, iflags); | 2408 | write_lock_irqsave(&sg_index_lock, iflags); |
2435 | __sg_remove_sfp(sdp, sfp); | 2409 | __sg_remove_sfp(sdp, sfp); |
2436 | if (sdp->detached && (NULL == sdp->headfp)) { | 2410 | if (sdp->detached && (NULL == sdp->headfp)) { |
2437 | int k, maxd; | 2411 | idr_remove(&sg_index_idr, sdp->index); |
2438 | 2412 | kfree(sdp); | |
2439 | maxd = sg_dev_max; | ||
2440 | for (k = 0; k < maxd; ++k) { | ||
2441 | if (sdp == sg_dev_arr[k]) | ||
2442 | break; | ||
2443 | } | ||
2444 | if (k < maxd) | ||
2445 | sg_dev_arr[k] = NULL; | ||
2446 | kfree((char *) sdp); | ||
2447 | res = 1; | 2413 | res = 1; |
2448 | } | 2414 | } |
2449 | write_unlock_irqrestore(&sg_dev_arr_lock, iflags); | 2415 | write_unlock_irqrestore(&sg_index_lock, iflags); |
2450 | } else { | 2416 | } else { |
2451 | /* MOD_INC's to inhibit unloading sg and associated adapter driver */ | 2417 | /* MOD_INC's to inhibit unloading sg and associated adapter driver */ |
2452 | /* only bump the access_count if we actually succeeded in | 2418 | /* only bump the access_count if we actually succeeded in |
@@ -2546,16 +2512,25 @@ sg_allow_access(unsigned char opcode, char dev_type) | |||
2546 | 2512 | ||
2547 | #ifdef CONFIG_SCSI_PROC_FS | 2513 | #ifdef CONFIG_SCSI_PROC_FS |
2548 | static int | 2514 | static int |
2515 | sg_idr_max_id(int id, void *p, void *data) | ||
2516 | { | ||
2517 | int *k = data; | ||
2518 | |||
2519 | if (*k < id) | ||
2520 | *k = id; | ||
2521 | |||
2522 | return 0; | ||
2523 | } | ||
2524 | |||
2525 | static int | ||
2549 | sg_last_dev(void) | 2526 | sg_last_dev(void) |
2550 | { | 2527 | { |
2551 | int k; | 2528 | int k = 0; |
2552 | unsigned long iflags; | 2529 | unsigned long iflags; |
2553 | 2530 | ||
2554 | read_lock_irqsave(&sg_dev_arr_lock, iflags); | 2531 | read_lock_irqsave(&sg_index_lock, iflags); |
2555 | for (k = sg_dev_max - 1; k >= 0; --k) | 2532 | idr_for_each(&sg_index_idr, sg_idr_max_id, &k); |
2556 | if (sg_dev_arr[k] && sg_dev_arr[k]->device) | 2533 | read_unlock_irqrestore(&sg_index_lock, iflags); |
2557 | break; | ||
2558 | read_unlock_irqrestore(&sg_dev_arr_lock, iflags); | ||
2559 | return k + 1; /* origin 1 */ | 2534 | return k + 1; /* origin 1 */ |
2560 | } | 2535 | } |
2561 | #endif | 2536 | #endif |
@@ -2563,15 +2538,13 @@ sg_last_dev(void) | |||
2563 | static Sg_device * | 2538 | static Sg_device * |
2564 | sg_get_dev(int dev) | 2539 | sg_get_dev(int dev) |
2565 | { | 2540 | { |
2566 | Sg_device *sdp = NULL; | 2541 | Sg_device *sdp; |
2567 | unsigned long iflags; | 2542 | unsigned long iflags; |
2568 | 2543 | ||
2569 | if (sg_dev_arr && (dev >= 0)) { | 2544 | read_lock_irqsave(&sg_index_lock, iflags); |
2570 | read_lock_irqsave(&sg_dev_arr_lock, iflags); | 2545 | sdp = idr_find(&sg_index_idr, dev); |
2571 | if (dev < sg_dev_max) | 2546 | read_unlock_irqrestore(&sg_index_lock, iflags); |
2572 | sdp = sg_dev_arr[dev]; | 2547 | |
2573 | read_unlock_irqrestore(&sg_dev_arr_lock, iflags); | ||
2574 | } | ||
2575 | return sdp; | 2548 | return sdp; |
2576 | } | 2549 | } |
2577 | 2550 | ||
@@ -2805,8 +2778,6 @@ static void * dev_seq_start(struct seq_file *s, loff_t *pos) | |||
2805 | if (! it) | 2778 | if (! it) |
2806 | return NULL; | 2779 | return NULL; |
2807 | 2780 | ||
2808 | if (NULL == sg_dev_arr) | ||
2809 | return NULL; | ||
2810 | it->index = *pos; | 2781 | it->index = *pos; |
2811 | it->max = sg_last_dev(); | 2782 | it->max = sg_last_dev(); |
2812 | if (it->index >= it->max) | 2783 | if (it->index >= it->max) |
@@ -2942,8 +2913,8 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v) | |||
2942 | Sg_device *sdp; | 2913 | Sg_device *sdp; |
2943 | 2914 | ||
2944 | if (it && (0 == it->index)) { | 2915 | if (it && (0 == it->index)) { |
2945 | seq_printf(s, "dev_max(currently)=%d max_active_device=%d " | 2916 | seq_printf(s, "max_active_device=%d(origin 1)\n", |
2946 | "(origin 1)\n", sg_dev_max, (int)it->max); | 2917 | (int)it->max); |
2947 | seq_printf(s, " def_reserved_size=%d\n", sg_big_buff); | 2918 | seq_printf(s, " def_reserved_size=%d\n", sg_big_buff); |
2948 | } | 2919 | } |
2949 | sdp = it ? sg_get_dev(it->index) : NULL; | 2920 | sdp = it ? sg_get_dev(it->index) : NULL; |