.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Driver for the SWIM3 (Super Woz Integrated Machine 3) |
---|
3 | 4 | * floppy controller found on Power Macintoshes. |
---|
4 | 5 | * |
---|
5 | 6 | * Copyright (C) 1996 Paul Mackerras. |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or |
---|
8 | | - * modify it under the terms of the GNU General Public License |
---|
9 | | - * as published by the Free Software Foundation; either version |
---|
10 | | - * 2 of the License, or (at your option) any later version. |
---|
11 | 7 | */ |
---|
12 | 8 | |
---|
13 | 9 | /* |
---|
.. | .. |
---|
25 | 21 | #include <linux/delay.h> |
---|
26 | 22 | #include <linux/fd.h> |
---|
27 | 23 | #include <linux/ioctl.h> |
---|
28 | | -#include <linux/blkdev.h> |
---|
| 24 | +#include <linux/blk-mq.h> |
---|
29 | 25 | #include <linux/interrupt.h> |
---|
30 | 26 | #include <linux/mutex.h> |
---|
31 | 27 | #include <linux/module.h> |
---|
.. | .. |
---|
206 | 202 | char dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)]; |
---|
207 | 203 | int index; |
---|
208 | 204 | struct request *cur_req; |
---|
| 205 | + struct blk_mq_tag_set tag_set; |
---|
209 | 206 | }; |
---|
210 | 207 | |
---|
211 | 208 | #define swim3_err(fmt, arg...) dev_err(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg) |
---|
.. | .. |
---|
260 | 257 | static bool swim3_end_request(struct floppy_state *fs, blk_status_t err, unsigned int nr_bytes) |
---|
261 | 258 | { |
---|
262 | 259 | struct request *req = fs->cur_req; |
---|
263 | | - int rc; |
---|
264 | 260 | |
---|
265 | 261 | swim3_dbg(" end request, err=%d nr_bytes=%d, cur_req=%p\n", |
---|
266 | 262 | err, nr_bytes, req); |
---|
267 | 263 | |
---|
268 | 264 | if (err) |
---|
269 | 265 | nr_bytes = blk_rq_cur_bytes(req); |
---|
270 | | - rc = __blk_end_request(req, err, nr_bytes); |
---|
271 | | - if (rc) |
---|
| 266 | + if (blk_update_request(req, err, nr_bytes)) |
---|
272 | 267 | return true; |
---|
| 268 | + __blk_mq_end_request(req, err); |
---|
273 | 269 | fs->cur_req = NULL; |
---|
274 | 270 | return false; |
---|
275 | 271 | } |
---|
.. | .. |
---|
309 | 305 | return (stat & DATA) == 0; |
---|
310 | 306 | } |
---|
311 | 307 | |
---|
312 | | -static void start_request(struct floppy_state *fs) |
---|
| 308 | +static blk_status_t swim3_queue_rq(struct blk_mq_hw_ctx *hctx, |
---|
| 309 | + const struct blk_mq_queue_data *bd) |
---|
313 | 310 | { |
---|
314 | | - struct request *req; |
---|
| 311 | + struct floppy_state *fs = hctx->queue->queuedata; |
---|
| 312 | + struct request *req = bd->rq; |
---|
315 | 313 | unsigned long x; |
---|
316 | 314 | |
---|
317 | | - swim3_dbg("start request, initial state=%d\n", fs->state); |
---|
318 | | - |
---|
319 | | - if (fs->state == idle && fs->wanted) { |
---|
320 | | - fs->state = available; |
---|
321 | | - wake_up(&fs->wait); |
---|
322 | | - return; |
---|
| 315 | + spin_lock_irq(&swim3_lock); |
---|
| 316 | + if (fs->cur_req || fs->state != idle) { |
---|
| 317 | + spin_unlock_irq(&swim3_lock); |
---|
| 318 | + return BLK_STS_DEV_RESOURCE; |
---|
323 | 319 | } |
---|
324 | | - while (fs->state == idle) { |
---|
325 | | - swim3_dbg("start request, idle loop, cur_req=%p\n", fs->cur_req); |
---|
326 | | - if (!fs->cur_req) { |
---|
327 | | - fs->cur_req = blk_fetch_request(disks[fs->index]->queue); |
---|
328 | | - swim3_dbg(" fetched request %p\n", fs->cur_req); |
---|
329 | | - if (!fs->cur_req) |
---|
330 | | - break; |
---|
331 | | - } |
---|
332 | | - req = fs->cur_req; |
---|
333 | | - |
---|
334 | | - if (fs->mdev->media_bay && |
---|
335 | | - check_media_bay(fs->mdev->media_bay) != MB_FD) { |
---|
336 | | - swim3_dbg("%s", " media bay absent, dropping req\n"); |
---|
337 | | - swim3_end_request(fs, BLK_STS_IOERR, 0); |
---|
338 | | - continue; |
---|
339 | | - } |
---|
340 | | - |
---|
341 | | -#if 0 /* This is really too verbose */ |
---|
342 | | - swim3_dbg("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n", |
---|
343 | | - req->rq_disk->disk_name, req->cmd, |
---|
344 | | - (long)blk_rq_pos(req), blk_rq_sectors(req), |
---|
345 | | - bio_data(req->bio)); |
---|
346 | | - swim3_dbg(" current_nr_sectors=%u\n", |
---|
347 | | - blk_rq_cur_sectors(req)); |
---|
348 | | -#endif |
---|
349 | | - |
---|
350 | | - if (blk_rq_pos(req) >= fs->total_secs) { |
---|
351 | | - swim3_dbg(" pos out of bounds (%ld, max is %ld)\n", |
---|
352 | | - (long)blk_rq_pos(req), (long)fs->total_secs); |
---|
353 | | - swim3_end_request(fs, BLK_STS_IOERR, 0); |
---|
354 | | - continue; |
---|
355 | | - } |
---|
356 | | - if (fs->ejected) { |
---|
357 | | - swim3_dbg("%s", " disk ejected\n"); |
---|
358 | | - swim3_end_request(fs, BLK_STS_IOERR, 0); |
---|
359 | | - continue; |
---|
360 | | - } |
---|
361 | | - |
---|
362 | | - if (rq_data_dir(req) == WRITE) { |
---|
363 | | - if (fs->write_prot < 0) |
---|
364 | | - fs->write_prot = swim3_readbit(fs, WRITE_PROT); |
---|
365 | | - if (fs->write_prot) { |
---|
366 | | - swim3_dbg("%s", " try to write, disk write protected\n"); |
---|
367 | | - swim3_end_request(fs, BLK_STS_IOERR, 0); |
---|
368 | | - continue; |
---|
369 | | - } |
---|
370 | | - } |
---|
371 | | - |
---|
372 | | - /* Do not remove the cast. blk_rq_pos(req) is now a |
---|
373 | | - * sector_t and can be 64 bits, but it will never go |
---|
374 | | - * past 32 bits for this driver anyway, so we can |
---|
375 | | - * safely cast it down and not have to do a 64/32 |
---|
376 | | - * division |
---|
377 | | - */ |
---|
378 | | - fs->req_cyl = ((long)blk_rq_pos(req)) / fs->secpercyl; |
---|
379 | | - x = ((long)blk_rq_pos(req)) % fs->secpercyl; |
---|
380 | | - fs->head = x / fs->secpertrack; |
---|
381 | | - fs->req_sector = x % fs->secpertrack + 1; |
---|
382 | | - fs->state = do_transfer; |
---|
383 | | - fs->retries = 0; |
---|
384 | | - |
---|
385 | | - act(fs); |
---|
| 320 | + blk_mq_start_request(req); |
---|
| 321 | + fs->cur_req = req; |
---|
| 322 | + if (fs->mdev->media_bay && |
---|
| 323 | + check_media_bay(fs->mdev->media_bay) != MB_FD) { |
---|
| 324 | + swim3_dbg("%s", " media bay absent, dropping req\n"); |
---|
| 325 | + swim3_end_request(fs, BLK_STS_IOERR, 0); |
---|
| 326 | + goto out; |
---|
386 | 327 | } |
---|
387 | | -} |
---|
| 328 | + if (fs->ejected) { |
---|
| 329 | + swim3_dbg("%s", " disk ejected\n"); |
---|
| 330 | + swim3_end_request(fs, BLK_STS_IOERR, 0); |
---|
| 331 | + goto out; |
---|
| 332 | + } |
---|
| 333 | + if (rq_data_dir(req) == WRITE) { |
---|
| 334 | + if (fs->write_prot < 0) |
---|
| 335 | + fs->write_prot = swim3_readbit(fs, WRITE_PROT); |
---|
| 336 | + if (fs->write_prot) { |
---|
| 337 | + swim3_dbg("%s", " try to write, disk write protected\n"); |
---|
| 338 | + swim3_end_request(fs, BLK_STS_IOERR, 0); |
---|
| 339 | + goto out; |
---|
| 340 | + } |
---|
| 341 | + } |
---|
388 | 342 | |
---|
389 | | -static void do_fd_request(struct request_queue * q) |
---|
390 | | -{ |
---|
391 | | - start_request(q->queuedata); |
---|
| 343 | + /* |
---|
| 344 | + * Do not remove the cast. blk_rq_pos(req) is now a sector_t and can be |
---|
| 345 | + * 64 bits, but it will never go past 32 bits for this driver anyway, so |
---|
| 346 | + * we can safely cast it down and not have to do a 64/32 division |
---|
| 347 | + */ |
---|
| 348 | + fs->req_cyl = ((long)blk_rq_pos(req)) / fs->secpercyl; |
---|
| 349 | + x = ((long)blk_rq_pos(req)) % fs->secpercyl; |
---|
| 350 | + fs->head = x / fs->secpertrack; |
---|
| 351 | + fs->req_sector = x % fs->secpertrack + 1; |
---|
| 352 | + fs->state = do_transfer; |
---|
| 353 | + fs->retries = 0; |
---|
| 354 | + |
---|
| 355 | + act(fs); |
---|
| 356 | + |
---|
| 357 | +out: |
---|
| 358 | + spin_unlock_irq(&swim3_lock); |
---|
| 359 | + return BLK_STS_OK; |
---|
392 | 360 | } |
---|
393 | 361 | |
---|
394 | 362 | static void set_timeout(struct floppy_state *fs, int nticks, |
---|
.. | .. |
---|
585 | 553 | if (fs->retries > 5) { |
---|
586 | 554 | swim3_end_request(fs, BLK_STS_IOERR, 0); |
---|
587 | 555 | fs->state = idle; |
---|
588 | | - start_request(fs); |
---|
589 | 556 | } else { |
---|
590 | 557 | fs->state = jogging; |
---|
591 | 558 | act(fs); |
---|
.. | .. |
---|
609 | 576 | swim3_err("%s", "Seek timeout\n"); |
---|
610 | 577 | swim3_end_request(fs, BLK_STS_IOERR, 0); |
---|
611 | 578 | fs->state = idle; |
---|
612 | | - start_request(fs); |
---|
613 | 579 | spin_unlock_irqrestore(&swim3_lock, flags); |
---|
614 | 580 | } |
---|
615 | 581 | |
---|
.. | .. |
---|
638 | 604 | swim3_err("%s", "Seek settle timeout\n"); |
---|
639 | 605 | swim3_end_request(fs, BLK_STS_IOERR, 0); |
---|
640 | 606 | fs->state = idle; |
---|
641 | | - start_request(fs); |
---|
642 | 607 | unlock: |
---|
643 | 608 | spin_unlock_irqrestore(&swim3_lock, flags); |
---|
644 | 609 | } |
---|
.. | .. |
---|
667 | 632 | (long)blk_rq_pos(fs->cur_req)); |
---|
668 | 633 | swim3_end_request(fs, BLK_STS_IOERR, 0); |
---|
669 | 634 | fs->state = idle; |
---|
670 | | - start_request(fs); |
---|
671 | 635 | spin_unlock_irqrestore(&swim3_lock, flags); |
---|
672 | 636 | } |
---|
673 | 637 | |
---|
.. | .. |
---|
704 | 668 | if (fs->retries > 5) { |
---|
705 | 669 | swim3_end_request(fs, BLK_STS_IOERR, 0); |
---|
706 | 670 | fs->state = idle; |
---|
707 | | - start_request(fs); |
---|
708 | 671 | } else { |
---|
709 | 672 | fs->state = jogging; |
---|
710 | 673 | act(fs); |
---|
.. | .. |
---|
796 | 759 | fs->state, rq_data_dir(req), intr, err); |
---|
797 | 760 | swim3_end_request(fs, BLK_STS_IOERR, 0); |
---|
798 | 761 | fs->state = idle; |
---|
799 | | - start_request(fs); |
---|
800 | 762 | break; |
---|
801 | 763 | } |
---|
802 | 764 | fs->retries = 0; |
---|
.. | .. |
---|
813 | 775 | } else |
---|
814 | 776 | fs->state = idle; |
---|
815 | 777 | } |
---|
816 | | - if (fs->state == idle) |
---|
817 | | - start_request(fs); |
---|
818 | 778 | break; |
---|
819 | 779 | default: |
---|
820 | 780 | swim3_err("Don't know what to do in state %d\n", fs->state); |
---|
.. | .. |
---|
862 | 822 | |
---|
863 | 823 | static void release_drive(struct floppy_state *fs) |
---|
864 | 824 | { |
---|
| 825 | + struct request_queue *q = disks[fs->index]->queue; |
---|
865 | 826 | unsigned long flags; |
---|
866 | 827 | |
---|
867 | 828 | swim3_dbg("%s", "-> release drive\n"); |
---|
868 | 829 | |
---|
869 | 830 | spin_lock_irqsave(&swim3_lock, flags); |
---|
870 | 831 | fs->state = idle; |
---|
871 | | - start_request(fs); |
---|
872 | 832 | spin_unlock_irqrestore(&swim3_lock, flags); |
---|
| 833 | + |
---|
| 834 | + blk_mq_freeze_queue(q); |
---|
| 835 | + blk_mq_quiesce_queue(q); |
---|
| 836 | + blk_mq_unquiesce_queue(q); |
---|
| 837 | + blk_mq_unfreeze_queue(q); |
---|
873 | 838 | } |
---|
874 | 839 | |
---|
875 | 840 | static int fd_eject(struct floppy_state *fs) |
---|
.. | .. |
---|
980 | 945 | |
---|
981 | 946 | if (err == 0 && (mode & FMODE_NDELAY) == 0 |
---|
982 | 947 | && (mode & (FMODE_READ|FMODE_WRITE))) { |
---|
983 | | - check_disk_change(bdev); |
---|
| 948 | + if (bdev_check_media_change(bdev)) |
---|
| 949 | + floppy_revalidate(bdev->bd_disk); |
---|
984 | 950 | if (fs->ejected) |
---|
985 | 951 | err = -ENXIO; |
---|
986 | 952 | } |
---|
.. | .. |
---|
1090 | 1056 | .release = floppy_release, |
---|
1091 | 1057 | .ioctl = floppy_ioctl, |
---|
1092 | 1058 | .check_events = floppy_check_events, |
---|
1093 | | - .revalidate_disk= floppy_revalidate, |
---|
| 1059 | +}; |
---|
| 1060 | + |
---|
| 1061 | +static const struct blk_mq_ops swim3_mq_ops = { |
---|
| 1062 | + .queue_rq = swim3_queue_rq, |
---|
1094 | 1063 | }; |
---|
1095 | 1064 | |
---|
1096 | 1065 | static void swim3_mb_event(struct macio_dev* mdev, int mb_state) |
---|
.. | .. |
---|
1118 | 1087 | struct floppy_state *fs = &floppy_states[index]; |
---|
1119 | 1088 | int rc = -EBUSY; |
---|
1120 | 1089 | |
---|
1121 | | - /* Do this first for message macros */ |
---|
1122 | | - memset(fs, 0, sizeof(*fs)); |
---|
1123 | 1090 | fs->mdev = mdev; |
---|
1124 | 1091 | fs->index = index; |
---|
1125 | 1092 | |
---|
.. | .. |
---|
1182 | 1149 | swim3_err("%s", "Couldn't request interrupt\n"); |
---|
1183 | 1150 | pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 0); |
---|
1184 | 1151 | goto out_unmap; |
---|
1185 | | - return -EBUSY; |
---|
1186 | 1152 | } |
---|
1187 | 1153 | |
---|
1188 | 1154 | timer_setup(&fs->timeout, NULL, 0); |
---|
.. | .. |
---|
1206 | 1172 | static int swim3_attach(struct macio_dev *mdev, |
---|
1207 | 1173 | const struct of_device_id *match) |
---|
1208 | 1174 | { |
---|
| 1175 | + struct floppy_state *fs; |
---|
1209 | 1176 | struct gendisk *disk; |
---|
1210 | | - int index, rc; |
---|
| 1177 | + int rc; |
---|
1211 | 1178 | |
---|
1212 | | - index = floppy_count++; |
---|
1213 | | - if (index >= MAX_FLOPPIES) |
---|
| 1179 | + if (floppy_count >= MAX_FLOPPIES) |
---|
1214 | 1180 | return -ENXIO; |
---|
1215 | 1181 | |
---|
1216 | | - /* Add the drive */ |
---|
1217 | | - rc = swim3_add_device(mdev, index); |
---|
1218 | | - if (rc) |
---|
1219 | | - return rc; |
---|
1220 | | - /* Now register that disk. Same comment about failure handling */ |
---|
1221 | | - disk = disks[index] = alloc_disk(1); |
---|
1222 | | - if (disk == NULL) |
---|
1223 | | - return -ENOMEM; |
---|
1224 | | - disk->queue = blk_init_queue(do_fd_request, &swim3_lock); |
---|
1225 | | - if (disk->queue == NULL) { |
---|
1226 | | - put_disk(disk); |
---|
1227 | | - return -ENOMEM; |
---|
| 1182 | + if (floppy_count == 0) { |
---|
| 1183 | + rc = register_blkdev(FLOPPY_MAJOR, "fd"); |
---|
| 1184 | + if (rc) |
---|
| 1185 | + return rc; |
---|
| 1186 | + } |
---|
| 1187 | + |
---|
| 1188 | + disk = alloc_disk(1); |
---|
| 1189 | + if (disk == NULL) { |
---|
| 1190 | + rc = -ENOMEM; |
---|
| 1191 | + goto out_unregister; |
---|
| 1192 | + } |
---|
| 1193 | + |
---|
| 1194 | + fs = &floppy_states[floppy_count]; |
---|
| 1195 | + memset(fs, 0, sizeof(*fs)); |
---|
| 1196 | + |
---|
| 1197 | + disk->queue = blk_mq_init_sq_queue(&fs->tag_set, &swim3_mq_ops, 2, |
---|
| 1198 | + BLK_MQ_F_SHOULD_MERGE); |
---|
| 1199 | + if (IS_ERR(disk->queue)) { |
---|
| 1200 | + rc = PTR_ERR(disk->queue); |
---|
| 1201 | + disk->queue = NULL; |
---|
| 1202 | + goto out_put_disk; |
---|
1228 | 1203 | } |
---|
1229 | 1204 | blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH); |
---|
1230 | | - disk->queue->queuedata = &floppy_states[index]; |
---|
| 1205 | + disk->queue->queuedata = fs; |
---|
1231 | 1206 | |
---|
1232 | | - if (index == 0) { |
---|
1233 | | - /* If we failed, there isn't much we can do as the driver is still |
---|
1234 | | - * too dumb to remove the device, just bail out |
---|
1235 | | - */ |
---|
1236 | | - if (register_blkdev(FLOPPY_MAJOR, "fd")) |
---|
1237 | | - return 0; |
---|
1238 | | - } |
---|
| 1207 | + rc = swim3_add_device(mdev, floppy_count); |
---|
| 1208 | + if (rc) |
---|
| 1209 | + goto out_cleanup_queue; |
---|
1239 | 1210 | |
---|
1240 | 1211 | disk->major = FLOPPY_MAJOR; |
---|
1241 | | - disk->first_minor = index; |
---|
| 1212 | + disk->first_minor = floppy_count; |
---|
1242 | 1213 | disk->fops = &floppy_fops; |
---|
1243 | | - disk->private_data = &floppy_states[index]; |
---|
| 1214 | + disk->private_data = fs; |
---|
| 1215 | + disk->events = DISK_EVENT_MEDIA_CHANGE; |
---|
1244 | 1216 | disk->flags |= GENHD_FL_REMOVABLE; |
---|
1245 | | - sprintf(disk->disk_name, "fd%d", index); |
---|
| 1217 | + sprintf(disk->disk_name, "fd%d", floppy_count); |
---|
1246 | 1218 | set_capacity(disk, 2880); |
---|
1247 | 1219 | add_disk(disk); |
---|
1248 | 1220 | |
---|
| 1221 | + disks[floppy_count++] = disk; |
---|
1249 | 1222 | return 0; |
---|
| 1223 | + |
---|
| 1224 | +out_cleanup_queue: |
---|
| 1225 | + blk_cleanup_queue(disk->queue); |
---|
| 1226 | + disk->queue = NULL; |
---|
| 1227 | + blk_mq_free_tag_set(&fs->tag_set); |
---|
| 1228 | +out_put_disk: |
---|
| 1229 | + put_disk(disk); |
---|
| 1230 | +out_unregister: |
---|
| 1231 | + if (floppy_count == 0) |
---|
| 1232 | + unregister_blkdev(FLOPPY_MAJOR, "fd"); |
---|
| 1233 | + return rc; |
---|
1250 | 1234 | } |
---|
1251 | 1235 | |
---|
1252 | 1236 | static const struct of_device_id swim3_match[] = |
---|