.. | .. |
---|
4 | 4 | |
---|
5 | 5 | #include <linux/blkdev.h> |
---|
6 | 6 | #include <linux/blkpg.h> |
---|
| 7 | +#include <linux/blk-mq.h> |
---|
7 | 8 | #include <linux/clk.h> |
---|
8 | 9 | #include <linux/delay.h> |
---|
9 | 10 | #include <linux/freezer.h> |
---|
.. | .. |
---|
68 | 69 | #define DISABLE_READ _IO('V', 2) |
---|
69 | 70 | #define ENABLE_READ _IO('V', 3) |
---|
70 | 71 | |
---|
71 | | -static DECLARE_WAIT_QUEUE_HEAD(rkflash_thread_wait); |
---|
72 | | -static unsigned long rkflash_req_jiffies; |
---|
73 | | -static unsigned int rknand_req_do; |
---|
| 72 | +/* Thread for gc operation */ |
---|
| 73 | +static DECLARE_WAIT_QUEUE_HEAD(nand_gc_thread_wait); |
---|
| 74 | +static unsigned long nand_gc_do; |
---|
| 75 | +static struct task_struct *nand_gc_thread __read_mostly; |
---|
74 | 76 | |
---|
75 | 77 | /* For rkflash dev private data, including mtd dev and block dev */ |
---|
76 | | -static int rkflash_dev_initialised = 0; |
---|
| 78 | +static int rkflash_dev_initialised; |
---|
77 | 79 | static DEFINE_MUTEX(g_flash_ops_mutex); |
---|
78 | | - |
---|
79 | | -static int rkflash_flash_gc(void) |
---|
80 | | -{ |
---|
81 | | - int ret; |
---|
82 | | - |
---|
83 | | - if (g_boot_ops->gc) { |
---|
84 | | - mutex_lock(&g_flash_ops_mutex); |
---|
85 | | - ret = g_boot_ops->gc(); |
---|
86 | | - mutex_unlock(&g_flash_ops_mutex); |
---|
87 | | - } else { |
---|
88 | | - ret = -EPERM; |
---|
89 | | - } |
---|
90 | | - |
---|
91 | | - return ret; |
---|
92 | | -} |
---|
93 | | - |
---|
94 | | -static int rkflash_blk_discard(u32 sec, u32 n_sec) |
---|
95 | | -{ |
---|
96 | | - int ret; |
---|
97 | | - |
---|
98 | | - if (g_boot_ops->discard) { |
---|
99 | | - mutex_lock(&g_flash_ops_mutex); |
---|
100 | | - ret = g_boot_ops->discard(sec, n_sec); |
---|
101 | | - mutex_unlock(&g_flash_ops_mutex); |
---|
102 | | - } else { |
---|
103 | | - ret = -EPERM; |
---|
104 | | - } |
---|
105 | | - |
---|
106 | | - return ret; |
---|
107 | | -}; |
---|
108 | 80 | |
---|
109 | 81 | static unsigned int rk_partition_init(struct flash_part *part) |
---|
110 | 82 | { |
---|
.. | .. |
---|
172 | 144 | return single_open(file, rkflash_blk_proc_show, PDE_DATA(inode)); |
---|
173 | 145 | } |
---|
174 | 146 | |
---|
175 | | -static const struct file_operations rkflash_blk_proc_fops = { |
---|
176 | | - .owner = THIS_MODULE, |
---|
177 | | - .open = rkflash_blk_proc_open, |
---|
178 | | - .read = seq_read, |
---|
179 | | - .llseek = seq_lseek, |
---|
180 | | - .release = single_release, |
---|
| 147 | +static const struct proc_ops rkflash_blk_proc_fops = { |
---|
| 148 | + .proc_open = rkflash_blk_proc_open, |
---|
| 149 | + .proc_read = seq_read, |
---|
| 150 | + .proc_lseek = seq_lseek, |
---|
| 151 | + .proc_release = single_release, |
---|
181 | 152 | }; |
---|
182 | 153 | |
---|
183 | 154 | static int rkflash_blk_create_procfs(void) |
---|
.. | .. |
---|
192 | 163 | return 0; |
---|
193 | 164 | } |
---|
194 | 165 | |
---|
| 166 | +static int rkflash_blk_discard(u32 sec, u32 n_sec) |
---|
| 167 | +{ |
---|
| 168 | + int ret; |
---|
| 169 | + |
---|
| 170 | + if (g_boot_ops->discard) |
---|
| 171 | + ret = g_boot_ops->discard(sec, n_sec); |
---|
| 172 | + else |
---|
| 173 | + ret = -EPERM; |
---|
| 174 | + |
---|
| 175 | + return ret; |
---|
| 176 | +}; |
---|
| 177 | + |
---|
195 | 178 | static int rkflash_blk_xfer(struct flash_blk_dev *dev, |
---|
196 | 179 | unsigned long start, |
---|
197 | 180 | unsigned long nsector, |
---|
198 | 181 | char *buf, |
---|
199 | | - int cmd, |
---|
200 | | - int totle_nsec) |
---|
| 182 | + int cmd) |
---|
201 | 183 | { |
---|
202 | 184 | int ret; |
---|
203 | 185 | |
---|
.. | .. |
---|
213 | 195 | case READ: |
---|
214 | 196 | totle_read_data += nsector; |
---|
215 | 197 | totle_read_count++; |
---|
216 | | - mutex_lock(&g_flash_ops_mutex); |
---|
217 | 198 | rkflash_print_bio("rkflash r sec= %lx, n_sec= %lx\n", |
---|
218 | 199 | start, nsector); |
---|
219 | 200 | ret = g_boot_ops->read(start, nsector, buf); |
---|
220 | | - mutex_unlock(&g_flash_ops_mutex); |
---|
221 | 201 | if (ret) |
---|
222 | 202 | ret = -EIO; |
---|
223 | 203 | break; |
---|
.. | .. |
---|
225 | 205 | case WRITE: |
---|
226 | 206 | totle_write_data += nsector; |
---|
227 | 207 | totle_write_count++; |
---|
228 | | - mutex_lock(&g_flash_ops_mutex); |
---|
229 | 208 | rkflash_print_bio("rkflash w sec= %lx, n_sec= %lx\n", |
---|
230 | 209 | start, nsector); |
---|
231 | 210 | ret = g_boot_ops->write(start, nsector, buf); |
---|
232 | | - mutex_unlock(&g_flash_ops_mutex); |
---|
233 | 211 | if (ret) |
---|
234 | 212 | ret = -EIO; |
---|
235 | 213 | break; |
---|
.. | .. |
---|
270 | 248 | return 1; |
---|
271 | 249 | } |
---|
272 | 250 | |
---|
273 | | -static int rkflash_blktrans_thread(void *arg) |
---|
| 251 | +static blk_status_t do_blktrans_all_request(struct flash_blk_ops *tr, |
---|
| 252 | + struct flash_blk_dev *dev, |
---|
| 253 | + struct request *req) |
---|
274 | 254 | { |
---|
275 | | - struct flash_blk_ops *blk_ops = arg; |
---|
276 | | - struct request_queue *rq = blk_ops->rq; |
---|
277 | | - struct request *req = NULL; |
---|
278 | | - char *buf, *page_buf; |
---|
| 255 | + unsigned long block, nsect; |
---|
| 256 | + char *buf = NULL, *page_buf; |
---|
279 | 257 | struct req_iterator rq_iter; |
---|
280 | 258 | struct bio_vec bvec; |
---|
281 | | - unsigned long long sector_index = ULLONG_MAX; |
---|
| 259 | + int ret; |
---|
282 | 260 | unsigned long totle_nsect; |
---|
283 | | - int rw_flag = 0; |
---|
284 | 261 | |
---|
285 | | - spin_lock_irq(rq->queue_lock); |
---|
286 | | - while (!blk_ops->quit) { |
---|
287 | | - int res; |
---|
288 | | - struct flash_blk_dev *dev; |
---|
289 | | - DECLARE_WAITQUEUE(wait, current); |
---|
| 262 | + block = blk_rq_pos(req); |
---|
| 263 | + nsect = blk_rq_cur_bytes(req) >> 9; |
---|
| 264 | + totle_nsect = (req->__data_len) >> 9; |
---|
290 | 265 | |
---|
291 | | - if (!req) |
---|
292 | | - req = blk_fetch_request(rq); |
---|
293 | | - if (!req) { |
---|
294 | | - add_wait_queue(&blk_ops->thread_wq, &wait); |
---|
295 | | - set_current_state(TASK_INTERRUPTIBLE); |
---|
296 | | - spin_unlock_irq(rq->queue_lock); |
---|
297 | | - rkflash_req_jiffies = HZ / 10; |
---|
298 | | - rkflash_flash_gc(); |
---|
299 | | - wait_event_timeout(blk_ops->thread_wq, |
---|
300 | | - blk_ops->quit || rknand_req_do, |
---|
301 | | - rkflash_req_jiffies); |
---|
302 | | - rknand_req_do = 0; |
---|
303 | | - spin_lock_irq(rq->queue_lock); |
---|
304 | | - remove_wait_queue(&blk_ops->thread_wq, &wait); |
---|
305 | | - continue; |
---|
306 | | - } else { |
---|
307 | | - rkflash_req_jiffies = 1 * HZ; |
---|
| 266 | + if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > |
---|
| 267 | + get_capacity(req->rq_disk)) |
---|
| 268 | + return BLK_STS_IOERR; |
---|
| 269 | + |
---|
| 270 | + switch (req_op(req)) { |
---|
| 271 | + case REQ_OP_DISCARD: |
---|
| 272 | + rkflash_print_bio("%s discard\n", __func__); |
---|
| 273 | + if (rkflash_blk_discard(block, nsect)) |
---|
| 274 | + return BLK_STS_IOERR; |
---|
| 275 | + return BLK_STS_OK; |
---|
| 276 | + case REQ_OP_READ: |
---|
| 277 | + rkflash_print_bio("%s read block=%lx nsec=%lx\n", __func__, block, totle_nsect); |
---|
| 278 | + buf = mtd_read_temp_buffer; |
---|
| 279 | + rkflash_blk_check_buffer_align(req, &buf); |
---|
| 280 | + ret = rkflash_blk_xfer(dev, |
---|
| 281 | + block, |
---|
| 282 | + totle_nsect, |
---|
| 283 | + buf, |
---|
| 284 | + REQ_OP_READ); |
---|
| 285 | + if (buf == mtd_read_temp_buffer) { |
---|
| 286 | + char *p = buf; |
---|
| 287 | + |
---|
| 288 | + rq_for_each_segment(bvec, req, rq_iter) { |
---|
| 289 | + page_buf = kmap_atomic(bvec.bv_page); |
---|
| 290 | + memcpy(page_buf + |
---|
| 291 | + bvec.bv_offset, |
---|
| 292 | + p, |
---|
| 293 | + bvec.bv_len); |
---|
| 294 | + p += bvec.bv_len; |
---|
| 295 | + kunmap_atomic(page_buf); |
---|
| 296 | + } |
---|
308 | 297 | } |
---|
309 | 298 | |
---|
310 | | - dev = req->rq_disk->private_data; |
---|
311 | | - totle_nsect = (req->__data_len) >> 9; |
---|
312 | | - sector_index = blk_rq_pos(req); |
---|
313 | | - buf = 0; |
---|
314 | | - res = 0; |
---|
315 | | - rw_flag = req_op(req); |
---|
316 | | - if (rw_flag == REQ_OP_DISCARD) { |
---|
317 | | - spin_unlock_irq(rq->queue_lock); |
---|
318 | | - if (rkflash_blk_discard(blk_rq_pos(req) + |
---|
319 | | - dev->off_size, totle_nsect)) |
---|
320 | | - res = -EIO; |
---|
321 | | - spin_lock_irq(rq->queue_lock); |
---|
322 | | - if (!__blk_end_request_cur(req, res)) |
---|
323 | | - req = NULL; |
---|
324 | | - continue; |
---|
325 | | - } else if (rw_flag == REQ_OP_FLUSH) { |
---|
326 | | - if (!__blk_end_request_cur(req, res)) |
---|
327 | | - req = NULL; |
---|
328 | | - continue; |
---|
329 | | - } else if (rw_flag == REQ_OP_READ) { |
---|
330 | | - buf = mtd_read_temp_buffer; |
---|
331 | | - rkflash_blk_check_buffer_align(req, &buf); |
---|
332 | | - spin_unlock_irq(rq->queue_lock); |
---|
333 | | - res = rkflash_blk_xfer(dev, |
---|
334 | | - sector_index, |
---|
335 | | - totle_nsect, |
---|
336 | | - buf, |
---|
337 | | - rw_flag, |
---|
338 | | - totle_nsect); |
---|
339 | | - spin_lock_irq(rq->queue_lock); |
---|
340 | | - if (buf == mtd_read_temp_buffer) { |
---|
341 | | - char *p = buf; |
---|
| 299 | + if (ret) |
---|
| 300 | + return BLK_STS_IOERR; |
---|
| 301 | + else |
---|
| 302 | + return BLK_STS_OK; |
---|
| 303 | + case REQ_OP_WRITE: |
---|
| 304 | + rkflash_print_bio("%s write block=%lx nsec=%lx\n", __func__, block, totle_nsect); |
---|
342 | 305 | |
---|
343 | | - rq_for_each_segment(bvec, req, rq_iter) { |
---|
344 | | - page_buf = kmap_atomic(bvec.bv_page); |
---|
345 | | - memcpy(page_buf + |
---|
346 | | - bvec.bv_offset, |
---|
347 | | - p, |
---|
348 | | - bvec.bv_len); |
---|
349 | | - p += bvec.bv_len; |
---|
350 | | - kunmap_atomic(page_buf); |
---|
351 | | - } |
---|
352 | | - } |
---|
353 | | - } else if (rw_flag == REQ_OP_WRITE){ |
---|
354 | | - buf = mtd_read_temp_buffer; |
---|
355 | | - rkflash_blk_check_buffer_align(req, &buf); |
---|
356 | | - if (buf == mtd_read_temp_buffer) { |
---|
357 | | - char *p = buf; |
---|
| 306 | + buf = mtd_read_temp_buffer; |
---|
| 307 | + rkflash_blk_check_buffer_align(req, &buf); |
---|
| 308 | + if (buf == mtd_read_temp_buffer) { |
---|
| 309 | + char *p = buf; |
---|
358 | 310 | |
---|
359 | | - rq_for_each_segment(bvec, req, rq_iter) { |
---|
360 | | - page_buf = kmap_atomic(bvec.bv_page); |
---|
361 | | - memcpy(p, |
---|
362 | | - page_buf + |
---|
363 | | - bvec.bv_offset, |
---|
364 | | - bvec.bv_len); |
---|
365 | | - p += bvec.bv_len; |
---|
366 | | - kunmap_atomic(page_buf); |
---|
367 | | - } |
---|
| 311 | + rq_for_each_segment(bvec, req, rq_iter) { |
---|
| 312 | + page_buf = kmap_atomic(bvec.bv_page); |
---|
| 313 | + memcpy(p, |
---|
| 314 | + page_buf + |
---|
| 315 | + bvec.bv_offset, |
---|
| 316 | + bvec.bv_len); |
---|
| 317 | + p += bvec.bv_len; |
---|
| 318 | + kunmap_atomic(page_buf); |
---|
368 | 319 | } |
---|
369 | | - spin_unlock_irq(rq->queue_lock); |
---|
370 | | - res = rkflash_blk_xfer(dev, |
---|
371 | | - sector_index, |
---|
372 | | - totle_nsect, |
---|
373 | | - buf, |
---|
374 | | - rw_flag, |
---|
375 | | - totle_nsect); |
---|
376 | | - spin_lock_irq(rq->queue_lock); |
---|
377 | | - } else { |
---|
378 | | - pr_err("%s error req flag\n", __func__); |
---|
379 | 320 | } |
---|
380 | | - __blk_end_request_all(req, res); |
---|
381 | | - req = NULL; |
---|
| 321 | + ret = rkflash_blk_xfer(dev, |
---|
| 322 | + block, |
---|
| 323 | + totle_nsect, |
---|
| 324 | + buf, |
---|
| 325 | + REQ_OP_WRITE); |
---|
| 326 | + |
---|
| 327 | + if (ret) |
---|
| 328 | + return BLK_STS_IOERR; |
---|
| 329 | + else |
---|
| 330 | + return BLK_STS_OK; |
---|
| 331 | + default: |
---|
| 332 | + return BLK_STS_IOERR; |
---|
382 | 333 | } |
---|
383 | | - pr_info("flash th quited\n"); |
---|
384 | | - blk_ops->flash_th_quited = 1; |
---|
385 | | - if (req) |
---|
386 | | - __blk_end_request_all(req, -EIO); |
---|
387 | | - while ((req = blk_fetch_request(rq)) != NULL) |
---|
388 | | - __blk_end_request_all(req, -ENODEV); |
---|
389 | | - spin_unlock_irq(rq->queue_lock); |
---|
390 | | - complete_and_exit(&blk_ops->thread_exit, 0); |
---|
391 | | - return 0; |
---|
392 | 334 | } |
---|
393 | 335 | |
---|
394 | | -static void rkflash_blk_request(struct request_queue *rq) |
---|
| 336 | +static struct request *rkflash_next_request(struct flash_blk_dev *dev) |
---|
395 | 337 | { |
---|
396 | | - struct flash_blk_ops *blk_ops = rq->queuedata; |
---|
| 338 | + struct request *rq; |
---|
| 339 | + struct flash_blk_ops *tr = dev->blk_ops; |
---|
| 340 | + |
---|
| 341 | + rq = list_first_entry_or_null(&tr->rq_list, struct request, queuelist); |
---|
| 342 | + if (rq) { |
---|
| 343 | + list_del_init(&rq->queuelist); |
---|
| 344 | + blk_mq_start_request(rq); |
---|
| 345 | + return rq; |
---|
| 346 | + } |
---|
| 347 | + |
---|
| 348 | + return NULL; |
---|
| 349 | +} |
---|
| 350 | + |
---|
| 351 | +static void rkflash_blktrans_work(struct flash_blk_dev *dev) |
---|
| 352 | + __releases(&dev->blk_ops->queue_lock) |
---|
| 353 | + __acquires(&dev->blk_ops->queue_lock) |
---|
| 354 | +{ |
---|
| 355 | + struct flash_blk_ops *tr = dev->blk_ops; |
---|
397 | 356 | struct request *req = NULL; |
---|
398 | 357 | |
---|
399 | | - if (blk_ops->flash_th_quited) { |
---|
400 | | - while ((req = blk_fetch_request(rq)) != NULL) |
---|
401 | | - __blk_end_request_all(req, -ENODEV); |
---|
402 | | - return; |
---|
| 358 | + while (1) { |
---|
| 359 | + blk_status_t res; |
---|
| 360 | + |
---|
| 361 | + req = rkflash_next_request(dev); |
---|
| 362 | + if (!req) |
---|
| 363 | + break; |
---|
| 364 | + |
---|
| 365 | + spin_unlock_irq(&dev->blk_ops->queue_lock); |
---|
| 366 | + |
---|
| 367 | + mutex_lock(&g_flash_ops_mutex); |
---|
| 368 | + res = do_blktrans_all_request(tr, dev, req); |
---|
| 369 | + mutex_unlock(&g_flash_ops_mutex); |
---|
| 370 | + |
---|
| 371 | + if (!blk_update_request(req, res, req->__data_len)) { |
---|
| 372 | + __blk_mq_end_request(req, res); |
---|
| 373 | + req = NULL; |
---|
| 374 | + } |
---|
| 375 | + |
---|
| 376 | + spin_lock_irq(&dev->blk_ops->queue_lock); |
---|
403 | 377 | } |
---|
404 | | - rknand_req_do = 1; |
---|
405 | | - wake_up(&blk_ops->thread_wq); |
---|
| 378 | +} |
---|
| 379 | + |
---|
| 380 | +static blk_status_t rkflash_queue_rq(struct blk_mq_hw_ctx *hctx, |
---|
| 381 | + const struct blk_mq_queue_data *bd) |
---|
| 382 | +{ |
---|
| 383 | + struct flash_blk_dev *dev; |
---|
| 384 | + |
---|
| 385 | + dev = hctx->queue->queuedata; |
---|
| 386 | + if (!dev) { |
---|
| 387 | + blk_mq_start_request(bd->rq); |
---|
| 388 | + return BLK_STS_IOERR; |
---|
| 389 | + } |
---|
| 390 | + |
---|
| 391 | + nand_gc_do = 0; |
---|
| 392 | + spin_lock_irq(&dev->blk_ops->queue_lock); |
---|
| 393 | + list_add_tail(&bd->rq->queuelist, &dev->blk_ops->rq_list); |
---|
| 394 | + rkflash_blktrans_work(dev); |
---|
| 395 | + spin_unlock_irq(&dev->blk_ops->queue_lock); |
---|
| 396 | + |
---|
| 397 | + /* wake up gc thread */ |
---|
| 398 | + nand_gc_do = 1; |
---|
| 399 | + wake_up(&nand_gc_thread_wait); |
---|
| 400 | + |
---|
| 401 | + return BLK_STS_OK; |
---|
| 402 | +} |
---|
| 403 | + |
---|
| 404 | +static const struct blk_mq_ops rkflash_mq_ops = { |
---|
| 405 | + .queue_rq = rkflash_queue_rq, |
---|
| 406 | +}; |
---|
| 407 | + |
---|
| 408 | +static int nand_gc_has_work(void) |
---|
| 409 | +{ |
---|
| 410 | + return nand_gc_do; |
---|
| 411 | +} |
---|
| 412 | + |
---|
| 413 | +static int nand_gc_do_work(void) |
---|
| 414 | +{ |
---|
| 415 | + int ret = nand_gc_has_work(); |
---|
| 416 | + |
---|
| 417 | + /* do garbage collect at idle state */ |
---|
| 418 | + if (ret) { |
---|
| 419 | + mutex_lock(&g_flash_ops_mutex); |
---|
| 420 | + ret = g_boot_ops->gc(); |
---|
| 421 | + rkflash_print_bio("%s gc result= %d\n", __func__, ret); |
---|
| 422 | + mutex_unlock(&g_flash_ops_mutex); |
---|
| 423 | + } |
---|
| 424 | + |
---|
| 425 | + return ret; |
---|
| 426 | +} |
---|
| 427 | + |
---|
| 428 | +static void nand_gc_wait_work(void) |
---|
| 429 | +{ |
---|
| 430 | + unsigned long nand_gc_jiffies = HZ / 20; |
---|
| 431 | + |
---|
| 432 | + if (nand_gc_has_work()) |
---|
| 433 | + wait_event_freezable_timeout(nand_gc_thread_wait, |
---|
| 434 | + kthread_should_stop(), |
---|
| 435 | + nand_gc_jiffies); |
---|
| 436 | + else |
---|
| 437 | + wait_event_freezable(nand_gc_thread_wait, |
---|
| 438 | + kthread_should_stop() || nand_gc_has_work()); |
---|
| 439 | +} |
---|
| 440 | + |
---|
| 441 | +static int nand_gc_mythread(void *arg) |
---|
| 442 | +{ |
---|
| 443 | + int gc_done_times = 0; |
---|
| 444 | + |
---|
| 445 | + set_freezable(); |
---|
| 446 | + |
---|
| 447 | + while (!kthread_should_stop()) { |
---|
| 448 | + if (nand_gc_do_work() == 0) { |
---|
| 449 | + gc_done_times++; |
---|
| 450 | + if (gc_done_times > 10) |
---|
| 451 | + nand_gc_do = 0; |
---|
| 452 | + } else { |
---|
| 453 | + gc_done_times = 0; |
---|
| 454 | + } |
---|
| 455 | + |
---|
| 456 | + nand_gc_wait_work(); |
---|
| 457 | + } |
---|
| 458 | + pr_info("nand gc quited\n"); |
---|
| 459 | + |
---|
| 460 | + return 0; |
---|
406 | 461 | } |
---|
407 | 462 | |
---|
408 | 463 | static int rkflash_blk_open(struct block_device *bdev, fmode_t mode) |
---|
.. | .. |
---|
459 | 514 | .owner = THIS_MODULE, |
---|
460 | 515 | }; |
---|
461 | 516 | |
---|
462 | | -static int rkflash_blk_add_dev(struct flash_blk_ops *blk_ops, |
---|
463 | | - struct flash_part *part) |
---|
| 517 | +static int rkflash_blk_add_dev(struct flash_blk_dev *dev, |
---|
| 518 | + struct flash_blk_ops *blk_ops, |
---|
| 519 | + struct flash_part *part) |
---|
464 | 520 | { |
---|
465 | | - struct flash_blk_dev *dev; |
---|
466 | 521 | struct gendisk *gd; |
---|
467 | 522 | |
---|
468 | 523 | if (part->size == 0) |
---|
469 | 524 | return -1; |
---|
470 | | - |
---|
471 | | - dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
---|
472 | | - if (!dev) |
---|
473 | | - return -ENOMEM; |
---|
474 | 525 | |
---|
475 | 526 | gd = alloc_disk(1 << blk_ops->minorbits); |
---|
476 | 527 | if (!gd) { |
---|
.. | .. |
---|
509 | 560 | gd->private_data = dev; |
---|
510 | 561 | dev->blkcore_priv = gd; |
---|
511 | 562 | gd->queue = blk_ops->rq; |
---|
512 | | - gd->queue->bypass_depth = 1; |
---|
513 | 563 | |
---|
514 | 564 | if (part->type == PART_NO_ACCESS) |
---|
515 | 565 | dev->disable_access = 1; |
---|
.. | .. |
---|
545 | 595 | { |
---|
546 | 596 | int i, ret; |
---|
547 | 597 | u64 offset; |
---|
| 598 | + struct flash_blk_dev *dev; |
---|
548 | 599 | |
---|
549 | | - rknand_req_do = 0; |
---|
550 | | - blk_ops->quit = 0; |
---|
551 | | - blk_ops->flash_th_quited = 0; |
---|
| 600 | + dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
---|
| 601 | + if (!dev) |
---|
| 602 | + return -ENOMEM; |
---|
552 | 603 | |
---|
553 | 604 | mtd_read_temp_buffer = kmalloc(MTD_RW_SECTORS * 512, |
---|
554 | 605 | GFP_KERNEL | GFP_DMA); |
---|
555 | 606 | |
---|
556 | 607 | ret = register_blkdev(blk_ops->major, blk_ops->name); |
---|
557 | | - if (ret) |
---|
| 608 | + if (ret) { |
---|
| 609 | + kfree(dev); |
---|
| 610 | + |
---|
558 | 611 | return -1; |
---|
559 | | - |
---|
560 | | - spin_lock_init(&blk_ops->queue_lock); |
---|
561 | | - init_completion(&blk_ops->thread_exit); |
---|
562 | | - init_waitqueue_head(&blk_ops->thread_wq); |
---|
563 | | - |
---|
564 | | - blk_ops->rq = blk_init_queue(rkflash_blk_request, &blk_ops->queue_lock); |
---|
565 | | - if (!blk_ops->rq) { |
---|
566 | | - unregister_blkdev(blk_ops->major, blk_ops->name); |
---|
567 | | - return -1; |
---|
568 | 612 | } |
---|
| 613 | + |
---|
| 614 | + /* Create the request queue */ |
---|
| 615 | + spin_lock_init(&blk_ops->queue_lock); |
---|
| 616 | + INIT_LIST_HEAD(&blk_ops->rq_list); |
---|
| 617 | + |
---|
| 618 | + blk_ops->tag_set = kzalloc(sizeof(*blk_ops->tag_set), GFP_KERNEL); |
---|
| 619 | + if (!blk_ops->tag_set) |
---|
| 620 | + goto error1; |
---|
| 621 | + |
---|
| 622 | + blk_ops->rq = blk_mq_init_sq_queue(blk_ops->tag_set, &rkflash_mq_ops, 1, |
---|
| 623 | + BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING); |
---|
| 624 | + if (IS_ERR(blk_ops->rq)) { |
---|
| 625 | + ret = PTR_ERR(blk_ops->rq); |
---|
| 626 | + blk_ops->rq = NULL; |
---|
| 627 | + goto error2; |
---|
| 628 | + } |
---|
| 629 | + |
---|
| 630 | + blk_ops->rq->queuedata = dev; |
---|
569 | 631 | |
---|
570 | 632 | blk_queue_max_hw_sectors(blk_ops->rq, MTD_RW_SECTORS); |
---|
571 | 633 | blk_queue_max_segments(blk_ops->rq, MTD_RW_SECTORS); |
---|
572 | 634 | |
---|
573 | 635 | blk_queue_flag_set(QUEUE_FLAG_DISCARD, blk_ops->rq); |
---|
574 | 636 | blk_queue_max_discard_sectors(blk_ops->rq, UINT_MAX >> 9); |
---|
| 637 | + blk_ops->rq->limits.discard_granularity = 64 << 9; |
---|
575 | 638 | |
---|
576 | | - blk_ops->rq->queuedata = blk_ops; |
---|
| 639 | + if (g_flash_type == FLASH_TYPE_SFC_NAND || g_flash_type == FLASH_TYPE_NANDC_NAND) |
---|
| 640 | + nand_gc_thread = kthread_run(nand_gc_mythread, (void *)blk_ops, "rkflash_gc"); |
---|
| 641 | + |
---|
577 | 642 | INIT_LIST_HEAD(&blk_ops->devs); |
---|
578 | | - kthread_run(rkflash_blktrans_thread, (void *)blk_ops, "rkflash"); |
---|
579 | 643 | g_max_part_num = rk_partition_init(disk_array); |
---|
580 | 644 | if (g_max_part_num) { |
---|
581 | 645 | /* partition 0 is save vendor data, need hidden */ |
---|
.. | .. |
---|
587 | 651 | offset * 512, |
---|
588 | 652 | (u64)(offset + disk_array[i].size) * 512, |
---|
589 | 653 | (u64)disk_array[i].size / 2048); |
---|
590 | | - rkflash_blk_add_dev(blk_ops, &disk_array[i]); |
---|
| 654 | + rkflash_blk_add_dev(dev, blk_ops, &disk_array[i]); |
---|
591 | 655 | } |
---|
592 | | - rkflash_blk_add_dev(blk_ops, &fw_header_p); |
---|
| 656 | + rkflash_blk_add_dev(dev, blk_ops, &fw_header_p); |
---|
593 | 657 | } else { |
---|
594 | 658 | struct flash_part part; |
---|
595 | 659 | |
---|
.. | .. |
---|
597 | 661 | part.size = g_boot_ops->get_capacity(); |
---|
598 | 662 | part.type = 0; |
---|
599 | 663 | part.name[0] = 0; |
---|
600 | | - rkflash_blk_add_dev(&mytr, &part); |
---|
| 664 | + rkflash_blk_add_dev(dev, blk_ops, &part); |
---|
601 | 665 | } |
---|
602 | 666 | rkflash_blk_create_procfs(); |
---|
603 | 667 | |
---|
604 | 668 | return 0; |
---|
| 669 | + |
---|
| 670 | +error2: |
---|
| 671 | + kfree(blk_ops->tag_set); |
---|
| 672 | +error1: |
---|
| 673 | + unregister_blkdev(blk_ops->major, blk_ops->name); |
---|
| 674 | + kfree(dev); |
---|
| 675 | + |
---|
| 676 | + return ret; |
---|
605 | 677 | } |
---|
606 | 678 | |
---|
607 | 679 | static void rkflash_blk_unregister(struct flash_blk_ops *blk_ops) |
---|
608 | 680 | { |
---|
609 | 681 | struct list_head *this, *next; |
---|
610 | 682 | |
---|
611 | | - blk_ops->quit = 1; |
---|
612 | | - wake_up(&blk_ops->thread_wq); |
---|
613 | | - wait_for_completion(&blk_ops->thread_exit); |
---|
614 | 683 | list_for_each_safe(this, next, &blk_ops->devs) { |
---|
615 | 684 | struct flash_blk_dev *dev = |
---|
616 | 685 | list_entry(this, struct flash_blk_dev, list); |
---|
.. | .. |
---|
725 | 794 | case FLASH_TYPE_NANDC_NAND: |
---|
726 | 795 | default: |
---|
727 | 796 | g_flash_type = type; |
---|
728 | | - mytr.quit = 1; |
---|
729 | 797 | ret = rkflash_blk_register(&mytr); |
---|
730 | 798 | pr_err("%s device register as blk dev, ret= %d\n", __func__, ret); |
---|
731 | 799 | if (ret) |
---|
.. | .. |
---|
768 | 836 | void rkflash_dev_shutdown(void) |
---|
769 | 837 | { |
---|
770 | 838 | pr_info("rkflash_shutdown...\n"); |
---|
771 | | - if (g_flash_type != -1 && mytr.quit == 0) { |
---|
772 | | - mytr.quit = 1; |
---|
773 | | - wake_up(&mytr.thread_wq); |
---|
774 | | - wait_for_completion(&mytr.thread_exit); |
---|
775 | | - } |
---|
| 839 | + if (g_flash_type == FLASH_TYPE_SFC_NAND || g_flash_type == FLASH_TYPE_NANDC_NAND) |
---|
| 840 | + kthread_stop(nand_gc_thread); |
---|
| 841 | + |
---|
776 | 842 | mutex_lock(&g_flash_ops_mutex); |
---|
777 | 843 | g_boot_ops->deinit(); |
---|
778 | 844 | mutex_unlock(&g_flash_ops_mutex); |
---|