summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/DAC960.c1
-rw-r--r--drivers/block/cciss.c1
-rw-r--r--drivers/block/cpqarray.c1
-rw-r--r--drivers/block/elevator.c1
-rw-r--r--drivers/block/floppy.c1
-rw-r--r--drivers/block/ll_rw_blk.c5
-rw-r--r--drivers/block/loop.c84
-rw-r--r--drivers/block/nbd.c1
-rw-r--r--drivers/block/rd.c2
-rw-r--r--drivers/block/umem.c1
-rw-r--r--drivers/char/agp/agp.h4
-rw-r--r--drivers/char/agp/agpgart_be.c155
-rw-r--r--drivers/char/random.c1
-rw-r--r--drivers/ide/ioctl.c5
-rw-r--r--drivers/md/linear.c2
-rw-r--r--drivers/md/lvm-snap.c2
-rw-r--r--drivers/md/lvm.c1
-rw-r--r--drivers/md/md.c1
-rw-r--r--drivers/md/multipath.c1
-rw-r--r--drivers/md/raid0.c1
-rw-r--r--drivers/md/raid1.c1
-rw-r--r--drivers/md/raid5.c1
-rw-r--r--drivers/pci/pci-driver.c1
-rw-r--r--drivers/pcmcia/pci_socket.c1
-rw-r--r--drivers/pcmcia/yenta.c1
-rw-r--r--drivers/scsi/README.st46
-rw-r--r--drivers/scsi/cpqfcTSinit.c1
-rw-r--r--drivers/scsi/scsi_lib.c1
-rw-r--r--drivers/scsi/sd.c1
-rw-r--r--drivers/scsi/sr.c1
-rw-r--r--drivers/scsi/st.c429
-rw-r--r--drivers/scsi/st_options.h15
32 files changed, 291 insertions, 479 deletions
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index d57dc51df3f5..210449ad1715 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -28,6 +28,7 @@
#include <linux/types.h>
#include <linux/blk.h>
#include <linux/blkdev.h>
+#include <linux/bio.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/genhd.h>
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 9ae961460ff2..e06fd274b653 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -30,6 +30,7 @@
#include <linux/delay.h>
#include <linux/major.h>
#include <linux/fs.h>
+#include <linux/bio.h>
#include <linux/blkpg.h>
#include <linux/timer.h>
#include <linux/proc_fs.h>
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 727cdeb23c0c..fccef1bb792c 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -24,6 +24,7 @@
#include <linux/version.h>
#include <linux/types.h>
#include <linux/pci.h>
+#include <linux/bio.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 189814dbc7d1..cd3a4254e9e3 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -28,6 +28,7 @@
#include <linux/fs.h>
#include <linux/blkdev.h>
#include <linux/elevator.h>
+#include <linux/bio.h>
#include <linux/blk.h>
#include <linux/config.h>
#include <linux/module.h>
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 94f42b356556..aff8acff0ef3 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -165,6 +165,7 @@ static int print_unex=1;
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/mm.h>
+#include <linux/bio.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index d53122b1ae46..16abcb3f5481 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -18,6 +18,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/config.h>
+#include <linux/bio.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/init.h>
@@ -2002,8 +2003,8 @@ int __init blk_dev_init(void)
queue_nr_requests = (total_ram >> 8) & ~15; /* One per quarter-megabyte */
if (queue_nr_requests < 32)
queue_nr_requests = 32;
- if (queue_nr_requests > 512)
- queue_nr_requests = 512;
+ if (queue_nr_requests > 256)
+ queue_nr_requests = 256;
/*
* Batch frees according to queue length
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 5689de41b771..982604ff6bfd 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -60,6 +60,7 @@
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/file.h>
+#include <linux/bio.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/major.h>
@@ -168,6 +169,15 @@ static void figure_loop_size(struct loop_device *lo)
}
+static inline int lo_do_transfer(struct loop_device *lo, int cmd, char *rbuf,
+ char *lbuf, int size, int rblock)
+{
+ if (!lo->transfer)
+ return 0;
+
+ return lo->transfer(lo, cmd, rbuf, lbuf, size, rblock);
+}
+
static int
do_lo_send(struct loop_device *lo, struct bio_vec *bvec, int bsize, loff_t pos)
{
@@ -454,20 +464,43 @@ static struct bio *loop_get_buffer(struct loop_device *lo, struct bio *rbh)
out_bh:
bio->bi_sector = rbh->bi_sector + (lo->lo_offset >> 9);
bio->bi_rw = rbh->bi_rw;
- spin_lock_irq(&lo->lo_lock);
bio->bi_bdev = lo->lo_device;
- spin_unlock_irq(&lo->lo_lock);
return bio;
}
-static int loop_make_request(request_queue_t *q, struct bio *rbh)
+static int
+bio_transfer(struct loop_device *lo, struct bio *to_bio,
+ struct bio *from_bio)
{
- struct bio *bh = NULL;
+ unsigned long IV = loop_get_iv(lo, from_bio->bi_sector);
+ struct bio_vec *from_bvec, *to_bvec;
+ char *vto, *vfrom;
+ int ret = 0, i;
+
+ __bio_for_each_segment(from_bvec, from_bio, i, 0) {
+ to_bvec = &to_bio->bi_io_vec[i];
+
+ kmap(from_bvec->bv_page);
+ kmap(to_bvec->bv_page);
+ vfrom = page_address(from_bvec->bv_page) + from_bvec->bv_offset;
+ vto = page_address(to_bvec->bv_page) + to_bvec->bv_offset;
+ ret |= lo_do_transfer(lo, bio_data_dir(to_bio), vto, vfrom,
+ from_bvec->bv_len, IV);
+ kunmap(from_bvec->bv_page);
+ kunmap(to_bvec->bv_page);
+ }
+
+ return ret;
+}
+
+static int loop_make_request(request_queue_t *q, struct bio *old_bio)
+{
+ struct bio *new_bio = NULL;
struct loop_device *lo;
unsigned long IV;
- int rw = bio_rw(rbh);
- int unit = minor(to_kdev_t(rbh->bi_bdev->bd_dev));
+ int rw = bio_rw(old_bio);
+ int unit = minor(to_kdev_t(old_bio->bi_bdev->bd_dev));
if (unit >= max_loop)
goto out;
@@ -489,60 +522,41 @@ static int loop_make_request(request_queue_t *q, struct bio *rbh)
goto err;
}
- blk_queue_bounce(q, &rbh);
+ blk_queue_bounce(q, &old_bio);
/*
* file backed, queue for loop_thread to handle
*/
if (lo->lo_flags & LO_FLAGS_DO_BMAP) {
- loop_add_bio(lo, rbh);
+ loop_add_bio(lo, old_bio);
return 0;
}
/*
* piggy old buffer on original, and submit for I/O
*/
- bh = loop_get_buffer(lo, rbh);
- IV = loop_get_iv(lo, rbh->bi_sector);
+ new_bio = loop_get_buffer(lo, old_bio);
+ IV = loop_get_iv(lo, old_bio->bi_sector);
if (rw == WRITE) {
- if (lo_do_transfer(lo, WRITE, bio_data(bh), bio_data(rbh),
- bh->bi_size, IV))
+ if (bio_transfer(lo, new_bio, old_bio))
goto err;
}
- generic_make_request(bh);
+ generic_make_request(new_bio);
return 0;
err:
if (atomic_dec_and_test(&lo->lo_pending))
up(&lo->lo_bh_mutex);
- loop_put_buffer(bh);
+ loop_put_buffer(new_bio);
out:
- bio_io_error(rbh);
+ bio_io_error(old_bio);
return 0;
inactive:
spin_unlock_irq(&lo->lo_lock);
goto out;
}
-static int do_bio_blockbacked(struct loop_device *lo, struct bio *bio,
- struct bio *rbh)
-{
- unsigned long IV = loop_get_iv(lo, rbh->bi_sector);
- struct bio_vec *from;
- char *vto, *vfrom;
- int ret = 0, i;
-
- bio_for_each_segment(from, rbh, i) {
- vfrom = page_address(from->bv_page) + from->bv_offset;
- vto = page_address(bio->bi_io_vec[i].bv_page) + bio->bi_io_vec[i].bv_offset;
- ret |= lo_do_transfer(lo, bio_data_dir(bio), vto, vfrom,
- from->bv_len, IV);
- }
-
- return ret;
-}
-
static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio)
{
int ret;
@@ -556,7 +570,7 @@ static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio)
} else {
struct bio *rbh = bio->bi_private;
- ret = do_bio_blockbacked(lo, bio, rbh);
+ ret = bio_transfer(lo, bio, rbh);
bio_endio(rbh, !ret);
loop_put_buffer(bio);
@@ -588,10 +602,8 @@ static int loop_thread(void *data)
set_user_nice(current, -20);
- spin_lock_irq(&lo->lo_lock);
lo->lo_state = Lo_bound;
atomic_inc(&lo->lo_pending);
- spin_unlock_irq(&lo->lo_lock);
/*
* up sem, we are running
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 67344c7fcc1a..697e825c3a91 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -39,6 +39,7 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/fs.h>
+#include <linux/bio.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/file.h>
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 4faf52c7be5c..7b60e75d5584 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -45,6 +45,8 @@
#include <linux/config.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <asm/atomic.h>
+#include <linux/bio.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 8c61688cab1c..44909021aa06 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -37,6 +37,7 @@
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/fs.h>
+#include <linux/bio.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/mman.h>
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index be8178161e80..94e405104df4 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -118,8 +118,8 @@ struct agp_bridge_data {
int (*remove_memory) (agp_memory *, off_t, int);
agp_memory *(*alloc_by_type) (size_t, int);
void (*free_by_type) (agp_memory *);
- unsigned long (*agp_alloc_page) (void);
- void (*agp_destroy_page) (unsigned long);
+ void *(*agp_alloc_page) (void);
+ void (*agp_destroy_page) (void *);
int (*suspend)(void);
void (*resume)(void);
diff --git a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c
index 44cbc013d91c..8ba761695215 100644
--- a/drivers/char/agp/agpgart_be.c
+++ b/drivers/char/agp/agpgart_be.c
@@ -22,6 +22,8 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
+ * TODO:
+ * - Allocate more than order 0 pages to avoid too much linear map splitting.
*/
#include <linux/config.h>
#include <linux/version.h>
@@ -43,6 +45,7 @@
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/page.h>
+#include <asm/agp.h>
#include <linux/agp_backend.h>
#include "agp.h"
@@ -59,56 +62,28 @@ EXPORT_SYMBOL(agp_enable);
EXPORT_SYMBOL(agp_backend_acquire);
EXPORT_SYMBOL(agp_backend_release);
-static void flush_cache(void);
-
static struct agp_bridge_data agp_bridge;
static int agp_try_unsupported __initdata = 0;
-
-static inline void flush_cache(void)
-{
-#if defined(__i386__) || defined(__x86_64__)
- asm volatile ("wbinvd":::"memory");
-#elif defined(__alpha__) || defined(__ia64__) || defined(__sparc__)
- /* ??? I wonder if we'll really need to flush caches, or if the
- core logic can manage to keep the system coherent. The ARM
- speaks only of using `cflush' to get things in memory in
- preparation for power failure.
-
- If we do need to call `cflush', we'll need a target page,
- as we can only flush one page at a time.
-
- Ditto for IA-64. --davidm 00/08/07 */
- mb();
-#else
-#error "Please define flush_cache."
-#endif
-}
-
#ifdef CONFIG_SMP
-static atomic_t cpus_waiting;
-
static void ipi_handler(void *null)
{
- flush_cache();
- atomic_dec(&cpus_waiting);
- while (atomic_read(&cpus_waiting) > 0)
- barrier();
+ flush_agp_cache();
}
static void smp_flush_cache(void)
{
- atomic_set(&cpus_waiting, num_online_cpus() - 1);
- if (smp_call_function(ipi_handler, NULL, 1, 0) != 0)
+ if (smp_call_function(ipi_handler, NULL, 1, 1) != 0)
panic(PFX "timed out waiting for the other CPUs!\n");
- flush_cache();
- while (atomic_read(&cpus_waiting) > 0)
- barrier();
+ flush_agp_cache();
}
#define global_cache_flush smp_flush_cache
#else /* CONFIG_SMP */
-#define global_cache_flush flush_cache
-#endif /* CONFIG_SMP */
+static void global_cache_flush(void)
+{
+ flush_agp_cache();
+}
+#endif /* !CONFIG_SMP */
int agp_backend_acquire(void)
{
@@ -208,8 +183,7 @@ void agp_free_memory(agp_memory * curr)
if (curr->page_count != 0) {
for (i = 0; i < curr->page_count; i++) {
curr->memory[i] &= ~(0x00000fff);
- agp_bridge.agp_destroy_page((unsigned long)
- phys_to_virt(curr->memory[i]));
+ agp_bridge.agp_destroy_page(phys_to_virt(curr->memory[i]));
}
}
agp_free_key(curr->key);
@@ -252,21 +226,22 @@ agp_memory *agp_allocate_memory(size_t page_count, u32 type)
MOD_DEC_USE_COUNT;
return NULL;
}
+
for (i = 0; i < page_count; i++) {
- new->memory[i] = agp_bridge.agp_alloc_page();
+ void *addr = agp_bridge.agp_alloc_page();
- if (new->memory[i] == 0) {
+ if (addr == NULL) {
/* Free this structure */
agp_free_memory(new);
return NULL;
}
new->memory[i] =
- agp_bridge.mask_memory(
- virt_to_phys((void *) new->memory[i]),
- type);
+ agp_bridge.mask_memory(virt_to_phys(addr), type);
new->page_count++;
}
+ flush_agp_mappings();
+
return new;
}
@@ -561,6 +536,7 @@ static int agp_generic_create_gatt_table(void)
agp_bridge.current_size;
break;
}
+ temp = agp_bridge.current_size;
} else {
agp_bridge.aperture_size_idx = i;
}
@@ -761,7 +737,7 @@ static void agp_generic_free_by_type(agp_memory * curr)
* against a maximum value.
*/
-static unsigned long agp_generic_alloc_page(void)
+static void *agp_generic_alloc_page(void)
{
struct page * page;
@@ -769,24 +745,26 @@ static unsigned long agp_generic_alloc_page(void)
if (page == NULL)
return 0;
+ map_page_into_agp(page);
+
get_page(page);
SetPageLocked(page);
atomic_inc(&agp_bridge.current_memory_agp);
- return (unsigned long)page_address(page);
+ return page_address(page);
}
-static void agp_generic_destroy_page(unsigned long addr)
+static void agp_generic_destroy_page(void *addr)
{
- void *pt = (void *) addr;
struct page *page;
- if (pt == NULL)
+ if (addr == NULL)
return;
- page = virt_to_page(pt);
+ page = virt_to_page(addr);
+ unmap_page_from_agp(page);
put_page(page);
unlock_page(page);
- free_page((unsigned long) pt);
+ free_page((unsigned long)addr);
atomic_dec(&agp_bridge.current_memory_agp);
}
@@ -993,6 +971,7 @@ static agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
return new;
}
if(type == AGP_PHYS_MEMORY) {
+ void *addr;
/* The I810 requires a physical address to program
* it's mouse pointer into hardware. However the
* Xserver still writes to it through the agp
@@ -1007,17 +986,14 @@ static agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
return NULL;
}
MOD_INC_USE_COUNT;
- new->memory[0] = agp_bridge.agp_alloc_page();
+ addr = agp_bridge.agp_alloc_page();
- if (new->memory[0] == 0) {
+ if (addr == NULL) {
/* Free this structure */
agp_free_memory(new);
return NULL;
}
- new->memory[0] =
- agp_bridge.mask_memory(
- virt_to_phys((void *) new->memory[0]),
- type);
+ new->memory[0] = agp_bridge.mask_memory(virt_to_phys(addr), type);
new->page_count = 1;
new->num_scratch_pages = 1;
new->type = AGP_PHYS_MEMORY;
@@ -1032,7 +1008,7 @@ static void intel_i810_free_by_type(agp_memory * curr)
{
agp_free_key(curr->key);
if(curr->type == AGP_PHYS_MEMORY) {
- agp_bridge.agp_destroy_page((unsigned long)
+ agp_bridge.agp_destroy_page(
phys_to_virt(curr->memory[0]));
vfree(curr->memory);
}
@@ -1291,7 +1267,7 @@ static agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
if (type == AGP_DCACHE_MEMORY) return(NULL);
if (type == AGP_PHYS_MEMORY) {
- unsigned long physical;
+ void *addr;
/* The i830 requires a physical address to program
* it's mouse pointer into hardware. However the
@@ -1306,19 +1282,18 @@ static agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
if (nw == NULL) return(NULL);
MOD_INC_USE_COUNT;
- nw->memory[0] = agp_bridge.agp_alloc_page();
- physical = nw->memory[0];
- if (nw->memory[0] == 0) {
+ addr = agp_bridge.agp_alloc_page();
+ if (addr == NULL) {
/* free this structure */
agp_free_memory(nw);
return(NULL);
}
- nw->memory[0] = agp_bridge.mask_memory(virt_to_phys((void *) nw->memory[0]),type);
+ nw->memory[0] = agp_bridge.mask_memory(virt_to_phys(addr),type);
nw->page_count = 1;
nw->num_scratch_pages = 1;
nw->type = AGP_PHYS_MEMORY;
- nw->physical = virt_to_phys((void *) physical);
+ nw->physical = virt_to_phys(addr);
return(nw);
}
@@ -1849,16 +1824,17 @@ static int intel_i460_remove_memory(agp_memory * mem, off_t pg_start, int type)
* Let's just hope nobody counts on the allocated AGP memory being there
* before bind time (I don't think current drivers do)...
*/
-static unsigned long intel_i460_alloc_page(void)
+static void * intel_i460_alloc_page(void)
{
if (intel_i460_cpk)
return agp_generic_alloc_page();
/* Returning NULL would cause problems */
- return ~0UL;
+ /* AK: really dubious code. */
+ return (void *)~0UL;
}
-static void intel_i460_destroy_page(unsigned long page)
+static void intel_i460_destroy_page(void *page)
{
if (intel_i460_cpk)
agp_generic_destroy_page(page);
@@ -3298,38 +3274,29 @@ static void ali_cache_flush(void)
}
}
-static unsigned long ali_alloc_page(void)
+static void *ali_alloc_page(void)
{
- struct page *page;
- u32 temp;
+ void *adr = agp_generic_alloc_page();
+ unsigned temp;
- page = alloc_page(GFP_KERNEL);
- if (page == NULL)
+ if (adr == 0)
return 0;
- get_page(page);
- SetPageLocked(page);
- atomic_inc(&agp_bridge.current_memory_agp);
-
- global_cache_flush();
-
if (agp_bridge.type == ALI_M1541) {
pci_read_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, &temp);
pci_write_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL,
(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
- virt_to_phys(page_address(page))) |
+ virt_to_phys(adr)) |
ALI_CACHE_FLUSH_EN ));
}
- return (unsigned long)page_address(page);
+ return adr;
}
-static void ali_destroy_page(unsigned long addr)
+static void ali_destroy_page(void * addr)
{
u32 temp;
- void *pt = (void *) addr;
- struct page *page;
- if (pt == NULL)
+ if (addr == NULL)
return;
global_cache_flush();
@@ -3338,15 +3305,11 @@ static void ali_destroy_page(unsigned long addr)
pci_read_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, &temp);
pci_write_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL,
(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
- virt_to_phys((void *)pt)) |
+ virt_to_phys(addr)) |
ALI_CACHE_FLUSH_EN));
}
- page = virt_to_page(pt);
- put_page(page);
- unlock_page(page);
- free_page((unsigned long) pt);
- atomic_dec(&agp_bridge.current_memory_agp);
+ agp_generic_destroy_page(addr);
}
/* Setup function */
@@ -5011,15 +4974,15 @@ static int __init agp_backend_initialize(void)
}
if (agp_bridge.needs_scratch_page == TRUE) {
- agp_bridge.scratch_page = agp_bridge.agp_alloc_page();
+ void *addr;
+ addr = agp_bridge.agp_alloc_page();
- if (agp_bridge.scratch_page == 0) {
+ if (addr == NULL) {
printk(KERN_ERR PFX "unable to get memory for "
"scratch page.\n");
return -ENOMEM;
}
- agp_bridge.scratch_page =
- virt_to_phys((void *) agp_bridge.scratch_page);
+ agp_bridge.scratch_page = virt_to_phys(addr);
agp_bridge.scratch_page =
agp_bridge.mask_memory(agp_bridge.scratch_page, 0);
}
@@ -5064,8 +5027,7 @@ static int __init agp_backend_initialize(void)
err_out:
if (agp_bridge.needs_scratch_page == TRUE) {
agp_bridge.scratch_page &= ~(0x00000fff);
- agp_bridge.agp_destroy_page((unsigned long)
- phys_to_virt(agp_bridge.scratch_page));
+ agp_bridge.agp_destroy_page(phys_to_virt(agp_bridge.scratch_page));
}
if (got_gatt)
agp_bridge.free_gatt_table();
@@ -5084,8 +5046,7 @@ static void agp_backend_cleanup(void)
if (agp_bridge.needs_scratch_page == TRUE) {
agp_bridge.scratch_page &= ~(0x00000fff);
- agp_bridge.agp_destroy_page((unsigned long)
- phys_to_virt(agp_bridge.scratch_page));
+ agp_bridge.agp_destroy_page(phys_to_virt(agp_bridge.scratch_page));
}
}
diff --git a/drivers/char/random.c b/drivers/char/random.c
index db20dec287d0..9db52acb9ef2 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -252,6 +252,7 @@
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/fs.h>
+#include <linux/tqueue.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
diff --git a/drivers/ide/ioctl.c b/drivers/ide/ioctl.c
index b986555fd4f3..609ed7dcfa56 100644
--- a/drivers/ide/ioctl.c
+++ b/drivers/ide/ioctl.c
@@ -345,8 +345,9 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
if (!arg) {
if (ide_spin_wait_hwgroup(drive))
return -EBUSY;
- else
- return 0;
+ /* Do nothing, just unlock */
+ spin_unlock_irq(drive->channel->lock);
+ return 0;
}
return do_cmd_ioctl(drive, arg);
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 118ce821a208..48fb74e50d5c 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -20,7 +20,7 @@
#include <linux/raid/md.h>
#include <linux/slab.h>
-
+#include <linux/bio.h>
#include <linux/raid/linear.h>
#define MAJOR_NR MD_MAJOR
diff --git a/drivers/md/lvm-snap.c b/drivers/md/lvm-snap.c
index c90947fc5f89..46df5c8ff0ef 100644
--- a/drivers/md/lvm-snap.c
+++ b/drivers/md/lvm-snap.c
@@ -224,7 +224,7 @@ static inline void invalidate_snap_cache(unsigned long start, unsigned long nr,
for (i = 0; i < nr; i++)
{
- bh = get_hash_table(dev, start++, blksize);
+ bh = find_get_block(dev, start++, blksize);
if (bh)
bforget(bh);
}
diff --git a/drivers/md/lvm.c b/drivers/md/lvm.c
index dfc256c6a2ec..c44a1b8a74b2 100644
--- a/drivers/md/lvm.c
+++ b/drivers/md/lvm.c
@@ -209,6 +209,7 @@
#include <linux/hdreg.h>
#include <linux/stat.h>
#include <linux/fs.h>
+#include <linux/bio.h>
#include <linux/proc_fs.h>
#include <linux/blkdev.h>
#include <linux/genhd.h>
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 21e20ea10be7..d23270322804 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -33,6 +33,7 @@
#include <linux/linkage.h>
#include <linux/raid/md.h>
#include <linux/sysctl.h>
+#include <linux/bio.h>
#include <linux/raid/xor.h>
#include <linux/devfs_fs_kernel.h>
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 46f089ee8481..6db555317b13 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/raid/multipath.h>
+#include <linux/bio.h>
#include <linux/buffer_head.h>
#include <asm/atomic.h>
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 430448c566af..8f149a1efe1b 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/raid/raid0.h>
+#include <linux/bio.h>
#define MAJOR_NR MD_MAJOR
#define MD_DRIVER
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 43fdb75de0fe..96ad858cf033 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -23,6 +23,7 @@
*/
#include <linux/raid/raid1.h>
+#include <linux/bio.h>
#define MAJOR_NR MD_MAJOR
#define MD_DRIVER
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 9402b0c779b9..62873d89e395 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/raid/raid5.h>
+#include <linux/bio.h>
#include <asm/bitops.h>
#include <asm/atomic.h>
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 0260ccf2092a..db4cdb8e3ad4 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -210,3 +210,4 @@ EXPORT_SYMBOL(pci_match_device);
EXPORT_SYMBOL(pci_register_driver);
EXPORT_SYMBOL(pci_unregister_driver);
EXPORT_SYMBOL(pci_dev_driver);
+EXPORT_SYMBOL(pci_bus_type);
diff --git a/drivers/pcmcia/pci_socket.c b/drivers/pcmcia/pci_socket.c
index d30df9b4203a..5a4b78312391 100644
--- a/drivers/pcmcia/pci_socket.c
+++ b/drivers/pcmcia/pci_socket.c
@@ -20,6 +20,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
+#include <linux/tqueue.h>
#include <linux/interrupt.h>
#include <pcmcia/ss.h>
diff --git a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c
index e5453fb455e2..40b20b945488 100644
--- a/drivers/pcmcia/yenta.c
+++ b/drivers/pcmcia/yenta.c
@@ -6,6 +6,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
+#include <linux/tqueue.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/module.h>
diff --git a/drivers/scsi/README.st b/drivers/scsi/README.st
index e06a21597910..702a5b178b61 100644
--- a/drivers/scsi/README.st
+++ b/drivers/scsi/README.st
@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
The driver is currently maintained by Kai M{kisara (email
Kai.Makisara@metla.fi)
-Last modified: Tue Jan 22 21:08:57 2002 by makisara
+Last modified: Tue Jun 18 18:13:50 2002 by makisara
BASICS
@@ -105,15 +105,19 @@ The default is BSD semantics.
BUFFERING
-The driver uses tape buffers allocated either at system initialization
-or at run-time when needed. One buffer is used for each open tape
-device. The size of the buffers is selectable at compile and/or boot
-time. The buffers are used to store the data being transferred to/from
-the SCSI adapter. The following buffering options are selectable at
-compile time and/or at run time (via ioctl):
+The driver uses tape buffers allocated at run-time when needed and it
+is freed when the device file is closed. One buffer is used for each
+open tape device.
+
+The size of the buffers is always at least one tape block. In fixed
+block mode, the minimum buffer size is defined (in 1024 byte units) by
+ST_FIXED_BUFFER_BLOCKS. With small block size this allows buffering of
+several blocks and using one SCSI read or write to transfer all of the
+blocks. Buffering of data across write calls in fixed block mode is
+allowed if ST_BUFFER_WRITES is non-zero. Buffer allocation uses chunks of
+memory having sizes 2^n * (page size). Because of this the actual
+buffer size may be larger than the minimum allowable buffer size.
-Buffering of data across write calls in fixed block mode (define
-ST_BUFFER_WRITES).
Asynchronous writing. Writing the buffer contents to the tape is
started and the write call returns immediately. The status is checked
@@ -128,30 +132,6 @@ attempted even if the user does not want to get all of the data at
this read command. Should be disabled for those drives that don't like
a filemark to truncate a read request or that don't like backspacing.
-The buffer size is defined (in 1024 byte units) by ST_BUFFER_BLOCKS or
-at boot time. If this size is not large enough, the driver tries to
-temporarily enlarge the buffer. Buffer allocation uses chunks of
-memory having sizes 2^n * (page size). Because of this the actual
-buffer size may be larger than the buffer size specified with
-ST_BUFFER_BLOCKS.
-
-A small number of buffers are allocated at driver initialisation. The
-maximum number of these buffers is defined by ST_MAX_BUFFERS. The
-maximum can be changed with kernel or module startup options. One
-buffer is allocated for each drive detected when the driver is
-initialized up to the maximum.
-
-The driver tries to allocate new buffers at run-time if
-necessary. These buffers are freed after use. If the maximum number of
-initial buffers is set to zero, all buffer allocation is done at
-run-time. The advantage of run-time allocation is that memory is not
-wasted for buffers not being used. The disadvantage is that there may
-not be memory available at the time when a buffer is needed for the
-first time (once a buffer is allocated, it is not released). This risk
-should not be big if the tape drive is connected to a PCI adapter that
-supports scatter/gather (the allocation is not limited to "DMA memory"
-and the buffer can be composed of several fragments).
-
The threshold for triggering asynchronous write in fixed block mode
is defined by ST_WRITE_THRESHOLD. This may be optimized for each
use pattern. The default triggers asynchronous write after three
diff --git a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
index e6f03847c212..f38e377207c7 100644
--- a/drivers/scsi/cpqfcTSinit.c
+++ b/drivers/scsi/cpqfcTSinit.c
@@ -39,6 +39,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/timer.h>
+#include <linux/init.h>
#include <linux/ioport.h> // request_region() prototype
#include <linux/vmalloc.h> // ioremap()
//#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,7)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index fc69760ab484..bede96547efb 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -23,6 +23,7 @@
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/bio.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/stat.h>
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 382e04ceace2..63fe305e4342 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -36,6 +36,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/bio.h>
#include <linux/string.h>
#include <linux/hdreg.h>
#include <linux/errno.h>
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index d536f3bc94f6..0e28dc69652b 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -39,6 +39,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/bio.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/cdrom.h>
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index f48ac845bc08..7342c3e661f3 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -12,13 +12,13 @@
Copyright 1992 - 2002 Kai Makisara
email Kai.Makisara@metla.fi
- Last modified: Tue Feb 5 21:25:55 2002 by makisara
+ Last modified: Sat Jun 15 13:01:56 2002 by makisara
Some small formal changes - aeb, 950809
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
*/
-static char *verstr = "20020205";
+static char *verstr = "20020615";
#include <linux/module.h>
@@ -69,7 +69,6 @@ static char *verstr = "20020205";
static int buffer_kbs;
static int write_threshold_kbs;
-static int max_buffers = (-1);
static int max_sg_segs;
MODULE_AUTHOR("Kai Makisara");
@@ -80,8 +79,6 @@ MODULE_PARM(buffer_kbs, "i");
MODULE_PARM_DESC(buffer_kbs, "Default driver buffer size (KB; 32)");
MODULE_PARM(write_threshold_kbs, "i");
MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 30)");
-MODULE_PARM(max_buffers, "i");
-MODULE_PARM_DESC(max_buffers, "Maximum number of buffer allocated at initialisation (4)");
MODULE_PARM(max_sg_segs, "i");
MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (32)");
@@ -97,9 +94,6 @@ static struct st_dev_parm {
"write_threshold_kbs", &write_threshold_kbs
},
{
- "max_buffers", &max_buffers
- },
- {
"max_sg_segs", &max_sg_segs
}
};
@@ -108,12 +102,12 @@ static struct st_dev_parm {
/* The default definitions have been moved to st_options.h */
-#define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_KILOBYTE)
+#define ST_FIXED_BUFFER_SIZE (ST_FIXED_BUFFER_BLOCKS * ST_KILOBYTE)
#define ST_WRITE_THRESHOLD (ST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
/* The buffer size should fit into the 24 bits for length in the
6-byte SCSI read and write commands. */
-#if ST_BUFFER_SIZE >= (2 << 24 - 1)
+#if ST_FIXED_BUFFER_SIZE >= (2 << 24 - 1)
#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
#endif
@@ -121,7 +115,7 @@ DEB( static int debugging = DEBUG; )
#define MAX_RETRIES 0
#define MAX_WRITE_RETRIES 0
-#define MAX_READY_RETRIES 5
+#define MAX_READY_RETRIES 0
#define NO_TAPE NOT_READY
#define ST_TIMEOUT (900 * HZ)
@@ -137,18 +131,15 @@ DEB( static int debugging = DEBUG; )
#define ST_DEV_ARR_LUMP 6
static rwlock_t st_dev_arr_lock = RW_LOCK_UNLOCKED;
-static int st_nbr_buffers;
-static ST_buffer **st_buffers = NULL;
-static int st_buffer_size = ST_BUFFER_SIZE;
+static int st_fixed_buffer_size = ST_FIXED_BUFFER_SIZE;
static int st_write_threshold = ST_WRITE_THRESHOLD;
-static int st_max_buffers = ST_MAX_BUFFERS;
static int st_max_sg_segs = ST_MAX_SG;
static Scsi_Tape **scsi_tapes = NULL;
static int modes_defined;
-static ST_buffer *new_tape_buffer(int, int, int);
+static ST_buffer *new_tape_buffer(int, int);
static int enlarge_buffer(ST_buffer *, int, int);
static void normalize_buffer(ST_buffer *);
static int append_to_buffer(const char *, ST_buffer *, int);
@@ -914,8 +905,7 @@ static int check_tape(Scsi_Tape *STp, struct file *filp)
module count. */
static int st_open(struct inode *inode, struct file *filp)
{
- int i, need_dma_buffer;
- int retval = (-EIO);
+ int i, retval = (-EIO);
Scsi_Tape *STp;
ST_partstat *STps;
int dev = TAPE_NR(inode->i_rdev);
@@ -945,38 +935,15 @@ static int st_open(struct inode *inode, struct file *filp)
goto err_out;
}
- /* Allocate a buffer for this user */
- need_dma_buffer = STp->restr_dma;
- write_lock(&st_dev_arr_lock);
- for (i = 0; i < st_nbr_buffers; i++)
- if (!st_buffers[i]->in_use &&
- (!need_dma_buffer || st_buffers[i]->dma)) {
- STp->buffer = st_buffers[i];
- (STp->buffer)->in_use = 1;
- break;
- }
- write_unlock(&st_dev_arr_lock);
- if (i >= st_nbr_buffers) {
- STp->buffer = new_tape_buffer(FALSE, need_dma_buffer, TRUE);
- if (STp->buffer == NULL) {
- printk(KERN_WARNING "st%d: Can't allocate tape buffer.\n", dev);
- retval = (-EBUSY);
- goto err_out;
- }
+ /* See that we have at least a one page buffer available */
+ if (!enlarge_buffer(STp->buffer, PAGE_SIZE, STp->restr_dma)) {
+ printk(KERN_WARNING "st%d: Can't allocate tape buffer.\n", dev);
+ retval = (-EOVERFLOW);
+ goto err_out;
}
(STp->buffer)->writing = 0;
(STp->buffer)->syscall_result = 0;
- (STp->buffer)->use_sg = STp->device->host->sg_tablesize;
-
- /* Compute the usable buffer size for this SCSI adapter */
- if (!(STp->buffer)->use_sg)
- (STp->buffer)->buffer_size = (STp->buffer)->sg[0].length;
- else {
- for (i = 0, (STp->buffer)->buffer_size = 0; i < (STp->buffer)->use_sg &&
- i < (STp->buffer)->sg_segs; i++)
- (STp->buffer)->buffer_size += (STp->buffer)->sg[i].length;
- }
STp->write_prot = ((filp->f_flags & O_ACCMODE) == O_RDONLY);
@@ -999,10 +966,7 @@ static int st_open(struct inode *inode, struct file *filp)
return 0;
err_out:
- if (STp->buffer != NULL) {
- (STp->buffer)->in_use = 0;
- STp->buffer = NULL;
- }
+ normalize_buffer(STp->buffer);
STp->in_use = 0;
STp->device->access_count--;
if (STp->device->host->hostt->module)
@@ -1149,16 +1113,8 @@ static int st_release(struct inode *inode, struct file *filp)
if (STp->door_locked == ST_LOCKED_AUTO)
st_int_ioctl(STp, MTUNLOCK, 0);
- if (STp->buffer != NULL) {
- normalize_buffer(STp->buffer);
- write_lock(&st_dev_arr_lock);
- (STp->buffer)->in_use = 0;
- STp->buffer = NULL;
- }
- else {
- write_lock(&st_dev_arr_lock);
- }
-
+ normalize_buffer(STp->buffer);
+ write_lock(&st_dev_arr_lock);
STp->in_use = 0;
write_unlock(&st_dev_arr_lock);
STp->device->access_count--;
@@ -1168,31 +1124,11 @@ static int st_release(struct inode *inode, struct file *filp)
return result;
}
-
-/* Write command */
-static ssize_t
- st_write(struct file *filp, const char *buf, size_t count, loff_t * ppos)
+/* The checks common to both reading and writing */
+static ssize_t rw_checks(Scsi_Tape *STp, struct file *filp, size_t count, loff_t *ppos)
{
- struct inode *inode = filp->f_dentry->d_inode;
- ssize_t total;
- ssize_t i, do_count, blks, transfer;
+ int bufsize;
ssize_t retval = 0;
- int write_threshold;
- int doing_write = 0;
- unsigned char cmd[MAX_COMMAND_SIZE];
- const char *b_point;
- Scsi_Request *SRpnt = NULL;
- Scsi_Tape *STp;
- ST_mode *STm;
- ST_partstat *STps;
- int dev = TAPE_NR(inode->i_rdev);
-
- read_lock(&st_dev_arr_lock);
- STp = scsi_tapes[dev];
- read_unlock(&st_dev_arr_lock);
-
- if (down_interruptible(&STp->lock))
- return -ERESTARTSYS;
/*
* If we are in the middle of error recovery, don't let anyone
@@ -1219,13 +1155,11 @@ static ssize_t
goto out;
}
- STm = &(STp->modes[STp->current_mode]);
- if (!STm->defined) {
+ if (! STp->modes[STp->current_mode].defined) {
retval = (-ENXIO);
goto out;
}
- if (count == 0)
- goto out;
+
/*
* If there was a bus reset, block further access
@@ -1236,30 +1170,20 @@ static ssize_t
goto out;
}
+ if (count == 0)
+ goto out;
+
DEB(
if (!STp->in_use) {
+ int dev = TAPE_NR(filp->f_dentry->d_inode->i_rdev);
printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev);
retval = (-EIO);
goto out;
} ) /* end DEB */
- /* Write must be integral number of blocks */
- if (STp->block_size != 0 && (count % STp->block_size) != 0) {
- printk(KERN_WARNING "st%d: Write not multiple of tape block size.\n",
- dev);
- retval = (-EINVAL);
- goto out;
- }
-
if (STp->can_partitions &&
(retval = update_partition(STp)) < 0)
goto out;
- STps = &(STp->ps[STp->partition]);
-
- if (STp->write_prot) {
- retval = (-EACCES);
- goto out;
- }
if (STp->block_size == 0) {
if (STp->max_block > 0 &&
@@ -1273,19 +1197,73 @@ static ssize_t
goto out;
}
}
- if ((STp->buffer)->buffer_blocks < 1) {
- /* Fixed block mode with too small buffer */
- if (!enlarge_buffer(STp->buffer, STp->block_size, STp->restr_dma)) {
+ else {
+ /* Fixed block mode with too small buffer? */
+ bufsize = STp->block_size > st_fixed_buffer_size ?
+ STp->block_size : st_fixed_buffer_size;
+ if ((STp->buffer)->buffer_size < bufsize &&
+ !enlarge_buffer(STp->buffer, bufsize, STp->restr_dma)) {
retval = (-EOVERFLOW);
goto out;
}
- (STp->buffer)->buffer_blocks = 1;
+ (STp->buffer)->buffer_blocks = bufsize / STp->block_size;
}
if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
!st_int_ioctl(STp, MTLOCK, 0))
STp->door_locked = ST_LOCKED_AUTO;
+ out:
+ return retval;
+}
+
+
+/* Write command */
+static ssize_t
+ st_write(struct file *filp, const char *buf, size_t count, loff_t * ppos)
+{
+ struct inode *inode = filp->f_dentry->d_inode;
+ ssize_t total;
+ ssize_t i, do_count, blks, transfer;
+ ssize_t retval;
+ int write_threshold;
+ int doing_write = 0;
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ const char *b_point;
+ Scsi_Request *SRpnt = NULL;
+ Scsi_Tape *STp;
+ ST_mode *STm;
+ ST_partstat *STps;
+ int dev = TAPE_NR(inode->i_rdev);
+
+ read_lock(&st_dev_arr_lock);
+ STp = scsi_tapes[dev];
+ read_unlock(&st_dev_arr_lock);
+
+ if (down_interruptible(&STp->lock))
+ return -ERESTARTSYS;
+
+ retval = rw_checks(STp, filp, count, ppos);
+ if (retval || count == 0)
+ goto out;
+
+ /* Write must be integral number of blocks */
+ if (STp->block_size != 0 && (count % STp->block_size) != 0) {
+ printk(KERN_WARNING "st%d: Write not multiple of tape block size.\n",
+ dev);
+ retval = (-EINVAL);
+ goto out;
+ }
+
+ STm = &(STp->modes[STp->current_mode]);
+ STps = &(STp->ps[STp->partition]);
+
+ if (STp->write_prot) {
+ retval = (-EACCES);
+ goto out;
+ }
+
+
if (STps->rw == ST_READING) {
retval = flush_buffer(STp, 0);
if (retval)
@@ -1718,77 +1696,17 @@ static ssize_t
if (down_interruptible(&STp->lock))
return -ERESTARTSYS;
- /*
- * If we are in the middle of error recovery, don't let anyone
- * else try and use this device. Also, if error recovery fails, it
- * may try and take the device offline, in which case all further
- * access to the device is prohibited.
- */
- if (!scsi_block_when_processing_errors(STp->device)) {
- retval = (-ENXIO);
- goto out;
- }
-
- if (ppos != &filp->f_pos) {
- /* "A request was outside the capabilities of the device." */
- retval = (-ENXIO);
+ retval = rw_checks(STp, filp, count, ppos);
+ if (retval || count == 0)
goto out;
- }
- if (STp->ready != ST_READY) {
- if (STp->ready == ST_NO_TAPE)
- retval = (-ENOMEDIUM);
- else
- retval = (-EIO);
- goto out;
- }
STm = &(STp->modes[STp->current_mode]);
- if (!STm->defined) {
- retval = (-ENXIO);
- goto out;
- }
- DEB(
- if (!STp->in_use) {
- printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev);
- retval = (-EIO);
- goto out;
- } ) /* end DEB */
-
- if (STp->can_partitions &&
- (retval = update_partition(STp)) < 0)
- goto out;
-
- if (STp->block_size == 0) {
- if (STp->max_block > 0 &&
- (count < STp->min_block || count > STp->max_block)) {
- retval = (-EINVAL);
- goto out;
- }
- if (count > (STp->buffer)->buffer_size &&
- !enlarge_buffer(STp->buffer, count, STp->restr_dma)) {
- retval = (-EOVERFLOW);
- goto out;
- }
- }
- if ((STp->buffer)->buffer_blocks < 1) {
- /* Fixed block mode with too small buffer */
- if (!enlarge_buffer(STp->buffer, STp->block_size, STp->restr_dma)) {
- retval = (-EOVERFLOW);
- goto out;
- }
- (STp->buffer)->buffer_blocks = 1;
- }
-
if (!(STm->do_read_ahead) && STp->block_size != 0 &&
(count % STp->block_size) != 0) {
retval = (-EINVAL); /* Read must be integral number of blocks */
goto out;
}
- if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
- !st_int_ioctl(STp, MTLOCK, 0))
- STp->door_locked = ST_LOCKED_AUTO;
-
STps = &(STp->ps[STp->partition]);
if (STps->rw == ST_WRITING) {
retval = flush_buffer(STp, 0);
@@ -1986,7 +1904,7 @@ static int st_set_options(Scsi_Tape *STp, long options)
st_log_options(STp, STm, dev);
} else if (code == MT_ST_WRITE_THRESHOLD) {
value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
- if (value < 1 || value > st_buffer_size) {
+ if (value < 1 || value > st_fixed_buffer_size) {
printk(KERN_WARNING
"st%d: Write threshold %d too small or too large.\n",
dev, value);
@@ -2289,8 +2207,10 @@ static int do_load_unload(Scsi_Tape *STp, struct file *filp, int load_code)
if (!retval) { /* SCSI command successful */
- if (!load_code)
+ if (!load_code) {
STp->rew_at_close = 0;
+ STp->ready = ST_NO_TAPE;
+ }
else {
STp->rew_at_close = STp->autorew_dev;
retval = check_tape(STp, filp);
@@ -2619,10 +2539,14 @@ static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg)
ioctl_result = st_int_ioctl(STp, MTBSF, 1);
if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) {
+ int old_block_size = STp->block_size;
STp->block_size = arg & MT_ST_BLKSIZE_MASK;
- if (STp->block_size != 0)
+ if (STp->block_size != 0) {
+ if (old_block_size == 0)
+ normalize_buffer(STp->buffer);
(STp->buffer)->buffer_blocks =
(STp->buffer)->buffer_size / STp->block_size;
+ }
(STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;
if (cmd_in == SET_DENS_AND_BLK)
STp->density = arg >> MT_ST_DENSITY_SHIFT;
@@ -3372,18 +3296,11 @@ static int st_ioctl(struct inode *inode, struct file *file,
/* Try to allocate a new tape buffer. Calling function must not hold
dev_arr_lock. */
static ST_buffer *
- new_tape_buffer(int from_initialization, int need_dma, int in_use)
+ new_tape_buffer(int from_initialization, int need_dma)
{
- int i, priority, b_size, order, got = 0, segs = 0;
+ int i, priority, got = 0, segs = 0;
ST_buffer *tb;
- read_lock(&st_dev_arr_lock);
- if (st_nbr_buffers >= st_template.dev_max) {
- read_unlock(&st_dev_arr_lock);
- return NULL; /* Should never happen */
- }
- read_unlock(&st_dev_arr_lock);
-
if (from_initialization)
priority = GFP_ATOMIC;
else
@@ -3391,85 +3308,19 @@ static ST_buffer *
i = sizeof(ST_buffer) + (st_max_sg_segs - 1) * sizeof(struct scatterlist);
tb = kmalloc(i, priority);
- if (tb) {
- if (need_dma)
- priority |= GFP_DMA;
-
- /* Try to allocate the first segment up to ST_FIRST_ORDER and the
- others big enough to reach the goal */
- for (b_size = PAGE_SIZE, order=0;
- b_size < st_buffer_size && order < ST_FIRST_ORDER;
- order++, b_size *= 2)
- ;
- for ( ; b_size >= PAGE_SIZE; order--, b_size /= 2) {
- tb->sg[0].page = alloc_pages(priority, order);
- tb->sg[0].offset = 0;
- if (tb->sg[0].page != NULL) {
- tb->sg[0].length = b_size;
- break;
- }
- }
- if (tb->sg[segs].page == NULL) {
- kfree(tb);
- tb = NULL;
- } else { /* Got something, continue */
-
- for (b_size = PAGE_SIZE, order=0;
- st_buffer_size >
- tb->sg[0].length + (ST_FIRST_SG - 1) * b_size;
- order++, b_size *= 2)
- ;
- for (segs = 1, got = tb->sg[0].length;
- got < st_buffer_size && segs < ST_FIRST_SG;) {
- tb->sg[segs].page = alloc_pages(priority, order);
- tb->sg[segs].offset = 0;
- if (tb->sg[segs].page == NULL) {
- if (st_buffer_size - got <=
- (ST_FIRST_SG - segs) * b_size / 2) {
- b_size /= 2; /* Large enough for the
- rest of the buffers */
- order--;
- continue;
- }
- tb->sg_segs = segs;
- tb->orig_sg_segs = 0;
- DEB(tb->buffer_size = got);
- normalize_buffer(tb);
- kfree(tb);
- tb = NULL;
- break;
- }
- tb->sg[segs].length = b_size;
- got += b_size;
- segs++;
- }
- }
- }
-
if (!tb) {
- printk(KERN_NOTICE "st: Can't allocate new tape buffer (nbr %d).\n",
- st_nbr_buffers);
+ printk(KERN_NOTICE "st: Can't allocate new tape buffer.\n");
return NULL;
}
tb->sg_segs = tb->orig_sg_segs = segs;
- tb->b_data = page_address(tb->sg[0].page);
+ if (segs > 0)
+ tb->b_data = page_address(tb->sg[0].page);
- DEBC(printk(ST_DEB_MSG
- "st: Allocated tape buffer %d (%d bytes, %d segments, dma: %d, a: %p).\n",
- st_nbr_buffers, got, tb->sg_segs, need_dma, tb->b_data);
- printk(ST_DEB_MSG
- "st: segment sizes: first %d, last %d bytes.\n",
- tb->sg[0].length, tb->sg[segs - 1].length);
- )
- tb->in_use = in_use;
+ tb->in_use = TRUE;
tb->dma = need_dma;
tb->buffer_size = got;
tb->writing = 0;
- write_lock(&st_dev_arr_lock);
- st_buffers[st_nbr_buffers++] = tb;
- write_unlock(&st_dev_arr_lock);
-
return tb;
}
@@ -3479,6 +3330,9 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma)
{
int segs, nbr, max_segs, b_size, priority, order, got;
+ if (new_size <= STbuffer->buffer_size)
+ return TRUE;
+
normalize_buffer(STbuffer);
max_segs = STbuffer->use_sg;
@@ -3492,13 +3346,14 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma)
if (need_dma)
priority |= GFP_DMA;
for (b_size = PAGE_SIZE, order=0;
- b_size * nbr < new_size - STbuffer->buffer_size;
+ b_size < new_size - STbuffer->buffer_size;
order++, b_size *= 2)
; /* empty */
for (segs = STbuffer->sg_segs, got = STbuffer->buffer_size;
segs < max_segs && got < new_size;) {
STbuffer->sg[segs].page = alloc_pages(priority, order);
+ /* printk("st: allocated %x, order %d\n", STbuffer->sg[segs].page, order); */
STbuffer->sg[segs].offset = 0;
if (STbuffer->sg[segs].page == NULL) {
if (new_size - got <= (max_segs - segs) * b_size / 2) {
@@ -3518,9 +3373,10 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma)
STbuffer->buffer_size = got;
segs++;
}
+ STbuffer->b_data = page_address(STbuffer->sg[0].page);
DEBC(printk(ST_DEB_MSG
- "st: Succeeded to enlarge buffer to %d bytes (segs %d->%d, %d).\n",
- got, STbuffer->orig_sg_segs, STbuffer->sg_segs, b_size));
+ "st: Succeeded to enlarge buffer at %p to %d bytes (segs %d->%d, %d).\n",
+ STbuffer, got, STbuffer->orig_sg_segs, STbuffer->sg_segs, b_size));
return TRUE;
}
@@ -3535,14 +3391,14 @@ static void normalize_buffer(ST_buffer * STbuffer)
for (b_size=PAGE_SIZE, order=0; b_size < STbuffer->sg[i].length;
order++, b_size *= 2)
; /* empty */
+ /* printk("st: freeing %x, order %d\n", STbuffer->sg[i].page, order); */
__free_pages(STbuffer->sg[i].page, order);
STbuffer->buffer_size -= STbuffer->sg[i].length;
}
DEB(
if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
printk(ST_DEB_MSG "st: Buffer at %p normalized to %d bytes (segs %d).\n",
- page_address(STbuffer->sg[0].page), STbuffer->buffer_size,
- STbuffer->sg_segs);
+ STbuffer, STbuffer->buffer_size, STbuffer->sg_segs);
) /* end DEB */
STbuffer->sg_segs = STbuffer->orig_sg_segs;
}
@@ -3619,18 +3475,16 @@ static int from_buffer(ST_buffer * st_bp, char *ubp, int do_count)
static void validate_options(void)
{
if (buffer_kbs > 0)
- st_buffer_size = buffer_kbs * ST_KILOBYTE;
+ st_fixed_buffer_size = buffer_kbs * ST_KILOBYTE;
if (write_threshold_kbs > 0)
st_write_threshold = write_threshold_kbs * ST_KILOBYTE;
else if (buffer_kbs > 0)
- st_write_threshold = st_buffer_size - 2048;
- if (st_write_threshold > st_buffer_size) {
- st_write_threshold = st_buffer_size;
+ st_write_threshold = st_fixed_buffer_size - 2048;
+ if (st_write_threshold > st_fixed_buffer_size) {
+ st_write_threshold = st_fixed_buffer_size;
printk(KERN_WARNING "st: write_threshold limited to %d bytes.\n",
st_write_threshold);
}
- if (max_buffers >= 0)
- st_max_buffers = max_buffers;
if (max_sg_segs >= ST_FIRST_SG)
st_max_sg_segs = max_sg_segs;
}
@@ -3694,7 +3548,8 @@ static int st_attach(Scsi_Device * SDp)
Scsi_Tape *tpnt;
ST_mode *STm;
ST_partstat *STps;
- int i, mode, target_nbr, dev_num;
+ ST_buffer *buffer;
+ int i, mode, dev_num;
char *stp;
if (SDp->type != TYPE_TAPE)
@@ -3707,6 +3562,12 @@ static int st_attach(Scsi_Device * SDp)
return 1;
}
+ buffer = new_tape_buffer(TRUE, (SDp->host)->unchecked_isa_dma);
+ if (buffer == NULL) {
+ printk(KERN_ERR "st: Can't allocate new tape buffer. Device not attached.\n");
+ return 1;
+ }
+
write_lock(&st_dev_arr_lock);
if (st_template.nr_dev >= st_template.dev_max) {
Scsi_Tape **tmp_da;
@@ -3745,14 +3606,6 @@ static int st_attach(Scsi_Device * SDp)
}
scsi_tapes = tmp_da;
- memset(tmp_ba, 0, tmp_dev_max * sizeof(ST_buffer *));
- if (st_buffers != NULL) {
- memcpy(tmp_ba, st_buffers,
- st_template.dev_max * sizeof(ST_buffer *));
- kfree(st_buffers);
- }
- st_buffers = tmp_ba;
-
st_template.dev_max = tmp_dev_max;
}
@@ -3799,6 +3652,9 @@ static int st_attach(Scsi_Device * SDp)
else
tpnt->tape_type = MT_ISSCSI2;
+ buffer->use_sg = tpnt->device->host->sg_tablesize;
+ tpnt->buffer = buffer;
+
tpnt->inited = 0;
tpnt->devt = mk_kdev(SCSI_TAPE_MAJOR, i);
tpnt->dirty = 0;
@@ -3858,18 +3714,6 @@ static int st_attach(Scsi_Device * SDp)
"Attached scsi tape st%d at scsi%d, channel %d, id %d, lun %d\n",
dev_num, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);
- /* See if we need to allocate more static buffers */
- target_nbr = st_template.nr_dev;
- if (target_nbr > st_max_buffers)
- target_nbr = st_max_buffers;
- for (i=st_nbr_buffers; i < target_nbr; i++)
- if (!new_tape_buffer(TRUE, TRUE, FALSE)) {
- printk(KERN_INFO "st: Unable to allocate new static buffer.\n");
- break;
- }
- /* If the previous allocation fails, we will try again when the buffer is
- really needed. */
-
return 0;
};
@@ -3897,6 +3741,11 @@ static void st_detach(Scsi_Device * SDp)
devfs_unregister (tpnt->de_n[mode]);
tpnt->de_n[mode] = NULL;
}
+ if (tpnt->buffer) {
+ tpnt->buffer->orig_sg_segs = 0;
+ normalize_buffer(tpnt->buffer);
+ kfree(tpnt->buffer);
+ }
kfree(tpnt);
scsi_tapes[i] = 0;
SDp->attached--;
@@ -3916,10 +3765,10 @@ static int __init init_st(void)
validate_options();
printk(KERN_INFO
- "st: Version %s, bufsize %d, wrt %d, "
- "max init. bufs %d, s/g segs %d\n",
- verstr, st_buffer_size, st_write_threshold,
- st_max_buffers, st_max_sg_segs);
+ "st: Version %s, fixed bufsize %d, wrt %d, "
+ "s/g segs %d\n",
+ verstr, st_fixed_buffer_size, st_write_threshold,
+ st_max_sg_segs);
if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0)
return scsi_register_device(&st_template);
@@ -3939,16 +3788,6 @@ static void __exit exit_st(void)
if (scsi_tapes[i])
kfree(scsi_tapes[i]);
kfree(scsi_tapes);
- if (st_buffers != NULL) {
- for (i = 0; i < st_nbr_buffers; i++) {
- if (st_buffers[i] != NULL) {
- st_buffers[i]->orig_sg_segs = 0;
- normalize_buffer(st_buffers[i]);
- kfree(st_buffers[i]);
- }
- }
- kfree(st_buffers);
- }
}
st_template.dev_max = 0;
printk(KERN_INFO "st: Unloaded.\n");
diff --git a/drivers/scsi/st_options.h b/drivers/scsi/st_options.h
index 325bd3cb5c1e..2c412f72be13 100644
--- a/drivers/scsi/st_options.h
+++ b/drivers/scsi/st_options.h
@@ -3,7 +3,7 @@
Copyright 1995-2000 Kai Makisara.
- Last modified: Tue Jan 22 21:52:34 2002 by makisara
+ Last modified: Sun May 5 15:09:56 2002 by makisara
*/
#ifndef _ST_OPTIONS_H
@@ -30,22 +30,17 @@
SENSE. */
#define ST_DEFAULT_BLOCK 0
-/* The tape driver buffer size in kilobytes. Must be non-zero. */
-#define ST_BUFFER_BLOCKS 32
+/* The minimum tape driver buffer size in kilobytes in fixed block mode.
+ Must be non-zero. */
+#define ST_FIXED_BUFFER_BLOCKS 32
/* The number of kilobytes of data in the buffer that triggers an
asynchronous write in fixed block mode. See also ST_ASYNC_WRITES
below. */
#define ST_WRITE_THRESHOLD_BLOCKS 30
-/* The maximum number of tape buffers the driver tries to allocate at
- driver initialisation. The number is also constrained by the number
- of drives detected. If more buffers are needed, they are allocated
- at run time and freed after use. */
-#define ST_MAX_BUFFERS 4
-
/* Maximum number of scatter/gather segments */
-#define ST_MAX_SG 16
+#define ST_MAX_SG 64
/* The number of scatter/gather segments to allocate at first try (must be
smaller or equal to the maximum). */