aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/mtd_blkdevs.c26
-rw-r--r--include/linux/mtd/blktrans.h2
2 files changed, 28 insertions, 0 deletions
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 344ac1037ee7..e0b5f6442171 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -119,11 +119,22 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr,
119 } 119 }
120} 120}
121 121
122int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev)
123{
124 if (kthread_should_stop())
125 return 1;
126
127 return !elv_queue_empty(dev->rq);
128}
129EXPORT_SYMBOL_GPL(mtd_blktrans_cease_background);
130
122static int mtd_blktrans_thread(void *arg) 131static int mtd_blktrans_thread(void *arg)
123{ 132{
124 struct mtd_blktrans_dev *dev = arg; 133 struct mtd_blktrans_dev *dev = arg;
134 struct mtd_blktrans_ops *tr = dev->tr;
125 struct request_queue *rq = dev->rq; 135 struct request_queue *rq = dev->rq;
126 struct request *req = NULL; 136 struct request *req = NULL;
137 int background_done = 0;
127 138
128 spin_lock_irq(rq->queue_lock); 139 spin_lock_irq(rq->queue_lock);
129 140
@@ -131,6 +142,19 @@ static int mtd_blktrans_thread(void *arg)
131 int res; 142 int res;
132 143
133 if (!req && !(req = blk_fetch_request(rq))) { 144 if (!req && !(req = blk_fetch_request(rq))) {
145 if (tr->background && !background_done) {
146 spin_unlock_irq(rq->queue_lock);
147 mutex_lock(&dev->lock);
148 tr->background(dev);
149 mutex_unlock(&dev->lock);
150 spin_lock_irq(rq->queue_lock);
151 /*
152 * Do background processing just once per idle
153 * period.
154 */
155 background_done = 1;
156 continue;
157 }
134 set_current_state(TASK_INTERRUPTIBLE); 158 set_current_state(TASK_INTERRUPTIBLE);
135 159
136 if (kthread_should_stop()) 160 if (kthread_should_stop())
@@ -152,6 +176,8 @@ static int mtd_blktrans_thread(void *arg)
152 176
153 if (!__blk_end_request_cur(req, res)) 177 if (!__blk_end_request_cur(req, res))
154 req = NULL; 178 req = NULL;
179
180 background_done = 0;
155 } 181 }
156 182
157 if (req) 183 if (req)
diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
index 26529ebd59cc..66bec4bf2b0a 100644
--- a/include/linux/mtd/blktrans.h
+++ b/include/linux/mtd/blktrans.h
@@ -62,6 +62,7 @@ struct mtd_blktrans_ops {
62 unsigned long block, char *buffer); 62 unsigned long block, char *buffer);
63 int (*discard)(struct mtd_blktrans_dev *dev, 63 int (*discard)(struct mtd_blktrans_dev *dev,
64 unsigned long block, unsigned nr_blocks); 64 unsigned long block, unsigned nr_blocks);
65 void (*background)(struct mtd_blktrans_dev *dev);
65 66
66 /* Block layer ioctls */ 67 /* Block layer ioctls */
67 int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo); 68 int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo);
@@ -85,6 +86,7 @@ extern int register_mtd_blktrans(struct mtd_blktrans_ops *tr);
85extern int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr); 86extern int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr);
86extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); 87extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
87extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); 88extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
89extern int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev);
88 90
89 91
90#endif /* __MTD_TRANS_H__ */ 92#endif /* __MTD_TRANS_H__ */