Commit 04741d7d authored by James Bottomley's avatar James Bottomley

Merge

parents 3b6e7223 133d35e0
...@@ -5862,14 +5862,7 @@ static void __devexit dc395x_remove_one(struct pci_dev *dev) ...@@ -5862,14 +5862,7 @@ static void __devexit dc395x_remove_one(struct pci_dev *dev)
struct Scsi_Host *host = pci_get_drvdata(dev); struct Scsi_Host *host = pci_get_drvdata(dev);
dprintkdbg(DBG_0, "Removing instance\n"); dprintkdbg(DBG_0, "Removing instance\n");
if (!host) { scsi_remove_host(host);
dprintkl(KERN_ERR, "no host allocated\n");
return;
}
if (scsi_remove_host(host)) {
dprintkl(KERN_ERR, "scsi_remove_host failed\n");
return;
}
host_release(host); host_release(host);
scsi_host_put(host); scsi_host_put(host);
pci_set_drvdata(dev, NULL); pci_set_drvdata(dev, NULL);
......
...@@ -40,6 +40,16 @@ ...@@ -40,6 +40,16 @@
static int scsi_host_next_hn; /* host_no for next new host */ static int scsi_host_next_hn; /* host_no for next new host */
static void scsi_host_cls_release(struct class_device *class_dev)
{
put_device(&class_to_shost(class_dev)->shost_gendev);
}
static struct class shost_class = {
.name = "scsi_host",
.release = scsi_host_cls_release,
};
/** /**
* scsi_host_cancel - cancel outstanding IO to this host * scsi_host_cancel - cancel outstanding IO to this host
* @shost: pointer to struct Scsi_Host * @shost: pointer to struct Scsi_Host
...@@ -64,10 +74,18 @@ void scsi_host_cancel(struct Scsi_Host *shost, int recovery) ...@@ -64,10 +74,18 @@ void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
**/ **/
void scsi_remove_host(struct Scsi_Host *shost) void scsi_remove_host(struct Scsi_Host *shost)
{ {
unsigned long flags;
scsi_host_cancel(shost, 0); scsi_host_cancel(shost, 0);
scsi_proc_host_rm(shost); scsi_proc_host_rm(shost);
scsi_forget_host(shost); scsi_forget_host(shost);
scsi_sysfs_remove_host(shost);
spin_lock_irqsave(shost->host_lock, flags);
set_bit(SHOST_DEL, &shost->shost_state);
spin_unlock_irqrestore(shost->host_lock, flags);
class_device_unregister(&shost->shost_classdev);
device_del(&shost->shost_gendev);
} }
/** /**
...@@ -89,21 +107,45 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) ...@@ -89,21 +107,45 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
if (!shost->can_queue) { if (!shost->can_queue) {
printk(KERN_ERR "%s: can_queue = 0 no longer supported\n", printk(KERN_ERR "%s: can_queue = 0 no longer supported\n",
sht->name); sht->name);
error = -EINVAL; return -EINVAL;
} }
error = scsi_sysfs_add_host(shost, dev); if (!shost->shost_gendev.parent)
if (!error) shost->shost_gendev.parent = dev ? dev : &legacy_bus;
error = device_add(&shost->shost_gendev);
if (error)
goto out;
set_bit(SHOST_ADD, &shost->shost_state);
get_device(shost->shost_gendev.parent);
error = class_device_add(&shost->shost_classdev);
if (error)
goto out_del_gendev;
get_device(&shost->shost_gendev);
error = scsi_sysfs_add_host(shost);
if (error)
goto out_del_classdev;
scsi_proc_host_add(shost); scsi_proc_host_add(shost);
return error; return error;
out_del_classdev:
class_device_del(&shost->shost_classdev);
out_del_gendev:
device_del(&shost->shost_gendev);
out:
return error;
} }
/** static void scsi_host_dev_release(struct device *dev)
* scsi_free_sdev - free a scsi hosts resources
* @shost: scsi host to free
**/
void scsi_free_shost(struct Scsi_Host *shost)
{ {
struct Scsi_Host *shost = dev_to_shost(dev);
struct device *parent = dev->parent;
if (shost->ehandler) { if (shost->ehandler) {
DECLARE_COMPLETION(sem); DECLARE_COMPLETION(sem);
shost->eh_notify = &sem; shost->eh_notify = &sem;
...@@ -115,6 +157,8 @@ void scsi_free_shost(struct Scsi_Host *shost) ...@@ -115,6 +157,8 @@ void scsi_free_shost(struct Scsi_Host *shost)
scsi_proc_hostdir_rm(shost->hostt); scsi_proc_hostdir_rm(shost->hostt);
scsi_destroy_command_freelist(shost); scsi_destroy_command_freelist(shost);
put_device(parent);
kfree(shost); kfree(shost);
} }
...@@ -214,7 +258,18 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) ...@@ -214,7 +258,18 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
if (rval) if (rval)
goto fail; goto fail;
scsi_sysfs_init_host(shost); device_initialize(&shost->shost_gendev);
snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
shost->host_no);
snprintf(shost->shost_gendev.name, DEVICE_NAME_SIZE, "%s",
shost->hostt->proc_name);
shost->shost_gendev.release = scsi_host_dev_release;
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);
shost->eh_notify = &complete; shost->eh_notify = &complete;
/* XXX(hch): handle error return */ /* XXX(hch): handle error return */
...@@ -299,3 +354,13 @@ void scsi_host_put(struct Scsi_Host *shost) ...@@ -299,3 +354,13 @@ void scsi_host_put(struct Scsi_Host *shost)
{ {
put_device(&shost->shost_gendev); put_device(&shost->shost_gendev);
} }
int scsi_init_hosts(void)
{
return class_register(&shost_class);
}
void scsi_exit_hosts(void)
{
class_unregister(&shost_class);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -106,8 +106,10 @@ ...@@ -106,8 +106,10 @@
#define IPS_REMOVE_HOST(shost) #define IPS_REMOVE_HOST(shost)
#define IPS_SCSI_SET_DEVICE(sh,ha) scsi_set_pci_device(sh, (ha)->pcidev) #define IPS_SCSI_SET_DEVICE(sh,ha) scsi_set_pci_device(sh, (ha)->pcidev)
#define IPS_PRINTK(level, pcidev, format, arg...) \ #define IPS_PRINTK(level, pcidev, format, arg...) \
printk(level "%s %s:" format , (pcidev)->driver->name , \ printk(level "%s %s:" format , "ips" , \
pci_name(pcidev) , ## arg) (pcidev)->slot_name , ## arg)
#define scsi_host_alloc(sh,size) scsi_register(sh,size)
#define scsi_host_put(sh) scsi_unregister(sh)
#else #else
#define IPS_REGISTER_HOSTS(SHT) (!ips_detect(SHT)) #define IPS_REGISTER_HOSTS(SHT) (!ips_detect(SHT))
#define IPS_UNREGISTER_HOSTS(SHT) #define IPS_UNREGISTER_HOSTS(SHT)
...@@ -126,22 +128,13 @@ ...@@ -126,22 +128,13 @@
#define min(x,y) ((x) < (y) ? x : y) #define min(x,y) ((x) < (y) ? x : y)
#endif #endif
#define pci_dma_hi32(a) ((a >> 16) >> 16)
#define pci_dma_lo32(a) (a & 0xffffffff) #define pci_dma_lo32(a) (a & 0xffffffff)
#if (BITS_PER_LONG > 32) || (defined CONFIG_HIGHMEM64G && defined IPS_HIGHIO) #if (BITS_PER_LONG > 32) || (defined CONFIG_HIGHMEM64G && defined IPS_HIGHIO)
#define IPS_ENABLE_DMA64 (1) #define IPS_ENABLE_DMA64 (1)
#define pci_dma_hi32(a) (a >> 32)
#else #else
#define IPS_ENABLE_DMA64 (0) #define IPS_ENABLE_DMA64 (0)
#define pci_dma_hi32(a) (0)
#endif
#if defined(__ia64__)
#define IPS_ATOMIC_GFP (GFP_DMA | GFP_ATOMIC)
#define IPS_INIT_GFP GFP_DMA
#else
#define IPS_ATOMIC_GFP GFP_ATOMIC
#define IPS_INIT_GFP GFP_KERNEL
#endif #endif
/* /*
...@@ -451,9 +444,11 @@ ...@@ -451,9 +444,11 @@
* Scsi_Host Template * Scsi_Host Template
*/ */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
static int ips_proc24_info(char *, char **, off_t, int, int, int);
static void ips_select_queue_depth(struct Scsi_Host *, Scsi_Device *); static void ips_select_queue_depth(struct Scsi_Host *, Scsi_Device *);
static int ips_biosparam(Disk *disk, kdev_t dev, int geom[]); static int ips_biosparam(Disk *disk, kdev_t dev, int geom[]);
#else #else
int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev, static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int geom[]); sector_t capacity, int geom[]);
int ips_slave_configure(Scsi_Device *SDptr); int ips_slave_configure(Scsi_Device *SDptr);
...@@ -1106,7 +1101,8 @@ typedef struct ips_ha { ...@@ -1106,7 +1101,8 @@ typedef struct ips_ha {
uint16_t device_id; /* PCI device ID */ uint16_t device_id; /* PCI device ID */
uint8_t slot_num; /* PCI Slot Number */ uint8_t slot_num; /* PCI Slot Number */
uint16_t subdevice_id; /* Subsystem device ID */ uint16_t subdevice_id; /* Subsystem device ID */
uint8_t ioctl_order; /* Number of pages in ioctl */ int ioctl_len; /* size of ioctl buffer */
dma_addr_t ioctl_busaddr; /* dma address of ioctl buffer*/
uint8_t bios_version[8]; /* BIOS Revision */ uint8_t bios_version[8]; /* BIOS Revision */
uint32_t mem_addr; /* Memory mapped address */ uint32_t mem_addr; /* Memory mapped address */
uint32_t io_len; /* Size of IO Address */ uint32_t io_len; /* Size of IO Address */
...@@ -1116,8 +1112,10 @@ typedef struct ips_ha { ...@@ -1116,8 +1112,10 @@ typedef struct ips_ha {
ips_hw_func_t func; /* hw function pointers */ ips_hw_func_t func; /* hw function pointers */
struct pci_dev *pcidev; /* PCI device handle */ struct pci_dev *pcidev; /* PCI device handle */
char *flash_data; /* Save Area for flash data */ char *flash_data; /* Save Area for flash data */
u8 flash_order; /* Save Area for flash size order */ int flash_len; /* length of flash buffer */
u32 flash_datasize; /* Save Area for flash data size */ u32 flash_datasize; /* Save Area for flash data size */
dma_addr_t flash_busaddr; /* dma address of flash buffer*/
dma_addr_t enq_busaddr; /* dma address of enq struct */
uint8_t requires_esl; /* Requires an EraseStripeLock */ uint8_t requires_esl; /* Requires an EraseStripeLock */
} ips_ha_t; } ips_ha_t;
...@@ -1203,25 +1201,29 @@ typedef struct { ...@@ -1203,25 +1201,29 @@ typedef struct {
* *
*************************************************************************/ *************************************************************************/
#define IPS_VER_MAJOR 5 #define IPS_VER_MAJOR 6
#define IPS_VER_MAJOR_STRING "5" #define IPS_VER_MAJOR_STRING "6"
#define IPS_VER_MINOR 99 #define IPS_VER_MINOR 10
#define IPS_VER_MINOR_STRING "99" #define IPS_VER_MINOR_STRING "10"
#define IPS_VER_BUILD 00 #define IPS_VER_BUILD 90
#define IPS_VER_BUILD_STRING "00" #define IPS_VER_BUILD_STRING "90"
#define IPS_VER_STRING "5.99.00" #define IPS_VER_STRING "6.10.90"
#define IPS_BUILD_IDENT 1132 #define IPS_RELEASE_ID 0x00010000
#define IPS_BUILD_IDENT 364
#define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2003. All Rights Reserved."
#define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to present. All Rights Reserved."
#define IPS_NT_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2003."
/* Version numbers for various adapters */ /* Version numbers for various adapters */
#define IPS_VER_SERVERAID1 "2.25.01" #define IPS_VER_SERVERAID1 "2.25.01"
#define IPS_VER_SERVERAID2 "2.88.13" #define IPS_VER_SERVERAID2 "2.88.13"
#define IPS_VER_NAVAJO "2.88.13" #define IPS_VER_NAVAJO "2.88.13"
#define IPS_VER_SERVERAID3 "5.11.05" #define IPS_VER_SERVERAID3 "6.10.24"
#define IPS_VER_SERVERAID4H "5.11.05" #define IPS_VER_SERVERAID4H "6.10.24"
#define IPS_VER_SERVERAID4MLx "5.11.05" #define IPS_VER_SERVERAID4MLx "6.10.24"
#define IPS_VER_SARASOTA "5.11.05" #define IPS_VER_SARASOTA "6.10.24"
#define IPS_VER_MARCO "0.00.00" #define IPS_VER_MARCO "6.10.24"
#define IPS_VER_SEBRING "0.00.00" #define IPS_VER_SEBRING "6.10.24"
/* Compatability IDs for various adapters */ /* Compatability IDs for various adapters */
#define IPS_COMPAT_UNKNOWN "" #define IPS_COMPAT_UNKNOWN ""
...@@ -1230,17 +1232,17 @@ typedef struct { ...@@ -1230,17 +1232,17 @@ typedef struct {
#define IPS_COMPAT_SERVERAID2 "2.88.13" #define IPS_COMPAT_SERVERAID2 "2.88.13"
#define IPS_COMPAT_NAVAJO "2.88.13" #define IPS_COMPAT_NAVAJO "2.88.13"
#define IPS_COMPAT_KIOWA "2.88.13" #define IPS_COMPAT_KIOWA "2.88.13"
#define IPS_COMPAT_SERVERAID3H "SA510" #define IPS_COMPAT_SERVERAID3H "SB610"
#define IPS_COMPAT_SERVERAID3L "SA510" #define IPS_COMPAT_SERVERAID3L "SB610"
#define IPS_COMPAT_SERVERAID4H "SA510" #define IPS_COMPAT_SERVERAID4H "SB610"
#define IPS_COMPAT_SERVERAID4M "SA510" #define IPS_COMPAT_SERVERAID4M "SB610"
#define IPS_COMPAT_SERVERAID4L "SA510" #define IPS_COMPAT_SERVERAID4L "SB610"
#define IPS_COMPAT_SERVERAID4Mx "SA510" #define IPS_COMPAT_SERVERAID4Mx "SB610"
#define IPS_COMPAT_SERVERAID4Lx "SA510" #define IPS_COMPAT_SERVERAID4Lx "SB610"
#define IPS_COMPAT_SARASOTA "SA510" #define IPS_COMPAT_SARASOTA "SB610"
#define IPS_COMPAT_MARCO "SA000" #define IPS_COMPAT_MARCO "SB610"
#define IPS_COMPAT_SEBRING "SA000" #define IPS_COMPAT_SEBRING "SB610"
#define IPS_COMPAT_BIOS "SA510" #define IPS_COMPAT_BIOS "SB610"
#define IPS_COMPAT_MAX_ADAPTER_TYPE 16 #define IPS_COMPAT_MAX_ADAPTER_TYPE 16
#define IPS_COMPAT_ID_LENGTH 8 #define IPS_COMPAT_ID_LENGTH 8
......
...@@ -177,13 +177,8 @@ static void aha152x_detach(dev_link_t *link) ...@@ -177,13 +177,8 @@ static void aha152x_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
aha152x_release_cs(link); aha152x_release_cs(link);
if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK;
return;
}
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -302,9 +297,6 @@ static void aha152x_release_cs(dev_link_t *link) ...@@ -302,9 +297,6 @@ static void aha152x_release_cs(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
scsi_unregister(info->host); scsi_unregister(info->host);
if (link->state & DEV_STALE_LINK)
aha152x_detach(link);
} }
static int aha152x_event(event_t event, int priority, static int aha152x_event(event_t event, int priority,
......
...@@ -166,13 +166,8 @@ static void fdomain_detach(dev_link_t *link) ...@@ -166,13 +166,8 @@ static void fdomain_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
fdomain_release(link); fdomain_release(link);
if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK;
return;
}
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -283,9 +278,7 @@ static void fdomain_release(dev_link_t *link) ...@@ -283,9 +278,7 @@ static void fdomain_release(dev_link_t *link)
scsi_unregister(info->host); scsi_unregister(info->host);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_LINK) }
fdomain_detach(link);
} /* fdomain_release */
/*====================================================================*/ /*====================================================================*/
......
...@@ -1553,18 +1553,12 @@ static void nsp_cs_detach(dev_link_t *link) ...@@ -1553,18 +1553,12 @@ static void nsp_cs_detach(dev_link_t *link)
return; return;
} }
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
nsp_cs_release(link); nsp_cs_release(link);
if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK;
return;
}
}
/* Break the link with Card Services */ /* Break the link with Card Services */
if (link->handle) { if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
}
/* Unlink device structure, free bits */ /* Unlink device structure, free bits */
*linkp = link->next; *linkp = link->next;
...@@ -1792,17 +1786,6 @@ static void nsp_cs_release(dev_link_t *link) ...@@ -1792,17 +1786,6 @@ static void nsp_cs_release(dev_link_t *link)
DEBUG(0, "%s(0x%p)\n", __FUNCTION__, link); DEBUG(0, "%s(0x%p)\n", __FUNCTION__, link);
/*
* If the device is currently in use, we won't release until it
* is actually closed.
*/
if (link->open) {
DEBUG(1, "nsp_cs: release postponed, '%s' still open\n",
link->dev->dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
/* Unlink the device chain */ /* Unlink the device chain */
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,2)) #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,2))
scsi_unregister_module(MODULE_SCSI_HA, &nsp_driver_template); scsi_unregister_module(MODULE_SCSI_HA, &nsp_driver_template);
...@@ -1824,11 +1807,7 @@ static void nsp_cs_release(dev_link_t *link) ...@@ -1824,11 +1807,7 @@ static void nsp_cs_release(dev_link_t *link)
CardServices(ReleaseIRQ, link->handle, &link->irq); CardServices(ReleaseIRQ, link->handle, &link->irq);
} }
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
}
if (link->state & DEV_STALE_LINK) {
nsp_cs_detach(link);
}
} /* nsp_cs_release */
/*====================================================================== /*======================================================================
......
...@@ -165,13 +165,8 @@ static void qlogic_detach(dev_link_t * link) ...@@ -165,13 +165,8 @@ static void qlogic_detach(dev_link_t * link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
qlogic_release(link); qlogic_release(link);
if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK;
return;
}
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -296,9 +291,7 @@ static void qlogic_release(dev_link_t *link) ...@@ -296,9 +291,7 @@ static void qlogic_release(dev_link_t *link)
scsi_unregister(info->host); scsi_unregister(info->host);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_LINK) }
qlogic_detach(link);
} /* qlogic_release */
/*====================================================================*/ /*====================================================================*/
......
...@@ -76,6 +76,7 @@ int ppa_release(struct Scsi_Host *host) ...@@ -76,6 +76,7 @@ int ppa_release(struct Scsi_Host *host)
int host_no = host->unique_id; int host_no = host->unique_id;
printk("Releasing ppa%i\n", host_no); printk("Releasing ppa%i\n", host_no);
scsi_unregister(host);
parport_unregister_device(ppa_hosts[host_no].dev); parport_unregister_device(ppa_hosts[host_no].dev);
return 0; return 0;
} }
......
...@@ -16,9 +16,11 @@ ...@@ -16,9 +16,11 @@
* General Public License for more details. * General Public License for more details.
* *
******************************************************************************/ ******************************************************************************/
#define QLA1280_VERSION "3.23.34" #define QLA1280_VERSION "3.23.35"
/***************************************************************************** /*****************************************************************************
Revision History: Revision History:
Rev 3.23.35 August 14, 2003, Jes Sorensen
- Build against 2.6
Rev 3.23.34 July 23, 2003, Jes Sorensen Rev 3.23.34 July 23, 2003, Jes Sorensen
- Remove pointless TRUE/FALSE macros - Remove pointless TRUE/FALSE macros
- Clean up vchan handling - Clean up vchan handling
...@@ -296,14 +298,12 @@ ...@@ -296,14 +298,12 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/blk.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pci_ids.h> #include <linux/pci_ids.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
...@@ -312,7 +312,10 @@ ...@@ -312,7 +312,10 @@
#include <asm/system.h> #include <asm/system.h>
#if LINUX_VERSION_CODE < 0x020545 #if LINUX_VERSION_CODE < 0x020545
#include <linux/blk.h>
#include "sd.h" #include "sd.h"
#else
#include <scsi/scsi_host.h>
#endif #endif
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
...@@ -634,11 +637,14 @@ static int ql_debug_level = 1; ...@@ -634,11 +637,14 @@ static int ql_debug_level = 1;
*************************************************************************/ *************************************************************************/
#define PROC_BUF &qla1280_buffer[len] #define PROC_BUF &qla1280_buffer[len]
int #if LINUX_VERSION_CODE < 0x020600
qla1280_proc_info(char *buffer, char **start, off_t offset, int length, int qla1280_proc_info(char *buffer, char **start, off_t offset, int length,
int hostno, int inout) int hostno, int inout)
#else
int qla1280_proc_info(struct Scsi_Host *host, char *buffer, char **start,
off_t offset, int length, int inout)
#endif
{ {
struct Scsi_Host *host;
struct scsi_qla_host *ha; struct scsi_qla_host *ha;
int size = 0; int size = 0;
int len = 0; int len = 0;
...@@ -647,7 +653,10 @@ qla1280_proc_info(char *buffer, char **start, off_t offset, int length, ...@@ -647,7 +653,10 @@ qla1280_proc_info(char *buffer, char **start, off_t offset, int length,
struct scsi_lu *up; struct scsi_lu *up;
uint32_t b, t, l; uint32_t b, t, l;
#endif #endif
#if LINUX_VERSION_CODE >= 0x020600
ha = (struct scsi_qla_host *)host->hostdata;
#else
struct Scsi_Host *host;
/* Find the host that was specified */ /* Find the host that was specified */
for (ha = qla1280_hostlist; (ha != NULL) for (ha = qla1280_hostlist; (ha != NULL)
&& ha->host->host_no != hostno; ha = ha->next) ; && ha->host->host_no != hostno; ha = ha->next) ;
...@@ -664,6 +673,7 @@ qla1280_proc_info(char *buffer, char **start, off_t offset, int length, ...@@ -664,6 +673,7 @@ qla1280_proc_info(char *buffer, char **start, off_t offset, int length,
} }
host = ha->host; host = ha->host;
#endif
if (inout) if (inout)
return -ENOSYS; return -ENOSYS;
...@@ -1828,7 +1838,7 @@ qla1280_done(struct scsi_qla_host *ha, struct srb ** done_q_first, ...@@ -1828,7 +1838,7 @@ qla1280_done(struct scsi_qla_host *ha, struct srb ** done_q_first,
CMD_HANDLE(sp->cmd) = (unsigned char *)INVALID_HANDLE; CMD_HANDLE(sp->cmd) = (unsigned char *)INVALID_HANDLE;
ha->actthreads--; ha->actthreads--;
#if LINUX_KERNEL_VERSION < 0x020500 #if LINUX_VERSION_CODE < 0x020500
if (cmd->cmnd[0] == INQUIRY) if (cmd->cmnd[0] == INQUIRY)
qla1280_get_target_options(cmd, ha); qla1280_get_target_options(cmd, ha);
#endif #endif
...@@ -4497,7 +4507,7 @@ qla1280_rst_aen(struct scsi_qla_host *ha) ...@@ -4497,7 +4507,7 @@ qla1280_rst_aen(struct scsi_qla_host *ha)
} }
#if LINUX_KERNEL_VERSION < 0x020500 #if LINUX_VERSION_CODE < 0x020500
/* /*
* *
*/ */
......
...@@ -1111,7 +1111,11 @@ struct scsi_qla_host { ...@@ -1111,7 +1111,11 @@ struct scsi_qla_host {
/* /*
* Linux - SCSI Driver Interface Function Prototypes. * Linux - SCSI Driver Interface Function Prototypes.
*/ */
#if LINUX_VERSION_CODE < 0x020600
int qla1280_proc_info(char *, char **, off_t, int, int, int); int qla1280_proc_info(char *, char **, off_t, int, int, int);
#else
int qla1280_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
#endif
const char *qla1280_info(struct Scsi_Host *host); const char *qla1280_info(struct Scsi_Host *host);
int qla1280_detect(Scsi_Host_Template *); int qla1280_detect(Scsi_Host_Template *);
int qla1280_release(struct Scsi_Host *); int qla1280_release(struct Scsi_Host *);
...@@ -1147,8 +1151,6 @@ int qla1280_eh_adapter_reset(struct scsi_cmnd *cmd); ...@@ -1147,8 +1151,6 @@ int qla1280_eh_adapter_reset(struct scsi_cmnd *cmd);
.detect = qla1280_detect, \ .detect = qla1280_detect, \
.release = qla1280_release, \ .release = qla1280_release, \
.info = qla1280_info, \ .info = qla1280_info, \
.ioctl = NULL, \
.command = NULL, \
.queuecommand = qla1280_queuecommand, \ .queuecommand = qla1280_queuecommand, \
.eh_strategy_handler = NULL, \ .eh_strategy_handler = NULL, \
.eh_abort_handler = qla1280_eh_abort, \ .eh_abort_handler = qla1280_eh_abort, \
......
...@@ -1003,9 +1003,12 @@ static int __init init_scsi(void) ...@@ -1003,9 +1003,12 @@ static int __init init_scsi(void)
error = scsi_init_devinfo(); error = scsi_init_devinfo();
if (error) if (error)
goto cleanup_procfs; goto cleanup_procfs;
error = scsi_sysfs_register(); error = scsi_init_hosts();
if (error) if (error)
goto cleanup_devlist; goto cleanup_devlist;
error = scsi_sysfs_register();
if (error)
goto cleanup_hosts;
for (i = 0; i < NR_CPUS; i++) for (i = 0; i < NR_CPUS; i++)
INIT_LIST_HEAD(&done_q[i]); INIT_LIST_HEAD(&done_q[i]);
...@@ -1015,6 +1018,8 @@ static int __init init_scsi(void) ...@@ -1015,6 +1018,8 @@ static int __init init_scsi(void)
printk(KERN_NOTICE "SCSI subsystem initialized\n"); printk(KERN_NOTICE "SCSI subsystem initialized\n");
return 0; return 0;
cleanup_hosts:
scsi_exit_hosts();
cleanup_devlist: cleanup_devlist:
scsi_exit_devinfo(); scsi_exit_devinfo();
cleanup_procfs: cleanup_procfs:
...@@ -1029,6 +1034,7 @@ static int __init init_scsi(void) ...@@ -1029,6 +1034,7 @@ static int __init init_scsi(void)
static void __exit exit_scsi(void) static void __exit exit_scsi(void)
{ {
scsi_sysfs_unregister(); scsi_sysfs_unregister();
scsi_exit_hosts();
scsi_exit_devinfo(); scsi_exit_devinfo();
devfs_remove("scsi"); devfs_remove("scsi");
scsi_exit_procfs(); scsi_exit_procfs();
......
...@@ -1285,7 +1285,12 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) ...@@ -1285,7 +1285,12 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
maybe_retry: maybe_retry:
if ((++scmd->retries) < scmd->allowed) { /* we requeue for retry because the error was retryable, and
* the request was not marked fast fail. Note that above,
* even if the request is marked fast fail, we still requeue
* for queue congestion conditions (QUEUE_FULL or BUSY) */
if ((++scmd->retries) < scmd->allowed
&& !blk_noretry_request(scmd->request)) {
return NEEDS_RETRY; return NEEDS_RETRY;
} else { } else {
/* /*
......
...@@ -502,15 +502,23 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, ...@@ -502,15 +502,23 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
* to queue the remainder of them. * to queue the remainder of them.
*/ */
if (end_that_request_first(req, uptodate, sectors)) { if (end_that_request_first(req, uptodate, sectors)) {
if (requeue) { int leftover = req->hard_nr_sectors - sectors;
/* kill remainder if no retrys */
if (!uptodate && blk_noretry_request(req))
end_that_request_first(req, 0, leftover);
else {
if (requeue)
/* /*
* Bleah. Leftovers again. Stick the leftovers in * Bleah. Leftovers again. Stick the
* the front of the queue, and goose the queue again. * leftovers in the front of the
* queue, and goose the queue again.
*/ */
scsi_requeue_command(q, cmd); scsi_requeue_command(q, cmd);
}
return cmd; return cmd;
} }
}
add_disk_randomness(req->rq_disk); add_disk_randomness(req->rq_disk);
......
...@@ -41,6 +41,12 @@ ...@@ -41,6 +41,12 @@
#define SCSI_SENSE_VALID(scmd) \ #define SCSI_SENSE_VALID(scmd) \
(((scmd)->sense_buffer[0] & 0x70) == 0x70) (((scmd)->sense_buffer[0] & 0x70) == 0x70)
/*
* Special value for scanning to specify scanning or rescanning of all
* possible channels, (target) ids, or luns on a given shost.
*/
#define SCAN_WILD_CARD ~0
/* /*
* scsi_target: representation of a scsi target, for now, this is only * scsi_target: representation of a scsi target, for now, this is only
* used for single_lun devices. If no one has active IO to the target, * used for single_lun devices. If no one has active IO to the target,
...@@ -51,6 +57,9 @@ struct scsi_target { ...@@ -51,6 +57,9 @@ struct scsi_target {
unsigned int starget_refcnt; unsigned int starget_refcnt;
}; };
/* hosts.c */
extern int scsi_init_hosts(void);
extern void scsi_exit_hosts(void);
/* scsi.c */ /* scsi.c */
extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
...@@ -106,20 +115,18 @@ extern void scsi_exit_procfs(void); ...@@ -106,20 +115,18 @@ extern void scsi_exit_procfs(void);
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
/* scsi_scan.c */ /* scsi_scan.c */
int scsi_scan_host_selected(struct Scsi_Host *, unsigned int, unsigned int,
unsigned int, int);
extern void scsi_forget_host(struct Scsi_Host *); extern void scsi_forget_host(struct Scsi_Host *);
extern void scsi_free_sdev(struct scsi_device *); extern void scsi_free_sdev(struct scsi_device *);
extern void scsi_free_shost(struct Scsi_Host *);
extern void scsi_rescan_device(struct device *); extern void scsi_rescan_device(struct device *);
/* scsi_sysfs.c */ /* scsi_sysfs.c */
extern int scsi_device_register(struct scsi_device *); extern int scsi_device_register(struct scsi_device *);
extern void scsi_sysfs_init_host(struct Scsi_Host *); extern int scsi_sysfs_add_host(struct Scsi_Host *);
extern int scsi_sysfs_add_host(struct Scsi_Host *, struct device *);
extern void scsi_sysfs_remove_host(struct Scsi_Host *);
extern int scsi_sysfs_register(void); extern int scsi_sysfs_register(void);
extern void scsi_sysfs_unregister(void); extern void scsi_sysfs_unregister(void);
extern struct class shost_class;
extern struct class sdev_class; extern struct class sdev_class;
extern struct bus_type scsi_bus_type; extern struct bus_type scsi_bus_type;
......
...@@ -81,6 +81,9 @@ static int proc_scsi_write_proc(struct file *file, const char *buf, ...@@ -81,6 +81,9 @@ static int proc_scsi_write_proc(struct file *file, const char *buf,
void scsi_proc_hostdir_add(struct scsi_host_template *sht) void scsi_proc_hostdir_add(struct scsi_host_template *sht)
{ {
if (!sht->proc_info)
return;
down(&global_host_template_sem); down(&global_host_template_sem);
if (!sht->present++) { if (!sht->present++) {
sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi); sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi);
...@@ -96,6 +99,9 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht) ...@@ -96,6 +99,9 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
void scsi_proc_hostdir_rm(struct scsi_host_template *sht) void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
{ {
if (!sht->proc_info)
return;
down(&global_host_template_sem); down(&global_host_template_sem);
if (!--sht->present && sht->proc_dir) { if (!--sht->present && sht->proc_dir) {
remove_proc_entry(sht->proc_name, proc_scsi); remove_proc_entry(sht->proc_name, proc_scsi);
...@@ -189,21 +195,13 @@ static int proc_print_scsidevice(struct device *dev, void *data) ...@@ -189,21 +195,13 @@ static int proc_print_scsidevice(struct device *dev, void *data)
static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) static int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
{ {
struct Scsi_Host *shost; struct Scsi_Host *shost;
struct scsi_device *sdev;
int error = -ENXIO; int error = -ENXIO;
shost = scsi_host_lookup(host); shost = scsi_host_lookup(host);
if (IS_ERR(shost)) if (IS_ERR(shost))
return PTR_ERR(shost); return PTR_ERR(shost);
if (!scsi_find_device(shost, channel, id, lun)) { error = scsi_scan_host_selected(shost, channel, id, lun, 1);
sdev = scsi_add_device(shost, channel, id, lun);
if (IS_ERR(sdev))
error = PTR_ERR(sdev);
else
error = 0;
}
scsi_host_put(shost); scsi_host_put(shost);
return error; return error;
} }
......
...@@ -656,13 +656,32 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) ...@@ -656,13 +656,32 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
**/ **/
static int scsi_probe_and_add_lun(struct Scsi_Host *host, static int scsi_probe_and_add_lun(struct Scsi_Host *host,
uint channel, uint id, uint lun, int *bflagsp, uint channel, uint id, uint lun, int *bflagsp,
struct scsi_device **sdevp) struct scsi_device **sdevp, int rescan)
{ {
struct scsi_device *sdev; struct scsi_device *sdev;
struct scsi_request *sreq; struct scsi_request *sreq;
unsigned char *result; unsigned char *result;
int bflags, res = SCSI_SCAN_NO_RESPONSE; int bflags, res = SCSI_SCAN_NO_RESPONSE;
/*
* The rescan flag is used as an optimization, the first scan of a
* host adapter calls into here with rescan == 0.
*/
if (rescan) {
sdev = scsi_find_device(host, channel, id, lun);
if (sdev) {
SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
"scsi scan: device exists on <%d:%d:%d:%d>\n",
host->host_no, channel, id, lun));
if (sdevp)
*sdevp = sdev;
if (bflagsp)
*bflagsp = scsi_get_device_flags(sdev->vendor,
sdev->model);
return SCSI_SCAN_LUN_PRESENT;
}
}
sdev = scsi_alloc_sdev(host, channel, id, lun); sdev = scsi_alloc_sdev(host, channel, id, lun);
if (!sdev) if (!sdev)
goto out; goto out;
...@@ -737,7 +756,7 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host, ...@@ -737,7 +756,7 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host,
* Modifies sdevscan->lun. * Modifies sdevscan->lun.
**/ **/
static void scsi_sequential_lun_scan(struct Scsi_Host *shost, uint channel, static void scsi_sequential_lun_scan(struct Scsi_Host *shost, uint channel,
uint id, int bflags, int lun0_res, int scsi_level) uint id, int bflags, int lun0_res, int scsi_level, int rescan)
{ {
unsigned int sparse_lun, lun, max_dev_lun; unsigned int sparse_lun, lun, max_dev_lun;
...@@ -806,7 +825,8 @@ static void scsi_sequential_lun_scan(struct Scsi_Host *shost, uint channel, ...@@ -806,7 +825,8 @@ static void scsi_sequential_lun_scan(struct Scsi_Host *shost, uint channel,
*/ */
for (lun = 1; lun < max_dev_lun; ++lun) for (lun = 1; lun < max_dev_lun; ++lun)
if ((scsi_probe_and_add_lun(shost, channel, id, lun, if ((scsi_probe_and_add_lun(shost, channel, id, lun,
NULL, NULL) != SCSI_SCAN_LUN_PRESENT) && !sparse_lun) NULL, NULL, rescan) != SCSI_SCAN_LUN_PRESENT) &&
!sparse_lun)
return; return;
} }
...@@ -857,7 +877,8 @@ static int scsilun_to_int(struct scsi_lun *scsilun) ...@@ -857,7 +877,8 @@ static int scsilun_to_int(struct scsi_lun *scsilun)
* 0: scan completed (or no memory, so further scanning is futile) * 0: scan completed (or no memory, so further scanning is futile)
* 1: no report lun scan, or not configured * 1: no report lun scan, or not configured
**/ **/
static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags) static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
int rescan)
{ {
char devname[64]; char devname[64];
unsigned char scsi_cmd[MAX_COMMAND_SIZE]; unsigned char scsi_cmd[MAX_COMMAND_SIZE];
...@@ -1011,7 +1032,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags) ...@@ -1011,7 +1032,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags)
int res; int res;
res = scsi_probe_and_add_lun(sdev->host, sdev->channel, res = scsi_probe_and_add_lun(sdev->host, sdev->channel,
sdev->id, lun, NULL, NULL); sdev->id, lun, NULL, NULL, rescan);
if (res == SCSI_SCAN_NO_RESPONSE) { if (res == SCSI_SCAN_NO_RESPONSE) {
/* /*
* Got some results, but now none, abort. * Got some results, but now none, abort.
...@@ -1037,7 +1058,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags) ...@@ -1037,7 +1058,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags)
return 0; return 0;
} }
#else #else
# define scsi_report_lun_scan(sdev, blags) (1) # define scsi_report_lun_scan(sdev, blags, rescan) (1)
#endif /* CONFIG_SCSI_REPORT_LUNS */ #endif /* CONFIG_SCSI_REPORT_LUNS */
struct scsi_device *scsi_add_device(struct Scsi_Host *shost, struct scsi_device *scsi_add_device(struct Scsi_Host *shost,
...@@ -1046,7 +1067,7 @@ struct scsi_device *scsi_add_device(struct Scsi_Host *shost, ...@@ -1046,7 +1067,7 @@ struct scsi_device *scsi_add_device(struct Scsi_Host *shost,
struct scsi_device *sdev; struct scsi_device *sdev;
int res; int res;
res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, &sdev); res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, &sdev, 1);
if (res != SCSI_SCAN_LUN_PRESENT) if (res != SCSI_SCAN_LUN_PRESENT)
sdev = ERR_PTR(-ENODEV); sdev = ERR_PTR(-ENODEV);
return sdev; return sdev;
...@@ -1083,7 +1104,7 @@ void scsi_rescan_device(struct device *dev) ...@@ -1083,7 +1104,7 @@ void scsi_rescan_device(struct device *dev)
* sequential scan of LUNs on the target id. * sequential scan of LUNs on the target id.
**/ **/
static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel, static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel,
unsigned int id) unsigned int id, unsigned int lun, int rescan)
{ {
int bflags = 0; int bflags = 0;
int res; int res;
...@@ -1095,19 +1116,29 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel, ...@@ -1095,19 +1116,29 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel,
*/ */
return; return;
if (lun != SCAN_WILD_CARD) {
/*
* Scan for a specific host/chan/id/lun.
*/
scsi_probe_and_add_lun(shost, channel, id, lun, NULL, NULL,
rescan);
return;
}
/* /*
* Scan LUN 0, if there is some response, scan further. Ideally, we * Scan LUN 0, if there is some response, scan further. Ideally, we
* would not configure LUN 0 until all LUNs are scanned. * would not configure LUN 0 until all LUNs are scanned.
*/ */
res = scsi_probe_and_add_lun(shost, channel, id, 0, &bflags, &sdev); res = scsi_probe_and_add_lun(shost, channel, id, 0, &bflags, &sdev,
rescan);
if (res == SCSI_SCAN_LUN_PRESENT) { if (res == SCSI_SCAN_LUN_PRESENT) {
if (scsi_report_lun_scan(sdev, bflags) != 0) if (scsi_report_lun_scan(sdev, bflags, rescan) != 0)
/* /*
* The REPORT LUN did not scan the target, * The REPORT LUN did not scan the target,
* do a sequential scan. * do a sequential scan.
*/ */
scsi_sequential_lun_scan(shost, channel, id, bflags, scsi_sequential_lun_scan(shost, channel, id, bflags,
res, sdev->scsi_level); res, sdev->scsi_level, rescan);
} else if (res == SCSI_SCAN_TARGET_PRESENT) { } else if (res == SCSI_SCAN_TARGET_PRESENT) {
/* /*
* There's a target here, but lun 0 is offline so we * There's a target here, but lun 0 is offline so we
...@@ -1116,27 +1147,17 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel, ...@@ -1116,27 +1147,17 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel,
* a default scsi level of SCSI_2 * a default scsi level of SCSI_2
*/ */
scsi_sequential_lun_scan(shost, channel, id, BLIST_SPARSELUN, scsi_sequential_lun_scan(shost, channel, id, BLIST_SPARSELUN,
SCSI_SCAN_TARGET_PRESENT, SCSI_2); SCSI_SCAN_TARGET_PRESENT, SCSI_2, rescan);
} }
} }
/** static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
* scsi_scan_host - scan the given adapter unsigned int id, unsigned int lun, int rescan)
* @shost: adapter to scan
*
* Description:
* Iterate and call scsi_scan_target to scan all possible target id's
* on all possible channels.
**/
void scsi_scan_host(struct Scsi_Host *shost)
{ {
uint channel, id, order_id; uint order_id;
/* if (id == SCAN_WILD_CARD)
* The sdevscan host, channel, id and lun are filled in as for (id = 0; id < shost->max_id; ++id) {
* needed to scan.
*/
for (channel = 0; channel <= shost->max_channel; channel++) {
/* /*
* XXX adapter drivers when possible (FCP, iSCSI) * XXX adapter drivers when possible (FCP, iSCSI)
* could modify max_id to match the current max, * could modify max_id to match the current max,
...@@ -1146,7 +1167,6 @@ void scsi_scan_host(struct Scsi_Host *shost) ...@@ -1146,7 +1167,6 @@ void scsi_scan_host(struct Scsi_Host *shost)
* the FC ID can be the same as a target id * the FC ID can be the same as a target id
* without a huge overhead of sparse id's. * without a huge overhead of sparse id's.
*/ */
for (id = 0; id < shost->max_id; ++id) {
if (shost->reverse_ordering) if (shost->reverse_ordering)
/* /*
* Scan from high to low id. * Scan from high to low id.
...@@ -1154,9 +1174,39 @@ void scsi_scan_host(struct Scsi_Host *shost) ...@@ -1154,9 +1174,39 @@ void scsi_scan_host(struct Scsi_Host *shost)
order_id = shost->max_id - id - 1; order_id = shost->max_id - id - 1;
else else
order_id = id; order_id = id;
scsi_scan_target(shost, channel, order_id); scsi_scan_target(shost, channel, order_id, lun, rescan);
}
} }
else
scsi_scan_target(shost, channel, id, lun, rescan);
}
int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
unsigned int id, unsigned int lun, int rescan)
{
SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "%s: <%u:%u:%u:%u>\n",
__FUNCTION__, shost->host_no, channel, id, lun));
if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
((id != SCAN_WILD_CARD) && (id > shost->max_id)) ||
((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
return -EINVAL;
if (channel == SCAN_WILD_CARD)
for (channel = 0; channel <= shost->max_channel; channel++)
scsi_scan_channel(shost, channel, id, lun, rescan);
else
scsi_scan_channel(shost, channel, id, lun, rescan);
return 0;
}
/**
* scsi_scan_host - scan the given adapter
* @shost: adapter to scan
**/
void scsi_scan_host(struct Scsi_Host *shost)
{
scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD,
SCAN_WILD_CARD, 0);
} }
void scsi_forget_host(struct Scsi_Host *shost) void scsi_forget_host(struct Scsi_Host *shost)
......
...@@ -15,6 +15,43 @@ ...@@ -15,6 +15,43 @@
#include "hosts.h" #include "hosts.h"
#include "scsi_priv.h" #include "scsi_priv.h"
#include "scsi_logging.h"
static int check_set(unsigned int *val, char *src)
{
char *last;
if (strncmp(src, "-", 20) == 0) {
*val = SCAN_WILD_CARD;
} else {
/*
* Doesn't check for int overflow
*/
*val = simple_strtoul(src, &last, 0);
if (*last != '\0')
return 1;
}
return 0;
}
static int scsi_scan(struct Scsi_Host *shost, const char *str)
{
char s1[15], s2[15], s3[15], junk;
unsigned int channel, id, lun;
int res;
res = sscanf(str, "%10s %10s %10s %c", s1, s2, s3, &junk);
if (res != 3)
return -EINVAL;
if (check_set(&channel, s1))
return -EINVAL;
if (check_set(&id, s2))
return -EINVAL;
if (check_set(&lun, s3))
return -EINVAL;
res = scsi_scan_host_selected(shost, channel, id, lun, 1);
return res;
}
/* /*
* shost_show_function: macro to create an attr function that can be used to * shost_show_function: macro to create an attr function that can be used to
...@@ -39,6 +76,20 @@ static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL) ...@@ -39,6 +76,20 @@ static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL)
/* /*
* Create the actual show/store functions and data structures. * Create the actual show/store functions and data structures.
*/ */
static ssize_t store_scan(struct class_device *class_dev, const char *buf,
size_t count)
{
struct Scsi_Host *shost = class_to_shost(class_dev);
int res;
res = scsi_scan(shost, buf);
if (res == 0)
res = count;
return res;
};
static CLASS_DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
shost_rd_attr(unique_id, "%u\n"); shost_rd_attr(unique_id, "%u\n");
shost_rd_attr(host_busy, "%hu\n"); shost_rd_attr(host_busy, "%hu\n");
shost_rd_attr(cmd_per_lun, "%hd\n"); shost_rd_attr(cmd_per_lun, "%hd\n");
...@@ -51,33 +102,10 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = { ...@@ -51,33 +102,10 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
&class_device_attr_cmd_per_lun, &class_device_attr_cmd_per_lun,
&class_device_attr_sg_tablesize, &class_device_attr_sg_tablesize,
&class_device_attr_unchecked_isa_dma, &class_device_attr_unchecked_isa_dma,
&class_device_attr_scan,
NULL NULL
}; };
static void scsi_host_cls_release(struct class_device *class_dev)
{
struct Scsi_Host *shost;
shost = class_to_shost(class_dev);
put_device(&shost->shost_gendev);
}
static void scsi_host_dev_release(struct device *dev)
{
struct Scsi_Host *shost;
struct device *parent;
parent = dev->parent;
shost = dev_to_shost(dev);
scsi_free_shost(shost);
put_device(parent);
}
struct class shost_class = {
.name = "scsi_host",
.release = scsi_host_cls_release,
};
static void scsi_device_cls_release(struct class_device *class_dev) static void scsi_device_cls_release(struct class_device *class_dev)
{ {
struct scsi_device *sdev; struct scsi_device *sdev;
...@@ -113,33 +141,23 @@ struct bus_type scsi_bus_type = { ...@@ -113,33 +141,23 @@ struct bus_type scsi_bus_type = {
.match = scsi_bus_match, .match = scsi_bus_match,
}; };
int scsi_sysfs_register(void) int scsi_sysfs_register(void)
{ {
int error; int error;
error = bus_register(&scsi_bus_type); error = bus_register(&scsi_bus_type);
if (error) if (!error) {
return error;
error = class_register(&shost_class);
if (error)
goto bus_unregister;
error = class_register(&sdev_class); error = class_register(&sdev_class);
if (error) if (error)
goto class_unregister;
return 0;
class_unregister:
class_unregister(&shost_class);
bus_unregister:
bus_unregister(&scsi_bus_type); bus_unregister(&scsi_bus_type);
}
return error; return error;
} }
void scsi_sysfs_unregister(void) void scsi_sysfs_unregister(void)
{ {
class_unregister(&sdev_class); class_unregister(&sdev_class);
class_unregister(&shost_class);
bus_unregister(&scsi_bus_type); bus_unregister(&scsi_bus_type);
} }
...@@ -243,6 +261,24 @@ store_rescan_field (struct device *dev, const char *buf, size_t count) ...@@ -243,6 +261,24 @@ store_rescan_field (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field) static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field)
static ssize_t sdev_store_delete(struct device *dev, const char *buf,
size_t count)
{
struct scsi_device *sdev = to_scsi_device(dev);
int res = count;
if (sdev->access_count)
/*
* FIXME and scsi_proc.c: racey use of access_count,
* possibly add a new arg to scsi_remove_device.
*/
res = -EBUSY;
else
scsi_remove_device(sdev);
return res;
};
static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
/* Default template for device attributes. May NOT be modified */ /* Default template for device attributes. May NOT be modified */
static struct device_attribute *scsi_sysfs_sdev_attrs[] = { static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
&dev_attr_device_blocked, &dev_attr_device_blocked,
...@@ -255,6 +291,7 @@ static struct device_attribute *scsi_sysfs_sdev_attrs[] = { ...@@ -255,6 +291,7 @@ static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
&dev_attr_rev, &dev_attr_rev,
&dev_attr_online, &dev_attr_online,
&dev_attr_rescan, &dev_attr_rescan,
&dev_attr_delete,
NULL NULL
}; };
...@@ -403,20 +440,6 @@ int scsi_register_interface(struct class_interface *intf) ...@@ -403,20 +440,6 @@ int scsi_register_interface(struct class_interface *intf)
} }
void scsi_sysfs_init_host(struct Scsi_Host *shost)
{
device_initialize(&shost->shost_gendev);
snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
shost->host_no);
shost->shost_gendev.release = scsi_host_dev_release;
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( static struct class_device_attribute *class_attr_overridden(
struct class_device_attribute **attrs, struct class_device_attribute **attrs,
struct class_device_attribute *attr) struct class_device_attribute *attr)
...@@ -459,31 +482,16 @@ static int class_attr_add(struct class_device *classdev, ...@@ -459,31 +482,16 @@ static int class_attr_add(struct class_device *classdev,
* @shost: scsi host struct to add to subsystem * @shost: scsi host struct to add to subsystem
* @dev: parent struct device pointer * @dev: parent struct device pointer
**/ **/
int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev) int scsi_sysfs_add_host(struct Scsi_Host *shost)
{ {
int error, i; int error, i;
if (!shost->shost_gendev.parent)
shost->shost_gendev.parent = dev ? dev : &legacy_bus;
error = device_add(&shost->shost_gendev);
if (error)
return error;
set_bit(SHOST_ADD, &shost->shost_state);
get_device(shost->shost_gendev.parent);
error = class_device_add(&shost->shost_classdev);
if (error)
goto clean_device;
get_device(&shost->shost_gendev);
if (shost->hostt->shost_attrs) { if (shost->hostt->shost_attrs) {
for (i = 0; shost->hostt->shost_attrs[i]; i++) { for (i = 0; shost->hostt->shost_attrs[i]; i++) {
error = class_attr_add(&shost->shost_classdev, error = class_attr_add(&shost->shost_classdev,
shost->hostt->shost_attrs[i]); shost->hostt->shost_attrs[i]);
if (error) if (error)
goto clean_class; return error;
} }
} }
...@@ -493,31 +501,9 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev) ...@@ -493,31 +501,9 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev)
error = class_device_create_file(&shost->shost_classdev, error = class_device_create_file(&shost->shost_classdev,
scsi_sysfs_shost_attrs[i]); scsi_sysfs_shost_attrs[i]);
if (error) if (error)
goto clean_class; return error;
} }
} }
return error; return 0;
clean_class:
class_device_del(&shost->shost_classdev);
clean_device:
device_del(&shost->shost_gendev);
return error;
}
/**
* scsi_sysfs_remove_host - remove scsi host from subsystem
* @shost: scsi host to remove from subsystem
**/
void scsi_sysfs_remove_host(struct Scsi_Host *shost)
{
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
set_bit(SHOST_DEL, &shost->shost_state);
spin_unlock_irqrestore(shost->host_lock, flags);
class_device_unregister(&shost->shost_classdev);
device_del(&shost->shost_gendev);
} }
...@@ -308,6 +308,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) ...@@ -308,6 +308,8 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
SCpnt->cmnd[4] = (unsigned char) this_count; SCpnt->cmnd[4] = (unsigned char) this_count;
SCpnt->cmnd[5] = 0; SCpnt->cmnd[5] = 0;
} }
SCpnt->request_bufflen = SCpnt->bufflen =
this_count * sdp->sector_size;
/* /*
* We shouldn't disconnect in the middle of a sector, so with a dumb * We shouldn't disconnect in the middle of a sector, so with a dumb
...@@ -1353,10 +1355,14 @@ static int sd_remove(struct device *dev) ...@@ -1353,10 +1355,14 @@ static int sd_remove(struct device *dev)
static void sd_shutdown(struct device *dev) static void sd_shutdown(struct device *dev)
{ {
struct scsi_device *sdp = to_scsi_device(dev); struct scsi_device *sdp = to_scsi_device(dev);
struct scsi_disk *sdkp = dev_get_drvdata(dev); struct scsi_disk *sdkp;
struct scsi_request *sreq; struct scsi_request *sreq;
int retries, res; int retries, res;
sdkp = dev_get_drvdata(dev);
if (!sdkp)
return; /* this can happen */
if (!sdp->online || !sdkp->WCE) if (!sdp->online || !sdkp->WCE)
return; return;
......
...@@ -340,6 +340,20 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) ...@@ -340,6 +340,20 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
return 0; return 0;
} }
{
struct scatterlist *sg = SCpnt->request_buffer;
int i, size = 0;
for (i = 0; i < SCpnt->use_sg; i++)
size += sg[i].length;
if (size != SCpnt->request_bufflen && SCpnt->use_sg) {
printk(KERN_ERR "sr: mismatch count %d, bytes %d\n",
size, SCpnt->request_bufflen);
if (SCpnt->request_bufflen > size)
SCpnt->request_bufflen = SCpnt->bufflen = size;
}
}
/* /*
* request doesn't start on hw block boundary, add scatter pads * request doesn't start on hw block boundary, add scatter pads
*/ */
...@@ -361,8 +375,11 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) ...@@ -361,8 +375,11 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
SCpnt->cmnd[1] = 0; SCpnt->cmnd[1] = 0;
block = (unsigned int)SCpnt->request->sector / (s_size >> 9); block = (unsigned int)SCpnt->request->sector / (s_size >> 9);
if (this_count > 0xffff) if (this_count > 0xffff) {
this_count = 0xffff; this_count = 0xffff;
SCpnt->request_bufflen = SCpnt->bufflen =
this_count * s_size;
}
SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
...@@ -390,18 +407,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) ...@@ -390,18 +407,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
*/ */
SCpnt->done = rw_intr; SCpnt->done = rw_intr;
{
struct scatterlist *sg = SCpnt->request_buffer;
int i, size = 0;
for (i = 0; i < SCpnt->use_sg; i++)
size += sg[i].length;
if (size != SCpnt->request_bufflen && SCpnt->use_sg) {
printk("sr: mismatch count %d, bytes %d\n", size, SCpnt->request_bufflen);
SCpnt->request_bufflen = size;
}
}
/* /*
* This indicates that the command is ready from our end to be * This indicates that the command is ready from our end to be
* queued. * queued.
......
...@@ -2029,7 +2029,7 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev) ...@@ -2029,7 +2029,7 @@ sym_attach (struct scsi_host_template *tpnt, int unit, sym_device *dev)
printf_info("%s: giving up ...\n", sym_name(np)); printf_info("%s: giving up ...\n", sym_name(np));
if (np) if (np)
sym_free_resources(np); sym_free_resources(np);
scsi_unregister(instance); scsi_host_put(instance);
return -1; return -1;
} }
......
...@@ -5942,14 +5942,7 @@ int sym_hcb_attach(hcb_p np, struct sym_fw *fw) ...@@ -5942,14 +5942,7 @@ int sym_hcb_attach(hcb_p np, struct sym_fw *fw)
*/ */
return 0; return 0;
/*
* We have failed.
* We will try to free all the resources we have
* allocated, but if we are a boot device, this
* will not help that much.;)
*/
attach_failed: attach_failed:
sym_hcb_free(np);
return -ENXIO; return -ENXIO;
} }
......
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