Commit 1bf8b5fd authored by Patrick Mochel's avatar Patrick Mochel

Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin

into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-core
parents b00a75ab f1d4b51f
......@@ -2248,6 +2248,15 @@ D: Ziatech ZT5550 and generic CompactPCI hotplug drivers
S: Toronto, Ontario
S: Canada
N: Zwane Mwaikambo
E: zwane@linuxpower.ca
W: http://function.linuxpower.ca
D: Various driver hacking
D: Lowlevel x86 kernel hacking
D: General debugging
S: (ask for current address)
S: Tanzania
N: Trond Myklebust
E: trond.myklebust@fys.uio.no
D: current NFS client hacker.
......@@ -2722,7 +2731,7 @@ S: Finland
N: Thomas Sailer
E: t.sailer@alumni.ethz.ch
E: HB9JNX@HB9W.CHE.EU (packet radio)
D: hfmodem, Baycom and sound card radio modem driver
D: Baycom driver
S: Markusstrasse 18
S: 8006 Zuerich
S: Switzerland
......@@ -3093,8 +3102,14 @@ S: 97078 Wuerzburg
S: Germany
N: Greg Ungerer
E: gerg@moreton.com.au
E: gerg@snapgear.com
D: uClinux kernel hacker
D: Port uClinux to the Motorola ColdFire CPU
D: Author of Stallion multiport serial drivers
S: SnapGear Inc.
S: 825 Stanley St
S: Woolloongabba. QLD. 4102
S: Australia
N: Jeffrey A. Uphoff
E: juphoff@transmeta.com
......
......@@ -261,11 +261,11 @@ M: ralf@linux-mips.org
L: linux-hams@vger.kernel.org
S: Maintained
BAYCOM/HDLCDRV/SOUNDMODEM DRIVERS FOR AX.25
BAYCOM/HDLCDRV DRIVERS FOR AX.25
P: Thomas Sailer
M: sailer@ife.ee.ethz.ch
M: t.sailer@alumni.ethz.ch
L: linux-hams@vger.kernel.org
W: http://www.ife.ee.ethz.ch/~sailer/ham/ham.html
W: http://www.baycom.org/~tom/ham/ham.html
S: Maintained
BERKSHIRE PRODUCTS PC WATCHDOG DRIVER
......
......@@ -2935,9 +2935,9 @@ int acornscsi_proc_info(char *buffer, char **start, off_t offset,
}
}
p += sprintf(p, "\nAttached devices:%s\n", instance->host_queue ? "" : " none");
p += sprintf(p, "\nAttached devices:\n");
for (scd = instance->host_queue; scd; scd = scd->next) {
list_for_each_entry(scd, &instance->my_devices, siblings) {
int len;
proc_print_scsidevice(scd, p, &len, 0);
......@@ -3051,7 +3051,7 @@ acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
acornscsi_resetcard(ashost);
ret = scsi_add_host(host);
ret = scsi_add_host(host, &ec->dev);
if (ret == 0)
goto out;
......
......@@ -311,7 +311,7 @@ int arxescsi_proc_info(char *buffer, char **start, off_t offset,
pos += sprintf (buffer+pos, "\nAttached devices:\n");
for (scd = host->host_queue; scd; scd = scd->next) {
list_for_each_entry(scd, &host->my_devices, siblings) {
pos += fas216_print_device(&info->info, scd, buffer + pos);
if (pos + begin < offset) {
......@@ -398,7 +398,7 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
fas216_init(host);
ret = scsi_add_host(host);
ret = scsi_add_host(host, &ec->dev);
if (ret == 0)
goto out;
......
......@@ -299,7 +299,7 @@ cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id)
NCR5380_print_options(host);
printk("\n");
ret = scsi_add_host(host);
ret = scsi_add_host(host, &ec->dev);
if (ret == 0)
goto out;
......
......@@ -387,7 +387,7 @@ int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset,
pos += sprintf(buffer+pos, "\nAttached devices:\n");
for (scd = host->host_queue; scd; scd = scd->next) {
list_for_each_entry(scd, &host->my_devices, siblings) {
int len;
proc_print_scsidevice(scd, buffer, &len, pos);
......@@ -503,7 +503,7 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
fas216_init(host);
ret = scsi_add_host(host);
ret = scsi_add_host(host, &ec->dev);
if (ret == 0)
goto out;
......
......@@ -390,7 +390,7 @@ int eesoxscsi_proc_info(char *buffer, char **start, off_t offset,
pos += sprintf(buffer+pos, "\nAttached devices:\n");
for (scd = host->host_queue; scd; scd = scd->next) {
list_for_each_entry(scd, &host->my_devices, siblings) {
int len;
proc_print_scsidevice(scd, buffer, &len, pos);
......@@ -502,7 +502,7 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
}
fas216_init(host);
ret = scsi_add_host(host);
ret = scsi_add_host(host, &ec->dev);
if (ret == 0)
goto out;
......
......@@ -2631,7 +2631,7 @@ int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
* all command structures. Leave the running
* command in place.
*/
for (SDpnt = info->host->host_queue; SDpnt; SDpnt = SDpnt->next) {
list_for_each_entry(SDpnt, &info->host->my_devices, siblings) {
int i;
if (SDpnt->soft_reset)
......
......@@ -160,7 +160,7 @@ oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
NCR5380_print_options(host);
printk("\n");
ret = scsi_add_host(host);
ret = scsi_add_host(host, &ec->dev);
if (ret == 0)
goto out;
......
......@@ -269,7 +269,7 @@ int powertecscsi_proc_info(char *buffer, char **start, off_t offset,
pos += sprintf(buffer+pos, "\nAttached devices:\n");
for (scd = host->host_queue; scd; scd = scd->next) {
list_for_each_entry(scd, &host->my_devices, siblings) {
pos += fas216_print_device(&info->info, scd, buffer + pos);
if (pos + begin < offset) {
......@@ -376,7 +376,7 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
fas216_init(host);
ret = scsi_add_host(host);
ret = scsi_add_host(host, &ec->dev);
if (ret == 0)
goto out;
......
......@@ -372,6 +372,8 @@ int tty_check_change(struct tty_struct * tty)
return -ERESTARTSYS;
}
EXPORT_SYMBOL(tty_check_change);
static ssize_t hung_up_tty_read(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
......@@ -540,6 +542,8 @@ void tty_hangup(struct tty_struct * tty)
schedule_work(&tty->hangup_work);
}
EXPORT_SYMBOL(tty_hangup);
void tty_vhangup(struct tty_struct * tty)
{
#ifdef TTY_DEBUG_HANGUP
......@@ -556,6 +560,8 @@ int tty_hung_up_p(struct file * filp)
return (filp->f_op == &hung_up_tty_fops);
}
EXPORT_SYMBOL(tty_hung_up_p);
/*
* This function is typically called only by the session leader, when
* it wants to disassociate itself from its controlling tty.
......@@ -1886,6 +1892,8 @@ void do_SAK(struct tty_struct *tty)
schedule_work(&tty->SAK_work);
}
EXPORT_SYMBOL(do_SAK);
/*
* This routine is called out of the software interrupt to flush data
* from the flip buffer to the line discipline.
......@@ -1946,34 +1954,44 @@ static int baud_table[] = {
#endif
};
static int n_baud_table = sizeof(baud_table)/sizeof(int);
static int n_baud_table = ARRAY_SIZE(baud_table);
int tty_get_baud_rate(struct tty_struct *tty)
int tty_termios_baud_rate(struct termios *termios)
{
unsigned int cflag, i;
unsigned int cbaud = termios->c_cflag & CBAUD;
cflag = tty->termios->c_cflag;
if (cbaud & CBAUDEX) {
cbaud &= ~CBAUDEX;
i = cflag & CBAUD;
if (i & CBAUDEX) {
i &= ~CBAUDEX;
if (i < 1 || i+15 >= n_baud_table)
tty->termios->c_cflag &= ~CBAUDEX;
if (cbaud < 1 || cbaud + 15 > n_baud_table)
termios->c_cflag &= ~CBAUDEX;
else
i += 15;
cbaud += 15;
}
if (i==15 && tty->alt_speed) {
return baud_table[cbaud];
}
EXPORT_SYMBOL(tty_termios_baud_rate);
int tty_get_baud_rate(struct tty_struct *tty)
{
int baud = tty_termios_baud_rate(tty->termios);
if (baud == 38400 && tty->alt_speed) {
if (!tty->warned) {
printk(KERN_WARNING "Use of setserial/setrocket to "
"set SPD_* flags is deprecated\n");
tty->warned = 1;
}
return(tty->alt_speed);
baud = tty->alt_speed;
}
return baud_table[i];
return baud;
}
EXPORT_SYMBOL(tty_get_baud_rate);
void tty_flip_buffer_push(struct tty_struct *tty)
{
if (tty->low_latency)
......
......@@ -1602,6 +1602,38 @@ static void set_multicast_list(struct net_device *dev)
}
}
/* Set a MAC change in hardware.
*/
static int
fec_set_mac_address(struct net_device *dev, void *p)
{
int i;
struct sockaddr *addr = p;
volatile fec_t *fecp;
fecp = fec_hwp;
if (netif_running(dev))
return -EBUSY;
/* Set the device copy of the Ethernet address
*/
memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
/* Set our copy of the Ethernet address
*/
for (i = 0; i < (ETH_ALEN / 2); i++) {
my_enet_addr[i] = (dev->dev_addr[i*2] << 8) | dev->dev_addr[i*2 + 1];
}
/* Set station address.
*/
fecp->fec_addr_low = (my_enet_addr[0] << 16) | my_enet_addr[1];
fecp->fec_addr_high = my_enet_addr[2] << 16;
return 0;
}
/* Initialize the FEC Ethernet on 860T (or ColdFire 5272).
*/
int __init fec_enet_init(struct net_device *dev)
......@@ -1734,6 +1766,7 @@ int __init fec_enet_init(struct net_device *dev)
dev->stop = fec_enet_close;
dev->get_stats = fec_enet_get_stats;
dev->set_multicast_list = set_multicast_list;
dev->set_mac_address = fec_set_mac_address;
for (i=0; i<NMII-1; i++)
mii_cmds[i].mii_next = &mii_cmds[i+1];
......@@ -1767,9 +1800,9 @@ fec_restart(struct net_device *dev, int duplex)
{
struct fec_enet_private *fep;
int i;
unsigned char *eap;
volatile cbd_t *bdp;
volatile fec_t *fecp;
unsigned char *eap;
volatile cbd_t *bdp;
volatile fec_t *fecp;
fecp = fec_hwp;
......
......@@ -301,7 +301,8 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
#ifdef CONFIG_X86_IO_APIC
extern int nr_ioapics;
#include <asm/io_apic.h>
/*
* VIA 686A/B: If an IO-APIC is active, we need to route all on-chip
......@@ -561,7 +562,7 @@ static struct pci_fixup pci_fixups[] __devinitdata = {
#ifdef CONFIG_X86_IO_APIC
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_SIS, PCI_ANY_ID, quirk_ioapic_rmw },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw },
#endif
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi },
......
......@@ -124,8 +124,6 @@
#include <linux/spinlock.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/mca.h>
#include <asm/dma.h>
#include <asm/system.h>
#include <asm/io.h>
......@@ -236,7 +234,7 @@ static __u8 NCR_700_SDTR_msg[] = {
NCR_700_MAX_OFFSET
};
struct Scsi_Host * __init
struct Scsi_Host *
NCR_700_detect(Scsi_Host_Template *tpnt,
struct NCR_700_Host_Parameters *hostdata)
{
......@@ -2020,3 +2018,5 @@ NCR_700_slave_destroy(Scsi_Device *SDp)
EXPORT_SYMBOL(NCR_700_detect);
EXPORT_SYMBOL(NCR_700_release);
EXPORT_SYMBOL(NCR_700_intr);
no_module_init;
......@@ -123,7 +123,8 @@ obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o
obj-$(CONFIG_CHR_DEV_SG) += sg.o
scsi_mod-objs := scsi.o hosts.o scsi_ioctl.o constants.o scsicam.o \
scsi_error.o scsi_lib.o scsi_scan.o scsi_syms.o
scsi_error.o scsi_lib.o scsi_scan.o scsi_syms.o \
scsi_sysfs.o
ifdef CONFIG_PROC_FS
scsi_mod-objs += scsi_proc.o
......
......@@ -22,11 +22,11 @@ static int D700_release(struct Scsi_Host *host);
* remaining parameters shown below must be filled in. The 53c700
* routine NCR_700_detect will fill in all of the missing routines */
#define NCR_D700_SCSI { \
name: "NCR Dual 700 MCA", \
proc_name: "NCR_D700", \
detect: D700_detect, \
release: D700_release, \
this_id: 7, \
.name = "NCR Dual 700 MCA", \
.proc_name = "NCR_D700", \
.detect = D700_detect, \
.release = D700_release, \
.this_id = 7, \
}
......
......@@ -1113,12 +1113,12 @@ static int query_disk(struct aac_dev *dev, void *arg)
qd.locked = fsa_dev_ptr->locked[qd.cnum];
qd.deleted = fsa_dev_ptr->deleted[qd.cnum];
if (fsa_dev_ptr->devno[qd.cnum][0] == '\0')
if (fsa_dev_ptr->devname[qd.cnum][0] == '\0')
qd.unmapped = 1;
else
qd.unmapped = 0;
strncpy(dq.name, fsa_dev_ptr->devname[qd.cnum], 8);
strncpy(qd.name, fsa_dev_ptr->devname[qd.cnum], 8);
if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk)))
return -EFAULT;
......@@ -1170,7 +1170,7 @@ static int delete_disk(struct aac_dev *dev, void *arg)
* Mark the container as no longer being valid.
*/
fsa_dev_ptr->valid[dd.cnum] = 0;
fsa_dev_ptr->devno[dd.cnum][0] = '\0';
fsa_dev_ptr->devname[dd.cnum][0] = '\0';
return 0;
}
}
......
......@@ -36,7 +36,6 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/smp_lock.h>
#define __KERNEL_SYSCALLS__
......@@ -50,7 +49,6 @@ 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 */
static char *scsihosts;
MODULE_PARM(scsihosts, "s");
......@@ -173,14 +171,14 @@ int scsi_tp_for_each_host(Scsi_Host_Template *shost_tp, int
}
/**
* scsi_host_generic_release - default release function for hosts
* scsi_host_legacy_release - default release function for hosts
* @shost:
*
* Description:
* This is the default case for the release function. Its completely
* useless for anything but old ISA adapters
**/
static void scsi_host_legacy_release(struct Scsi_Host *shost)
static int scsi_host_legacy_release(struct Scsi_Host *shost)
{
if (shost->irq)
free_irq(shost->irq, NULL);
......@@ -188,23 +186,17 @@ static void scsi_host_legacy_release(struct Scsi_Host *shost)
free_dma(shost->dma_channel);
if (shost->io_port && shost->n_io_port)
release_region(shost->io_port, shost->n_io_port);
return 0;
}
static int scsi_remove_legacy_host(struct Scsi_Host *shost)
{
int error, pcount = scsi_hosts_registered;
int error;
error = scsi_remove_host(shost);
if (error)
return error;
if (shost->hostt->release)
if (!error)
(*shost->hostt->release)(shost);
else
scsi_host_legacy_release(shost);
if (pcount == scsi_hosts_registered)
scsi_unregister(shost);
return 0;
}
......@@ -260,7 +252,6 @@ static int scsi_check_device_busy(struct scsi_device *sdev)
int scsi_remove_host(struct Scsi_Host *shost)
{
struct scsi_device *sdev;
struct list_head *le, *lh;
/*
* FIXME Do ref counting. We force all of the devices offline to
......@@ -287,20 +278,13 @@ int scsi_remove_host(struct Scsi_Host *shost)
sdev->attached);
return 1;
}
devfs_unregister(sdev->de);
device_unregister(&sdev->sdev_driverfs_dev);
}
/* Next we free up the Scsi_Cmnd structures for this host */
list_for_each_safe(le, lh, &shost->my_devices) {
scsi_free_sdev(list_entry(le, Scsi_Device, siblings));
}
scsi_forget_host(shost);
return 0;
}
int scsi_add_host(struct Scsi_Host *shost)
int __scsi_add_host(struct Scsi_Host *shost)
{
Scsi_Host_Template *sht = shost->hostt;
struct scsi_device *sdev;
......@@ -309,7 +293,6 @@ int scsi_add_host(struct Scsi_Host *shost)
printk(KERN_INFO "scsi%d : %s\n", shost->host_no,
sht->info ? sht->info(shost) : sht->name);
device_register(&shost->host_driverfs_dev);
scsi_scan_host(shost);
list_for_each_entry (sdev, &shost->my_devices, siblings) {
......@@ -321,6 +304,22 @@ int scsi_add_host(struct Scsi_Host *shost)
return saved_error;
}
/**
* scsi_add_host - add a scsi host
* @shost: scsi host pointer to add
* @dev: a struct device of type scsi class
*
* Return value:
* 0 on success / != 0 for error
**/
int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
{
dev->class_data = shost;
shost->host_gendev = dev;
return __scsi_add_host(shost);
}
/**
* scsi_unregister - unregister a scsi host
* @shost: scsi host to be unregistered
......@@ -343,12 +342,10 @@ void scsi_unregister(struct Scsi_Host *shost)
shost->eh_notify = NULL;
}
scsi_hosts_registered--;
shost->hostt->present--;
/* Cleanup proc and driverfs */
/* Cleanup proc */
scsi_proc_host_rm(shost);
device_unregister(&shost->host_driverfs_dev);
kfree(shost);
}
......@@ -395,7 +392,6 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
memset(shost, 0, sizeof(struct Scsi_Host) + xtr_bytes);
shost->host_no = scsi_alloc_host_num(shost_tp->proc_name);
scsi_hosts_registered++;
spin_lock_init(&shost->default_lock);
scsi_assign_lock(shost, &shost->default_lock);
......@@ -462,11 +458,6 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
scsi_proc_host_add(shost);
strncpy(shost->host_driverfs_dev.name, shost_tp->proc_name,
DEVICE_NAME_SIZE-1);
sprintf(shost->host_driverfs_dev.bus_id, "scsi%d",
shost->host_no);
shost->eh_notify = &sem;
kernel_thread((int (*)(void *)) scsi_error_handler, (void *) shost, 0);
/*
......@@ -491,64 +482,34 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
int scsi_register_host(Scsi_Host_Template *shost_tp)
{
struct Scsi_Host *shost;
int cur_cnt;
/*
* Check no detect routine.
*/
if (!shost_tp->detect)
return 1;
BUG_ON(!shost_tp->detect);
/* If max_sectors isn't set, default to max */
if (!shost_tp->max_sectors)
if (!shost_tp->max_sectors) {
printk(KERN_WARNING
"scsi HBA driver %s didn't set max_sectors, "
"please fix the template", shost_tp->name);
shost_tp->max_sectors = 1024;
}
cur_cnt = scsi_hosts_registered;
/*
* The detect routine must carefully spinunlock/spinlock if it
* enables interrupts, since all interrupt handlers do spinlock as
* well.
*/
if (!shost_tp->release) {
printk(KERN_WARNING
"scsi HBA driver %s didn't set a release method, "
"please fix the template", shost_tp->name);
shost_tp->release = &scsi_host_legacy_release;
}
/*
* detect should do its own locking
* FIXME present is now set is scsi_register which breaks manual
* registration code below.
*/
shost_tp->detect(shost_tp);
if (!shost_tp->present)
return 0;
if (cur_cnt == scsi_hosts_registered) {
if (shost_tp->present > 1) {
printk(KERN_ERR "scsi: Failure to register"
"low-level scsi driver");
scsi_unregister_host(shost_tp);
return 1;
}
/*
* The low-level driver failed to register a driver.
* We can do this now.
*
* XXX Who needs manual registration and why???
*/
if (!scsi_register(shost_tp, 0)) {
printk(KERN_ERR "scsi: register failed.\n");
scsi_unregister_host(shost_tp);
return 1;
}
}
/*
* XXX(hch) use scsi_tp_for_each_host() once it propagates
* error returns properly.
*/
list_for_each_entry(shost, &scsi_host_list, sh_list)
if (shost->hostt == shost_tp)
if (scsi_add_host(shost))
if (__scsi_add_host(shost))
goto out_of_space;
return 0;
......@@ -575,20 +536,7 @@ int scsi_register_host(Scsi_Host_Template *shost_tp)
**/
int scsi_unregister_host(Scsi_Host_Template *shost_tp)
{
int pcount;
/* get the big kernel lock, so we don't race with open() */
lock_kernel();
pcount = scsi_hosts_registered;
scsi_tp_for_each_host(shost_tp, scsi_remove_legacy_host);
if (pcount != scsi_hosts_registered)
printk(KERN_INFO "scsi : %d host%s left.\n", scsi_hosts_registered,
(scsi_hosts_registered == 1) ? "" : "s");
unlock_kernel();
return 0;
}
......@@ -668,64 +616,6 @@ void __init scsi_host_init(void)
}
}
/*
* Function: scsi_get_host_dev()
*
* Purpose: Create a Scsi_Device that points to the host adapter itself.
*
* Arguments: SHpnt - Host that needs a Scsi_Device
*
* Lock status: None assumed.
*
* Returns: The Scsi_Device or NULL
*
* Notes:
* Attach a single Scsi_Device to the Scsi_Host - this should
* be made to look like a "pseudo-device" that points to the
* HA itself.
*
* Note - this device is not accessible from any high-level
* drivers (including generics), which is probably not
* optimal. We can add hooks later to attach
*/
struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
{
struct scsi_device *sdev;
sdev = scsi_alloc_sdev(shost, 0, shost->this_id, 0);
if (sdev) {
scsi_build_commandblocks(sdev);
if (sdev->current_queue_depth == 0)
goto fail;
sdev->borken = 0;
}
return sdev;
fail:
kfree(sdev);
return NULL;
}
/*
* Function: scsi_free_host_dev()
*
* Purpose: Free a scsi_device that points to the host adapter itself.
*
* Arguments: SHpnt - Host that needs a Scsi_Device
*
* Lock status: None assumed.
*
* Returns: Nothing
*
* Notes:
*/
void scsi_free_host_dev(struct scsi_device *sdev)
{
BUG_ON(sdev->id != sdev->host->this_id);
scsi_free_sdev(sdev);
}
void scsi_host_busy_inc(struct Scsi_Host *shost, Scsi_Device *sdev)
{
unsigned long flags;
......@@ -765,22 +655,3 @@ void scsi_host_failed_inc_and_test(struct Scsi_Host *shost)
}
spin_unlock_irqrestore(shost->host_lock, flags);
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-indent-level: 4
* c-brace-imaginary-offset: 0
* c-brace-offset: -4
* c-argdecl-indent: 4
* c-label-offset: -4
* c-continued-statement-offset: 4
* c-continued-brace-offset: 0
* indent-tabs-mode: nil
* tab-width: 8
* End:
*/
......@@ -488,7 +488,7 @@ struct Scsi_Host
/*
* Support for driverfs filesystem
*/
struct device host_driverfs_dev;
struct device *host_gendev;
/*
* We should ensure that this is aligned, both for better performance
......@@ -499,6 +499,8 @@ struct Scsi_Host
__attribute__ ((aligned (sizeof(unsigned long))));
};
#define to_scsi_host(d) d->class_data
/*
* These two functions are used to allocate and free a pseudo device
* which will connect to the host adapter itself rather than any
......@@ -524,7 +526,7 @@ static inline void scsi_set_pci_device(struct Scsi_Host *shost,
struct pci_dev *pdev)
{
shost->pci_dev = pdev;
shost->host_driverfs_dev.parent=&pdev->dev;
shost->host_gendev = &pdev->dev;
}
......@@ -532,12 +534,13 @@ static inline void scsi_set_pci_device(struct Scsi_Host *shost,
* Prototypes for functions/data in scsi_scan.c
*/
extern void scsi_scan_host(struct Scsi_Host *);
extern void scsi_forget_host(struct Scsi_Host *);
struct Scsi_Device_Template
{
struct list_head list;
const char * name;
const char * tag;
struct module * module; /* Used for loadable modules */
unsigned char scsi_type;
int (*attach)(Scsi_Device *); /* Attach devices to arrays */
......@@ -565,7 +568,7 @@ extern void scsi_unregister(struct Scsi_Host *);
/*
* HBA registration/unregistration.
*/
extern int scsi_add_host(struct Scsi_Host *);
extern int scsi_add_host(struct Scsi_Host *, struct device *);
extern int scsi_remove_host(struct Scsi_Host *);
/*
......@@ -603,7 +606,15 @@ static inline Scsi_Device *scsi_find_device(struct Scsi_Host *shost,
break;
return sdev;
}
/*
* sysfs support
*/
extern int scsi_upper_driver_register(struct Scsi_Device_Template *);
extern void scsi_upper_driver_unregister(struct Scsi_Device_Template *);
extern struct device_class shost_devclass;
#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
......
This diff is collapsed.
......@@ -510,7 +510,7 @@ typedef struct os_header_s {
#define OS_AUX_SIZE (512)
//#define OSST_MAX_SG 2
/* The tape buffer descriptor. */
/* The OnStream tape buffer descriptor. */
typedef struct {
unsigned char in_use;
unsigned char dma; /* DMA-able buffer */
......@@ -523,14 +523,14 @@ typedef struct {
int syscall_result;
Scsi_Request *last_SRpnt;
unsigned char *b_data;
os_aux_t *aux; /* onstream AUX structure at end of each block */
unsigned short use_sg; /* zero or number of segments for this adapter */
unsigned short sg_segs; /* total number of allocated segments */
unsigned short orig_sg_segs; /* number of segments allocated at first try */
struct scatterlist sg[1]; /* MUST BE last item */
os_aux_t *aux; /* onstream AUX structure at end of each block */
unsigned short use_sg; /* zero or number of s/g segments for this adapter */
unsigned short sg_segs; /* number of segments in s/g list */
unsigned short orig_sg_segs; /* number of segments allocated at first try */
struct scatterlist sg[1]; /* MUST BE last item */
} OSST_buffer;
/* The tape drive descriptor */
/* The OnStream tape drive descriptor */
typedef struct {
struct Scsi_Device_Template *driver;
unsigned capacity;
......@@ -549,6 +549,7 @@ typedef struct {
unsigned char restr_dma;
unsigned char scsi2_logical;
unsigned char default_drvbuffer; /* 0xff = don't touch, value 3 bits */
unsigned char pos_unknown; /* after reset position unknown */
int write_threshold;
int timeout; /* timeout for normal commands */
int long_timeout; /* timeout for commands known to take long time*/
......@@ -556,10 +557,10 @@ typedef struct {
/* Mode characteristics */
ST_mode modes[ST_NBR_MODES];
int current_mode;
#ifdef CONFIG_DEVFS_FS
devfs_handle_t de_r[ST_NBR_MODES]; /* Rewind entries */
devfs_handle_t de_n[ST_NBR_MODES]; /* No-rewind entries */
#endif
struct device driverfs_dev_r[ST_NBR_MODES];
struct device driverfs_dev_n[ST_NBR_MODES];
/* Status variables */
int partition;
......@@ -628,7 +629,7 @@ typedef struct {
unsigned char last_cmnd[6];
unsigned char last_sense[16];
#endif
struct gendisk *disk;
struct gendisk *drive;
} OS_Scsi_Tape;
/* Values of write_type */
......
......@@ -92,7 +92,8 @@ static int fdomain_event(event_t event, int priority,
static dev_link_t *fdomain_attach(void);
static void fdomain_detach(dev_link_t *);
static Scsi_Host_Template driver_template = FDOMAIN_16X0;
#define driver_template fdomain_driver_template
extern Scsi_Host_Template fdomain_driver_template;
static dev_link_t *dev_list = NULL;
......
This diff is collapsed.
......@@ -169,30 +169,13 @@ void scsi_build_commandblocks(Scsi_Device * SDpnt);
/*
* Function: scsi_initialize_queue()
*
* Purpose: Selects queue handler function for a device.
* Purpose: Sets up the block queue for a device.
*
* Arguments: SDpnt - device for which we need a handler function.
*
* Returns: Nothing
*
* Lock status: No locking assumed or required.
*
* Notes: Most devices will end up using scsi_request_fn for the
* handler function (at least as things are done now).
* The "block" feature basically ensures that only one of
* the blocked hosts is active at one time, mainly to work around
* buggy DMA chipsets where the memory gets starved.
* For this case, we have a special handler function, which
* does some checks and ultimately calls scsi_request_fn.
*
* The single_lun feature is a similar special case.
*
* We handle these things by stacking the handlers. The
* special case handlers simply check a few conditions,
* and return if they are not supposed to do anything.
* In the event that things are OK, then they call the next
* handler in the list - ultimately they call scsi_request_fn
* to do the dirty deed.
*/
void scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt)
{
......@@ -793,7 +776,6 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
rtn = host->hostt->queuecommand(SCpnt, scsi_done);
spin_unlock_irqrestore(host->host_lock, flags);
if (rtn != 0) {
scsi_delete_timer(SCpnt);
scsi_mlqueue_insert(SCpnt, rtn == SCSI_MLQUEUE_DEVICE_BUSY ? rtn : SCSI_MLQUEUE_HOST_BUSY);
SCSI_LOG_MLQUEUE(3,
printk("queuecommand : request rejected\n"));
......@@ -1895,20 +1877,12 @@ int scsi_attach_device(struct scsi_device *sdev)
struct Scsi_Device_Template *sdt;
down_read(&scsi_devicelist_mutex);
list_for_each_entry(sdt, &scsi_devicelist, list)
if (sdt->attach) {
/*
* XXX check result when the upper level attach
* return values are fixed, and on failure goto
* fail.
*/
if(try_module_get(sdt->module)) {
(*sdt->attach)(sdev);
module_put(sdt->module);
} else {
printk(KERN_WARNING "SCSI module %s not ready, skipping attach.\n", sdt->name);
}
}
list_for_each_entry(sdt, &scsi_devicelist, list) {
if (!try_module_get(sdt->module))
continue;
(*sdt->attach)(sdev);
module_put(sdt->module);
}
up_read(&scsi_devicelist_mutex);
return 0;
}
......@@ -1918,18 +1892,30 @@ void scsi_detach_device(struct scsi_device *sdev)
struct Scsi_Device_Template *sdt;
down_read(&scsi_devicelist_mutex);
list_for_each_entry(sdt, &scsi_devicelist, list)
if (sdt->detach) {
if(try_module_get(sdt->module)) {
(*sdt->detach)(sdev);
module_put(sdt->module);
} else {
printk(KERN_WARNING "SCSI module %s not ready, skipping detach.\n", sdt->name);
}
}
list_for_each_entry(sdt, &scsi_devicelist, list) {
if (!try_module_get(sdt->module))
continue;
(*sdt->detach)(sdev);
module_put(sdt->module);
}
up_read(&scsi_devicelist_mutex);
}
int scsi_device_get(struct scsi_device *sdev)
{
if (!try_module_get(sdev->host->hostt->module))
return -ENXIO;
sdev->access_count++;
return 0;
}
void scsi_device_put(struct scsi_device *sdev)
{
sdev->access_count--;
module_put(sdev->host->hostt->module);
}
/*
* Function: scsi_slave_attach()
*
......@@ -1953,7 +1939,7 @@ int scsi_slave_attach(struct scsi_device *sdev)
printk(KERN_ERR "scsi: Allocation failure during"
" attach, some SCSI devices might not be"
" configured\n");
return 1;
return -ENOMEM;
}
if (sdev->host->hostt->slave_configure != NULL) {
if (sdev->host->hostt->slave_configure(sdev) != 0) {
......@@ -1961,7 +1947,7 @@ int scsi_slave_attach(struct scsi_device *sdev)
" attach, some SCSI device might not be"
" configured\n");
scsi_release_commandblocks(sdev);
return 1;
return -ENOMEM;
}
} else if (sdev->host->cmd_per_lun != 0)
scsi_adjust_queue_depth(sdev, 0,
......@@ -2019,10 +2005,7 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
list_add_tail(&tpnt->list, &scsi_devicelist);
up_write(&scsi_devicelist_mutex);
tpnt->scsi_driverfs_driver.name = (char *)tpnt->tag;
tpnt->scsi_driverfs_driver.bus = &scsi_driverfs_bus_type;
driver_register(&tpnt->scsi_driverfs_driver);
scsi_upper_driver_register(tpnt);
for (shpnt = scsi_host_get_next(NULL); shpnt;
shpnt = scsi_host_get_next(shpnt))
......@@ -2037,7 +2020,6 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
Scsi_Device *SDpnt;
struct Scsi_Host *shpnt;
driver_unregister(&tpnt->scsi_driverfs_driver);
/*
* Next, detach the devices from the driver.
......@@ -2055,6 +2037,8 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
list_del(&tpnt->list);
up_write(&scsi_devicelist_mutex);
scsi_upper_driver_unregister(tpnt);
/*
* Final cleanup for the driver is done in the driver sources in the
* cleanup function.
......@@ -2153,34 +2137,6 @@ void scsi_free_sgtable(struct scatterlist *sgl, int index)
mempool_free(sgl, sgp->pool);
}
static int scsi_bus_match(struct device *scsi_driverfs_dev,
struct device_driver *scsi_driverfs_drv)
{
char *p=0;
if (!strcmp("sd", scsi_driverfs_drv->name)) {
if ((p = strstr(scsi_driverfs_dev->bus_id, ":disc")) ||
(p = strstr(scsi_driverfs_dev->bus_id, ":p"))) {
return 1;
}
} else if (!strcmp("sg", scsi_driverfs_drv->name)) {
if (strstr(scsi_driverfs_dev->bus_id, ":gen"))
return 1;
} else if (!strcmp("sr",scsi_driverfs_drv->name)) {
if (strstr(scsi_driverfs_dev->bus_id,":cd"))
return 1;
} else if (!strcmp("st",scsi_driverfs_drv->name)) {
if (strstr(scsi_driverfs_dev->bus_id,":mt"))
return 1;
}
return 0;
}
struct bus_type scsi_driverfs_bus_type = {
.name = "scsi",
.match = scsi_bus_match,
};
static int __init init_scsi(void)
{
int i;
......@@ -2207,7 +2163,7 @@ static int __init init_scsi(void)
scsi_devfs_handle = devfs_mk_dir(NULL, "scsi", NULL);
scsi_host_init();
scsi_dev_info_list_init(scsi_dev_flags);
bus_register(&scsi_driverfs_bus_type);
scsi_sysfs_register();
open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL);
return 0;
}
......@@ -2216,7 +2172,7 @@ static void __exit exit_scsi(void)
{
int i;
bus_unregister(&scsi_driverfs_bus_type);
scsi_sysfs_unregister();
scsi_dev_info_list_delete();
devfs_unregister(scsi_devfs_handle);
scsi_exit_procfs();
......@@ -2230,5 +2186,5 @@ static void __exit exit_scsi(void)
}
}
module_init(init_scsi);
subsys_initcall(init_scsi);
module_exit(exit_scsi);
......@@ -401,9 +401,6 @@ typedef struct scsi_request Scsi_Request;
extern unsigned int scsi_logging_level; /* What do we log? */
extern struct bus_type scsi_driverfs_bus_type;
/*
* These are the error handling functions defined in scsi_error.c
*/
......@@ -451,8 +448,10 @@ extern void scsi_release_commandblocks(Scsi_Device * SDpnt);
extern void scsi_build_commandblocks(Scsi_Device * SDpnt);
extern void scsi_adjust_queue_depth(Scsi_Device *, int, int);
extern int scsi_track_queue_full(Scsi_Device *, int);
extern int scsi_slave_attach(struct scsi_device *sdev);
extern void scsi_slave_detach(struct scsi_device *sdev);
extern int scsi_slave_attach(struct scsi_device *);
extern void scsi_slave_detach(struct scsi_device *);
extern int scsi_device_get(struct scsi_device *);
extern void scsi_device_put(struct scsi_device *);
extern void scsi_done(Scsi_Cmnd * SCpnt);
extern void scsi_finish_command(Scsi_Cmnd *);
extern int scsi_retry_command(Scsi_Cmnd *);
......@@ -509,9 +508,6 @@ static inline void scsi_proc_host_rm(struct Scsi_Host *);
/*
* Prototypes for functions in scsi_scan.c
*/
extern struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *,
uint, uint, uint);
extern void scsi_free_sdev(struct scsi_device *);
extern int scsi_add_single_device(uint, uint, uint, uint);
extern int scsi_remove_single_device(uint, uint, uint, uint);
......@@ -992,4 +988,10 @@ static inline Scsi_Cmnd *scsi_find_tag(Scsi_Device *SDpnt, int tag) {
int scsi_set_medium_removal(Scsi_Device *dev, char state);
extern int scsi_device_register(struct scsi_device *);
extern void scsi_device_unregister(struct scsi_device *);
extern int scsi_sysfs_register(void);
extern void scsi_sysfs_unregister(void);
#endif
......@@ -155,6 +155,7 @@ static rwlock_t atomic_rw = RW_LOCK_UNLOCKED;
static char sdebug_proc_name[] = "scsi_debug";
static struct device_driver sdebug_driverfs_driver = {
.name = sdebug_proc_name,
.devclass = &shost_devclass,
};
/* function declarations */
......@@ -1501,7 +1502,7 @@ static void sdebug_add_shost(int num)
printk(KERN_ERR "sdebug_add_shost: scsi_register failed\n");
return;
}
err = scsi_add_host(hpnt);
err = scsi_add_host(hpnt, scsi_debug_hosts[num].dev);
if (err) {
printk(KERN_ERR "sdebug_add_shost: scsi_add_host failed\n");
scsi_unregister(hpnt);
......
......@@ -7,18 +7,15 @@
* of people at Linux Expo.
*/
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/bio.h>
#include <linux/kernel.h>
#include <linux/blk.h>
#include <asm/hardirq.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include "scsi.h"
#include "hosts.h"
#include <scsi/scsi_ioctl.h>
/*
* Function: scsi_insert_special_cmd()
......@@ -665,7 +662,7 @@ static int scsi_init_io(Scsi_Cmnd *SCpnt)
{
struct request *req = SCpnt->request;
struct scatterlist *sgpnt;
int count, gfp_mask, ret = 0;
int count, ret = 0;
/*
* if this is a rq->data based REQ_BLOCK_PC, setup for a non-sg xfer
......@@ -685,16 +682,10 @@ static int scsi_init_io(Scsi_Cmnd *SCpnt)
*/
SCpnt->use_sg = req->nr_phys_segments;
gfp_mask = GFP_NOIO;
if (likely(in_atomic())) {
gfp_mask &= ~__GFP_WAIT;
gfp_mask |= __GFP_HIGH;
}
/*
* if sg table allocation fails, requeue request later.
*/
sgpnt = scsi_alloc_sgtable(SCpnt, gfp_mask);
sgpnt = scsi_alloc_sgtable(SCpnt, GFP_ATOMIC);
if (unlikely(!sgpnt)) {
req->flags |= REQ_SPECIAL;
ret = BLKPREP_DEFER;
......
......@@ -312,73 +312,6 @@ static void scsi_unlock_floptical(Scsi_Request *sreq, unsigned char *result)
SCSI_TIMEOUT, 3);
}
/**
* scsi_device_type_read - copy out the SCSI type
* @driverfs_dev: driverfs device to check
* @page: copy data into this area
* @count: number of bytes to copy
* @off: start at this offset in page
*
* Description:
* Called via driverfs when the "type" (in scsi_device_type_file)
* field is read. Copy the appropriate SCSI type string into @page,
* followed by a newline and a '\0'. Go through gyrations so we don't
* write more than @count, and we don't write past @off.
*
* Notes:
* This is for the top-most scsi entry in driverfs, the upper-level
* drivers have their own type file. XXX This is not part of scanning,
* other than we reference the attr struct in this file, move to
* scsi.c or scsi_lib.c.
*
* Return:
* number of bytes written into page.
**/
static ssize_t scsi_device_type_read(struct device *driverfs_dev, char *page,
size_t count, loff_t off)
{
struct scsi_device *sdev = to_scsi_device(driverfs_dev);
const char *type;
size_t size, len;
if ((sdev->type > MAX_SCSI_DEVICE_CODE) ||
(scsi_device_types[(int)sdev->type] == NULL))
type = "Unknown";
else
type = scsi_device_types[(int)sdev->type];
size = strlen(type);
/*
* Check if off is past size + 1 for newline + 1 for a '\0'.
*/
if (off >= (size + 2))
return 0;
if (size > off) {
len = min((size_t) (size - off), count);
memcpy(page + off, type + off, len);
} else
len = 0;
if (((len + off) == size) && (len < count))
/*
* We are at the end of the string and have space, add a
* new line.
*/
*(page + off + len++) = '\n';
if (((len + off) == (size + 1)) && (len < count))
/*
* We are past the newline and have space, add a
* terminating '\0'.
*/
*(page + off + len++) = '\0';
return len;
}
/*
* Create dev_attr_type. This is different from the dev_attr_type in scsi
* upper level drivers.
*/
static DEVICE_ATTR(type,S_IRUGO,scsi_device_type_read,NULL);
/**
* print_inquiry - printk the inquiry information
* @inq_result: printk this SCSI INQUIRY
......@@ -472,8 +405,8 @@ static void scsi_initialize_merge_fn(struct scsi_device *sd)
* Return value:
* Scsi_Device pointer, or NULL on failure.
**/
struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel,
uint id, uint lun)
static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
uint channel, uint id, uint lun)
{
struct scsi_device *sdev, *device;
......@@ -542,7 +475,7 @@ struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel,
* Undo the actions in scsi_alloc_sdev, including removing @sdev from
* the list, and freeing @sdev.
**/
void scsi_free_sdev(struct scsi_device *sdev)
static void scsi_free_sdev(struct scsi_device *sdev)
{
list_del(&sdev->siblings);
list_del(&sdev->same_target_siblings);
......@@ -1365,20 +1298,8 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
* function.
*/
scsi_load_identifier(sdev, sreq);
/*
* create driverfs files
*/
sprintf(sdev->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d",
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
sdev->sdev_driverfs_dev.parent = &sdev->host->host_driverfs_dev;
sdev->sdev_driverfs_dev.bus = &scsi_driverfs_bus_type;
device_register(&sdev->sdev_driverfs_dev);
/*
* Create driverfs file entries
*/
device_create_file(&sdev->sdev_driverfs_dev, &dev_attr_type);
scsi_device_register(sdev);
sprintf(devname, "scsi/host%d/bus%d/target%d/lun%d",
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
......@@ -1419,6 +1340,14 @@ static int scsi_add_lun(Scsi_Device *sdevscan, Scsi_Device **sdevnew,
return SCSI_SCAN_LUN_PRESENT;
}
static void scsi_remove_lun(struct scsi_device *sdev)
{
devfs_unregister(sdev->de);
scsi_device_unregister(sdev);
scsi_free_sdev(sdev);
}
/**
* scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it
* @sdevscan: probe the LUN corresponding to this Scsi_Device
......@@ -1941,8 +1870,7 @@ int scsi_remove_single_device(uint host, uint channel, uint id, uint lun)
if (sdev->attached)
goto out;
devfs_unregister(sdev->de);
scsi_free_sdev(sdev);
scsi_remove_lun(sdev);
error = 0;
out:
......@@ -2068,3 +1996,69 @@ void scsi_scan_host(struct Scsi_Host *shost)
}
scsi_free_sdev(sdevscan);
}
void scsi_forget_host(struct Scsi_Host *shost)
{
struct list_head *le, *lh;
list_for_each_safe(le, lh, &shost->my_devices)
scsi_remove_lun(list_entry(le, struct scsi_device, siblings));
}
/*
* Function: scsi_get_host_dev()
*
* Purpose: Create a Scsi_Device that points to the host adapter itself.
*
* Arguments: SHpnt - Host that needs a Scsi_Device
*
* Lock status: None assumed.
*
* Returns: The Scsi_Device or NULL
*
* Notes:
* Attach a single Scsi_Device to the Scsi_Host - this should
* be made to look like a "pseudo-device" that points to the
* HA itself.
*
* Note - this device is not accessible from any high-level
* drivers (including generics), which is probably not
* optimal. We can add hooks later to attach
*/
struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
{
struct scsi_device *sdev;
sdev = scsi_alloc_sdev(shost, 0, shost->this_id, 0);
if (sdev) {
scsi_build_commandblocks(sdev);
if (sdev->current_queue_depth == 0)
goto fail;
sdev->borken = 0;
}
return sdev;
fail:
kfree(sdev);
return NULL;
}
/*
* Function: scsi_free_host_dev()
*
* Purpose: Free a scsi_device that points to the host adapter itself.
*
* Arguments: SHpnt - Host that needs a Scsi_Device
*
* Lock status: None assumed.
*
* Returns: Nothing
*
* Notes:
*/
void scsi_free_host_dev(struct scsi_device *sdev)
{
BUG_ON(sdev->id != sdev->host->this_id);
scsi_free_sdev(sdev);
}
......@@ -81,6 +81,8 @@ EXPORT_SYMBOL(scsi_register_blocked_host);
EXPORT_SYMBOL(scsi_deregister_blocked_host);
EXPORT_SYMBOL(scsi_slave_attach);
EXPORT_SYMBOL(scsi_slave_detach);
EXPORT_SYMBOL(scsi_device_get);
EXPORT_SYMBOL(scsi_device_put);
/*
* This symbol is for the highlevel drivers (e.g. sg) only.
......@@ -104,6 +106,6 @@ EXPORT_SYMBOL(scsi_add_timer);
EXPORT_SYMBOL(scsi_delete_timer);
/*
* driverfs support for determining driver types
* sysfs support
*/
EXPORT_SYMBOL(scsi_driverfs_bus_type);
EXPORT_SYMBOL(shost_devclass);
/*
* scsi_sysfs.c
*
* SCSI sysfs interface routines.
*
* Created to pull SCSI mid layer sysfs routines into one file.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/device.h>
#include "scsi.h"
#include "hosts.h"
/**
* scsi_host_class_name_show - copy out the SCSI host name
* @dev: device to check
* @page: copy data into this area
* @count: number of bytes to copy
* @off: start at this offset in page
* Return:
* number of bytes written into page.
**/
static ssize_t scsi_host_class_name_show(struct device *dev, char *page,
size_t count, loff_t off)
{
struct Scsi_Host *shost;
if (off)
return 0;
shost = to_scsi_host(dev);
if (!shost)
return 0;
return snprintf(page, count, "scsi%d\n", shost->host_no);
}
DEVICE_ATTR(class_name, S_IRUGO, scsi_host_class_name_show, NULL);
static int scsi_host_class_add_dev(struct device * dev)
{
device_create_file(dev, &dev_attr_class_name);
return 0;
}
static void scsi_host_class_rm_dev(struct device * dev)
{
device_remove_file(dev, &dev_attr_class_name);
}
struct device_class shost_devclass = {
.name = "scsi-host",
.add_device = scsi_host_class_add_dev,
.remove_device = scsi_host_class_rm_dev,
};
/**
* scsi_bus_match:
* @dev:
* @dev_driver:
*
* Return value:
**/
static int scsi_bus_match(struct device *dev,
struct device_driver *dev_driver)
{
if (!strcmp("sg", dev_driver->name)) {
if (strstr(dev->bus_id, ":gen"))
return 1;
} else if (!strcmp("st",dev_driver->name)) {
if (strstr(dev->bus_id,":mt"))
return 1;
} else if (!strcmp("sd", dev_driver->name)) {
if ((!strstr(dev->bus_id, ":gen")) &&
(!strstr(dev->bus_id, ":mt"))) {
return 1;
}
}
return 0;
}
static struct bus_type scsi_bus_type = {
.name = "scsi",
.match = scsi_bus_match,
};
int scsi_sysfs_register(void)
{
bus_register(&scsi_bus_type);
devclass_register(&shost_devclass);
return 0;
}
void scsi_sysfs_unregister(void)
{
devclass_unregister(&shost_devclass);
bus_unregister(&scsi_bus_type);
}
/**
* scsi_upper_driver_register - register upper level driver.
* @sdev_tp: Upper level driver to register with the scsi bus.
*
* Return value:
* 0 on Success / non-zero on Failure
**/
int scsi_upper_driver_register(struct Scsi_Device_Template *sdev_tp)
{
int error = 0;
sdev_tp->scsi_driverfs_driver.bus = &scsi_bus_type;
error = driver_register(&sdev_tp->scsi_driverfs_driver);
return error;
}
/**
* scsi_upper_driver_unregister - unregister upper level driver
* @sdev_tp: Upper level driver to unregister with the scsi bus.
*
**/
void scsi_upper_driver_unregister(struct Scsi_Device_Template *sdev_tp)
{
driver_unregister(&sdev_tp->scsi_driverfs_driver);
}
/**
* scsi_device_type_read - copy out the SCSI type
* @dev: device to check
* @page: copy data into this area
* @count: number of bytes to copy
* @off: start at this offset in page
*
* Return:
* number of bytes written into page.
**/
static ssize_t scsi_device_type_read(struct device *dev, char *page,
size_t count, loff_t off)
{
struct scsi_device *sdev = to_scsi_device(dev);
const char *type;
if (off)
return 0;
if ((sdev->type > MAX_SCSI_DEVICE_CODE) ||
(scsi_device_types[(int)sdev->type] == NULL))
type = "Unknown";
else
type = scsi_device_types[(int)sdev->type];
return snprintf(page, count, "%s\n", type);
}
/*
* Create dev_attr_type. This is different from the dev_attr_type in scsi
* upper level drivers.
*/
static DEVICE_ATTR(type,S_IRUGO,scsi_device_type_read,NULL);
/**
* scsi_device_register - register a scsi device with the scsi bus
* @sdev: scsi_device to register
*
* Return value:
* 0 on Success / non-zero on Failure
**/
int scsi_device_register(struct scsi_device *sdev)
{
int error = 0;
sprintf(sdev->sdev_driverfs_dev.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;
error = device_register(&sdev->sdev_driverfs_dev);
if (error)
return error;
error = device_create_file(&sdev->sdev_driverfs_dev, &dev_attr_type);
if (error)
device_unregister(&sdev->sdev_driverfs_dev);
return error;
}
/**
* scsi_device_unregister - unregister a device from the scsi bus
* @sdev: scsi_device to unregister
**/
void scsi_device_unregister(struct scsi_device *sdev)
{
device_remove_file(&sdev->sdev_driverfs_dev, &dev_attr_type);
device_unregister(&sdev->sdev_driverfs_dev);
}
This diff is collapsed.
......@@ -122,10 +122,12 @@ static struct Scsi_Device_Template sg_template = {
.module = THIS_MODULE,
.list = LIST_HEAD_INIT(sg_template.list),
.name = "generic",
.tag = "sg",
.scsi_type = 0xff,
.attach = sg_attach,
.detach = sg_detach
.detach = sg_detach,
.scsi_driverfs_driver = {
.name = "sg",
},
};
typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
......@@ -259,9 +261,9 @@ sg_open(struct inode *inode, struct file *filp)
/* This driver's module count bumped by fops_get in <linux/fs.h> */
/* Prevent the device driver from vanishing while we sleep */
if (!try_module_get(sdp->device->host->hostt->module))
return -ENXIO;
sdp->device->access_count++;
retval = scsi_device_get(sdp->device);
if (retval)
return retval;
if (!((flags & O_NONBLOCK) ||
scsi_block_when_processing_errors(sdp->device))) {
......@@ -314,8 +316,7 @@ sg_open(struct inode *inode, struct file *filp)
return 0;
error_out:
sdp->device->access_count--;
module_put(sdp->device->host->hostt->module);
scsi_device_put(sdp->device);
return retval;
}
......@@ -332,8 +333,7 @@ sg_release(struct inode *inode, struct file *filp)
sg_fasync(-1, filp, 0); /* remove filp from async notification list */
if (0 == sg_remove_sfp(sdp, sfp)) { /* Returns 1 when sdp gone */
if (!sdp->detached) {
sdp->device->access_count--;
module_put(sdp->device->host->hostt->module);
scsi_device_put(sdp->device);
}
sdp->exclude = 0;
wake_up_interruptible(&sdp->o_excl_wait);
......@@ -1296,8 +1296,7 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
if (NULL == sfp->headrp) {
SCSI_LOG_TIMEOUT(1, printk("sg...bh: already closed, final cleanup\n"));
if (0 == sg_remove_sfp(sdp, sfp)) { /* device still present */
sdp->device->access_count--;
module_put(sdp->device->host->hostt->module);
scsi_device_put(sdp->device);
}
sfp = NULL;
}
......@@ -1372,15 +1371,19 @@ static DEVICE_ATTR(type,S_IRUGO,sg_device_type_read,NULL);
static int
sg_attach(Scsi_Device * scsidp)
{
struct gendisk *disk = alloc_disk(1);
struct gendisk *disk;
Sg_device *sdp = NULL;
unsigned long iflags;
int k;
int k, error;
disk = alloc_disk(1);
if (!disk)
return 1;
if (scsi_slave_attach(scsidp))
return 1;
return -ENOMEM;
error = scsi_slave_attach(scsidp);
if (error)
goto out_put;
write_lock_irqsave(&sg_dev_arr_lock, iflags);
if (sg_nr_dev >= sg_dev_max) { /* try to resize */
Sg_device **tmp_da;
......@@ -1392,9 +1395,8 @@ sg_attach(Scsi_Device * scsidp)
if (NULL == tmp_da) {
printk(KERN_ERR
"sg_attach: device array cannot be resized\n");
put_disk(disk);
scsi_slave_detach(scsidp);
return 1;
error = -ENOMEM;
goto out_detach;
}
write_lock_irqsave(&sg_dev_arr_lock, iflags);
memset(tmp_da, 0, tmp_dev_max * sizeof (Sg_device *));
......@@ -1418,9 +1420,8 @@ sg_attach(Scsi_Device * scsidp)
scsidp->lun, scsidp->type, SG_MAX_DEVS_MASK);
if (NULL != sdp)
vfree((char *) sdp);
put_disk(disk);
scsi_slave_detach(scsidp);
return 1;
error = -ENODEV;
goto out_detach;
}
if (k < sg_dev_max) {
if (NULL == sdp) {
......@@ -1435,9 +1436,8 @@ sg_attach(Scsi_Device * scsidp)
if (NULL == sdp) {
write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
printk(KERN_ERR "sg_attach: Sg_device cannot be allocated\n");
put_disk(disk);
scsi_slave_detach(scsidp);
return 1;
error = -ENOMEM;
goto out_detach;
}
SCSI_LOG_TIMEOUT(3, printk("sg_attach: dev=%d \n", k));
......@@ -1462,7 +1462,7 @@ sg_attach(Scsi_Device * scsidp)
sprintf(sdp->sg_driverfs_dev.name, "%sgeneric",
scsidp->sdev_driverfs_dev.name);
sdp->sg_driverfs_dev.parent = &scsidp->sdev_driverfs_dev;
sdp->sg_driverfs_dev.bus = &scsi_driverfs_bus_type;
sdp->sg_driverfs_dev.bus = scsidp->sdev_driverfs_dev.bus;
sg_nr_dev++;
sg_dev_arr[k] = sdp;
......@@ -1490,6 +1490,12 @@ sg_attach(Scsi_Device * scsidp)
scsidp->lun, scsidp->type);
}
return 0;
out_detach:
scsi_slave_detach(scsidp);
out_put:
put_disk(disk);
return error;
}
static void
......@@ -1521,8 +1527,7 @@ sg_detach(Scsi_Device * scsidp)
sg_finish_rem_req(srp);
}
if (sfp->closed) {
sdp->device->access_count--;
module_put(sdp->device->host->hostt->module);
scsi_device_put(sdp->device);
__sg_remove_sfp(sdp, sfp);
} else {
delay = 1;
......@@ -2510,8 +2515,7 @@ sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
/* MOD_INC's to inhibit unloading sg and associated adapter driver */
/* only bump the access_count if we actually succeeded in
* throwing another counter on the host module */
if(try_module_get(sdp->device->host->hostt->module))
sdp->device->access_count++;
scsi_device_get(sdp->device); /* XXX: retval ignored? */
sfp->closed = 1; /* flag dirty state on this fd */
SCSI_LOG_TIMEOUT(1, printk("sg_remove_sfp: worrisome, %d writes pending\n",
dirty));
......
......@@ -32,8 +32,6 @@
* check resource allocation in sr_init and some cleanups
*/
#define MAJOR_NR SCSI_CDROM_MAJOR
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kernel.h>
......@@ -57,6 +55,9 @@
MODULE_PARM(xa_test, "i"); /* see sr_ioctl.c */
#define SR_DISKS (1 << KDEV_MINOR_BITS)
#define MAX_RETRIES 3
#define SR_TIMEOUT (30 * HZ)
#define SR_CAPABILITIES \
......@@ -73,18 +74,24 @@ static struct Scsi_Device_Template sr_template = {
.module = THIS_MODULE,
.list = LIST_HEAD_INIT(sr_template.list),
.name = "cdrom",
.tag = "sr",
.scsi_type = TYPE_ROM,
.attach = sr_attach,
.detach = sr_detach,
.init_command = sr_init_command
.init_command = sr_init_command,
.scsi_driverfs_driver = {
.name = "sr",
},
};
static int sr_nr_dev; /* XXX(hch) bad hack, we want a bitmap instead */
static LIST_HEAD(sr_devlist);
static spinlock_t sr_devlist_lock = SPIN_LOCK_UNLOCKED;
static unsigned long sr_index_bits[SR_DISKS / BITS_PER_LONG];
static spinlock_t sr_index_lock = SPIN_LOCK_UNLOCKED;
static int sr_open(struct cdrom_device_info *, int);
static void sr_release(struct cdrom_device_info *);
static void get_sectorsize(struct scsi_cd *);
static void get_capabilities(struct scsi_cd *);
......@@ -122,16 +129,6 @@ static inline void sr_devlist_remove(Scsi_CD *cd)
spin_unlock(&sr_devlist_lock);
}
static void sr_release(struct cdrom_device_info *cdi)
{
struct scsi_cd *cd = cdi->handle;
if (cd->device->sector_size > 2048)
sr_set_blocklength(cd, 2048);
cd->device->access_count--;
module_put(cd->device->host->hostt->module);
}
static struct cdrom_device_ops sr_dops = {
.open = sr_open,
.release = sr_release,
......@@ -458,43 +455,59 @@ struct block_device_operations sr_bdops =
static int sr_open(struct cdrom_device_info *cdi, int purpose)
{
struct scsi_cd *cd = cdi->handle;
struct scsi_device *sdev = cd->device;
int retval;
if (!cd->device)
return -ENXIO; /* No such device */
retval = scsi_device_get(sdev);
if (retval)
return retval;
/*
* If the device is in error recovery, wait until it is done.
* If the device is offline, then disallow any access to it.
*/
if (!scsi_block_when_processing_errors(cd->device)) {
return -ENXIO;
}
if(!try_module_get(cd->device->host->hostt->module))
return -ENXIO;
cd->device->access_count++;
retval = -ENXIO;
if (!scsi_block_when_processing_errors(sdev))
goto error_out;
/* If this device did not have media in the drive at boot time, then
/*
* If this device did not have media in the drive at boot time, then
* we would have been unable to get the sector size. Check to see if
* this is the case, and try again.
*/
if (cd->needs_sector_size)
get_sectorsize(cd);
return 0;
error_out:
scsi_device_put(sdev);
return retval;
}
static void sr_release(struct cdrom_device_info *cdi)
{
struct scsi_cd *cd = cdi->handle;
if (cd->device->sector_size > 2048)
sr_set_blocklength(cd, 2048);
scsi_device_put(cd->device);
}
static int sr_attach(struct scsi_device *sdev)
{
struct gendisk *disk;
struct scsi_cd *cd;
int minor;
int minor, error;
if (sdev->type != TYPE_ROM && sdev->type != TYPE_WORM)
return 1;
if (scsi_slave_attach(sdev))
return 1;
error = scsi_slave_attach(sdev);
if (error)
return error;
error = -ENOMEM;
cd = kmalloc(sizeof(*cd), GFP_KERNEL);
if (!cd)
goto fail;
......@@ -504,16 +517,17 @@ static int sr_attach(struct scsi_device *sdev)
if (!disk)
goto fail_free;
/*
* 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_nr_dev++;
spin_lock(&sr_index_lock);
minor = find_first_zero_bit(sr_index_bits, SR_DISKS);
if (minor == SR_DISKS) {
spin_unlock(&sr_index_lock);
error = -EBUSY;
goto fail_put;
}
__set_bit(minor, sr_index_bits);
spin_unlock(&sr_index_lock);
disk->major = MAJOR_NR;
disk->major = SCSI_CDROM_MAJOR;
disk->first_minor = minor;
sprintf(disk->disk_name, "sr%d", minor);
disk->fops = &sr_bdops;
......@@ -560,11 +574,13 @@ static int sr_attach(struct scsi_device *sdev)
sdev->id, sdev->lun);
return 0;
fail_put:
put_disk(disk);
fail_free:
kfree(cd);
fail:
scsi_slave_detach(sdev);
return 1;
return error;
}
......@@ -792,13 +808,15 @@ static void sr_detach(struct scsi_device * SDp)
return;
sr_devlist_remove(cd);
scsi_slave_detach(SDp);
del_gendisk(cd->disk);
put_disk(cd->disk);
unregister_cdrom(&cd->cdi);
scsi_slave_detach(SDp);
sr_nr_dev--;
spin_lock(&sr_index_lock);
clear_bit(cd->disk->first_minor, sr_index_bits);
spin_unlock(&sr_index_lock);
put_disk(cd->disk);
unregister_cdrom(&cd->cdi);
kfree(cd);
}
......@@ -806,7 +824,7 @@ static int __init init_sr(void)
{
int rc;
rc = register_blkdev(MAJOR_NR, "sr", &sr_bdops);
rc = register_blkdev(SCSI_CDROM_MAJOR, "sr", &sr_bdops);
if (rc)
return rc;
return scsi_register_device(&sr_template);
......@@ -815,7 +833,7 @@ static int __init init_sr(void)
static void __exit exit_sr(void)
{
scsi_unregister_device(&sr_template);
unregister_blkdev(MAJOR_NR, "sr");
unregister_blkdev(SCSI_CDROM_MAJOR, "sr");
}
module_init(init_sr);
......
This diff is collapsed.
This diff is collapsed.
......@@ -176,6 +176,7 @@ get_pci_port(struct pci_dev *dev, struct pci_board *board,
return 0;
}
req->io_type = SERIAL_IO_MEM;
req->iomap_base = port;
req->iomem_base = ioremap(port, board->uart_offset);
if (req->iomem_base == NULL)
return -ENOMEM;
......@@ -262,12 +263,14 @@ static int __devinit pci_plx9050_fn(struct pci_dev *dev, int enable)
* interface chip and different configuration methods:
* - 10x cards have control registers in IO and/or memory space;
* - 20x cards have control registers in standard PCI configuration space.
*
* Note: some SIIG cards are probed by the parport_serial object.
*/
#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
static int __devinit pci_siig10x_fn(struct pci_dev *dev, int enable)
int pci_siig10x_fn(struct pci_dev *dev, int enable)
{
u16 data, *p;
......@@ -295,10 +298,12 @@ static int __devinit pci_siig10x_fn(struct pci_dev *dev, int enable)
return 0;
}
EXPORT_SYMBOL(pci_siig10x_fn);
#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
static int __devinit pci_siig20x_fn(struct pci_dev *dev, int enable)
int pci_siig20x_fn(struct pci_dev *dev, int enable)
{
u8 data;
......@@ -318,6 +323,8 @@ static int __devinit pci_siig20x_fn(struct pci_dev *dev, int enable)
return 0;
}
EXPORT_SYMBOL(pci_siig20x_fn);
/* Added for EKF Intel i960 serial boards */
static int __devinit pci_inteli960ni_fn(struct pci_dev *dev, int enable)
{
......
......@@ -4,7 +4,7 @@
# $Id: Makefile,v 1.8 2002/07/21 21:32:30 rmk Exp $
#
export-objs := core.o 8250.o suncore.o
export-objs := core.o 8250.o 8250_pci.o suncore.o
serial-8250-y :=
serial-8250-$(CONFIG_GSC) += 8250_gsc.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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