Commit 6350779e authored by James Bottomley's avatar James Bottomley

Merge ssh://raven/BK/scsi-sg-cleanup-2.5

into mulgrave.(none):/home/jejb/BK/scsi-misc-2.5
parents df9a0c82 c23ee349
......@@ -55,7 +55,6 @@
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <linux/mempool.h>
#define __KERNEL_SYSCALLS__
......@@ -74,24 +73,6 @@
#include <linux/kmod.h>
#endif
#define SG_MEMPOOL_NR 5
#define SG_MEMPOOL_SIZE 32
struct scsi_host_sg_pool {
int size;
char *name;
kmem_cache_t *slab;
mempool_t *pool;
};
#define SP(x) { x, "sgpool-" #x }
struct scsi_host_sg_pool scsi_sg_pools[SG_MEMPOOL_NR] = {
SP(8), SP(16), SP(32), SP(64), SP(MAX_PHYS_SEGMENTS)
};
#undef SP
/*
static const char RCSid[] = "$Header: /vger/u4/cvs/linux/drivers/scsi/scsi.c,v 1.38 1997/01/19 23:07:18 davem Exp $";
*/
/*
* Definitions and constants.
......@@ -668,10 +649,7 @@ int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason)
*/
void scsi_release_command(Scsi_Cmnd * SCpnt)
{
request_queue_t *q;
Scsi_Device * SDpnt;
SDpnt = SCpnt->device;
request_queue_t *q = &SCpnt->device->request_queue;
__scsi_release_command(SCpnt);
......@@ -681,7 +659,6 @@ void scsi_release_command(Scsi_Cmnd * SCpnt)
* This won't block - if the device cannot take any more, life
* will go on.
*/
q = &SDpnt->request_queue;
scsi_queue_next_request(q, NULL);
}
......@@ -2082,81 +2059,12 @@ static int __init setup_scsi_default_dev_flags(char *str)
__setup("scsi_default_dev_flags=", setup_scsi_default_dev_flags);
#endif
static void *scsi_pool_alloc(int gfp_mask, void *data)
{
return kmem_cache_alloc(data, gfp_mask);
}
static void scsi_pool_free(void *ptr, void *data)
{
kmem_cache_free(data, ptr);
}
struct scatterlist *scsi_alloc_sgtable(Scsi_Cmnd *SCpnt, int gfp_mask)
{
struct scsi_host_sg_pool *sgp;
struct scatterlist *sgl;
int pf_flags;
BUG_ON(!SCpnt->use_sg);
switch (SCpnt->use_sg) {
case 1 ... 8 : SCpnt->sglist_len = 0; break;
case 9 ... 16 : SCpnt->sglist_len = 1; break;
case 17 ... 32 : SCpnt->sglist_len = 2; break;
case 33 ... 64 : SCpnt->sglist_len = 3; break;
case 65 ... MAX_PHYS_SEGMENTS : SCpnt->sglist_len = 4; break;
default: return NULL;
}
sgp = scsi_sg_pools + SCpnt->sglist_len;
pf_flags = current->flags;
current->flags |= PF_NOWARN;
sgl = mempool_alloc(sgp->pool, gfp_mask);
current->flags = pf_flags;
if (sgl) {
memset(sgl, 0, sgp->size);
return sgl;
}
return sgl;
}
void scsi_free_sgtable(struct scatterlist *sgl, int index)
{
struct scsi_host_sg_pool *sgp = scsi_sg_pools + index;
if (unlikely(index > SG_MEMPOOL_NR)) {
printk("scsi_free_sgtable: mempool %d\n", index);
BUG();
}
mempool_free(sgl, sgp->pool);
}
static int __init init_scsi(void)
{
int i;
printk(KERN_INFO "SCSI subsystem driver " REVISION "\n");
/*
* setup sg memory pools
*/
for (i = 0; i < SG_MEMPOOL_NR; i++) {
struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
int size = sgp->size * sizeof(struct scatterlist);
sgp->slab = kmem_cache_create(sgp->name, size, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
if (!sgp->slab)
printk(KERN_ERR "SCSI: can't init sg slab %s\n", sgp->name);
sgp->pool = mempool_create(SG_MEMPOOL_SIZE, scsi_pool_alloc, scsi_pool_free, sgp->slab);
if (!sgp->pool)
printk(KERN_ERR "SCSI: can't init sg mempool %s\n", sgp->name);
}
scsi_init_queue();
scsi_init_procfs();
devfs_mk_dir(NULL, "scsi", NULL);
scsi_host_init();
......@@ -2168,20 +2076,11 @@ static int __init init_scsi(void)
static void __exit exit_scsi(void)
{
int i;
scsi_sysfs_unregister();
scsi_dev_info_list_delete();
devfs_remove("scsi");
scsi_exit_procfs();
for (i = 0; i < SG_MEMPOOL_NR; i++) {
struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
mempool_destroy(sgp->pool);
kmem_cache_destroy(sgp->slab);
sgp->pool = NULL;
sgp->slab = NULL;
}
scsi_exit_queue();
}
subsys_initcall(init_scsi);
......
......@@ -420,12 +420,6 @@ extern int scsi_partsize(unsigned char *buf, unsigned long capacity,
unsigned int *cyls, unsigned int *hds,
unsigned int *secs);
/*
* sg list allocations
*/
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_lib.c
*/
......@@ -437,13 +431,13 @@ extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
extern void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt);
extern int scsi_prep_fn(struct request_queue *q, struct request *req);
extern void scsi_request_fn(request_queue_t * q);
extern int scsi_starvation_completion(Scsi_Device * SDpnt);
extern int scsi_init_queue(void);
extern void scsi_exit_queue(void);
/*
* Prototypes for functions in scsi.c
*/
extern int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt);
extern void scsi_bottom_half_handler(void);
extern void scsi_release_commandblocks(Scsi_Device * SDpnt);
extern void scsi_build_commandblocks(Scsi_Device * SDpnt);
extern void scsi_adjust_queue_depth(Scsi_Device *, int, int);
......@@ -462,7 +456,6 @@ extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd,
void *buffer, unsigned bufflen,
void (*done) (struct scsi_cmnd *),
int timeout, int retries);
extern int scsi_dev_init(void);
extern int scsi_mlqueue_insert(struct scsi_cmnd *, int);
extern int scsi_attach_device(struct scsi_device *);
extern void scsi_detach_device(struct scsi_device *);
......
......@@ -11,12 +11,29 @@
#include <linux/blk.h>
#include <linux/completion.h>
#include <linux/kernel.h>
#include <linux/mempool.h>
#include <linux/slab.h>
#include "scsi.h"
#include "hosts.h"
#define SG_MEMPOOL_NR 5
#define SG_MEMPOOL_SIZE 32
struct scsi_host_sg_pool {
size_t size;
char *name;
kmem_cache_t *slab;
mempool_t *pool;
};
#define SP(x) { x, "sgpool-" #x }
struct scsi_host_sg_pool scsi_sg_pools[SG_MEMPOOL_NR] = {
SP(8), SP(16), SP(32), SP(64), SP(MAX_PHYS_SEGMENTS)
};
#undef SP
/*
* Function: scsi_insert_special_cmd()
*
......@@ -348,6 +365,51 @@ static Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt,
return NULL;
}
static struct scatterlist *scsi_alloc_sgtable(Scsi_Cmnd *SCpnt, int gfp_mask)
{
struct scsi_host_sg_pool *sgp;
struct scatterlist *sgl;
BUG_ON(!SCpnt->use_sg);
switch (SCpnt->use_sg) {
case 1 ... 8:
SCpnt->sglist_len = 0;
break;
case 9 ... 16:
SCpnt->sglist_len = 1;
break;
case 17 ... 32:
SCpnt->sglist_len = 2;
break;
case 33 ... 64:
SCpnt->sglist_len = 3;
break;
case 65 ... MAX_PHYS_SEGMENTS:
SCpnt->sglist_len = 4;
break;
default:
return NULL;
}
sgp = scsi_sg_pools + SCpnt->sglist_len;
sgl = mempool_alloc(sgp->pool, gfp_mask);
if (sgl)
memset(sgl, 0, sgp->size);
return sgl;
}
static void scsi_free_sgtable(struct scatterlist *sgl, int index)
{
struct scsi_host_sg_pool *sgp;
BUG_ON(index > SG_MEMPOOL_NR);
sgp = scsi_sg_pools + index;
mempool_free(sgl, sgp->pool);
}
/*
* Function: scsi_release_buffers()
*
......@@ -374,15 +436,10 @@ static void scsi_release_buffers(Scsi_Cmnd * SCpnt)
/*
* Free up any indirection buffers we allocated for DMA purposes.
*/
if (SCpnt->use_sg) {
struct scatterlist *sgpnt;
sgpnt = (struct scatterlist *) SCpnt->request_buffer;
if (SCpnt->use_sg)
scsi_free_sgtable(SCpnt->request_buffer, SCpnt->sglist_len);
} else {
if (SCpnt->request_buffer != req->buffer)
kfree(SCpnt->request_buffer);
}
else if (SCpnt->request_buffer != req->buffer)
kfree(SCpnt->request_buffer);
/*
* Zero these out. They now point to freed memory, and it is
......@@ -462,22 +519,16 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
* For the case of a READ, we need to copy the data out of the
* bounce buffer and into the real buffer.
*/
if (SCpnt->use_sg) {
struct scatterlist *sgpnt;
sgpnt = (struct scatterlist *) SCpnt->buffer;
if (SCpnt->use_sg)
scsi_free_sgtable(SCpnt->buffer, SCpnt->sglist_len);
} else {
if (SCpnt->buffer != req->buffer) {
if (rq_data_dir(req) == READ) {
unsigned long flags;
char *to = bio_kmap_irq(req->bio, &flags);
memcpy(to, SCpnt->buffer, SCpnt->bufflen);
bio_kunmap_irq(to, &flags);
}
kfree(SCpnt->buffer);
else if (SCpnt->buffer != req->buffer) {
if (rq_data_dir(req) == READ) {
unsigned long flags;
char *to = bio_kmap_irq(req->bio, &flags);
memcpy(to, SCpnt->buffer, SCpnt->bufflen);
bio_kunmap_irq(to, &flags);
}
kfree(SCpnt->buffer);
}
if (blk_pc_request(req)) {
......@@ -1093,3 +1144,41 @@ void scsi_register_blocked_host(struct Scsi_Host * SHpnt)
void scsi_deregister_blocked_host(struct Scsi_Host * SHpnt)
{
}
int __init scsi_init_queue(void)
{
int i;
for (i = 0; i < SG_MEMPOOL_NR; i++) {
struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
int size = sgp->size * sizeof(struct scatterlist);
sgp->slab = kmem_cache_create(sgp->name, size, 0,
SLAB_HWCACHE_ALIGN, NULL, NULL);
if (!sgp->slab) {
printk(KERN_ERR "SCSI: can't init sg slab %s\n",
sgp->name);
}
sgp->pool = mempool_create(SG_MEMPOOL_SIZE,
mempool_alloc_slab, mempool_free_slab,
sgp->slab);
if (!sgp->pool) {
printk(KERN_ERR "SCSI: can't init sg mempool %s\n",
sgp->name);
}
}
return 0;
}
void __exit scsi_exit_lib(void)
{
int i;
for (i = 0; i < SG_MEMPOOL_NR; i++) {
struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
mempool_destroy(sgp->pool);
kmem_cache_destroy(sgp->slab);
}
}
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