Commit c23ee349 authored by Christoph Hellwig's avatar Christoph Hellwig

[PATCH] move all sgtable handling in one place

We only need it in scsi_lib.c so the helper should be there aswell.
parent d9841db4
...@@ -55,7 +55,6 @@ ...@@ -55,7 +55,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/mempool.h>
#define __KERNEL_SYSCALLS__ #define __KERNEL_SYSCALLS__
...@@ -74,24 +73,6 @@ ...@@ -74,24 +73,6 @@
#include <linux/kmod.h> #include <linux/kmod.h>
#endif #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. * Definitions and constants.
...@@ -668,10 +649,7 @@ int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason) ...@@ -668,10 +649,7 @@ int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason)
*/ */
void scsi_release_command(Scsi_Cmnd * SCpnt) void scsi_release_command(Scsi_Cmnd * SCpnt)
{ {
request_queue_t *q; request_queue_t *q = &SCpnt->device->request_queue;
Scsi_Device * SDpnt;
SDpnt = SCpnt->device;
__scsi_release_command(SCpnt); __scsi_release_command(SCpnt);
...@@ -681,7 +659,6 @@ void scsi_release_command(Scsi_Cmnd * SCpnt) ...@@ -681,7 +659,6 @@ void scsi_release_command(Scsi_Cmnd * SCpnt)
* This won't block - if the device cannot take any more, life * This won't block - if the device cannot take any more, life
* will go on. * will go on.
*/ */
q = &SDpnt->request_queue;
scsi_queue_next_request(q, NULL); scsi_queue_next_request(q, NULL);
} }
...@@ -2084,81 +2061,12 @@ static int __init setup_scsi_default_dev_flags(char *str) ...@@ -2084,81 +2061,12 @@ static int __init setup_scsi_default_dev_flags(char *str)
__setup("scsi_default_dev_flags=", setup_scsi_default_dev_flags); __setup("scsi_default_dev_flags=", setup_scsi_default_dev_flags);
#endif #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) static int __init init_scsi(void)
{ {
int i;
printk(KERN_INFO "SCSI subsystem driver " REVISION "\n"); printk(KERN_INFO "SCSI subsystem driver " REVISION "\n");
/* scsi_init_queue();
* 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_procfs(); scsi_init_procfs();
scsi_devfs_handle = devfs_mk_dir(NULL, "scsi", NULL); scsi_devfs_handle = devfs_mk_dir(NULL, "scsi", NULL);
scsi_host_init(); scsi_host_init();
...@@ -2170,20 +2078,11 @@ static int __init init_scsi(void) ...@@ -2170,20 +2078,11 @@ static int __init init_scsi(void)
static void __exit exit_scsi(void) static void __exit exit_scsi(void)
{ {
int i;
scsi_sysfs_unregister(); scsi_sysfs_unregister();
scsi_dev_info_list_delete(); scsi_dev_info_list_delete();
devfs_unregister(scsi_devfs_handle); devfs_unregister(scsi_devfs_handle);
scsi_exit_procfs(); scsi_exit_procfs();
scsi_exit_queue();
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;
}
} }
subsys_initcall(init_scsi); subsys_initcall(init_scsi);
......
...@@ -420,12 +420,6 @@ extern int scsi_partsize(unsigned char *buf, unsigned long capacity, ...@@ -420,12 +420,6 @@ extern int scsi_partsize(unsigned char *buf, unsigned long capacity,
unsigned int *cyls, unsigned int *hds, unsigned int *cyls, unsigned int *hds,
unsigned int *secs); 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 * Prototypes for functions in scsi_lib.c
*/ */
...@@ -437,13 +431,13 @@ extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors, ...@@ -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 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 int scsi_prep_fn(struct request_queue *q, struct request *req);
extern void scsi_request_fn(request_queue_t * q); 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 * Prototypes for functions in scsi.c
*/ */
extern int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt); 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_release_commandblocks(Scsi_Device * SDpnt);
extern void scsi_build_commandblocks(Scsi_Device * SDpnt); extern void scsi_build_commandblocks(Scsi_Device * SDpnt);
extern void scsi_adjust_queue_depth(Scsi_Device *, int, int); extern void scsi_adjust_queue_depth(Scsi_Device *, int, int);
...@@ -462,7 +456,6 @@ extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd, ...@@ -462,7 +456,6 @@ extern void scsi_do_cmd(Scsi_Cmnd *, const void *cmnd,
void *buffer, unsigned bufflen, void *buffer, unsigned bufflen,
void (*done) (struct scsi_cmnd *), void (*done) (struct scsi_cmnd *),
int timeout, int retries); int timeout, int retries);
extern int scsi_dev_init(void);
extern int scsi_mlqueue_insert(struct scsi_cmnd *, int); extern int scsi_mlqueue_insert(struct scsi_cmnd *, int);
extern int scsi_attach_device(struct scsi_device *); extern int scsi_attach_device(struct scsi_device *);
extern void scsi_detach_device(struct scsi_device *); extern void scsi_detach_device(struct scsi_device *);
......
...@@ -11,12 +11,29 @@ ...@@ -11,12 +11,29 @@
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mempool.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.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() * Function: scsi_insert_special_cmd()
* *
...@@ -348,6 +365,51 @@ static Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, ...@@ -348,6 +365,51 @@ static Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt,
return NULL; 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() * Function: scsi_release_buffers()
* *
...@@ -374,15 +436,10 @@ static void scsi_release_buffers(Scsi_Cmnd * SCpnt) ...@@ -374,15 +436,10 @@ static void scsi_release_buffers(Scsi_Cmnd * SCpnt)
/* /*
* Free up any indirection buffers we allocated for DMA purposes. * Free up any indirection buffers we allocated for DMA purposes.
*/ */
if (SCpnt->use_sg) { if (SCpnt->use_sg)
struct scatterlist *sgpnt;
sgpnt = (struct scatterlist *) SCpnt->request_buffer;
scsi_free_sgtable(SCpnt->request_buffer, SCpnt->sglist_len); scsi_free_sgtable(SCpnt->request_buffer, SCpnt->sglist_len);
} else { else if (SCpnt->request_buffer != req->buffer)
if (SCpnt->request_buffer != req->buffer)
kfree(SCpnt->request_buffer); kfree(SCpnt->request_buffer);
}
/* /*
* Zero these out. They now point to freed memory, and it is * Zero these out. They now point to freed memory, and it is
...@@ -462,23 +519,17 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors, ...@@ -462,23 +519,17 @@ 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 * For the case of a READ, we need to copy the data out of the
* bounce buffer and into the real buffer. * bounce buffer and into the real buffer.
*/ */
if (SCpnt->use_sg) { if (SCpnt->use_sg)
struct scatterlist *sgpnt;
sgpnt = (struct scatterlist *) SCpnt->buffer;
scsi_free_sgtable(SCpnt->buffer, SCpnt->sglist_len); scsi_free_sgtable(SCpnt->buffer, SCpnt->sglist_len);
} else { else if (SCpnt->buffer != req->buffer) {
if (SCpnt->buffer != req->buffer) {
if (rq_data_dir(req) == READ) { if (rq_data_dir(req) == READ) {
unsigned long flags; unsigned long flags;
char *to = bio_kmap_irq(req->bio, &flags); char *to = bio_kmap_irq(req->bio, &flags);
memcpy(to, SCpnt->buffer, SCpnt->bufflen); memcpy(to, SCpnt->buffer, SCpnt->bufflen);
bio_kunmap_irq(to, &flags); bio_kunmap_irq(to, &flags);
} }
kfree(SCpnt->buffer); kfree(SCpnt->buffer);
} }
}
if (blk_pc_request(req)) { if (blk_pc_request(req)) {
req->errors = result & 0xff; req->errors = result & 0xff;
...@@ -1093,3 +1144,41 @@ void scsi_register_blocked_host(struct Scsi_Host * SHpnt) ...@@ -1093,3 +1144,41 @@ void scsi_register_blocked_host(struct Scsi_Host * SHpnt)
void scsi_deregister_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