Commit 2e621110 authored by James Bottomley's avatar James Bottomley

Merge ssh://linux-scsi@linux-scsi.bkbits.net/scsi-misc-2.5

into mulgrave.(none):/home/jejb/BK/scsi-misc-2.5
parents 6ea618a8 15ec34c5
......@@ -122,8 +122,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_proc.o scsi_error.o scsi_lib.o scsi_merge.o \
scsi_scan.o scsi_syms.o
scsi_proc.o scsi_error.o scsi_lib.o scsi_scan.o \
scsi_syms.o
sd_mod-objs := sd.o
sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o
......
......@@ -445,20 +445,6 @@ extern int scsi_partsize(unsigned char *buf, unsigned long capacity,
struct scatterlist *scsi_alloc_sgtable(Scsi_Cmnd *SCpnt, int gfp_mask);
void scsi_free_sgtable(struct scatterlist *sgl, int index);
/*
* Prototypes for functions in scsi_dma.c
*/
void scsi_resize_dma_pool(void);
int scsi_init_minimal_dma_pool(void);
void *scsi_malloc(unsigned int);
int scsi_free(void *, unsigned int);
/*
* Prototypes for functions in scsi_merge.c
*/
extern void scsi_initialize_merge_fn(Scsi_Device *SDpnt);
extern int scsi_init_io(Scsi_Cmnd *SCpnt);
/*
* Prototypes for functions in scsi_lib.c
*/
......
......@@ -729,6 +729,92 @@ struct Scsi_Device_Template *scsi_get_request_dev(struct request *req)
return NULL;
}
/*
* Function: scsi_init_io()
*
* Purpose: SCSI I/O initialize function.
*
* Arguments: SCpnt - Command descriptor we wish to initialize
*
* Returns: 1 on success.
*/
static int scsi_init_io(Scsi_Cmnd *SCpnt)
{
struct request *req = SCpnt->request;
struct scatterlist *sgpnt;
int count, gfp_mask;
/*
* non-sg block request. FIXME: check bouncing for isa hosts!
*/
if ((req->flags & REQ_BLOCK_PC) && !req->bio) {
/*
* FIXME: isa bouncing
*/
if (SCpnt->host->unchecked_isa_dma)
goto fail;
SCpnt->request_bufflen = req->data_len;
SCpnt->request_buffer = req->data;
req->buffer = req->data;
SCpnt->use_sg = 0;
return 1;
}
/*
* we used to not use scatter-gather for single segment request,
* but now we do (it makes highmem I/O easier to support without
* kmapping pages)
*/
SCpnt->use_sg = req->nr_phys_segments;
gfp_mask = GFP_NOIO;
if (in_interrupt()) {
gfp_mask &= ~__GFP_WAIT;
gfp_mask |= __GFP_HIGH;
}
/*
* if sg table allocation fails, requeue request later.
*/
sgpnt = scsi_alloc_sgtable(SCpnt, gfp_mask);
if (unlikely(!sgpnt))
goto out;
SCpnt->request_buffer = (char *) sgpnt;
SCpnt->request_bufflen = req->nr_sectors << 9;
req->buffer = NULL;
/*
* Next, walk the list, and fill in the addresses and sizes of
* each segment.
*/
count = blk_rq_map_sg(req->q, req, SCpnt->request_buffer);
/*
* mapped well, send it off
*/
if (unlikely(count > SCpnt->use_sg))
goto incorrect;
SCpnt->use_sg = count;
return 1;
incorrect:
printk(KERN_ERR "Incorrect number of segments after building list\n");
printk(KERN_ERR "counted %d, received %d\n", count, SCpnt->use_sg);
printk(KERN_ERR "req nr_sec %lu, cur_nr_sec %u\n", req->nr_sectors,
req->current_nr_sectors);
/*
* kill it. there should be no leftover blocks in this request
*/
fail:
SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors);
BUG_ON(SCpnt);
out:
return 0;
}
/*
* Function: scsi_request_fn()
*
......
/*
* scsi_merge.c Copyright (C) 1999 Eric Youngdale
*
* SCSI queueing library.
* Initial versions: Eric Youngdale (eric@andante.org).
* Based upon conversations with large numbers
* of people at Linux Expo.
* Support for dynamic DMA mapping: Jakub Jelinek (jakub@redhat.com).
* Support for highmem I/O: Jens Axboe <axboe@suse.de>
*/
/*
* This file contains queue management functions that are used by SCSI.
* We need to ensure that commands do not grow so large that they cannot
* be handled all at once by a host adapter.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/stat.h>
#include <linux/blk.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/smp_lock.h>
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/io.h>
#include "scsi.h"
#include "hosts.h"
#include <scsi/scsi_ioctl.h>
/*
* Function: scsi_init_io()
*
* Purpose: SCSI I/O initialize function.
*
* Arguments: SCpnt - Command descriptor we wish to initialize
*
* Returns: 1 on success.
*
* Lock status:
*/
int scsi_init_io(Scsi_Cmnd *SCpnt)
{
struct request *req = SCpnt->request;
struct scatterlist *sgpnt;
int count, gfp_mask;
/*
* non-sg block request. FIXME: check bouncing for isa hosts!
*/
if ((req->flags & REQ_BLOCK_PC) && !req->bio) {
/*
* FIXME: isa bouncing
*/
if (SCpnt->host->unchecked_isa_dma)
goto fail;
SCpnt->request_bufflen = req->data_len;
SCpnt->request_buffer = req->data;
req->buffer = req->data;
SCpnt->use_sg = 0;
return 1;
}
/*
* we used to not use scatter-gather for single segment request,
* but now we do (it makes highmem I/O easier to support without
* kmapping pages)
*/
SCpnt->use_sg = req->nr_phys_segments;
gfp_mask = GFP_NOIO;
if (in_interrupt()) {
gfp_mask &= ~__GFP_WAIT;
gfp_mask |= __GFP_HIGH;
}
/*
* if sg table allocation fails, requeue request later.
*/
sgpnt = scsi_alloc_sgtable(SCpnt, gfp_mask);
if (!sgpnt)
return 0;
SCpnt->request_buffer = (char *) sgpnt;
SCpnt->request_bufflen = req->nr_sectors << 9;
req->buffer = NULL;
/*
* Next, walk the list, and fill in the addresses and sizes of
* each segment.
*/
count = blk_rq_map_sg(req->q, req, SCpnt->request_buffer);
/*
* mapped well, send it off
*/
if (count <= SCpnt->use_sg) {
SCpnt->use_sg = count;
return 1;
}
printk("Incorrect number of segments after building list\n");
printk("counted %d, received %d\n", count, SCpnt->use_sg);
printk("req nr_sec %lu, cur_nr_sec %u\n", req->nr_sectors, req->current_nr_sectors);
/*
* kill it. there should be no leftover blocks in this request
*/
fail:
SCpnt = scsi_end_request(SCpnt, 0, req->nr_sectors);
BUG_ON(SCpnt);
return 0;
}
/*
* Function: scsi_initialize_merge_fn()
*
* Purpose: Initialize merge function for a host
*
* Arguments: SHpnt - Host descriptor.
*
* Returns: Nothing.
*
* Lock status:
*
* Notes:
*/
void scsi_initialize_merge_fn(Scsi_Device * SDpnt)
{
struct Scsi_Host *SHpnt = SDpnt->host;
request_queue_t *q = &SDpnt->request_queue;
u64 bounce_limit;
/*
* The generic merging functions work just fine for us.
* Enable highmem I/O, if appropriate.
*/
bounce_limit = BLK_BOUNCE_HIGH;
if (SHpnt->highmem_io) {
if (!PCI_DMA_BUS_IS_PHYS)
/* Platforms with virtual-DMA translation
* hardware have no practical limit.
*/
bounce_limit = BLK_BOUNCE_ANY;
else if (SHpnt->pci_dev)
bounce_limit = SHpnt->pci_dev->dma_mask;
} else if (SHpnt->unchecked_isa_dma)
bounce_limit = BLK_BOUNCE_ISA;
blk_queue_bounce_limit(q, bounce_limit);
}
......@@ -482,6 +482,35 @@ static int get_device_flags(unsigned char *vendor, unsigned char *model)
return 0;
}
/**
* scsi_initialize_merge_fn() -ƣinitialize merge function for a host
* @sd: host descriptor
*/
static void scsi_initialize_merge_fn(struct scsi_device *sd)
{
request_queue_t *q = &sd->request_queue;
struct Scsi_Host *sh = sd->host;
u64 bounce_limit;
if (sh->highmem_io) {
if (sh->pci_dev && PCI_DMA_BUS_IS_PHYS) {
bounce_limit = sh->pci_dev->dma_mask;
} else {
/*
* Platforms with virtual-DMA translation
* hardware have no practical limit.
*/
bounce_limit = BLK_BOUNCE_ANY;
}
} else if (sh->unchecked_isa_dma) {
bounce_limit = BLK_BOUNCE_ISA;
} else {
bounce_limit = BLK_BOUNCE_HIGH;
}
blk_queue_bounce_limit(q, bounce_limit);
}
/**
* scsi_alloc_sdev - allocate and setup a Scsi_Device
*
......
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