Commit 2983e9a6 authored by James Bottomley's avatar James Bottomley

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

into mulgrave.(none):/home/jejb/BK/scsi-for-linus-2.5
parents 37256d28 d67cf443
...@@ -1037,6 +1037,16 @@ void blk_stop_queue(request_queue_t *q) ...@@ -1037,6 +1037,16 @@ void blk_stop_queue(request_queue_t *q)
spin_unlock_irqrestore(q->queue_lock, flags); spin_unlock_irqrestore(q->queue_lock, flags);
} }
/**
* blk_run_queue - run a single device queue
* @q The queue to run
*/
void __blk_run_queue(request_queue_t *q)
{
blk_remove_plug(q);
q->request_fn(q);
}
/** /**
* blk_run_queues - fire all plugged queues * blk_run_queues - fire all plugged queues
* *
...@@ -2198,4 +2208,5 @@ EXPORT_SYMBOL(blk_queue_invalidate_tags); ...@@ -2198,4 +2208,5 @@ EXPORT_SYMBOL(blk_queue_invalidate_tags);
EXPORT_SYMBOL(blk_start_queue); EXPORT_SYMBOL(blk_start_queue);
EXPORT_SYMBOL(blk_stop_queue); EXPORT_SYMBOL(blk_stop_queue);
EXPORT_SYMBOL(__blk_stop_queue); EXPORT_SYMBOL(__blk_stop_queue);
EXPORT_SYMBOL(__blk_run_queue);
EXPORT_SYMBOL(blk_run_queues); EXPORT_SYMBOL(blk_run_queues);
...@@ -669,6 +669,67 @@ void __init scsi_host_init(void) ...@@ -669,6 +669,67 @@ 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. For the moment, we include it at the head of
* the host_queue itself - I don't think we want to show this
* to the HA in select_queue_depths(), as this would probably confuse
* matters.
*
* 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) void scsi_host_busy_inc(struct Scsi_Host *shost, Scsi_Device *sdev)
{ {
unsigned long flags; unsigned long flags;
......
...@@ -500,15 +500,6 @@ extern Scsi_Device * scsi_get_host_dev(struct Scsi_Host *); ...@@ -500,15 +500,6 @@ extern Scsi_Device * scsi_get_host_dev(struct Scsi_Host *);
extern void scsi_unblock_requests(struct Scsi_Host *); extern void scsi_unblock_requests(struct Scsi_Host *);
extern void scsi_block_requests(struct Scsi_Host *); extern void scsi_block_requests(struct Scsi_Host *);
extern void scsi_report_bus_reset(struct Scsi_Host *, int); extern void scsi_report_bus_reset(struct Scsi_Host *, int);
typedef struct SHN
{
struct list_head shn_list;
char *name;
unsigned short host_no;
unsigned short host_registered;
} Scsi_Host_Name;
extern void scsi_register_blocked_host(struct Scsi_Host *); extern void scsi_register_blocked_host(struct Scsi_Host *);
extern void scsi_deregister_blocked_host(struct Scsi_Host *); extern void scsi_deregister_blocked_host(struct Scsi_Host *);
......
...@@ -155,7 +155,6 @@ const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = ...@@ -155,7 +155,6 @@ const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
"Enclosure ", "Enclosure ",
}; };
static char * scsi_null_device_strs = "nullnullnullnull";
static const char * const spaces = " "; /* 16 of them */ static const char * const spaces = " "; /* 16 of them */
static unsigned scsi_default_dev_flags; static unsigned scsi_default_dev_flags;
...@@ -2225,6 +2224,8 @@ static int __init init_scsi(void) ...@@ -2225,6 +2224,8 @@ static int __init init_scsi(void)
printk(KERN_ERR "SCSI: can't init sg mempool %s\n", sgp->name); printk(KERN_ERR "SCSI: can't init sg mempool %s\n", sgp->name);
} }
scsi_init_procfs();
scsi_devfs_handle = devfs_mk_dir(NULL, "scsi", NULL);
scsi_host_init(); scsi_host_init();
scsi_dev_info_list_init(scsi_dev_flags); scsi_dev_info_list_init(scsi_dev_flags);
bus_register(&scsi_driverfs_bus_type); bus_register(&scsi_driverfs_bus_type);
...@@ -2236,9 +2237,10 @@ static void __exit exit_scsi(void) ...@@ -2236,9 +2237,10 @@ static void __exit exit_scsi(void)
{ {
int i; int i;
bus_unregister(&scsi_driverfs_bus_type);
scsi_dev_info_list_delete();
devfs_unregister(scsi_devfs_handle); devfs_unregister(scsi_devfs_handle);
scsi_exit_procfs(); scsi_exit_procfs();
scsi_dev_info_list_delete();
for (i = 0; i < SG_MEMPOOL_NR; i++) { for (i = 0; i < SG_MEMPOOL_NR; i++) {
struct scsi_host_sg_pool *sgp = scsi_sg_pools + i; struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
...@@ -2251,95 +2253,3 @@ static void __exit exit_scsi(void) ...@@ -2251,95 +2253,3 @@ static void __exit exit_scsi(void)
module_init(init_scsi); module_init(init_scsi);
module_exit(exit_scsi); module_exit(exit_scsi);
/*
* 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:
*/
Scsi_Device * scsi_get_host_dev(struct Scsi_Host * SHpnt)
{
Scsi_Device * SDpnt;
/*
* 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. For the moment, we include it at the head of
* the host_queue itself - I don't think we want to show this
* to the HA in select_queue_depths(), as this would probably confuse
* matters.
* 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
*/
SDpnt = (Scsi_Device *) kmalloc(sizeof(Scsi_Device),
GFP_ATOMIC);
if(SDpnt == NULL)
return NULL;
memset(SDpnt, 0, sizeof(Scsi_Device));
SDpnt->vendor = scsi_null_device_strs;
SDpnt->model = scsi_null_device_strs;
SDpnt->rev = scsi_null_device_strs;
SDpnt->host = SHpnt;
SDpnt->id = SHpnt->this_id;
SDpnt->type = -1;
SDpnt->new_queue_depth = 1;
scsi_build_commandblocks(SDpnt);
if(SDpnt->current_queue_depth == 0) {
kfree(SDpnt);
return NULL;
}
scsi_initialize_queue(SDpnt, SHpnt);
SDpnt->online = TRUE;
/*
* Initialize the object that we will use to wait for command blocks.
*/
init_waitqueue_head(&SDpnt->scpnt_wait);
return SDpnt;
}
/*
* Function: scsi_free_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: Nothing
*
* Notes:
*/
void scsi_free_host_dev(Scsi_Device * SDpnt)
{
if( (unsigned char) SDpnt->id != (unsigned char) SDpnt->host->this_id )
{
panic("Attempt to delete wrong device\n");
}
blk_cleanup_queue(&SDpnt->request_queue);
/*
* We only have a single SCpnt attached to this device. Free
* it now.
*/
scsi_release_commandblocks(SDpnt);
if (SDpnt->inquiry)
kfree(SDpnt->inquiry);
kfree(SDpnt);
}
...@@ -519,6 +519,13 @@ static inline void scsi_proc_host_add(struct Scsi_Host *); ...@@ -519,6 +519,13 @@ static inline void scsi_proc_host_add(struct Scsi_Host *);
static inline void scsi_proc_host_rm(struct Scsi_Host *); static inline void scsi_proc_host_rm(struct Scsi_Host *);
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
/*
* 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 *);
/* /*
* Prototypes for functions in constants.c * Prototypes for functions in constants.c
* Some of these used to live in constants.h * Some of these used to live in constants.h
......
This diff is collapsed.
...@@ -43,6 +43,7 @@ static Scsi_Host_Template sdebug_driver_template = { ...@@ -43,6 +43,7 @@ static Scsi_Host_Template sdebug_driver_template = {
.max_sectors = 4096, .max_sectors = 4096,
.unchecked_isa_dma = 0, .unchecked_isa_dma = 0,
.use_clustering = ENABLE_CLUSTERING, .use_clustering = ENABLE_CLUSTERING,
.module = THIS_MODULE,
}; };
#endif #endif
...@@ -1479,8 +1479,6 @@ static void scsi_restart_operations(struct Scsi_Host *shost) ...@@ -1479,8 +1479,6 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
*/ */
spin_lock_irqsave(shost->host_lock, flags); spin_lock_irqsave(shost->host_lock, flags);
for (sdev = shost->host_queue; sdev; sdev = sdev->next) { for (sdev = shost->host_queue; sdev; sdev = sdev->next) {
request_queue_t *q = &sdev->request_queue;
if ((shost->can_queue > 0 && if ((shost->can_queue > 0 &&
(shost->host_busy >= shost->can_queue)) (shost->host_busy >= shost->can_queue))
|| (shost->host_blocked) || (shost->host_blocked)
...@@ -1488,7 +1486,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost) ...@@ -1488,7 +1486,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
break; break;
} }
q->request_fn(q); __blk_run_queue(&sdev->request_queue);
} }
spin_unlock_irqrestore(shost->host_lock, flags); spin_unlock_irqrestore(shost->host_lock, flags);
} }
......
...@@ -7,49 +7,18 @@ ...@@ -7,49 +7,18 @@
* of people at Linux Expo. * of people at Linux Expo.
*/ */
/*
* The fundamental purpose of this file is to contain a library of utility
* routines that can be used by low-level drivers. Ultimately the idea
* is that there should be a sufficiently rich number of functions that it
* would be possible for a driver author to fashion a queueing function for
* a low-level driver if they wished. Note however that this file also
* contains the "default" versions of these functions, as we don't want to
* go through and retrofit queueing functions into all 30 some-odd drivers.
*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/ioport.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/stat.h>
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/completion.h> #include <linux/completion.h>
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/dma.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
#include <scsi/scsi_ioctl.h> #include <scsi/scsi_ioctl.h>
/*
* This entire source file deals with the new queueing code.
*/
/* /*
* Function: scsi_insert_special_cmd() * Function: scsi_insert_special_cmd()
* *
...@@ -259,7 +228,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt) ...@@ -259,7 +228,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
/* /*
* Just hit the requeue function for the queue. * Just hit the requeue function for the queue.
*/ */
q->request_fn(q); __blk_run_queue(q);
SDpnt = (Scsi_Device *) q->queuedata; SDpnt = (Scsi_Device *) q->queuedata;
SHpnt = SDpnt->host; SHpnt = SDpnt->host;
...@@ -272,8 +241,6 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt) ...@@ -272,8 +241,6 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
* use function pointers to pick the right one. * use function pointers to pick the right one.
*/ */
if (SDpnt->single_lun && blk_queue_empty(q) && SDpnt->device_busy ==0) { if (SDpnt->single_lun && blk_queue_empty(q) && SDpnt->device_busy ==0) {
request_queue_t *q;
for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
if (((SHpnt->can_queue > 0) if (((SHpnt->can_queue > 0)
&& (SHpnt->host_busy >= SHpnt->can_queue)) && (SHpnt->host_busy >= SHpnt->can_queue))
...@@ -283,8 +250,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt) ...@@ -283,8 +250,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
break; break;
} }
q = &SDpnt->request_queue; __blk_run_queue(&SDpnt->request_queue);
q->request_fn(q);
} }
} }
...@@ -299,7 +265,6 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt) ...@@ -299,7 +265,6 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
all_clear = 1; all_clear = 1;
if (SHpnt->some_device_starved) { if (SHpnt->some_device_starved) {
for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
request_queue_t *q;
if ((SHpnt->can_queue > 0 && (SHpnt->host_busy >= SHpnt->can_queue)) if ((SHpnt->can_queue > 0 && (SHpnt->host_busy >= SHpnt->can_queue))
|| (SHpnt->host_blocked) || (SHpnt->host_blocked)
|| (SHpnt->host_self_blocked)) { || (SHpnt->host_self_blocked)) {
...@@ -308,8 +273,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt) ...@@ -308,8 +273,7 @@ void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt)
if (SDpnt->device_blocked || !SDpnt->starved) { if (SDpnt->device_blocked || !SDpnt->starved) {
continue; continue;
} }
q = &SDpnt->request_queue; __blk_run_queue(&SDpnt->request_queue);
q->request_fn(q);
all_clear = 0; all_clear = 0;
} }
if (SDpnt == NULL && all_clear) { if (SDpnt == NULL && all_clear) {
...@@ -1021,10 +985,11 @@ void scsi_request_fn(request_queue_t * q) ...@@ -1021,10 +985,11 @@ void scsi_request_fn(request_queue_t * q)
break; break;
if(!req) { if(!req) {
/* can happen if the prep fails /* If the device is busy, a returning I/O
* FIXME: elv_next_request() should be plugging the * will restart the queue. Otherwise, we have
* queue */ * to plug the queue */
blk_plug_device(q); if(SDpnt->device_busy == 0)
blk_plug_device(q);
break; break;
} }
......
...@@ -607,25 +607,9 @@ static int proc_scsi_gen_write(struct file * file, const char * buf, ...@@ -607,25 +607,9 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
if (sdev->attached == 0) { if (sdev->attached == 0) {
devfs_unregister (sdev->de); devfs_unregister (sdev->de);
scsi_free_sdev(sdev);
/* Now we can remove the device structure */ err = 0;
if (sdev->next != NULL)
sdev->next->prev = sdev->prev;
if (sdev->prev != NULL)
sdev->prev->next = sdev->next;
if (shost->host_queue == sdev) {
shost->host_queue = sdev->next;
}
blk_cleanup_queue(&sdev->request_queue);
if (sdev->inquiry)
kfree(sdev->inquiry);
kfree((char *) sdev);
} else {
goto out;
} }
err = 0;
} }
out: out:
......
...@@ -465,12 +465,12 @@ static void scsi_initialize_merge_fn(struct scsi_device *sd) ...@@ -465,12 +465,12 @@ static void scsi_initialize_merge_fn(struct scsi_device *sd)
* Return value: * Return value:
* Scsi_Device pointer, or NULL on failure. * Scsi_Device pointer, or NULL on failure.
**/ **/
static Scsi_Device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel, struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel,
uint id, uint lun) uint id, uint lun)
{ {
Scsi_Device *sdev; struct scsi_device *sdev;
sdev = (Scsi_Device *) kmalloc(sizeof(Scsi_Device), GFP_ATOMIC); sdev = kmalloc(sizeof(*sdev), GFP_ATOMIC);
if (sdev == NULL) if (sdev == NULL)
printk(ALLOC_FAILURE_MSG, __FUNCTION__); printk(ALLOC_FAILURE_MSG, __FUNCTION__);
else { else {
...@@ -522,7 +522,7 @@ static Scsi_Device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel, ...@@ -522,7 +522,7 @@ static Scsi_Device *scsi_alloc_sdev(struct Scsi_Host *shost, uint channel,
* Undo the actions in scsi_alloc_sdev, including removing @sdev from * Undo the actions in scsi_alloc_sdev, including removing @sdev from
* the list, and freeing @sdev. * the list, and freeing @sdev.
**/ **/
static void scsi_free_sdev(Scsi_Device *sdev) void scsi_free_sdev(struct scsi_device *sdev)
{ {
if (sdev->prev != NULL) if (sdev->prev != NULL)
sdev->prev->next = sdev->next; sdev->prev->next = sdev->next;
......
...@@ -321,6 +321,7 @@ extern int scsi_cmd_ioctl(struct block_device *, unsigned int, unsigned long); ...@@ -321,6 +321,7 @@ extern int scsi_cmd_ioctl(struct block_device *, unsigned int, unsigned long);
extern void blk_start_queue(request_queue_t *q); extern void blk_start_queue(request_queue_t *q);
extern void blk_stop_queue(request_queue_t *q); extern void blk_stop_queue(request_queue_t *q);
extern void __blk_stop_queue(request_queue_t *q); extern void __blk_stop_queue(request_queue_t *q);
extern void __blk_run_queue(request_queue_t *q);
static inline request_queue_t *bdev_get_queue(struct block_device *bdev) static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
{ {
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
struct scsi_device;
/* /*
* Structures used for scsi_ioctl et al. * Structures used for scsi_ioctl et al.
*/ */
...@@ -33,19 +35,15 @@ typedef struct scsi_idlun { ...@@ -33,19 +35,15 @@ typedef struct scsi_idlun {
} Scsi_Idlun; } Scsi_Idlun;
/* Fibre Channel WWN, port_id struct */ /* Fibre Channel WWN, port_id struct */
typedef struct scsi_fctargaddress typedef struct scsi_fctargaddress {
{
__u32 host_port_id; __u32 host_port_id;
unsigned char host_wwn[8]; // include NULL term. unsigned char host_wwn[8]; // include NULL term.
} Scsi_FCTargAddress; } Scsi_FCTargAddress;
extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg); extern int scsi_ioctl(struct scsi_device *, int, void *);
extern int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg); extern int kernel_scsi_ioctl(struct scsi_device *, int , void *);
extern int scsi_ioctl_send_command(Scsi_Device *dev, extern int scsi_ioctl_send_command(struct scsi_device *,
Scsi_Ioctl_Command *arg); struct scsi_ioctl_command *);
#endif
#endif
#endif /* __KERNEL__ */
#endif /* _SCSI_IOCTL_H */
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