.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * PS3 Disk Storage Driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2007 Sony Computer Entertainment Inc. |
---|
5 | 6 | * Copyright 2007 Sony Corp. |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify it |
---|
8 | | - * under the terms of the GNU General Public License as published |
---|
9 | | - * by the Free Software Foundation; version 2 of the License. |
---|
10 | | - * |
---|
11 | | - * This program is distributed in the hope that it will be useful, but |
---|
12 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
14 | | - * General Public License for more details. |
---|
15 | | - * |
---|
16 | | - * You should have received a copy of the GNU General Public License along |
---|
17 | | - * with this program; if not, write to the Free Software Foundation, Inc., |
---|
18 | | - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
---|
19 | 7 | */ |
---|
20 | 8 | |
---|
21 | 9 | #include <linux/ata.h> |
---|
22 | | -#include <linux/blkdev.h> |
---|
| 10 | +#include <linux/blk-mq.h> |
---|
23 | 11 | #include <linux/slab.h> |
---|
24 | 12 | #include <linux/module.h> |
---|
25 | 13 | |
---|
.. | .. |
---|
42 | 30 | struct ps3disk_private { |
---|
43 | 31 | spinlock_t lock; /* Request queue spinlock */ |
---|
44 | 32 | struct request_queue *queue; |
---|
| 33 | + struct blk_mq_tag_set tag_set; |
---|
45 | 34 | struct gendisk *gendisk; |
---|
46 | 35 | unsigned int blocking_factor; |
---|
47 | 36 | struct request *req; |
---|
.. | .. |
---|
101 | 90 | |
---|
102 | 91 | rq_for_each_segment(bvec, req, iter) { |
---|
103 | 92 | unsigned long flags; |
---|
104 | | - dev_dbg(&dev->sbd.core, "%s:%u: bio %u: %u sectors from %lu\n", |
---|
| 93 | + dev_dbg(&dev->sbd.core, "%s:%u: bio %u: %u sectors from %llu\n", |
---|
105 | 94 | __func__, __LINE__, i, bio_sectors(iter.bio), |
---|
106 | 95 | iter.bio->bi_iter.bi_sector); |
---|
107 | 96 | |
---|
.. | .. |
---|
118 | 107 | } |
---|
119 | 108 | } |
---|
120 | 109 | |
---|
121 | | -static int ps3disk_submit_request_sg(struct ps3_storage_device *dev, |
---|
122 | | - struct request *req) |
---|
| 110 | +static blk_status_t ps3disk_submit_request_sg(struct ps3_storage_device *dev, |
---|
| 111 | + struct request *req) |
---|
123 | 112 | { |
---|
124 | 113 | struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); |
---|
125 | 114 | int write = rq_data_dir(req), res; |
---|
.. | .. |
---|
158 | 147 | if (res) { |
---|
159 | 148 | dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__, |
---|
160 | 149 | __LINE__, op, res); |
---|
161 | | - __blk_end_request_all(req, BLK_STS_IOERR); |
---|
162 | | - return 0; |
---|
| 150 | + return BLK_STS_IOERR; |
---|
163 | 151 | } |
---|
164 | 152 | |
---|
165 | 153 | priv->req = req; |
---|
166 | | - return 1; |
---|
| 154 | + return BLK_STS_OK; |
---|
167 | 155 | } |
---|
168 | 156 | |
---|
169 | | -static int ps3disk_submit_flush_request(struct ps3_storage_device *dev, |
---|
170 | | - struct request *req) |
---|
| 157 | +static blk_status_t ps3disk_submit_flush_request(struct ps3_storage_device *dev, |
---|
| 158 | + struct request *req) |
---|
171 | 159 | { |
---|
172 | 160 | struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); |
---|
173 | 161 | u64 res; |
---|
.. | .. |
---|
180 | 168 | if (res) { |
---|
181 | 169 | dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n", |
---|
182 | 170 | __func__, __LINE__, res); |
---|
183 | | - __blk_end_request_all(req, BLK_STS_IOERR); |
---|
184 | | - return 0; |
---|
| 171 | + return BLK_STS_IOERR; |
---|
185 | 172 | } |
---|
186 | 173 | |
---|
187 | 174 | priv->req = req; |
---|
188 | | - return 1; |
---|
| 175 | + return BLK_STS_OK; |
---|
189 | 176 | } |
---|
190 | 177 | |
---|
191 | | -static void ps3disk_do_request(struct ps3_storage_device *dev, |
---|
192 | | - struct request_queue *q) |
---|
| 178 | +static blk_status_t ps3disk_do_request(struct ps3_storage_device *dev, |
---|
| 179 | + struct request *req) |
---|
193 | 180 | { |
---|
194 | | - struct request *req; |
---|
195 | | - |
---|
196 | 181 | dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); |
---|
197 | 182 | |
---|
198 | | - while ((req = blk_fetch_request(q))) { |
---|
199 | | - switch (req_op(req)) { |
---|
200 | | - case REQ_OP_FLUSH: |
---|
201 | | - if (ps3disk_submit_flush_request(dev, req)) |
---|
202 | | - return; |
---|
203 | | - break; |
---|
204 | | - case REQ_OP_READ: |
---|
205 | | - case REQ_OP_WRITE: |
---|
206 | | - if (ps3disk_submit_request_sg(dev, req)) |
---|
207 | | - return; |
---|
208 | | - break; |
---|
209 | | - default: |
---|
210 | | - blk_dump_rq_flags(req, DEVICE_NAME " bad request"); |
---|
211 | | - __blk_end_request_all(req, BLK_STS_IOERR); |
---|
212 | | - } |
---|
| 183 | + switch (req_op(req)) { |
---|
| 184 | + case REQ_OP_FLUSH: |
---|
| 185 | + return ps3disk_submit_flush_request(dev, req); |
---|
| 186 | + case REQ_OP_READ: |
---|
| 187 | + case REQ_OP_WRITE: |
---|
| 188 | + return ps3disk_submit_request_sg(dev, req); |
---|
| 189 | + default: |
---|
| 190 | + blk_dump_rq_flags(req, DEVICE_NAME " bad request"); |
---|
| 191 | + return BLK_STS_IOERR; |
---|
213 | 192 | } |
---|
214 | 193 | } |
---|
215 | 194 | |
---|
216 | | -static void ps3disk_request(struct request_queue *q) |
---|
| 195 | +static blk_status_t ps3disk_queue_rq(struct blk_mq_hw_ctx *hctx, |
---|
| 196 | + const struct blk_mq_queue_data *bd) |
---|
217 | 197 | { |
---|
| 198 | + struct request_queue *q = hctx->queue; |
---|
218 | 199 | struct ps3_storage_device *dev = q->queuedata; |
---|
219 | 200 | struct ps3disk_private *priv = ps3_system_bus_get_drvdata(&dev->sbd); |
---|
| 201 | + blk_status_t ret; |
---|
220 | 202 | |
---|
221 | | - if (priv->req) { |
---|
222 | | - dev_dbg(&dev->sbd.core, "%s:%u busy\n", __func__, __LINE__); |
---|
223 | | - return; |
---|
224 | | - } |
---|
| 203 | + blk_mq_start_request(bd->rq); |
---|
225 | 204 | |
---|
226 | | - ps3disk_do_request(dev, q); |
---|
| 205 | + spin_lock_irq(&priv->lock); |
---|
| 206 | + ret = ps3disk_do_request(dev, bd->rq); |
---|
| 207 | + spin_unlock_irq(&priv->lock); |
---|
| 208 | + |
---|
| 209 | + return ret; |
---|
227 | 210 | } |
---|
228 | 211 | |
---|
229 | 212 | static irqreturn_t ps3disk_interrupt(int irq, void *data) |
---|
.. | .. |
---|
280 | 263 | } |
---|
281 | 264 | |
---|
282 | 265 | spin_lock(&priv->lock); |
---|
283 | | - __blk_end_request_all(req, error); |
---|
284 | 266 | priv->req = NULL; |
---|
285 | | - ps3disk_do_request(dev, priv->queue); |
---|
| 267 | + blk_mq_end_request(req, error); |
---|
286 | 268 | spin_unlock(&priv->lock); |
---|
287 | 269 | |
---|
| 270 | + blk_mq_run_hw_queues(priv->queue, true); |
---|
288 | 271 | return IRQ_HANDLED; |
---|
289 | 272 | } |
---|
290 | 273 | |
---|
.. | .. |
---|
404 | 387 | |
---|
405 | 388 | static DEFINE_MUTEX(ps3disk_mask_mutex); |
---|
406 | 389 | |
---|
| 390 | +static const struct blk_mq_ops ps3disk_mq_ops = { |
---|
| 391 | + .queue_rq = ps3disk_queue_rq, |
---|
| 392 | +}; |
---|
| 393 | + |
---|
407 | 394 | static int ps3disk_probe(struct ps3_system_bus_device *_dev) |
---|
408 | 395 | { |
---|
409 | 396 | struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); |
---|
.. | .. |
---|
454 | 441 | |
---|
455 | 442 | ps3disk_identify(dev); |
---|
456 | 443 | |
---|
457 | | - queue = blk_init_queue(ps3disk_request, &priv->lock); |
---|
458 | | - if (!queue) { |
---|
459 | | - dev_err(&dev->sbd.core, "%s:%u: blk_init_queue failed\n", |
---|
| 444 | + queue = blk_mq_init_sq_queue(&priv->tag_set, &ps3disk_mq_ops, 1, |
---|
| 445 | + BLK_MQ_F_SHOULD_MERGE); |
---|
| 446 | + if (IS_ERR(queue)) { |
---|
| 447 | + dev_err(&dev->sbd.core, "%s:%u: blk_mq_init_queue failed\n", |
---|
460 | 448 | __func__, __LINE__); |
---|
461 | | - error = -ENOMEM; |
---|
| 449 | + error = PTR_ERR(queue); |
---|
462 | 450 | goto fail_teardown; |
---|
463 | 451 | } |
---|
464 | 452 | |
---|
.. | .. |
---|
495 | 483 | dev->regions[dev->region_idx].size*priv->blocking_factor); |
---|
496 | 484 | |
---|
497 | 485 | dev_info(&dev->sbd.core, |
---|
498 | | - "%s is a %s (%llu MiB total, %lu MiB for OtherOS)\n", |
---|
| 486 | + "%s is a %s (%llu MiB total, %llu MiB for OtherOS)\n", |
---|
499 | 487 | gendisk->disk_name, priv->model, priv->raw_capacity >> 11, |
---|
500 | 488 | get_capacity(gendisk) >> 11); |
---|
501 | 489 | |
---|
502 | | - device_add_disk(&dev->sbd.core, gendisk); |
---|
| 490 | + device_add_disk(&dev->sbd.core, gendisk, NULL); |
---|
503 | 491 | return 0; |
---|
504 | 492 | |
---|
505 | 493 | fail_cleanup_queue: |
---|
506 | 494 | blk_cleanup_queue(queue); |
---|
| 495 | + blk_mq_free_tag_set(&priv->tag_set); |
---|
507 | 496 | fail_teardown: |
---|
508 | 497 | ps3stor_teardown(dev); |
---|
509 | 498 | fail_free_bounce: |
---|
.. | .. |
---|
529 | 518 | mutex_unlock(&ps3disk_mask_mutex); |
---|
530 | 519 | del_gendisk(priv->gendisk); |
---|
531 | 520 | blk_cleanup_queue(priv->queue); |
---|
| 521 | + blk_mq_free_tag_set(&priv->tag_set); |
---|
532 | 522 | put_disk(priv->gendisk); |
---|
533 | 523 | dev_notice(&dev->sbd.core, "Synchronizing disk cache\n"); |
---|
534 | 524 | ps3disk_sync_cache(dev); |
---|