Blame view
drivers/ide/ide-park.c
3.45 KB
4abdc6ee7 ide: Implement di... |
1 |
#include <linux/kernel.h> |
5a0e3ad6a include cleanup: ... |
2 |
#include <linux/gfp.h> |
4abdc6ee7 ide: Implement di... |
3 4 5 6 7 8 9 10 |
#include <linux/ide.h> #include <linux/jiffies.h> #include <linux/blkdev.h> DECLARE_WAIT_QUEUE_HEAD(ide_park_wq); static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) { |
b65fac32c ide: merge ide_hw... |
11 |
ide_hwif_t *hwif = drive->hwif; |
4abdc6ee7 ide: Implement di... |
12 13 14 15 16 |
struct request_queue *q = drive->queue; struct request *rq; int rc; timeout += jiffies; |
b65fac32c ide: merge ide_hw... |
17 |
spin_lock_irq(&hwif->lock); |
4abdc6ee7 ide: Implement di... |
18 |
if (drive->dev_flags & IDE_DFLAG_PARKED) { |
2a2ca6a96 ide: replace the ... |
19 |
int reset_timer = time_before(timeout, drive->sleep); |
201bffa46 ide: use per-devi... |
20 |
int start_queue = 0; |
4abdc6ee7 ide: Implement di... |
21 |
|
4abdc6ee7 ide: Implement di... |
22 23 |
drive->sleep = timeout; wake_up_all(&ide_park_wq); |
b65fac32c ide: merge ide_hw... |
24 |
if (reset_timer && del_timer(&hwif->timer)) |
201bffa46 ide: use per-devi... |
25 |
start_queue = 1; |
b65fac32c ide: merge ide_hw... |
26 |
spin_unlock_irq(&hwif->lock); |
201bffa46 ide: use per-devi... |
27 |
|
853280a4d ide: use blk_run_... |
28 29 |
if (start_queue) blk_run_queue(q); |
4abdc6ee7 ide: Implement di... |
30 31 |
return; } |
b65fac32c ide: merge ide_hw... |
32 |
spin_unlock_irq(&hwif->lock); |
4abdc6ee7 ide: Implement di... |
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
rq = blk_get_request(q, READ, __GFP_WAIT); rq->cmd[0] = REQ_PARK_HEADS; rq->cmd_len = 1; rq->cmd_type = REQ_TYPE_SPECIAL; rq->special = &timeout; rc = blk_execute_rq(q, NULL, rq, 1); blk_put_request(rq); if (rc) goto out; /* * Make sure that *some* command is sent to the drive after the * timeout has expired, so power management will be reenabled. */ rq = blk_get_request(q, READ, GFP_NOWAIT); if (unlikely(!rq)) goto out; rq->cmd[0] = REQ_UNPARK_HEADS; rq->cmd_len = 1; rq->cmd_type = REQ_TYPE_SPECIAL; |
7eaceacca block: remove per... |
55 |
elv_add_request(q, rq, ELEVATOR_INSERT_FRONT); |
4abdc6ee7 ide: Implement di... |
56 57 58 59 |
out: return; } |
c4e66c36c ide: move ide_do_... |
60 61 |
ide_startstop_t ide_do_park_unpark(ide_drive_t *drive, struct request *rq) { |
22aa4b32a ide: remove ide_t... |
62 63 |
struct ide_cmd cmd; struct ide_taskfile *tf = &cmd.tf; |
c4e66c36c ide: move ide_do_... |
64 |
|
22aa4b32a ide: remove ide_t... |
65 |
memset(&cmd, 0, sizeof(cmd)); |
c4e66c36c ide: move ide_do_... |
66 67 68 69 70 71 72 73 |
if (rq->cmd[0] == REQ_PARK_HEADS) { drive->sleep = *(unsigned long *)rq->special; drive->dev_flags |= IDE_DFLAG_SLEEPING; tf->command = ATA_CMD_IDLEIMMEDIATE; tf->feature = 0x44; tf->lbal = 0x4c; tf->lbam = 0x4e; tf->lbah = 0x55; |
60f85019c ide: replace IDE_... |
74 75 |
cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; |
c4e66c36c ide: move ide_do_... |
76 77 |
} else /* cmd == REQ_UNPARK_HEADS */ tf->command = ATA_CMD_CHK_POWER; |
d364c7f50 ide: use ide_comp... |
78 |
cmd.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER; |
0dfb991c6 ide: use ata_tf_p... |
79 |
cmd.protocol = ATA_PROT_NODATA; |
22aa4b32a ide: remove ide_t... |
80 |
cmd.rq = rq; |
22aa4b32a ide: remove ide_t... |
81 82 |
return do_rw_taskfile(drive, &cmd); |
c4e66c36c ide: move ide_do_... |
83 |
} |
4abdc6ee7 ide: Implement di... |
84 85 86 87 |
ssize_t ide_park_show(struct device *dev, struct device_attribute *attr, char *buf) { ide_drive_t *drive = to_ide_device(dev); |
b65fac32c ide: merge ide_hw... |
88 |
ide_hwif_t *hwif = drive->hwif; |
4abdc6ee7 ide: Implement di... |
89 90 91 92 93 |
unsigned long now; unsigned int msecs; if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD) return -EOPNOTSUPP; |
b65fac32c ide: merge ide_hw... |
94 |
spin_lock_irq(&hwif->lock); |
4abdc6ee7 ide: Implement di... |
95 96 97 98 99 100 |
now = jiffies; if (drive->dev_flags & IDE_DFLAG_PARKED && time_after(drive->sleep, now)) msecs = jiffies_to_msecs(drive->sleep - now); else msecs = 0; |
b65fac32c ide: merge ide_hw... |
101 |
spin_unlock_irq(&hwif->lock); |
4abdc6ee7 ide: Implement di... |
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
return snprintf(buf, 20, "%u ", msecs); } ssize_t ide_park_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { #define MAX_PARK_TIMEOUT 30000 ide_drive_t *drive = to_ide_device(dev); long int input; int rc; rc = strict_strtol(buf, 10, &input); if (rc || input < -2) return -EINVAL; if (input > MAX_PARK_TIMEOUT) { input = MAX_PARK_TIMEOUT; rc = -EOVERFLOW; } mutex_lock(&ide_setting_mtx); if (input >= 0) { if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD) rc = -EOPNOTSUPP; else if (input || drive->dev_flags & IDE_DFLAG_PARKED) issue_park_cmd(drive, msecs_to_jiffies(input)); } else { if (drive->media == ide_disk) switch (input) { case -1: drive->dev_flags &= ~IDE_DFLAG_NO_UNLOAD; break; case -2: drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; break; } else rc = -EOPNOTSUPP; } mutex_unlock(&ide_setting_mtx); return rc ? rc : len; } |