aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sg.c
diff options
context:
space:
mode:
authorDouglas Gilbert <dougg@torque.net>2006-09-20 18:20:49 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-09-26 12:23:15 -0400
commit6460e75a104d10458817d2f5b2fbff775bf0b43a (patch)
tree88e2a88aef94282728d1c764d02e5efa7ef7fee4 /drivers/scsi/sg.c
parent8aee918a1cff2a3722ce76fc6fa5abe09aa98d1b (diff)
[SCSI] sg: fixes for large page_size
This sg driver patch addresses the problem with larger page sizes reported by Brian King in this post: http://marc.theaimsgroup.com/?l=linux-scsi&m=115867718623631&w=2 Some other related matters are also addressed. Some of these prevent oopses when the SG_SCATTER_SZ or scatter_elem_sz are set to inappropriate values. The scatter_elem_sz has been tested up to 4 MB which should make the largest data transfer with one SCSI command, 32 MB less one block, achievable with a relatively small number of elements in the scatter gather list. ChangeLog: - add scatter_elem_sz boot time parameter and sysfs module parameter that is initialized to SG_SCATTER_SZ - the driver will then adjust scatter_elem_sz to be the max(given(scatter_elem_sz), PAGE_SIZE) It will also round it up, if necessary, to be a power of two - clean up sg.h header, correct bad urls and some statements that are no longer valid - make the def_reserved_size sysfs module attribute writable Signed-off-by: Douglas Gilbert <dougg@torque.net> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/sg.c')
-rw-r--r--drivers/scsi/sg.c53
1 files changed, 40 insertions, 13 deletions
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 34f9343ed0af..3f8b93188567 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -60,7 +60,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */
60 60
61#ifdef CONFIG_SCSI_PROC_FS 61#ifdef CONFIG_SCSI_PROC_FS
62#include <linux/proc_fs.h> 62#include <linux/proc_fs.h>
63static char *sg_version_date = "20060818"; 63static char *sg_version_date = "20060920";
64 64
65static int sg_proc_init(void); 65static int sg_proc_init(void);
66static void sg_proc_cleanup(void); 66static void sg_proc_cleanup(void);
@@ -94,6 +94,9 @@ int sg_big_buff = SG_DEF_RESERVED_SIZE;
94static int def_reserved_size = -1; /* picks up init parameter */ 94static int def_reserved_size = -1; /* picks up init parameter */
95static int sg_allow_dio = SG_ALLOW_DIO_DEF; 95static int sg_allow_dio = SG_ALLOW_DIO_DEF;
96 96
97static int scatter_elem_sz = SG_SCATTER_SZ;
98static int scatter_elem_sz_prev = SG_SCATTER_SZ;
99
97#define SG_SECTOR_SZ 512 100#define SG_SECTOR_SZ 512
98#define SG_SECTOR_MSK (SG_SECTOR_SZ - 1) 101#define SG_SECTOR_MSK (SG_SECTOR_SZ - 1)
99 102
@@ -1537,11 +1540,9 @@ sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf)
1537 msleep(10); /* dirty detach so delay device destruction */ 1540 msleep(10); /* dirty detach so delay device destruction */
1538} 1541}
1539 1542
1540/* Set 'perm' (4th argument) to 0 to disable module_param's definition 1543module_param_named(scatter_elem_sz, scatter_elem_sz, int, S_IRUGO | S_IWUSR);
1541 * of sysfs parameters (which module_param doesn't yet support). 1544module_param_named(def_reserved_size, def_reserved_size, int,
1542 * Sysfs parameters defined explicitly below. 1545 S_IRUGO | S_IWUSR);
1543 */
1544module_param_named(def_reserved_size, def_reserved_size, int, S_IRUGO);
1545module_param_named(allow_dio, sg_allow_dio, int, S_IRUGO | S_IWUSR); 1546module_param_named(allow_dio, sg_allow_dio, int, S_IRUGO | S_IWUSR);
1546 1547
1547MODULE_AUTHOR("Douglas Gilbert"); 1548MODULE_AUTHOR("Douglas Gilbert");
@@ -1550,6 +1551,8 @@ MODULE_LICENSE("GPL");
1550MODULE_VERSION(SG_VERSION_STR); 1551MODULE_VERSION(SG_VERSION_STR);
1551MODULE_ALIAS_CHARDEV_MAJOR(SCSI_GENERIC_MAJOR); 1552MODULE_ALIAS_CHARDEV_MAJOR(SCSI_GENERIC_MAJOR);
1552 1553
1554MODULE_PARM_DESC(scatter_elem_sz, "scatter gather element "
1555 "size (default: max(SG_SCATTER_SZ, PAGE_SIZE))");
1553MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd"); 1556MODULE_PARM_DESC(def_reserved_size, "size of buffer reserved for each fd");
1554MODULE_PARM_DESC(allow_dio, "allow direct I/O (default: 0 (disallow))"); 1557MODULE_PARM_DESC(allow_dio, "allow direct I/O (default: 0 (disallow))");
1555 1558
@@ -1558,8 +1561,14 @@ init_sg(void)
1558{ 1561{
1559 int rc; 1562 int rc;
1560 1563
1564 if (scatter_elem_sz < PAGE_SIZE) {
1565 scatter_elem_sz = PAGE_SIZE;
1566 scatter_elem_sz_prev = scatter_elem_sz;
1567 }
1561 if (def_reserved_size >= 0) 1568 if (def_reserved_size >= 0)
1562 sg_big_buff = def_reserved_size; 1569 sg_big_buff = def_reserved_size;
1570 else
1571 def_reserved_size = sg_big_buff;
1563 1572
1564 rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), 1573 rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0),
1565 SG_MAX_DEVS, "sg"); 1574 SG_MAX_DEVS, "sg");
@@ -1842,15 +1851,30 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
1842 if (mx_sc_elems < 0) 1851 if (mx_sc_elems < 0)
1843 return mx_sc_elems; /* most likely -ENOMEM */ 1852 return mx_sc_elems; /* most likely -ENOMEM */
1844 1853
1854 num = scatter_elem_sz;
1855 if (unlikely(num != scatter_elem_sz_prev)) {
1856 if (num < PAGE_SIZE) {
1857 scatter_elem_sz = PAGE_SIZE;
1858 scatter_elem_sz_prev = PAGE_SIZE;
1859 } else
1860 scatter_elem_sz_prev = num;
1861 }
1845 for (k = 0, sg = schp->buffer, rem_sz = blk_size; 1862 for (k = 0, sg = schp->buffer, rem_sz = blk_size;
1846 (rem_sz > 0) && (k < mx_sc_elems); 1863 (rem_sz > 0) && (k < mx_sc_elems);
1847 ++k, rem_sz -= ret_sz, ++sg) { 1864 ++k, rem_sz -= ret_sz, ++sg) {
1848 1865
1849 num = (rem_sz > SG_SCATTER_SZ) ? SG_SCATTER_SZ : rem_sz; 1866 num = (rem_sz > scatter_elem_sz_prev) ?
1867 scatter_elem_sz_prev : rem_sz;
1850 p = sg_page_malloc(num, sfp->low_dma, &ret_sz); 1868 p = sg_page_malloc(num, sfp->low_dma, &ret_sz);
1851 if (!p) 1869 if (!p)
1852 return -ENOMEM; 1870 return -ENOMEM;
1853 1871
1872 if (num == scatter_elem_sz_prev) {
1873 if (unlikely(ret_sz > scatter_elem_sz_prev)) {
1874 scatter_elem_sz = ret_sz;
1875 scatter_elem_sz_prev = ret_sz;
1876 }
1877 }
1854 sg->page = p; 1878 sg->page = p;
1855 sg->length = ret_sz; 1879 sg->length = ret_sz;
1856 1880
@@ -2341,6 +2365,9 @@ sg_add_sfp(Sg_device * sdp, int dev)
2341 } 2365 }
2342 write_unlock_irqrestore(&sg_dev_arr_lock, iflags); 2366 write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
2343 SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp)); 2367 SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp));
2368 if (unlikely(sg_big_buff != def_reserved_size))
2369 sg_big_buff = def_reserved_size;
2370
2344 sg_build_reserve(sfp, sg_big_buff); 2371 sg_build_reserve(sfp, sg_big_buff);
2345 SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: bufflen=%d, k_use_sg=%d\n", 2372 SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: bufflen=%d, k_use_sg=%d\n",
2346 sfp->reserve.bufflen, sfp->reserve.k_use_sg)); 2373 sfp->reserve.bufflen, sfp->reserve.k_use_sg));
@@ -2437,16 +2464,16 @@ sg_res_in_use(Sg_fd * sfp)
2437 return srp ? 1 : 0; 2464 return srp ? 1 : 0;
2438} 2465}
2439 2466
2440/* If retSzp==NULL want exact size or fail */ 2467/* The size fetched (value output via retSzp) set when non-NULL return */
2441static struct page * 2468static struct page *
2442sg_page_malloc(int rqSz, int lowDma, int *retSzp) 2469sg_page_malloc(int rqSz, int lowDma, int *retSzp)
2443{ 2470{
2444 struct page *resp = NULL; 2471 struct page *resp = NULL;
2445 gfp_t page_mask; 2472 gfp_t page_mask;
2446 int order, a_size; 2473 int order, a_size;
2447 int resSz = rqSz; 2474 int resSz;
2448 2475
2449 if (rqSz <= 0) 2476 if ((rqSz <= 0) || (NULL == retSzp))
2450 return resp; 2477 return resp;
2451 2478
2452 if (lowDma) 2479 if (lowDma)
@@ -2456,8 +2483,9 @@ sg_page_malloc(int rqSz, int lowDma, int *retSzp)
2456 2483
2457 for (order = 0, a_size = PAGE_SIZE; a_size < rqSz; 2484 for (order = 0, a_size = PAGE_SIZE; a_size < rqSz;
2458 order++, a_size <<= 1) ; 2485 order++, a_size <<= 1) ;
2486 resSz = a_size; /* rounded up if necessary */
2459 resp = alloc_pages(page_mask, order); 2487 resp = alloc_pages(page_mask, order);
2460 while ((!resp) && order && retSzp) { 2488 while ((!resp) && order) {
2461 --order; 2489 --order;
2462 a_size >>= 1; /* divide by 2, until PAGE_SIZE */ 2490 a_size >>= 1; /* divide by 2, until PAGE_SIZE */
2463 resp = alloc_pages(page_mask, order); /* try half */ 2491 resp = alloc_pages(page_mask, order); /* try half */
@@ -2466,8 +2494,7 @@ sg_page_malloc(int rqSz, int lowDma, int *retSzp)
2466 if (resp) { 2494 if (resp) {
2467 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) 2495 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
2468 memset(page_address(resp), 0, resSz); 2496 memset(page_address(resp), 0, resSz);
2469 if (retSzp) 2497 *retSzp = resSz;
2470 *retSzp = resSz;
2471 } 2498 }
2472 return resp; 2499 return resp;
2473} 2500}