summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/block/cciss_scsi.c3
-rw-r--r--drivers/block/elevator.c13
-rw-r--r--drivers/block/ll_rw_blk.c18
-rw-r--r--drivers/scsi/53c700.c25
-rw-r--r--drivers/scsi/NCR_D700.c4
-rw-r--r--drivers/scsi/NCR_Q720.c11
-rw-r--r--drivers/scsi/aha152x.c15
-rw-r--r--drivers/scsi/aha1740.c26
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c3
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c3
-rw-r--r--drivers/scsi/arm/acornscsi.c8
-rw-r--r--drivers/scsi/arm/cumana_1.c8
-rw-r--r--drivers/scsi/arm/ecoscsi.c3
-rw-r--r--drivers/scsi/arm/fas216.c2
-rw-r--r--drivers/scsi/arm/oak.c8
-rw-r--r--drivers/scsi/dc395x.c3
-rw-r--r--drivers/scsi/hosts.c22
-rw-r--r--drivers/scsi/ide-scsi.c4
-rw-r--r--drivers/scsi/ips.h2
-rw-r--r--drivers/scsi/lasi700.c4
-rw-r--r--drivers/scsi/nsp32.c3
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c3
-rw-r--r--drivers/scsi/pcmcia/fdomain_stub.c3
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c3
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c3
-rw-r--r--drivers/scsi/scsi.h5
-rw-r--r--drivers/scsi/scsi_debug.c5
-rw-r--r--drivers/scsi/scsi_lib.c28
-rw-r--r--drivers/scsi/scsi_module.c1
-rw-r--r--drivers/scsi/scsi_priv.h6
-rw-r--r--drivers/scsi/scsi_scan.c3
-rw-r--r--drivers/scsi/scsi_syms.c1
-rw-r--r--drivers/scsi/scsi_sysfs.c307
-rw-r--r--drivers/scsi/sd.c31
-rw-r--r--drivers/scsi/sim710.c3
-rw-r--r--drivers/scsi/sr.c2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c5
-rw-r--r--drivers/scsi/zalon.c13
-rw-r--r--drivers/usb/image/hpusbscsi.c3
-rw-r--r--drivers/usb/image/microtek.c3
-rw-r--r--drivers/usb/storage/usb.c2
-rw-r--r--include/linux/blkdev.h1
-rw-r--r--include/linux/elevator.h3
-rw-r--r--include/scsi/scsi_device.h7
-rw-r--r--include/scsi/scsi_host.h24
-rw-r--r--include/scsi/scsi_request.h2
46 files changed, 317 insertions, 338 deletions
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 8ad5d01e4d42..6951231d4ed5 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -712,7 +712,8 @@ cciss_scsi_detect(int ctlr)
sh->hostdata[0] = (unsigned long) hba[ctlr];
sh->irq = hba[ctlr]->intr;
sh->unique_id = sh->irq;
- scsi_add_host(sh, &hba[ctlr]->pdev->dev);
+ scsi_add_host(sh, &hba[ctlr]->pdev->dev); /* XXX handle failure */
+ scsi_scan_host(sh);
return 1;
}
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index a9bbb2f3d15a..85630fbb37ad 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -213,6 +213,18 @@ void elv_merge_requests(request_queue_t *q, struct request *rq,
e->elevator_merge_req_fn(q, rq, next);
}
+void elv_requeue_request(request_queue_t *q, struct request *rq)
+{
+ /*
+ * if iosched has an explicit requeue hook, then use that. otherwise
+ * just put the request at the front of the queue
+ */
+ if (q->elevator.elevator_requeue_req_fn)
+ q->elevator.elevator_requeue_req_fn(q, rq);
+ else
+ __elv_add_request(q, rq, 0, 0);
+}
+
void __elv_add_request(request_queue_t *q, struct request *rq, int at_end,
int plug)
{
@@ -416,6 +428,7 @@ EXPORT_SYMBOL(elevator_noop);
EXPORT_SYMBOL(elv_add_request);
EXPORT_SYMBOL(__elv_add_request);
+EXPORT_SYMBOL(elv_requeue_request);
EXPORT_SYMBOL(elv_next_request);
EXPORT_SYMBOL(elv_remove_request);
EXPORT_SYMBOL(elv_queue_empty);
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 180ac3e95a66..f9678d95a043 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -1494,6 +1494,23 @@ struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask)
return rq;
}
+/**
+ * blk_requeue_request - put a request back on queue
+ * @q: request queue where request should be inserted
+ * @rq: request to be inserted
+ *
+ * Description:
+ * Drivers often keep queueing requests until the hardware cannot accept
+ * more, when that condition happens we need to put the request back
+ * on the queue. Must be called with queue lock held.
+ */
+void blk_requeue_request(request_queue_t *q, struct request *rq)
+{
+ if (blk_rq_tagged(rq))
+ blk_queue_end_tag(q, rq);
+
+ elv_requeue_request(q, rq);
+}
/**
* blk_insert_request - insert a special request in to a request queue
@@ -2730,6 +2747,7 @@ EXPORT_SYMBOL(blk_hw_contig_segment);
EXPORT_SYMBOL(blk_get_request);
EXPORT_SYMBOL(blk_put_request);
EXPORT_SYMBOL(blk_insert_request);
+EXPORT_SYMBOL(blk_requeue_request);
EXPORT_SYMBOL(blk_queue_prep_rq);
EXPORT_SYMBOL(blk_queue_merge_bvec);
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 3e70fb999f56..c2fce462e847 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -172,7 +172,7 @@ STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
STATIC int NCR_700_slave_configure(Scsi_Device *SDpnt);
STATIC void NCR_700_slave_destroy(Scsi_Device *SDpnt);
-static struct device_attribute **NCR_700_dev_attrs = NULL;
+STATIC struct device_attribute *NCR_700_dev_attrs[];
static char *NCR_700_phase[] = {
"",
@@ -2027,25 +2027,12 @@ static struct device_attribute NCR_700_active_tags_attr = {
.show = NCR_700_show_active_tags,
};
-STATIC int __init
-NCR_700_init(void)
-{
- scsi_sysfs_modify_sdev_attribute(&NCR_700_dev_attrs,
- &NCR_700_queue_depth_attr);
- scsi_sysfs_modify_sdev_attribute(&NCR_700_dev_attrs,
- &NCR_700_active_tags_attr);
- return 0;
-}
-
-/* NULL exit routine to keep modutils happy */
-STATIC void __exit
-NCR_700_exit(void)
-{
-}
+STATIC struct device_attribute *NCR_700_dev_attrs[] = {
+ &NCR_700_queue_depth_attr,
+ &NCR_700_active_tags_attr,
+ NULL,
+};
EXPORT_SYMBOL(NCR_700_detect);
EXPORT_SYMBOL(NCR_700_release);
EXPORT_SYMBOL(NCR_700_intr);
-
-module_init(NCR_700_init);
-module_exit(NCR_700_exit);
diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
index f1eb7aaf22e4..7bff5570b6a0 100644
--- a/drivers/scsi/NCR_D700.c
+++ b/drivers/scsi/NCR_D700.c
@@ -218,7 +218,8 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop,
goto irq_failed;
}
- scsi_add_host(host, p->dev);
+ scsi_add_host(host, p->dev); /* XXX handle failure */
+ scsi_scan_host(host);
p->hosts[siop] = host;
hostdata->dev = p->dev;
@@ -387,7 +388,6 @@ static int __init NCR_D700_init(void)
static void __exit NCR_D700_exit(void)
{
mca_unregister_driver(&NCR_D700_driver);
- scsi_sysfs_release_attributes(&NCR_D700_driver_template);
}
module_init(NCR_D700_init);
diff --git a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c
index c45c353cc9ad..b7d3b5264223 100644
--- a/drivers/scsi/NCR_Q720.c
+++ b/drivers/scsi/NCR_Q720.c
@@ -85,6 +85,7 @@ NCR_Q720_probe_one(struct NCR_Q720_private *p, int siop,
__u8 scsr1 = readb(vaddr + NCR_Q720_SCSR_OFFSET + 1);
__u8 differential = readb(vaddr + NCR_Q720_SCSR_OFFSET) & 0x20;
__u8 version;
+ int error;
scsi_id = scsr1 >> 4;
/* enable burst length 16 (FIXME: should allow this) */
@@ -120,9 +121,12 @@ NCR_Q720_probe_one(struct NCR_Q720_private *p, int siop,
scsr1 &= ~0x01;
writeb(scsr1, vaddr + NCR_Q720_SCSR_OFFSET + 1);
- scsi_add_host(p->hosts[siop], p->dev);
-
- return 0;
+ error = scsi_add_host(p->hosts[siop], p->dev);
+ if (error)
+ ncr53c8xx_release(p->hosts[siop]);
+ else
+ scsi_scan_host(p->hosts[siop]);
+ return error;
fail:
return -ENODEV;
@@ -347,7 +351,6 @@ static void __exit
NCR_Q720_exit(void)
{
mca_unregister_driver(&NCR_Q720_driver);
- //scsi_sysfs_release_attributes(&NCR_Q720_driver_template);
}
module_init(NCR_Q720_init);
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index ee380d8b0ba6..5618e688d6c3 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -939,7 +939,8 @@ static irqreturn_t swintr(int irqno, void *dev_id, struct pt_regs *regs)
struct Scsi_Host *shpnt = lookup_irq(irqno);
if (!shpnt) {
- printk(KERN_ERR "aha152x%d: catched software interrupt %d for unknown controller.\n", HOSTNO, irqno);
+ /* no point using HOSTNO here! */
+ printk(KERN_ERR "aha152x: catched software interrupt %d for unknown controller.\n", irqno);
return IRQ_NONE;
}
@@ -1047,6 +1048,10 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
printk(KERN_INFO "aha152x%d: trying software interrupt, ",
shost->host_no);
+
+ /* need to have host registered before triggering any interrupt */
+ aha152x_host[registered_count] = shost;
+ mb();
SETPORT(DMACNTRL0, SWINT|INTEN);
mdelay(1000);
free_irq(shost->irq, shost);
@@ -1062,7 +1067,7 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
printk(KERN_ERR "aha152x%d: IRQ %d possibly wrong. "
"Please verify.\n", shost->host_no, shost->irq);
- goto out_release_region;
+ goto out_unregister_host;
}
printk("ok.\n");
@@ -1075,12 +1080,12 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
"aha152x", shost) < 0) {
printk(KERN_ERR "aha152x%d: failed to reassign interrupt.\n",
shost->host_no);
- goto out_release_region;
+ goto out_unregister_host;
}
-
- aha152x_host[registered_count] = shost;
return shost; /* the pcmcia stub needs the return value; */
+out_unregister_host:
+ aha152x_host[registered_count] = NULL;
out_release_region:
release_region(shost->io_port, IO_RANGE);
out_unregister:
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index fe22bc364faf..9b1e7cace348 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -375,7 +375,7 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
#endif
/* locate an available ecb */
- spin_lock_irqsave(&SCpnt->device->host->host_lock, flags);
+ spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
ecbno = host->last_ecb_used + 1; /* An optimization */
if (ecbno >= AHA1740_ECBS)
ecbno = 0;
@@ -394,7 +394,7 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
doubles as reserved flag */
host->last_ecb_used = ecbno;
- spin_unlock_irqrestore(&SCpnt->device->host->host_lock, flags);
+ spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
#ifdef DEBUG
printk("Sending command (%d %x)...", ecbno, done);
@@ -491,7 +491,7 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
unsigned int base = SCpnt->device->host->io_port;
DEB(printk("aha1740[%d] critical section\n",ecbno));
- spin_lock_irqsave(&SCpnt->device->host->host_lock, flags);
+ spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
for (loopcnt = 0; ; loopcnt++) {
if (inb(G2STAT(base)) & G2STAT_MBXOUT) break;
if (loopcnt == LOOPCNT_WARN) {
@@ -511,7 +511,7 @@ static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
panic("aha1740.c: attn wait failed!\n");
}
outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */
- spin_unlock_irqrestore(&SCpnt->device->host->host_lock, flags);
+ spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
DEB(printk("aha1740[%d] request queued.\n",ecbno));
} else
printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
@@ -594,7 +594,7 @@ static int aha1740_probe (struct device *dev)
if (!request_region(slotbase, SLOTSIZE, "aha1740")) /* See if in use */
return -EBUSY;
if (!aha1740_test_port(slotbase))
- goto err_release;
+ goto err_release_region;
aha1740_getconfig(slotbase,&irq_level,&translation);
if ((inb(G2STAT(slotbase)) &
(G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) {
@@ -609,7 +609,7 @@ static int aha1740_probe (struct device *dev)
shpnt = scsi_host_alloc(&aha1740_template,
sizeof(struct aha1740_hostdata));
if(shpnt == NULL)
- goto err_release;
+ goto err_release_region;
shpnt->base = 0;
shpnt->io_port = slotbase;
@@ -625,21 +625,27 @@ static int aha1740_probe (struct device *dev)
if (!host->ecb_dma_addr) {
printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n");
scsi_unregister (shpnt);
- goto err_release;
+ goto err_host_put;
}
DEB(printk("aha1740_probe: enable interrupt channel %d\n",irq_level));
if (request_irq(irq_level,aha1740_intr_handle,0,"aha1740",shpnt)) {
printk(KERN_ERR "aha1740_probe: Unable to allocate IRQ %d.\n",
irq_level);
- goto err_release;
+ goto err_unmap;
}
eisa_set_drvdata (edev, shpnt);
- scsi_add_host (shpnt, dev);
+ scsi_add_host (shpnt, dev); /* XXX handle failure */
+ scsi_scan_host (shpnt);
return 0;
- err_release:
+ err_unmap:
+ dma_unmap_single (&edev->dev, host->ecb_dma_addr,
+ sizeof (host->ecb), DMA_BIDIRECTIONAL);
+ err_host_put:
+ scsi_host_put (shpnt);
+ err_release_region:
release_region(slotbase, SLOTSIZE);
return -ENODEV;
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index c50c2bb46973..1b87b2aac104 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -2173,7 +2173,8 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
ahd_unlock(ahd, &s);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- scsi_add_host(host, &ahd->dev_softc->dev);
+ scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */
+ scsi_scan_host(host);
#endif
return (0);
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index a2ec0a94f44c..8c1e4086a808 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -1811,7 +1811,8 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
ahc_unlock(ahc, &s);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL));
+ scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */
+ scsi_scan_host(host);
#endif
return (0);
}
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index 7ac9e317ec51..a0452a6c6122 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -3043,9 +3043,13 @@ acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
acornscsi_resetcard(ashost);
ret = scsi_add_host(host, &ec->dev);
- if (ret == 0)
- goto out;
+ if (ret)
+ goto err_7;
+
+ scsi_scan_host(host);
+ goto out;
+ err_7:
free_irq(host->irq, ashost);
err_6:
release_region(host->io_port, 2048);
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
index 35b1488ce2a6..aa75d505697f 100644
--- a/drivers/scsi/arm/cumana_1.c
+++ b/drivers/scsi/arm/cumana_1.c
@@ -297,9 +297,13 @@ cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id)
printk("\n");
ret = scsi_add_host(host, &ec->dev);
- if (ret == 0)
- goto out;
+ if (ret)
+ goto out_free_irq;
+
+ scsi_scan_host(host);
+ goto out;
+ out_free_irq:
free_irq(host->irq, host);
out_release:
release_region(host->io_port, host->n_io_port);
diff --git a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c
index ec1571c94539..7f27e54258b8 100644
--- a/drivers/scsi/arm/ecoscsi.c
+++ b/drivers/scsi/arm/ecoscsi.c
@@ -205,7 +205,8 @@ static int __init ecoscsi_init(void)
NCR5380_print_options(host);
printk("\n");
- scsi_add_host(host, NULL);
+ scsi_add_host(host, NULL); /* XXX handle failure */
+ scsi_scan_host(host);
return 0;
release_reg:
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index 11a733dea1c8..2648c6ee5b37 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -2861,6 +2861,8 @@ int fas216_add(struct Scsi_Host *host, struct device *dev)
ret = scsi_add_host(host, dev);
if (ret)
fas216_writeb(info, REG_CMD, CMD_RESETCHIP);
+ else
+ scsi_scan_host(host);
return ret;
}
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
index 34a54329d216..ccca39b6943d 100644
--- a/drivers/scsi/arm/oak.c
+++ b/drivers/scsi/arm/oak.c
@@ -158,9 +158,13 @@ oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
printk("\n");
ret = scsi_add_host(host, &ec->dev);
- if (ret == 0)
- goto out;
+ if (ret)
+ goto out_release;
+
+ scsi_scan_host(host);
+ goto out;
+ out_release:
release_region(host->io_port, host->n_io_port);
unreg:
scsi_host_put(host);
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 65c9467477f9..ecf0333f92d4 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -6214,7 +6214,8 @@ int __devinit dc395x_init_one(struct pci_dev *pdev,
pci_set_drvdata(pdev, scsi_host);
/* get the scsi mid level to scan for new devices on the bus */
- scsi_add_host(scsi_host, &pdev->dev);
+ scsi_add_host(scsi_host, &pdev->dev); /* XXX handle failure */
+ scsi_scan_host(scsi_host);
return 0;
}
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 755f7b837f04..f4f69bf1e148 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -81,19 +81,15 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
printk(KERN_INFO "scsi%d : %s\n", shost->host_no,
sht->info ? sht->info(shost) : sht->name);
- error = scsi_sysfs_add_host(shost, dev);
-
if (!shost->can_queue) {
printk(KERN_ERR "%s: can_queue = 0 no longer supported\n",
sht->name);
error = -EINVAL;
}
- if (!error) {
+ error = scsi_sysfs_add_host(shost, dev);
+ if (!error)
scsi_proc_host_add(shost);
- scsi_scan_host(shost);
- }
-
return error;
}
@@ -151,12 +147,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
dump_stack();
}
- /* if its not set in the template, use the default */
- if (!sht->shost_attrs)
- sht->shost_attrs = scsi_sysfs_shost_attrs;
- if (!sht->sdev_attrs)
- sht->sdev_attrs = scsi_sysfs_sdev_attrs;
-
shost = kmalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask);
if (!shost)
return NULL;
@@ -283,8 +273,8 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)
**/
void scsi_host_get(struct Scsi_Host *shost)
{
- get_device(&shost->host_gendev);
- class_device_get(&shost->class_dev);
+ get_device(&shost->shost_gendev);
+ class_device_get(&shost->shost_classdev);
}
/**
@@ -293,6 +283,6 @@ void scsi_host_get(struct Scsi_Host *shost)
**/
void scsi_host_put(struct Scsi_Host *shost)
{
- class_device_put(&shost->class_dev);
- put_device(&shost->host_gendev);
+ class_device_put(&shost->shost_classdev);
+ put_device(&shost->shost_gendev);
}
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index cfd1e581072c..84238c4de22a 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -978,8 +978,10 @@ static int idescsi_attach(ide_drive_t *drive)
idescsi_setup (drive, idescsi);
drive->disk->fops = &idescsi_ops;
err = scsi_add_host(host, &idescsi_primary);
- if (!err)
+ if (!err) {
+ scsi_scan_host(host);
return 0;
+ }
/* fall through on error */
ide_unregister_subdriver(drive);
}
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index 921d73f38f9d..0ad7adce9acf 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -111,7 +111,7 @@
#else
#define IPS_REGISTER_HOSTS(SHT) (!ips_detect(SHT))
#define IPS_UNREGISTER_HOSTS(SHT)
- #define IPS_ADD_HOST(shost,device) scsi_add_host(shost,device)
+ #define IPS_ADD_HOST(shost,device) do { scsi_add_host(shost,device); scsi_scan_host(shost); } while (0)
#define IPS_REMOVE_HOST(shost) scsi_remove_host(shost)
#define IPS_SCSI_SET_DEVICE(sh,ha) scsi_set_device(sh, &(ha)->pcidev->dev)
#define IPS_PRINTK(level, pcidev, format, arg...) \
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index b5c4b51b3cf3..25cff061f4a1 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -128,7 +128,8 @@ lasi700_driver_callback(struct parisc_device *dev)
}
dev_set_drvdata(&dev->dev, host);
- scsi_add_host(host, &dev->dev);
+ scsi_add_host(host, &dev->dev); /* XXX handle failure */
+ scsi_scan_host(host);
return 0;
@@ -165,7 +166,6 @@ static void __exit
lasi700_exit(void)
{
unregister_parisc_driver(&lasi700_driver);
- scsi_sysfs_release_attributes(&lasi700_template);
}
module_init(lasi700_init);
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index 963e409dcfd7..d9567d5b75f3 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -1820,7 +1820,8 @@ static int nsp32_detect(struct pci_dev *pdev)
goto free_irq;
}
- scsi_add_host(host, &pdev->dev);
+ scsi_add_host(host, &pdev->dev); /* XXX handle failure */
+ scsi_scan_host(host);
pci_set_drvdata(pdev, host);
return 0;
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 41f420335072..af999e9509b6 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -278,7 +278,8 @@ static void aha152x_config_cs(dev_link_t *link)
goto cs_failed;
}
- scsi_add_host(host, NULL);
+ scsi_add_host(host, NULL); /* XXX handle failure */
+ scsi_scan_host(host);
sprintf(info->node.dev_name, "scsi%d", host->host_no);
link->dev = &info->node;
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 7e12c1d37673..e91187dca450 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -254,7 +254,8 @@ static void fdomain_config(dev_link_t *link)
goto cs_failed;
}
- scsi_add_host(host, NULL);
+ scsi_add_host(host, NULL); /* XXX handle failure */
+ scsi_scan_host(host);
sprintf(info->node.dev_name, "scsi%d", host->host_no);
link->dev = &info->node;
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 59291c8b32c1..5165af63b6b5 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1773,7 +1773,8 @@ static void nsp_cs_config(dev_link_t *link)
req.Base+req.Size-1);
printk("\n");
- scsi_add_host(host, NULL);
+ scsi_add_host(host, NULL); /* XXX handle failure */
+ scsi_scan_host(host);
link->state &= ~DEV_CONFIG_PENDING;
return;
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index debc8c985330..503a5fd05d96 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -270,7 +270,8 @@ static void qlogic_config(dev_link_t * link)
link->dev = &info->node;
info->host = host;
- scsi_add_host(host, NULL);
+ scsi_add_host(host, NULL); /* XXX handle failure */
+ scsi_scan_host(host);
out:
link->state &= ~DEV_CONFIG_PENDING;
diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
index 3ff36ab84744..5d2e6d8aec01 100644
--- a/drivers/scsi/scsi.h
+++ b/drivers/scsi/scsi.h
@@ -174,11 +174,6 @@ extern const char *scsi_extd_sense_format(unsigned char, unsigned char);
#define SCSI_MLQUEUE_DEVICE_BUSY 0x1056
#define SCSI_MLQUEUE_EH_RETRY 0x1057
-extern int scsi_sysfs_modify_sdev_attribute(struct device_attribute ***dev_attrs,
- struct device_attribute *attr);
-extern int scsi_sysfs_modify_shost_attribute(struct class_device_attribute ***class_attrs,
- struct class_device_attribute *attr);
-
/*
* Legacy dma direction interfaces.
*
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 138e78f133b7..47125ef5d93e 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -687,7 +687,7 @@ static int resp_mode_sense(unsigned char * cmd, int target,
pcontrol = (cmd[2] & 0xc0) >> 6;
pcode = cmd[2] & 0x3f;
msense_6 = (MODE_SENSE == cmd[0]);
- alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[6]);
+ alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
/* printk(KERN_INFO "msense: dbd=%d pcontrol=%d pcode=%d "
"msense_6=%d alloc_len=%d\n", dbd, pcontrol, pcode, "
"msense_6, alloc_len); */
@@ -1701,7 +1701,8 @@ static int sdebug_driver_probe(struct device * dev)
printk(KERN_ERR "%s: scsi_add_host failed\n", __FUNCTION__);
error = -ENODEV;
scsi_host_put(hpnt);
- }
+ } else
+ scsi_scan_host(hpnt);
return error;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 3997f09783e0..3a5d82add006 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -444,22 +444,8 @@ static void scsi_run_queue(struct request_queue *q)
*/
static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
{
- unsigned long flags;
-
- spin_lock_irqsave(q->queue_lock, flags);
- cmd->request->special = cmd;
- if (blk_rq_tagged(cmd->request))
- blk_queue_end_tag(q, cmd->request);
-
- /*
- * set REQ_SPECIAL - we have a command
- * clear REQ_DONTPREP - we assume the sg table has been
- * nuked so we need to set it up again.
- */
- cmd->request->flags |= REQ_SPECIAL;
cmd->request->flags &= ~REQ_DONTPREP;
- __elv_add_request(q, cmd->request, 0, 0);
- spin_unlock_irqrestore(q->queue_lock, flags);
+ blk_insert_request(q, cmd->request, 1, cmd);
scsi_run_queue(q);
}
@@ -1213,9 +1199,7 @@ static void scsi_request_fn(struct request_queue *q)
* later time.
*/
spin_lock_irq(q->queue_lock);
- if (blk_rq_tagged(req))
- blk_queue_end_tag(q, req);
- __elv_add_request(q, req, 0, 0);
+ blk_requeue_request(q, req);
sdev->device_busy--;
if(sdev->device_busy == 0)
blk_plug_device(q);
@@ -1426,17 +1410,17 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage,
if(scsi_status_is_good(sreq->sr_result)) {
data->header_length = header_length;
if(use_10_for_ms) {
- data->length = buffer[0]*256 + buffer[1];
+ data->length = buffer[0]*256 + buffer[1] + 2;
data->medium_type = buffer[2];
data->device_specific = buffer[3];
data->longlba = buffer[4] & 0x01;
data->block_descriptor_length = buffer[6]*256
+ buffer[7];
} else {
- data->length = buffer[0];
+ data->length = buffer[0] + 1;
data->medium_type = buffer[1];
- data->device_specific = buffer[3];
- data->block_descriptor_length = buffer[4];
+ data->device_specific = buffer[2];
+ data->block_descriptor_length = buffer[3];
}
}
diff --git a/drivers/scsi/scsi_module.c b/drivers/scsi/scsi_module.c
index 7803089da533..515a3e4b48fe 100644
--- a/drivers/scsi/scsi_module.c
+++ b/drivers/scsi/scsi_module.c
@@ -40,6 +40,7 @@ static int __init init_this_scsi_driver(void)
error = scsi_add_host(shost, NULL);
if (error)
goto fail;
+ scsi_scan_host(shost);
}
return 0;
fail:
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 6346005e64c7..f17bdd42afe6 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -102,7 +102,6 @@ extern void scsi_exit_procfs(void);
#endif /* CONFIG_PROC_FS */
/* scsi_scan.c */
-extern void scsi_scan_host(struct Scsi_Host *);
extern void scsi_forget_host(struct Scsi_Host *);
extern void scsi_free_sdev(struct scsi_device *);
extern void scsi_free_shost(struct Scsi_Host *);
@@ -117,11 +116,6 @@ extern void scsi_sysfs_remove_host(struct Scsi_Host *);
extern int scsi_sysfs_register(void);
extern void scsi_sysfs_unregister(void);
-/* definitions for the linker default sections covering the host
- * class and device attributes */
-extern struct class_device_attribute *scsi_sysfs_shost_attrs[];
-extern struct device_attribute *scsi_sysfs_sdev_attrs[];
-
extern struct class shost_class;
extern struct bus_type scsi_bus_type;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 9dffa0c2caca..3b8309105021 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -464,8 +464,7 @@ static void scsi_set_name(struct scsi_device *sdev, char *inq_result)
while (i >= 0 && type[i] == ' ')
type[i--] = '\0';
- snprintf(sdev->sdev_driverfs_dev.name, DEVICE_NAME_SIZE, "SCSI %s",
- type);
+ snprintf(sdev->sdev_gendev.name, DEVICE_NAME_SIZE, "SCSI %s", type);
}
/**
diff --git a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
index 62e413ef5949..2ce7cb6c25bf 100644
--- a/drivers/scsi/scsi_syms.c
+++ b/drivers/scsi/scsi_syms.c
@@ -34,6 +34,7 @@ EXPORT_SYMBOL(scsi_register_driver);
EXPORT_SYMBOL(scsi_register_interface);
EXPORT_SYMBOL(scsi_host_alloc);
EXPORT_SYMBOL(scsi_add_host);
+EXPORT_SYMBOL(scsi_scan_host);
EXPORT_SYMBOL(scsi_remove_host);
EXPORT_SYMBOL(scsi_host_get);
EXPORT_SYMBOL(scsi_host_put);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 80be2659043d..3801b768c733 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -45,7 +45,7 @@ shost_rd_attr(cmd_per_lun, "%hd\n");
shost_rd_attr(sg_tablesize, "%hu\n");
shost_rd_attr(unchecked_isa_dma, "%d\n");
-struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
+static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
&class_device_attr_unique_id,
&class_device_attr_host_busy,
&class_device_attr_cmd_per_lun,
@@ -204,7 +204,7 @@ store_rescan_field (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field)
/* Default template for device attributes. May NOT be modified */
-struct device_attribute *scsi_sysfs_sdev_attrs[] = {
+static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
&dev_attr_device_blocked,
&dev_attr_queue_depth,
&dev_attr_type,
@@ -228,6 +228,42 @@ static void scsi_device_release(struct device *dev)
scsi_free_sdev(sdev);
}
+static struct device_attribute *attr_overridden(
+ struct device_attribute **attrs,
+ struct device_attribute *attr)
+{
+ int i;
+
+ if (!attrs)
+ return NULL;
+ for (i = 0; attrs[i]; i++)
+ if (!strcmp(attrs[i]->attr.name, attr->attr.name))
+ return attrs[i];
+ return NULL;
+}
+
+static int attr_add(struct device *dev, struct device_attribute *attr)
+{
+ struct device_attribute *base_attr;
+
+ /*
+ * Spare the caller from having to copy things it's not interested in.
+ */
+ base_attr = attr_overridden(scsi_sysfs_sdev_attrs, attr);
+ if (base_attr) {
+ /* extend permissions */
+ attr->attr.mode |= base_attr->attr.mode;
+
+ /* override null show/store with default */
+ if (!attr->show)
+ attr->show = base_attr->show;
+ if (!attr->store)
+ attr->store = base_attr->store;
+ }
+
+ return device_create_file(dev, attr);
+}
+
/**
* scsi_device_register - register a scsi device with the scsi bus
* @sdev: scsi_device to register
@@ -239,20 +275,20 @@ int scsi_device_register(struct scsi_device *sdev)
{
int error = 0, i;
- device_initialize(&sdev->sdev_driverfs_dev);
- sprintf(sdev->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d",
+ device_initialize(&sdev->sdev_gendev);
+ sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
- sdev->sdev_driverfs_dev.parent = &sdev->host->host_gendev;
- sdev->sdev_driverfs_dev.bus = &scsi_bus_type;
- sdev->sdev_driverfs_dev.release = scsi_device_release;
+ sdev->sdev_gendev.parent = &sdev->host->shost_gendev;
+ sdev->sdev_gendev.bus = &scsi_bus_type;
+ sdev->sdev_gendev.release = scsi_device_release;
class_device_initialize(&sdev->sdev_classdev);
- sdev->sdev_classdev.dev = &sdev->sdev_driverfs_dev;
+ sdev->sdev_classdev.dev = &sdev->sdev_gendev;
sdev->sdev_classdev.class = &sdev_class;
snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, "%d:%d:%d:%d",
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
- error = device_add(&sdev->sdev_driverfs_dev);
+ error = device_add(&sdev->sdev_gendev);
if (error) {
printk(KERN_INFO "error 1\n");
return error;
@@ -260,16 +296,28 @@ int scsi_device_register(struct scsi_device *sdev)
error = class_device_add(&sdev->sdev_classdev);
if (error) {
printk(KERN_INFO "error 2\n");
- device_unregister(&sdev->sdev_driverfs_dev);
+ device_unregister(&sdev->sdev_gendev);
return error;
}
- for (i = 0; !error && sdev->host->hostt->sdev_attrs[i] != NULL; i++)
- error = device_create_file(&sdev->sdev_driverfs_dev,
- sdev->host->hostt->sdev_attrs[i]);
-
- if (error)
- scsi_device_unregister(sdev);
+ if (sdev->host->hostt->sdev_attrs) {
+ for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
+ error = attr_add(&sdev->sdev_gendev,
+ sdev->host->hostt->sdev_attrs[i]);
+ if (error)
+ scsi_device_unregister(sdev);
+ }
+ }
+
+ for (i = 0; scsi_sysfs_sdev_attrs[i]; i++) {
+ if (!attr_overridden(sdev->host->hostt->sdev_attrs,
+ scsi_sysfs_sdev_attrs[i])) {
+ error = device_create_file(&sdev->sdev_gendev,
+ scsi_sysfs_sdev_attrs[i]);
+ if (error)
+ scsi_device_unregister(sdev);
+ }
+ }
return error;
}
@@ -280,12 +328,8 @@ int scsi_device_register(struct scsi_device *sdev)
**/
void scsi_device_unregister(struct scsi_device *sdev)
{
- int i;
-
- for (i = 0; sdev->host->hostt->sdev_attrs[i] != NULL; i++)
- device_remove_file(&sdev->sdev_driverfs_dev, sdev->host->hostt->sdev_attrs[i]);
class_device_unregister(&sdev->sdev_classdev);
- device_unregister(&sdev->sdev_driverfs_dev);
+ device_unregister(&sdev->sdev_gendev);
}
int scsi_register_driver(struct device_driver *drv)
@@ -315,20 +359,57 @@ static void scsi_host_release(struct device *dev)
void scsi_sysfs_init_host(struct Scsi_Host *shost)
{
- device_initialize(&shost->host_gendev);
- snprintf(shost->host_gendev.bus_id, BUS_ID_SIZE, "host%d",
+ device_initialize(&shost->shost_gendev);
+ snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
shost->host_no);
- snprintf(shost->host_gendev.name, DEVICE_NAME_SIZE, "%s",
+ snprintf(shost->shost_gendev.name, DEVICE_NAME_SIZE, "%s",
shost->hostt->proc_name);
- shost->host_gendev.release = scsi_host_release;
+ shost->shost_gendev.release = scsi_host_release;
- class_device_initialize(&shost->class_dev);
- shost->class_dev.dev = &shost->host_gendev;
- shost->class_dev.class = &shost_class;
- snprintf(shost->class_dev.class_id, BUS_ID_SIZE, "host%d",
+ class_device_initialize(&shost->shost_classdev);
+ shost->shost_classdev.dev = &shost->shost_gendev;
+ shost->shost_classdev.class = &shost_class;
+ snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d",
shost->host_no);
}
+static struct class_device_attribute *class_attr_overridden(
+ struct class_device_attribute **attrs,
+ struct class_device_attribute *attr)
+{
+ int i;
+
+ if (!attrs)
+ return NULL;
+ for (i = 0; attrs[i]; i++)
+ if (!strcmp(attrs[i]->attr.name, attr->attr.name))
+ return attrs[i];
+ return NULL;
+}
+
+static int class_attr_add(struct class_device *classdev,
+ struct class_device_attribute *attr)
+{
+ struct class_device_attribute *base_attr;
+
+ /*
+ * Spare the caller from having to copy things it's not interested in.
+ */
+ base_attr = class_attr_overridden(scsi_sysfs_shost_attrs, attr);
+ if (base_attr) {
+ /* extend permissions */
+ attr->attr.mode |= base_attr->attr.mode;
+
+ /* override null show/store with default */
+ if (!attr->show)
+ attr->show = base_attr->show;
+ if (!attr->store)
+ attr->store = base_attr->store;
+ }
+
+ return class_device_create_file(classdev, attr);
+}
+
/**
* scsi_sysfs_add_host - add scsi host to subsystem
* @shost: scsi host struct to add to subsystem
@@ -336,31 +417,44 @@ void scsi_sysfs_init_host(struct Scsi_Host *shost)
**/
int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev)
{
- int i, error;
+ int error, i;
- if (!shost->host_gendev.parent)
- shost->host_gendev.parent = dev ? dev : &legacy_bus;
+ if (!shost->shost_gendev.parent)
+ shost->shost_gendev.parent = dev ? dev : &legacy_bus;
- error = device_add(&shost->host_gendev);
+ error = device_add(&shost->shost_gendev);
if (error)
return error;
- error = class_device_add(&shost->class_dev);
+ error = class_device_add(&shost->shost_classdev);
if (error)
goto clean_device;
- for (i = 0; !error && shost->hostt->shost_attrs[i] != NULL; i++)
- error = class_device_create_file(&shost->class_dev,
- shost->hostt->shost_attrs[i]);
- if (error)
- goto clean_class;
+ if (shost->hostt->shost_attrs) {
+ for (i = 0; shost->hostt->shost_attrs[i]; i++) {
+ error = class_attr_add(&shost->shost_classdev,
+ shost->hostt->shost_attrs[i]);
+ if (error)
+ goto clean_class;
+ }
+ }
+
+ for (i = 0; scsi_sysfs_shost_attrs[i]; i++) {
+ if (!class_attr_overridden(shost->hostt->shost_attrs,
+ scsi_sysfs_shost_attrs[i])) {
+ error = class_device_create_file(&shost->shost_classdev,
+ scsi_sysfs_shost_attrs[i]);
+ if (error)
+ goto clean_class;
+ }
+ }
return error;
clean_class:
- class_device_del(&shost->class_dev);
+ class_device_del(&shost->shost_classdev);
clean_device:
- device_del(&shost->host_gendev);
+ device_del(&shost->shost_gendev);
return error;
}
@@ -371,133 +465,6 @@ clean_device:
**/
void scsi_sysfs_remove_host(struct Scsi_Host *shost)
{
- class_device_del(&shost->class_dev);
- device_del(&shost->host_gendev);
-}
-
-/** scsi_sysfs_modify_shost_attribute - modify or add a host class attribute
- *
- * @class_attrs:host class attribute list to be added to or modified
- * @attr: individual attribute to change or added
- *
- * returns zero if successful or error if not
- **/
-int scsi_sysfs_modify_shost_attribute(
- struct class_device_attribute ***class_attrs,
- struct class_device_attribute *attr)
-{
- int modify = -1;
- int num_attrs;
-
- if(*class_attrs == NULL)
- *class_attrs = scsi_sysfs_shost_attrs;
-
- for(num_attrs=0; (*class_attrs)[num_attrs] != NULL; num_attrs++)
- if(strcmp((*class_attrs)[num_attrs]->attr.name,
- attr->attr.name) == 0)
- modify = num_attrs;
-
- if(*class_attrs == scsi_sysfs_shost_attrs || modify < 0) {
- /* note: need space for null at the end as well */
- struct class_device_attribute **tmp_attrs =
- kmalloc(sizeof(*tmp_attrs) *
- (num_attrs + (modify >= 0 ? 1 : 2)),
- GFP_KERNEL);
- if(tmp_attrs == NULL)
- return -ENOMEM;
- memcpy(tmp_attrs, *class_attrs, sizeof(*tmp_attrs) *
- (num_attrs + 1));
- if(*class_attrs != scsi_sysfs_shost_attrs)
- kfree(*class_attrs);
- *class_attrs = tmp_attrs;
- }
- if(modify >= 0) {
- /* spare the caller from having to copy things it's
- * not interested in */
- struct class_device_attribute *old_attr =
- (*class_attrs)[modify];
- /* extend permissions */
- attr->attr.mode |= old_attr->attr.mode;
-
- /* override null show/store with default */
- if(attr->show == NULL)
- attr->show = old_attr->show;
- if(attr->store == NULL)
- attr->store = old_attr->store;
- (*class_attrs)[modify] = attr;
- } else {
- (*class_attrs)[num_attrs++] = attr;
- (*class_attrs)[num_attrs] = NULL;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(scsi_sysfs_modify_shost_attribute);
-
-/** scsi_sysfs_modify_sdev_attribute - modify or add a host device attribute
- *
- * @dev_attrs: pointer to the attribute list to be added to or modified
- * @attr: individual attribute to change or added
- *
- * returns zero if successful or error if not
- **/
-int scsi_sysfs_modify_sdev_attribute(struct device_attribute ***dev_attrs,
- struct device_attribute *attr)
-{
- int modify = -1;
- int num_attrs;
-
- if(*dev_attrs == NULL)
- *dev_attrs = scsi_sysfs_sdev_attrs;
-
- for(num_attrs=0; (*dev_attrs)[num_attrs] != NULL; num_attrs++)
- if(strcmp((*dev_attrs)[num_attrs]->attr.name,
- attr->attr.name) == 0)
- modify = num_attrs;
-
- if(*dev_attrs == scsi_sysfs_sdev_attrs || modify < 0) {
- /* note: need space for null at the end as well */
- struct device_attribute **tmp_attrs =
- kmalloc(sizeof(*tmp_attrs) *
- (num_attrs + (modify >= 0 ? 1 : 2)),
- GFP_KERNEL);
- if(tmp_attrs == NULL)
- return -ENOMEM;
- memcpy(tmp_attrs, *dev_attrs, sizeof(*tmp_attrs) *
- (num_attrs + 1));
- if(*dev_attrs != scsi_sysfs_sdev_attrs)
- kfree(*dev_attrs);
- *dev_attrs = tmp_attrs;
- }
- if(modify >= 0) {
- /* spare the caller from having to copy things it's
- * not interested in */
- struct device_attribute *old_attr =
- (*dev_attrs)[modify];
- /* extend permissions */
- attr->attr.mode |= old_attr->attr.mode;
-
- /* override null show/store with default */
- if(attr->show == NULL)
- attr->show = old_attr->show;
- if(attr->store == NULL)
- attr->store = old_attr->store;
- (*dev_attrs)[modify] = attr;
- } else {
- (*dev_attrs)[num_attrs++] = attr;
- (*dev_attrs)[num_attrs] = NULL;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(scsi_sysfs_modify_sdev_attribute);
-
-void scsi_sysfs_release_attributes(struct scsi_host_template *hostt)
-{
- if(hostt->sdev_attrs != scsi_sysfs_sdev_attrs)
- kfree(hostt->sdev_attrs);
-
- if(hostt->shost_attrs != scsi_sysfs_shost_attrs)
- kfree(hostt->shost_attrs);
+ class_device_del(&shost->shost_classdev);
+ device_del(&shost->shost_gendev);
}
-EXPORT_SYMBOL(scsi_sysfs_release_attributes);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index dead50aa989e..441ca6e58cfc 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -606,35 +606,8 @@ not_present:
static void sd_rescan(struct device *dev)
{
- struct scsi_device *sdp = to_scsi_device(dev);
struct scsi_disk *sdkp = dev_get_drvdata(dev);
- struct gendisk *gd;
- struct scsi_request *SRpnt;
- unsigned char *buffer;
-
- if (!sdkp || sdp->online == FALSE || !sdkp->media_present)
- return;
-
- gd = sdkp->disk;
-
- SCSI_LOG_HLQUEUE(3, printk("sd_rescan: disk=%s\n", gd->disk_name));
-
- SRpnt = scsi_allocate_request(sdp);
- if (!SRpnt) {
- printk(KERN_WARNING "(sd_rescan:) Request allocation "
- "failure.\n");
- return;
- }
-
- if (sdkp->device->host->unchecked_isa_dma)
- buffer = kmalloc(512, GFP_DMA);
- else
- buffer = kmalloc(512, GFP_KERNEL);
-
- sd_read_capacity(sdkp, gd->disk_name, SRpnt, buffer);
- set_capacity(gd, sdkp->capacity);
- scsi_release_request(SRpnt);
- kfree(buffer);
+ sd_revalidate_disk(sdkp->disk);
}
static struct block_device_operations sd_fops = {
@@ -1318,7 +1291,7 @@ static int sd_probe(struct device *dev)
sd_revalidate_disk(gd);
- gd->driverfs_dev = &sdp->sdev_driverfs_dev;
+ gd->driverfs_dev = &sdp->sdev_gendev;
gd->flags = GENHD_FL_DRIVERFS;
if (sdp->removable)
gd->flags |= GENHD_FL_REMOVABLE;
diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
index d5b8cb39b485..5132357c8fd8 100644
--- a/drivers/scsi/sim710.c
+++ b/drivers/scsi/sim710.c
@@ -138,7 +138,8 @@ sim710_probe_common(struct device *dev, unsigned long base_addr,
goto out_unregister;
}
- scsi_add_host(host, dev);
+ scsi_add_host(host, dev); /* XXX handle failure */
+ scsi_scan_host(host);
hostdata->dev = dev;
return 0;
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index e38e8d1d2231..7c24b78e45e6 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -533,7 +533,7 @@ static int sr_probe(struct device *dev)
snprintf(disk->devfs_name, sizeof(disk->devfs_name),
"%s/cd", sdev->devfs_name);
- disk->driverfs_dev = &sdev->sdev_driverfs_dev;
+ disk->driverfs_dev = &sdev->sdev_gendev;
register_cdrom(&cd->cdi);
set_capacity(disk, cd->capacity);
disk->private_data = &cd->driver;
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index be1548c00e3d..b0266f645172 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -1110,6 +1110,7 @@ static int sym_eh_handler(int op, char *opname, Scsi_Cmnd *cmd)
int sts = -1;
struct sym_eh_wait eh, *ep = &eh;
char devname[20];
+ unsigned long flags;
sprintf(devname, "%s:%d:%d", sym_name(np), cmd->device->id, cmd->device->lun);
@@ -1201,7 +1202,11 @@ finish:
ep->timer.data = (u_long)cmd;
ep->timed_out = 1; /* Be pessimistic for once :) */
add_timer(&ep->timer);
+ local_save_flags(flags);
+ spin_unlock_irq(cmd->device->host->host_lock);
down(&ep->sem);
+ local_irq_restore(flags);
+ spin_lock(cmd->device->host->host_lock);
if (ep->timed_out)
sts = -2;
}
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index bed64aaec0bc..05700528818b 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -85,7 +85,7 @@ zalon_scsi_callback(struct parisc_device *dev)
{
struct gsc_irq gsc_irq;
u32 zalon_vers;
- int irq;
+ int irq, error = -ENODEV;
unsigned long zalon = dev->hpa;
unsigned long io_port = zalon + GSC_SCSI_ZALON_OFFSET;
static int unit = 0;
@@ -147,11 +147,18 @@ zalon_scsi_callback(struct parisc_device *dev)
dev_set_drvdata(&dev->dev, host);
- scsi_add_host(host, &dev->dev);
+ error = scsi_add_host(host, &dev->dev);
+ if (error)
+ goto fail_free_irq;
+ scsi_scan_host(host);
return 0;
+
+ fail_free_irq:
+ free_irq(irq, host);
fail:
- return -ENODEV;
+ ncr53c8xx_release(host);
+ return error;
}
static struct parisc_device_id zalon_tbl[] = {
diff --git a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c
index cc1768849fcc..bc323a4c74bf 100644
--- a/drivers/usb/image/hpusbscsi.c
+++ b/drivers/usb/image/hpusbscsi.c
@@ -109,7 +109,8 @@ hpusbscsi_usb_probe(struct usb_interface *intf,
goto out_unlink_controlurb;
new->host->hostdata[0] = (unsigned long)new;
- scsi_add_host(new->host, &intf->dev);
+ scsi_add_host(new->host, &intf->dev); /* XXX handle failure */
+ scsi_scan_host(new->host);
new->sense_command[0] = REQUEST_SENSE;
new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH;
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index dcef1e90929d..e5f1a12dc2bb 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -817,7 +817,8 @@ static int mts_usb_probe(struct usb_interface *intf,
goto out_free_urb;
new_desc->host->hostdata[0] = (unsigned long)new_desc;
- scsi_add_host(new_desc->host, NULL);
+ scsi_add_host(new_desc->host, NULL); /* XXX handle failure */
+ scsi_scan_host(new_desc->host);
usb_set_intfdata(intf, new_desc);
return 0;
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index ef495072850f..ee67b5340adc 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -958,6 +958,8 @@ static int storage_probe(struct usb_interface *intf,
goto BadDevice;
}
+ scsi_scan_host(us->host);
+
printk(KERN_DEBUG
"WARNING: USB Mass Storage data integrity not assured\n");
printk(KERN_DEBUG
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 2e7f92aa1dc2..4f65bab2f201 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -491,6 +491,7 @@ extern void __blk_attempt_remerge(request_queue_t *, struct request *);
extern struct request *blk_get_request(request_queue_t *, int, int);
extern void blk_put_request(struct request *);
extern void blk_insert_request(request_queue_t *, struct request *, int, void *);
+extern void blk_requeue_request(request_queue_t *, struct request *);
extern void blk_plug_device(request_queue_t *);
extern int blk_remove_plug(request_queue_t *);
extern void blk_recount_segments(request_queue_t *, struct bio *);
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index b0e70562be94..3eeb5a2e4591 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -13,6 +13,7 @@ typedef struct request *(elevator_next_req_fn) (request_queue_t *);
typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, struct list_head *);
typedef int (elevator_queue_empty_fn) (request_queue_t *);
typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *);
+typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *);
typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *);
typedef struct list_head *(elevator_get_sort_head_fn) (request_queue_t *, struct request *);
typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *);
@@ -33,6 +34,7 @@ struct elevator_s
elevator_next_req_fn *elevator_next_req_fn;
elevator_add_req_fn *elevator_add_req_fn;
elevator_remove_req_fn *elevator_remove_req_fn;
+ elevator_requeue_req_fn *elevator_requeue_req_fn;
elevator_queue_empty_fn *elevator_queue_empty_fn;
elevator_completed_req_fn *elevator_completed_req_fn;
@@ -64,6 +66,7 @@ extern void elv_merge_requests(request_queue_t *, struct request *,
struct request *);
extern void elv_merged_request(request_queue_t *, struct request *);
extern void elv_remove_request(request_queue_t *, struct request *);
+extern void elv_requeue_request(request_queue_t *, struct request *);
extern int elv_queue_empty(request_queue_t *);
extern struct request *elv_next_request(struct request_queue *q);
extern struct request *elv_former_request(request_queue_t *, struct request *);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index c49c124fde74..de5ff9fd6c4a 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -11,8 +11,6 @@ struct scsi_mode_data;
struct scsi_device {
- struct class_device sdev_classdev;
-
struct list_head siblings; /* list of all devices on this host */
struct list_head same_target_siblings; /* just the devices sharing same target id */
struct Scsi_Host *host;
@@ -86,10 +84,11 @@ struct scsi_device {
unsigned int max_device_blocked; /* what device_blocked counts down from */
#define SCSI_DEFAULT_DEVICE_BLOCKED 3
- struct device sdev_driverfs_dev;
+ struct device sdev_gendev;
+ struct class_device sdev_classdev;
};
#define to_scsi_device(d) \
- container_of(d, struct scsi_device, sdev_driverfs_dev)
+ container_of(d, struct scsi_device, sdev_gendev)
extern struct scsi_device *scsi_add_device(struct Scsi_Host *,
uint, uint, uint);
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index d92dc75d131d..3ef701078fef 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -329,12 +329,12 @@ struct scsi_host_template {
#define SCSI_DEFAULT_HOST_BLOCKED 7
/*
- * Pointer to the sysfs class properties for this host
+ * Pointer to the sysfs class properties for this host, NULL terminated.
*/
struct class_device_attribute **shost_attrs;
/*
- * Pointer to the SCSI device properties for this host
+ * Pointer to the SCSI device properties for this host, NULL terminated.
*/
struct device_attribute **sdev_attrs;
@@ -442,12 +442,6 @@ struct Scsi_Host {
*/
unsigned int max_host_blocked;
- /*
- * Support for sysfs
- */
- struct device host_gendev;
- struct class_device class_dev;
-
/* legacy crap */
unsigned long base;
unsigned long io_port;
@@ -455,6 +449,9 @@ struct Scsi_Host {
unsigned char dma_channel;
unsigned int irq;
+ /* ldm bits */
+ struct device shost_gendev;
+ struct class_device shost_classdev;
/*
* List of hosts per template.
@@ -474,12 +471,13 @@ struct Scsi_Host {
__attribute__ ((aligned (sizeof(unsigned long))));
};
#define dev_to_shost(d) \
- container_of(d, struct Scsi_Host, host_gendev)
+ container_of(d, struct Scsi_Host, shost_gendev)
#define class_to_shost(d) \
- container_of(d, struct Scsi_Host, class_dev)
+ container_of(d, struct Scsi_Host, shost_classdev)
extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int);
extern int scsi_add_host(struct Scsi_Host *, struct device *);
+extern void scsi_scan_host(struct Scsi_Host *);
extern int scsi_remove_host(struct Scsi_Host *);
extern void scsi_host_get(struct Scsi_Host *);
extern void scsi_host_put(struct Scsi_Host *t);
@@ -495,16 +493,14 @@ static inline void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock)
static inline void scsi_set_device(struct Scsi_Host *shost,
struct device *dev)
{
- shost->host_gendev.parent = dev;
+ shost->shost_gendev.parent = dev;
}
static inline struct device *scsi_get_device(struct Scsi_Host *shost)
{
- return shost->host_gendev.parent;
+ return shost->shost_gendev.parent;
}
-extern void scsi_sysfs_release_attributes(struct scsi_host_template *);
-
extern void scsi_unblock_requests(struct Scsi_Host *);
extern void scsi_block_requests(struct Scsi_Host *);
diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h
index 90dcdaafe946..d591d365c983 100644
--- a/include/scsi/scsi_request.h
+++ b/include/scsi/scsi_request.h
@@ -56,7 +56,7 @@ extern void scsi_do_req(struct scsi_request *, const void *cmnd,
int timeout, int retries);
struct scsi_mode_data {
- __u16 length;
+ __u32 length;
__u16 block_descriptor_length;
__u8 medium_type;
__u8 device_specific;