aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@csr.com>2007-08-08 09:23:48 -0400
committerPierre Ossman <drzeus@drzeus.cx>2007-09-23 15:19:26 -0400
commit9a08f82b3cc522f727ace580a2aaee5402435bc8 (patch)
tree81818bba503a469184883b0ea8c436b9ce97aa0f
parent7616ee95f27a04fd5a6434e9ef4a82cec4b2807c (diff)
sdio: set the functions' block size
Before a driver is probed, set the function's block size to the default so the driver is sure the block size is something sensible and it needn't explicitly set it. The default block size is the largest that's supported by both the card and the host, with a maximum of 512 to ensure aribitrarily sized transfer use the optimal (least) number of commands. See http://lkml.org/lkml/2007/8/7/150 for reasons for the block size choice. Signed-off-by: David Vrabel <david.vrabel@csr.com> Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
-rw-r--r--drivers/mmc/core/sdio_bus.c9
-rw-r--r--drivers/mmc/core/sdio_cis.c2
-rw-r--r--drivers/mmc/core/sdio_io.c49
-rw-r--r--include/linux/mmc/sdio_func.h5
4 files changed, 63 insertions, 2 deletions
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index d229020db4a2..fcb13fb0daad 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -128,11 +128,20 @@ static int sdio_bus_probe(struct device *dev)
128 struct sdio_driver *drv = to_sdio_driver(dev->driver); 128 struct sdio_driver *drv = to_sdio_driver(dev->driver);
129 struct sdio_func *func = dev_to_sdio_func(dev); 129 struct sdio_func *func = dev_to_sdio_func(dev);
130 const struct sdio_device_id *id; 130 const struct sdio_device_id *id;
131 int ret;
131 132
132 id = sdio_match_device(func, drv); 133 id = sdio_match_device(func, drv);
133 if (!id) 134 if (!id)
134 return -ENODEV; 135 return -ENODEV;
135 136
137 /* Set the default block size so the driver is sure it's something
138 * sensible. */
139 sdio_claim_host(func);
140 ret = sdio_set_block_size(func, 0);
141 sdio_release_host(func);
142 if (ret)
143 return ret;
144
136 return drv->probe(func, id); 145 return drv->probe(func, id);
137} 146}
138 147
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index d050c40cf046..1d03f12bbb38 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -79,7 +79,7 @@ static int cistpl_funce_func(struct sdio_func *func,
79 return -EINVAL; 79 return -EINVAL;
80 80
81 /* TPLFE_MAX_BLK_SIZE */ 81 /* TPLFE_MAX_BLK_SIZE */
82 func->blksize = buf[12] | (buf[13] << 8); 82 func->max_blksize = buf[12] | (buf[13] << 8);
83 83
84 return 0; 84 return 0;
85} 85}
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index ecdb77242e98..c2bad1195e3b 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -141,6 +141,55 @@ err:
141EXPORT_SYMBOL_GPL(sdio_disable_func); 141EXPORT_SYMBOL_GPL(sdio_disable_func);
142 142
143/** 143/**
144 * sdio_set_block_size - set the block size of an SDIO function
145 * @func: SDIO function to change
146 * @blksz: new block size or 0 to use the default.
147 *
148 * The default block size is the largest supported by both the function
149 * and the host, with a maximum of 512 to ensure that arbitrarily sized
150 * data transfer use the optimal (least) number of commands.
151 *
152 * A driver may call this to override the default block size set by the
153 * core. This can be used to set a block size greater than the maximum
154 * that reported by the card; it is the driver's responsibility to ensure
155 * it uses a value that the card supports.
156 *
157 * Returns 0 on success, -EINVAL if the host does not support the
158 * requested block size, or -EIO (etc.) if one of the resultant FBR block
159 * size register writes failed.
160 *
161 */
162int sdio_set_block_size(struct sdio_func *func, unsigned blksz)
163{
164 int ret;
165
166 if (blksz > func->card->host->max_blk_size)
167 return -EINVAL;
168
169 if (blksz == 0) {
170 blksz = min(min(
171 func->max_blksize,
172 func->card->host->max_blk_size),
173 512u);
174 }
175
176 ret = mmc_io_rw_direct(func->card, 1, 0,
177 SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE,
178 blksz & 0xff, NULL);
179 if (ret)
180 return ret;
181 ret = mmc_io_rw_direct(func->card, 1, 0,
182 SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE + 1,
183 (blksz >> 8) & 0xff, NULL);
184 if (ret)
185 return ret;
186 func->cur_blksize = blksz;
187 return 0;
188}
189
190EXPORT_SYMBOL_GPL(sdio_set_block_size);
191
192/**
144 * sdio_readb - read a single byte from a SDIO function 193 * sdio_readb - read a single byte from a SDIO function
145 * @func: SDIO function to access 194 * @func: SDIO function to access
146 * @addr: address to read 195 * @addr: address to read
diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
index af813fffc4ac..f05757984e8d 100644
--- a/include/linux/mmc/sdio_func.h
+++ b/include/linux/mmc/sdio_func.h
@@ -43,7 +43,8 @@ struct sdio_func {
43 unsigned short vendor; /* vendor id */ 43 unsigned short vendor; /* vendor id */
44 unsigned short device; /* device id */ 44 unsigned short device; /* device id */
45 45
46 unsigned short blksize; /* maximum block size */ 46 unsigned max_blksize; /* maximum block size */
47 unsigned cur_blksize; /* current block size */
47 48
48 unsigned int state; /* function state */ 49 unsigned int state; /* function state */
49#define SDIO_STATE_PRESENT (1<<0) /* present in sysfs */ 50#define SDIO_STATE_PRESENT (1<<0) /* present in sysfs */
@@ -111,6 +112,8 @@ extern void sdio_release_host(struct sdio_func *func);
111extern int sdio_enable_func(struct sdio_func *func); 112extern int sdio_enable_func(struct sdio_func *func);
112extern int sdio_disable_func(struct sdio_func *func); 113extern int sdio_disable_func(struct sdio_func *func);
113 114
115extern int sdio_set_block_size(struct sdio_func *func, unsigned blksz);
116
114extern int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler); 117extern int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler);
115extern int sdio_release_irq(struct sdio_func *func); 118extern int sdio_release_irq(struct sdio_func *func);
116 119