Commit 0dc70072 authored by James Bottomley's avatar James Bottomley

Merge mulgrave.(none):/home/jejb/BK/linux-2.5

into mulgrave.(none):/home/jejb/BK/scsi-for-linus-2.5
parents db01fdce f1c5d5cd
......@@ -3137,14 +3137,14 @@ static int sbp2scsi_reset (Scsi_Cmnd *SCpnt)
/*
* Called by scsi stack to get bios parameters (used by fdisk, and at boot).
*/
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,44)
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,43)
static int sbp2scsi_biosparam (struct scsi_device *sdev,
struct block_device *dev, sector_t capacy, int geom[])
struct block_device *dev, sector_t capacity, int geom[])
{
#else
static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[])
{
sector_t capacy = disk->capacity;
sector_t capacity = disk->capacity;
#endif
int heads, sectors, cylinders;
......
......@@ -552,7 +552,8 @@ void sbp2scsi_setup(char *str, int *ints);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28)
static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]);
#else
static int sbp2scsi_biosparam (Scsi_Disk *disk, struct block_device *dev, int geom[]);
static int sbp2scsi_biosparam (struct scsi_device *sdev,
struct block_device *dev, sector_t capacy, int geom[]);
#endif
static int sbp2scsi_abort (Scsi_Cmnd *SCpnt);
static int sbp2scsi_reset (Scsi_Cmnd *SCpnt);
......
......@@ -85,23 +85,6 @@ config BLK_DEV_SR_VENDOR
drives (and HP Writers). If you have such a drive and get the first
session only, try saying Y here; everybody else says N.
config SR_EXTRA_DEVS
int "Maximum number of CDROM devices that can be loaded as modules"
depends on BLK_DEV_SR
default "2"
---help---
This controls the amount of additional space allocated in tables for
drivers that are loaded as modules after the kernel is booted. In
the event that the SCSI core itself was loaded as a module, this
value is the number of additional CD-ROMs that can be loaded after
the first host driver is loaded.
Admittedly this isn't pretty, but there are tons of race conditions
involved with resizing the internal arrays on the fly. Someday this
flag will go away, and everything will work automatically.
If you don't understand what's going on, go with the default.
config CHR_DEV_SG
tristate "SCSI generic support"
depends on SCSI
......
......@@ -45,13 +45,9 @@
#include "scsi.h"
#include "hosts.h"
LIST_HEAD(scsi_host_tmpl_list);
LIST_HEAD(scsi_host_hn_list);
LIST_HEAD(scsi_host_list);
spinlock_t scsi_host_list_lock = SPIN_LOCK_UNLOCKED;
struct Scsi_Device_Template * scsi_devicelist;
static LIST_HEAD(scsi_host_hn_list);
static LIST_HEAD(scsi_host_list);
static spinlock_t scsi_host_list_lock = SPIN_LOCK_UNLOCKED;
static int scsi_host_next_hn; /* host_no for next new host */
static int scsi_hosts_registered; /* cnt of registered scsi hosts */
......@@ -115,7 +111,6 @@ int scsi_host_chk_and_release(struct Scsi_Host *shost)
{
int pcount;
Scsi_Device *sdev;
struct Scsi_Device_Template *sdev_tp;
Scsi_Cmnd *scmd;
/*
......@@ -175,10 +170,7 @@ int scsi_host_chk_and_release(struct Scsi_Host *shost)
* structures
*/
for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
for (sdev_tp = scsi_devicelist; sdev_tp;
sdev_tp = sdev_tp->next)
if (sdev_tp->detach)
(*sdev_tp->detach) (sdev);
scsi_detach_device(sdev);
/* If something still attached, punt */
if (sdev->attached) {
......@@ -471,12 +463,9 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
{
int cur_cnt;
Scsi_Device *sdev;
struct Scsi_Device_Template *sdev_tp;
struct list_head *lh;
struct Scsi_Host *shost;
INIT_LIST_HEAD(&shost_tp->shtp_list);
/*
* Check no detect routine.
*/
......@@ -526,8 +515,6 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
}
}
list_add_tail(&shost_tp->shtp_list, &scsi_host_tmpl_list);
/* The next step is to call scan_scsis here. This generates the
* Scsi_Devices entries
*/
......@@ -549,31 +536,15 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
}
}
for (sdev_tp = scsi_devicelist; sdev_tp;
sdev_tp = sdev_tp->next) {
if (sdev_tp->init && sdev_tp->dev_noticed)
(*sdev_tp->init) ();
}
/*
* Next we create the Scsi_Cmnd structures for this host
*/
list_for_each(lh, &scsi_host_list) {
shost = list_entry(lh, struct Scsi_Host, sh_list);
for (sdev = shost->host_queue; sdev; sdev = sdev->next)
if (sdev->host->hostt == shost_tp) {
scsi_build_commandblocks(sdev);
if (sdev->current_queue_depth == 0)
if (sdev->host->hostt == shost_tp)
if (scsi_attach_device(sdev))
goto out_of_space;
for (sdev_tp = scsi_devicelist;
sdev_tp;
sdev_tp = sdev_tp->next)
if (sdev_tp->attach)
(*sdev_tp->attach) (sdev);
if (!sdev->attached) {
scsi_release_commandblocks(sdev);
}
}
}
}
......@@ -614,14 +585,6 @@ int scsi_unregister_host(Scsi_Host_Template *shost_tp)
printk(KERN_INFO "scsi : %d host%s left.\n", scsi_hosts_registered,
(scsi_hosts_registered == 1) ? "" : "s");
/*
* Remove it from the list if all
* hosts were successfully removed (ie preset == 0)
*/
if (!shost_tp->present) {
list_del(&shost_tp->shtp_list);
}
MOD_DEC_USE_COUNT;
unlock_kernel();
......
......@@ -57,9 +57,6 @@ typedef struct scsi_disk Disk;
typedef struct SHT
{
struct list_head shtp_list;
/* Used with loadable modules so that we know when it is safe to unload */
struct module * module;
......@@ -520,8 +517,6 @@ typedef struct SHN
unsigned short host_registered;
} Scsi_Host_Name;
extern struct Scsi_Device_Template * scsi_devicelist;
extern void scsi_proc_host_mkdir(Scsi_Host_Template *);
extern void scsi_proc_host_add(struct Scsi_Host *);
extern void scsi_proc_host_rm(struct Scsi_Host *);
......@@ -605,28 +600,6 @@ extern void scsi_host_busy_inc(struct Scsi_Host *, Scsi_Device *);
extern void scsi_host_busy_dec_and_test(struct Scsi_Host *, Scsi_Device *);
extern void scsi_host_failed_inc_and_test(struct Scsi_Host *);
/*
* This is an ugly hack. If we expect to be able to load devices at run time,
* we need to leave extra room in some of the data structures. Doing a
* realloc to enlarge the structures would be riddled with race conditions,
* so until a better solution is discovered, we use this crude approach
*
* Even bigger hack for SparcSTORAGE arrays. Those are at least 6 disks, but
* usually up to 30 disks, so everyone would need to change this. -jj
*
* Note: These things are all evil and all need to go away. My plan is to
* tackle the character devices first, as there aren't any locking implications
* in the block device layer. The block devices will require more work.
*
* The generics driver has been updated to resize as required. So as the tape
* driver. Two down, two more to go.
*/
#ifndef CONFIG_SR_EXTRA_DEVS
#define CONFIG_SR_EXTRA_DEVS 2
#endif
#define SR_EXTRA_DEVS CONFIG_SR_EXTRA_DEVS
/**
* scsi_find_device - find a device given the host
* @shost: SCSI host pointer
......
......@@ -2865,16 +2865,14 @@ static int mega_findCard (Scsi_Host_Template * pHostTmpl,
pciDevFun = pdev->devfn;
#endif
if ((flag & BOARD_QUARTZ) && (skip_id == -1)) {
pcibios_read_config_word (pciBus, pciDevFun,
PCI_CONF_AMISIG, &magic);
pci_read_config_word (pdev, PCI_CONF_AMISIG, &magic);
if ((magic != AMI_SIGNATURE)
&& (magic != AMI_SIGNATURE_471)) {
pciIdx++;
continue; /* not an AMI board */
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pcibios_read_config_dword (pciBus, pciDevFun,
PCI_CONF_AMISIG64, &magic64);
pci_read_config_dword (pdev, PCI_CONF_AMISIG64, &magic64);
if (magic64 == AMI_64BIT_SIGNATURE)
flag |= BOARD_64BIT;
......@@ -3215,7 +3213,6 @@ int megaraid_detect (Scsi_Host_Template * pHostTmpl)
count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI,
PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ);
mega_reorder_hosts ();
#ifdef CONFIG_PROC_FS
if (count) {
......@@ -3481,173 +3478,6 @@ mega_get_boot_ldrv(mega_host_config *megacfg)
}
static void mega_reorder_hosts (void)
{
struct Scsi_Host *shpnt;
struct Scsi_Host *shone;
struct Scsi_Host *shtwo;
mega_host_config *boot_host;
int i;
/*
* Find the (first) host which has it's BIOS enabled
*/
boot_host = NULL;
for (i = 0; i < MAX_CONTROLLERS; i++) {
if (mega_hbas[i].is_bios_enabled) {
boot_host = mega_hbas[i].hostdata_addr;
break;
}
}
if (boot_host == NULL) {
printk (KERN_WARNING "megaraid: no BIOS enabled.\n");
return;
}
/*
* Traverse through the list of SCSI hosts for our HBA locations
*/
shone = shtwo = NULL;
for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
/* Is it one of ours? */
for (i = 0; i < MAX_CONTROLLERS; i++) {
if ((mega_host_config *) shpnt->hostdata ==
mega_hbas[i].hostdata_addr) {
/* Does this one has BIOS enabled */
if (mega_hbas[i].hostdata_addr == boot_host) {
/* Are we first */
if (shtwo == NULL) /* Yes! */
return;
else { /* :-( */
shone = shpnt;
}
} else {
if (!shtwo) {
/* were we here before? xchng first */
shtwo = shpnt;
}
}
break;
}
}
/*
* Have we got the boot host and one which does not have the bios
* enabled.
*/
if (shone && shtwo)
break;
}
if (shone && shtwo) {
mega_swap_hosts (shone, shtwo);
}
return;
}
static void mega_swap_hosts (struct Scsi_Host *shone, struct Scsi_Host *shtwo)
{
struct Scsi_Host *prevtoshtwo;
struct Scsi_Host *prevtoshone;
struct Scsi_Host *save = NULL;;
/* Are these two nodes adjacent */
if (shtwo->next == shone) {
if (shtwo == scsi_hostlist && shone->next == NULL) {
/* just two nodes */
scsi_hostlist = shone;
shone->next = shtwo;
shtwo->next = NULL;
} else if (shtwo == scsi_hostlist) {
/* first two nodes of the list */
scsi_hostlist = shone;
shtwo->next = shone->next;
scsi_hostlist->next = shtwo;
} else if (shone->next == NULL) {
/* last two nodes of the list */
prevtoshtwo = scsi_hostlist;
while (prevtoshtwo->next != shtwo)
prevtoshtwo = prevtoshtwo->next;
prevtoshtwo->next = shone;
shone->next = shtwo;
shtwo->next = NULL;
} else {
prevtoshtwo = scsi_hostlist;
while (prevtoshtwo->next != shtwo)
prevtoshtwo = prevtoshtwo->next;
prevtoshtwo->next = shone;
shtwo->next = shone->next;
shone->next = shtwo;
}
} else if (shtwo == scsi_hostlist && shone->next == NULL) {
/* shtwo at head, shone at tail, not adjacent */
prevtoshone = scsi_hostlist;
while (prevtoshone->next != shone)
prevtoshone = prevtoshone->next;
scsi_hostlist = shone;
shone->next = shtwo->next;
prevtoshone->next = shtwo;
shtwo->next = NULL;
} else if (shtwo == scsi_hostlist && shone->next != NULL) {
/* shtwo at head, shone is not at tail */
prevtoshone = scsi_hostlist;
while (prevtoshone->next != shone)
prevtoshone = prevtoshone->next;
scsi_hostlist = shone;
prevtoshone->next = shtwo;
save = shtwo->next;
shtwo->next = shone->next;
shone->next = save;
} else if (shone->next == NULL) {
/* shtwo not at head, shone at tail */
prevtoshtwo = scsi_hostlist;
prevtoshone = scsi_hostlist;
while (prevtoshtwo->next != shtwo)
prevtoshtwo = prevtoshtwo->next;
while (prevtoshone->next != shone)
prevtoshone = prevtoshone->next;
prevtoshtwo->next = shone;
shone->next = shtwo->next;
prevtoshone->next = shtwo;
shtwo->next = NULL;
} else {
prevtoshtwo = scsi_hostlist;
prevtoshone = scsi_hostlist;
save = NULL;;
while (prevtoshtwo->next != shtwo)
prevtoshtwo = prevtoshtwo->next;
while (prevtoshone->next != shone)
prevtoshone = prevtoshone->next;
prevtoshtwo->next = shone;
save = shone->next;
shone->next = shtwo->next;
prevtoshone->next = shtwo;
shtwo->next = save;
}
return;
}
static inline void mega_freeSgList (mega_host_config * megaCfg)
{
int i;
......@@ -4235,7 +4065,7 @@ int megaraid_biosparam (struct scsi_device *sdev, struct block_device *bdev,
/* Default heads (64) & sectors (32) */
heads = 64;
sectors = 32;
cylinders = (unsigned long)capacity / (heads * sectors);
cylinders = (unsigned long)capacity >> 11;
/* Handle extended translation size for logical drives > 1Gb */
if (capacity >= 0x200000) {
......@@ -4293,7 +4123,6 @@ mega_partsize(struct block_device *bdev, sector_t capacity, int *geom)
struct partition *p, *largest = NULL;
int i, largest_cyl;
int heads, cyls, sectors;
int capacity = capacity;
unsigned char *buf;
if (!(buf = scsi_bios_ptable(bdev)))
......@@ -4324,7 +4153,7 @@ mega_partsize(struct block_device *bdev, sector_t capacity, int *geom)
return -1;
}
cyls = capacity/(heads * sectors);
cyls = (unsigned long)capacity/(heads * sectors);
geom[0] = heads;
geom[1] = sectors;
......@@ -4683,12 +4512,7 @@ static int megadev_ioctl (struct inode *inode, struct file *filep,
/*
* Find this host
*/
for( shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next ) {
if( shpnt->hostdata == (unsigned long *)megaCtlrs[adapno] ) {
megacfg = (mega_host_config *)shpnt->hostdata;
break;
}
}
shpnt = megaCtlrs[adapno]->host;
if(shpnt == NULL) return -ENODEV;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
......@@ -4803,12 +4627,7 @@ static int megadev_ioctl (struct inode *inode, struct file *filep,
/*
* Find this host
*/
for( shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next ) {
if( shpnt->hostdata == (unsigned long *)megaCtlrs[adapno] ) {
megacfg = (mega_host_config *)shpnt->hostdata;
break;
}
}
shpnt = megaCtlrs[adapno]->host;
if(shpnt == NULL) return -ENODEV;
/*
......
......@@ -214,8 +214,6 @@
info: megaraid_info, /* Driver Info Function */\
command: megaraid_command, /* Command Function */\
queuecommand: megaraid_queue, /* Queue Command Function */\
abort: megaraid_abort, /* Abort Command Function */\
reset: megaraid_reset, /* Reset Command Function */\
bios_param: megaraid_biosparam, /* Disk BIOS Parameters */\
can_queue: MAX_COMMANDS, /* Can Queue */\
this_id: 7, /* HBA Target ID */\
......@@ -989,8 +987,6 @@ static void enq_scb_freelist (mega_host_config *, mega_scb *,
int lock, int intr);
static int mega_is_bios_enabled (mega_host_config *);
static void mega_reorder_hosts (void);
static void mega_swap_hosts (struct Scsi_Host *, struct Scsi_Host *);
static void mega_create_proc_entry (int index, struct proc_dir_entry *);
static int mega_support_ext_cdb(mega_host_config *);
......
......@@ -163,7 +163,6 @@ struct Scsi_Device_Template osst_template =
tag: "osst",
scsi_type: TYPE_TAPE,
detect: osst_detect,
init: osst_init,
attach: osst_attach,
detach: osst_detach
};
......@@ -5411,6 +5410,8 @@ static int osst_attach(Scsi_Device * SDp)
if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
return 1;
osst_init();
disk = alloc_disk(1);
if (!disk)
return 1;
......
......@@ -132,6 +132,12 @@ struct softscsi_data {
static struct softscsi_data softscsi_data[NR_CPUS] __cacheline_aligned;
/*
* List of all highlevel drivers.
*/
static struct Scsi_Device_Template *scsi_devicelist;
static DECLARE_RWSEM(scsi_devicelist_mutex);
/*
* Note - the initial logging level can be set here to log events at boot time.
* After the system is up, you may enable logging via the /proc interface.
......@@ -1718,7 +1724,6 @@ static int scsi_proc_info(char *buffer, char **start, off_t offset, int length)
static int proc_scsi_gen_write(struct file * file, const char * buf,
unsigned long length, void *data)
{
struct Scsi_Device_Template *SDTpnt;
Scsi_Device *scd;
struct Scsi_Host *HBA_ptr;
char *p;
......@@ -1924,12 +1929,7 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
if (scd->access_count)
goto out;
SDTpnt = scsi_devicelist;
while (SDTpnt != NULL) {
if (SDTpnt->detach)
(*SDTpnt->detach) (scd);
SDTpnt = SDTpnt->next;
}
scsi_detach_device(scd);
if (scd->attached == 0) {
/*
......@@ -1969,6 +1969,56 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
}
#endif
void scsi_detect_device(struct scsi_device *sdev)
{
struct Scsi_Device_Template *sdt;
down_read(&scsi_devicelist_mutex);
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->detect)
sdev->attached += (*sdt->detect)(sdev);
up_read(&scsi_devicelist_mutex);
}
int scsi_attach_device(struct scsi_device *sdev)
{
struct Scsi_Device_Template *sdt;
scsi_build_commandblocks(sdev);
if (sdev->current_queue_depth == 0)
goto fail;
down_read(&scsi_devicelist_mutex);
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->init && sdt->dev_noticed)
(*sdt->init) ();
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->attach)
(*sdt->attach) (sdev);
up_read(&scsi_devicelist_mutex);
if (!sdev->attached)
scsi_release_commandblocks(sdev);
return 0;
fail:
printk(KERN_ERR "%s: Allocation failure during SCSI scanning, "
"some SCSI devices might not be configured\n",
__FUNCTION__);
return -ENOMEM;
}
void scsi_detach_device(struct scsi_device *sdev)
{
struct Scsi_Device_Template *sdt;
down_read(&scsi_devicelist_mutex);
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->detach)
(*sdt->detach)(sdev);
up_read(&scsi_devicelist_mutex);
}
/*
* This entry point should be called by a loadable module if it is trying
* add a high level scsi driver to the system.
......@@ -1987,8 +2037,10 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
if (tpnt->next)
return 1;
down_write(&scsi_devicelist_mutex);
tpnt->next = scsi_devicelist;
scsi_devicelist = tpnt;
up_write(&scsi_devicelist_mutex);
tpnt->scsi_driverfs_driver.name = (char *)tpnt->tag;
tpnt->scsi_driverfs_driver.bus = &scsi_driverfs_bus_type;
......@@ -2094,6 +2146,7 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
/*
* Extract the template from the linked list.
*/
down_write(&scsi_devicelist_mutex);
spnt = scsi_devicelist;
prev_spnt = NULL;
while (spnt != tpnt) {
......@@ -2104,6 +2157,7 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
scsi_devicelist = tpnt->next;
else
prev_spnt->next = spnt->next;
up_write(&scsi_devicelist_mutex);
MOD_DEC_USE_COUNT;
unlock_kernel();
......
......@@ -478,6 +478,9 @@ extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd,
int timeout, int retries);
extern int scsi_dev_init(void);
extern int scsi_mlqueue_insert(struct scsi_cmnd *, int);
extern void scsi_detect_device(struct scsi_device *);
extern int scsi_attach_device(struct scsi_device *);
extern void scsi_detach_device(struct scsi_device *);
/*
* Newer request-based interfaces.
......
This diff is collapsed.
......@@ -3,17 +3,20 @@
#include <linux/types.h>
#include <linux/kdev_t.h>
static int scsi_debug_detect(Scsi_Host_Template *);
static int scsi_debug_detect(struct SHT *);
static int scsi_debug_slave_attach(struct scsi_device *);
static void scsi_debug_slave_detach(struct scsi_device *);
static int scsi_debug_release(struct Scsi_Host *);
/* static int scsi_debug_command(Scsi_Cmnd *); */
static int scsi_debug_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
static int scsi_debug_ioctl(Scsi_Device *, int, void *);
/* static int scsi_debug_command(struct scsi_cmnd *); */
static int scsi_debug_queuecommand(struct scsi_cmnd *,
void (*done) (struct scsi_cmnd *));
static int scsi_debug_ioctl(struct scsi_device *, int, void *);
static int scsi_debug_biosparam(struct scsi_device *, struct block_device *,
sector_t, int[]);
static int scsi_debug_abort(Scsi_Cmnd *);
static int scsi_debug_bus_reset(Scsi_Cmnd *);
static int scsi_debug_device_reset(Scsi_Cmnd *);
static int scsi_debug_host_reset(Scsi_Cmnd *);
static int scsi_debug_abort(struct scsi_cmnd *);
static int scsi_debug_bus_reset(struct scsi_cmnd *);
static int scsi_debug_device_reset(struct scsi_cmnd *);
static int scsi_debug_host_reset(struct scsi_cmnd *);
static int scsi_debug_proc_info(char *, char **, off_t, int, int, int);
static const char * scsi_debug_info(struct Scsi_Host *);
......@@ -33,6 +36,8 @@ static Scsi_Host_Template driver_template = {
.name = "SCSI DEBUG",
.info = scsi_debug_info,
.detect = scsi_debug_detect,
.slave_attach = scsi_debug_slave_attach,
.slave_detach = scsi_debug_slave_detach,
.release = scsi_debug_release,
.ioctl = scsi_debug_ioctl,
.queuecommand = scsi_debug_queuecommand,
......
......@@ -1322,7 +1322,6 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
Scsi_Request *sreq, char *inq_result, int *bflags)
{
Scsi_Device *sdev;
struct Scsi_Device_Template *sdt;
char devname[64];
extern devfs_handle_t scsi_devfs_handle;
......@@ -1479,9 +1478,7 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
* function */
sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED;
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->detect)
sdev->attached += (*sdt->detect) (sdev);
scsi_detect_device(sdev);
if (sdev->host->hostt->slave_attach != NULL) {
if (sdev->host->hostt->slave_attach(sdev) != 0) {
......@@ -2010,7 +2007,6 @@ static void scsi_scan_selected_lun(struct Scsi_Host *shost, uint channel,
uint id, uint lun)
{
Scsi_Device *sdevscan, *sdev = NULL;
struct Scsi_Device_Template *sdt;
int res;
if ((channel > shost->max_channel) || (id >= shost->max_id) ||
......@@ -2028,24 +2024,7 @@ static void scsi_scan_selected_lun(struct Scsi_Host *shost, uint channel,
if (res != SCSI_SCAN_LUN_PRESENT)
return;
BUG_ON(sdev == NULL);
scsi_build_commandblocks(sdev);
if (sdev->current_queue_depth == 0) {
printk(ALLOC_FAILURE_MSG, __FUNCTION__);
return;
}
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->init && sdt->dev_noticed)
(*sdt->init) ();
for (sdt = scsi_devicelist; sdt; sdt = sdt->next)
if (sdt->attach)
(*sdt->attach) (sdev);
if (!sdev->attached)
scsi_release_commandblocks(sdev);
scsi_attach_device(sdev);
}
/**
......
......@@ -92,7 +92,6 @@ EXPORT_SYMBOL(scsi_reset_provider);
EXPORT_SYMBOL(scsi_host_get_next);
EXPORT_SYMBOL(scsi_host_hn_get);
EXPORT_SYMBOL(scsi_host_put);
EXPORT_SYMBOL(scsi_devicelist);
EXPORT_SYMBOL(scsi_device_types);
/*
......
......@@ -110,7 +110,6 @@ static int sg_allow_dio = SG_ALLOW_DIO_DEF;
#define SG_DEV_ARR_LUMP 6 /* amount to over allocate sg_dev_arr by */
static int sg_init(void);
static int sg_attach(Scsi_Device *);
static int sg_detect(Scsi_Device *);
static void sg_detach(Scsi_Device *);
......@@ -126,7 +125,6 @@ static struct Scsi_Device_Template sg_template = {
.tag = "sg",
.scsi_type = 0xff,
.detect = sg_detect,
.init = sg_init,
.attach = sg_attach,
.detach = sg_detach
};
......@@ -1344,55 +1342,6 @@ sg_detect(Scsi_Device * scsidp)
return 1;
}
/* Driver initialization */
static int
sg_init()
{
static int sg_registered = 0;
unsigned long iflags;
int tmp_dev_max;
Sg_device **tmp_da;
if ((sg_template.dev_noticed == 0) || sg_dev_arr)
return 0;
SCSI_LOG_TIMEOUT(3, printk("sg_init\n"));
write_lock_irqsave(&sg_dev_arr_lock, iflags);
tmp_dev_max = sg_template.dev_noticed + SG_DEV_ARR_LUMP;
write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
tmp_da = (Sg_device **)vmalloc(
tmp_dev_max * sizeof(Sg_device *));
if (NULL == tmp_da) {
printk(KERN_ERR "sg_init: no space for sg_dev_arr\n");
return 1;
}
write_lock_irqsave(&sg_dev_arr_lock, iflags);
if (!sg_registered) {
if (register_chrdev(SCSI_GENERIC_MAJOR, "sg", &sg_fops)) {
printk(KERN_ERR
"Unable to get major %d for generic SCSI device\n",
SCSI_GENERIC_MAJOR);
write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
vfree((char *) tmp_da);
return 1;
}
sg_registered++;
}
memset(tmp_da, 0, tmp_dev_max * sizeof (Sg_device *));
sg_template.dev_max = tmp_dev_max;
sg_dev_arr = tmp_da;
write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
#ifdef CONFIG_PROC_FS
sg_proc_init();
#endif /* CONFIG_PROC_FS */
return 0;
}
#ifndef MODULE
static int __init
sg_def_reserved_size_setup(char *str)
......@@ -1643,9 +1592,21 @@ MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd");
static int __init
init_sg(void)
{
int rc;
if (def_reserved_size >= 0)
sg_big_buff = def_reserved_size;
return scsi_register_device(&sg_template);
rc = register_chrdev(SCSI_GENERIC_MAJOR, "sg", &sg_fops);
if (rc)
return rc;
rc = scsi_register_device(&sg_template);
if (rc)
return rc;
#ifdef CONFIG_PROC_FS
sg_proc_init();
#endif /* CONFIG_PROC_FS */
return 0;
}
static void __exit
......
......@@ -65,7 +65,6 @@ MODULE_PARM(xa_test, "i"); /* see sr_ioctl.c */
CDC_PLAY_AUDIO|CDC_RESET|CDC_IOCTLS|CDC_DRIVE_STATUS| \
CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_GENERIC_PACKET)
static int sr_init(void);
static int sr_attach(struct scsi_device *);
static int sr_detect(struct scsi_device *);
static void sr_detach(struct scsi_device *);
......@@ -79,22 +78,52 @@ static struct Scsi_Device_Template sr_template = {
.scsi_type = TYPE_ROM,
.blk = 1,
.detect = sr_detect,
.init = sr_init,
.attach = sr_attach,
.detach = sr_detach,
.init_command = sr_init_command
};
static struct scsi_cd *scsi_CDs;
static LIST_HEAD(sr_devlist);
static spinlock_t sr_devlist_lock = SPIN_LOCK_UNLOCKED;
static int sr_open(struct cdrom_device_info *, int);
static void get_sectorsize(struct scsi_cd *);
static void get_capabilities(struct scsi_cd *);
static int sr_init_one(struct scsi_cd *, int);
static int sr_media_change(struct cdrom_device_info *, int);
static int sr_packet(struct cdrom_device_info *, struct cdrom_generic_command *);
static Scsi_CD *sr_find_by_sdev(Scsi_Device *sd)
{
struct list_head *p;
Scsi_CD *cd;
spin_lock(&sr_devlist_lock);
list_for_each(p, &sr_devlist) {
cd = list_entry(p, Scsi_CD, list);
if (cd->device == sd) {
spin_unlock(&sr_devlist_lock);
return cd;
}
}
spin_unlock(&sr_devlist_lock);
return NULL;
}
static inline void sr_devlist_insert(Scsi_CD *cd)
{
spin_lock(&sr_devlist_lock);
list_add(&cd->list, &sr_devlist);
spin_unlock(&sr_devlist_lock);
}
static inline void sr_devlist_remove(Scsi_CD *cd)
{
spin_lock(&sr_devlist_lock);
list_del(&cd->list);
spin_unlock(&sr_devlist_lock);
}
static void sr_release(struct cdrom_device_info *cdi)
{
struct scsi_cd *cd = cdi->handle;
......@@ -470,40 +499,84 @@ static int sr_detect(struct scsi_device * SDp)
return 1;
}
static int sr_attach(struct scsi_device * SDp)
static int sr_attach(struct scsi_device *sdev)
{
struct scsi_cd *cpnt;
int i;
struct gendisk *disk;
struct scsi_cd *cd;
int minor;
if (SDp->type != TYPE_ROM && SDp->type != TYPE_WORM)
if (sdev->type != TYPE_ROM && sdev->type != TYPE_WORM)
return 1;
if (sr_template.nr_dev >= sr_template.dev_max)
cd = kmalloc(sizeof(*cd), GFP_KERNEL);
if (!cd)
goto fail;
memset(cd, 0, sizeof(*cd));
for (cpnt = scsi_CDs, i = 0; i < sr_template.dev_max; i++, cpnt++)
if (!cpnt->device)
break;
disk = alloc_disk(1);
if (!disk)
goto fail_free;
if (i >= sr_template.dev_max)
panic("scsi_devices corrupt (sr)");
/*
* XXX This doesn't make us better than the previous code in the
* XXX end (not worse either, though..).
* XXX To properly support hotplugging we should have a bitmap and
* XXX use find_first_zero_bit on it. This will happen at the
* XXX same time template->nr_* goes away. --hch
*/
minor = sr_template.nr_dev++;
scsi_CDs[i].device = SDp;
disk->major = MAJOR_NR;
disk->first_minor = minor;
sprintf(disk->disk_name, "sr%d", minor);
disk->fops = &sr_bdops;
disk->flags = GENHD_FL_CD;
if (sr_init_one(cpnt, i))
goto fail;
cd->device = sdev;
cd->disk = disk;
cd->driver = &sr_template;
cd->disk = disk;
cd->capacity = 0x1fffff;
cd->needs_sector_size = 1;
cd->device->changed = 1; /* force recheck CD type */
cd->use = 1;
cd->readcd_known = 0;
cd->readcd_cdda = 0;
cd->cdi.ops = &sr_dops;
cd->cdi.handle = cd;
cd->cdi.mask = 0;
cd->cdi.capacity = 1;
sprintf(cd->cdi.name, "sr%d", minor);
sdev->sector_size = 2048; /* A guess, just in case */
sdev->ten = 1;
sdev->remap = 1;
/* FIXME: need to handle a get_capabilities failure properly ?? */
get_capabilities(cd);
sr_vendor_init(cd);
disk->de = sdev->de;
disk->driverfs_dev = &sdev->sdev_driverfs_dev;
register_cdrom(&cd->cdi);
set_capacity(disk, cd->capacity);
disk->private_data = &cd->driver;
disk->queue = &sdev->request_queue;
sr_template.nr_dev++;
if (sr_template.nr_dev > sr_template.dev_max)
panic("scsi_devices corrupt (sr)");
add_disk(disk);
sr_devlist_insert(cd);
printk("Attached scsi CD-ROM %s at scsi%d, channel %d, id %d, lun %d\n",
scsi_CDs[i].cdi.name, SDp->host->host_no, SDp->channel,
SDp->id, SDp->lun);
printk(KERN_DEBUG
"Attached scsi CD-ROM %s at scsi%d, channel %d, id %d, lun %d\n",
cd->cdi.name, sdev->host->host_no, sdev->channel,
sdev->id, sdev->lun);
return 0;
fail_free:
kfree(cd);
fail:
SDp->attached--;
sdev->attached--;
return 1;
}
......@@ -723,126 +796,32 @@ static int sr_packet(struct cdrom_device_info *cdi,
return cgc->stat;
}
static int sr_registered;
static int sr_init()
{
int i;
if (sr_template.dev_noticed == 0)
return 0;
if (!sr_registered) {
if (register_blkdev(MAJOR_NR, "sr", &sr_bdops)) {
printk("Unable to get major %d for SCSI-CD\n",
MAJOR_NR);
return 1;
}
sr_registered++;
}
if (scsi_CDs)
return 0;
sr_template.dev_max = sr_template.dev_noticed + SR_EXTRA_DEVS;
scsi_CDs = kmalloc(sr_template.dev_max * sizeof(struct scsi_cd), GFP_ATOMIC);
if (!scsi_CDs)
goto cleanup_dev;
memset(scsi_CDs, 0, sr_template.dev_max * sizeof(struct scsi_cd));
for (i = 0; i < sr_template.dev_max; i++)
sprintf(scsi_CDs[i].cdi.name, "sr%d", i);
return 0;
cleanup_dev:
unregister_blkdev(MAJOR_NR, "sr");
sr_registered--;
return 1;
}
static int sr_init_one(struct scsi_cd *cd, int first_minor)
{
struct gendisk *disk;
disk = alloc_disk(1);
if (!disk)
return -ENOMEM;
disk->major = MAJOR_NR;
disk->first_minor = first_minor;
strcpy(disk->disk_name, cd->cdi.name);
disk->fops = &sr_bdops;
disk->flags = GENHD_FL_CD;
cd->driver = &sr_template;
cd->disk = disk;
cd->capacity = 0x1fffff;
cd->device->sector_size = 2048;/* A guess, just in case */
cd->needs_sector_size = 1;
cd->device->changed = 1; /* force recheck CD type */
#if 0
/* seems better to leave this for later */
get_sectorsize(cd);
printk("Scd sectorsize = %d bytes.\n", cd->sector_size);
#endif
cd->use = 1;
cd->device->ten = 1;
cd->device->remap = 1;
cd->readcd_known = 0;
cd->readcd_cdda = 0;
cd->cdi.ops = &sr_dops;
cd->cdi.handle = cd;
cd->cdi.mask = 0;
cd->cdi.capacity = 1;
/*
* FIXME: someone needs to handle a get_capabilities
* failure properly ??
*/
get_capabilities(cd);
sr_vendor_init(cd);
disk->de = cd->device->de;
disk->driverfs_dev = &cd->device->sdev_driverfs_dev;
register_cdrom(&cd->cdi);
set_capacity(disk, cd->capacity);
disk->private_data = &cd->driver;
disk->queue = &cd->device->request_queue;
add_disk(disk);
return 0;
}
static void sr_detach(struct scsi_device * SDp)
{
struct scsi_cd *cpnt;
int i;
struct scsi_cd *cd;
for (cpnt = scsi_CDs, i = 0; i < sr_template.dev_max; i++, cpnt++) {
if (cpnt->device == SDp) {
/*
* Since the cdrom is read-only, no need to sync
* the device.
* We should be kind to our buffer cache, however.
*/
del_gendisk(cpnt->disk);
put_disk(cpnt->disk);
cpnt->disk = NULL;
cd = sr_find_by_sdev(SDp);
if (!cd)
return;
sr_devlist_remove(cd);
del_gendisk(cd->disk);
put_disk(cd->disk);
unregister_cdrom(&cd->cdi);
/*
* Reset things back to a sane state so that one can
* re-load a new driver (perhaps the same one).
*/
unregister_cdrom(&(cpnt->cdi));
cpnt->device = NULL;
cpnt->capacity = 0;
SDp->attached--;
sr_template.nr_dev--;
sr_template.dev_noticed--;
return;
}
}
kfree(cd);
}
static int __init init_sr(void)
{
int rc;
rc = register_blkdev(MAJOR_NR, "sr", &sr_bdops);
if (rc)
return rc;
return scsi_register_device(&sr_template);
}
......@@ -850,11 +829,6 @@ static void __exit exit_sr(void)
{
scsi_unregister_device(&sr_template);
unregister_blkdev(MAJOR_NR, "sr");
sr_registered--;
if (scsi_CDs != NULL)
kfree(scsi_CDs);
sr_template.dev_max = 0;
}
module_init(init_sr);
......
......@@ -26,6 +26,7 @@
typedef struct scsi_cd {
struct Scsi_Device_Template *driver;
struct list_head list;
unsigned capacity; /* size in blocks */
Scsi_Device *device;
unsigned int vendor; /* vendor code, see sr_vendor.c */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment