Blame view
drivers/ide/ide-io.c
23.6 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
/* * IDE I/O functions * * Basic PIO and command management functionality. * * This code was split off from ide.c. See ide.c for history and original * copyrights. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * For the avoidance of doubt the "preferred form" of this code is one which * is in an open non patent encumbered format. Where cryptographic key signing * forms part of the process of creating an executable the information * including keys needed to generate an equivalently functional executable * are deemed to be part of the source code. */ |
1da177e4c Linux-2.6.12-rc2 |
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
#include <linux/module.h> #include <linux/types.h> #include <linux/string.h> #include <linux/kernel.h> #include <linux/timer.h> #include <linux/mm.h> #include <linux/interrupt.h> #include <linux/major.h> #include <linux/errno.h> #include <linux/genhd.h> #include <linux/blkpg.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/delay.h> #include <linux/ide.h> #include <linux/completion.h> #include <linux/reboot.h> #include <linux/cdrom.h> #include <linux/seq_file.h> #include <linux/device.h> #include <linux/kmod.h> #include <linux/scatterlist.h> |
1977f0327 remove asm/bitops... |
50 |
#include <linux/bitops.h> |
1da177e4c Linux-2.6.12-rc2 |
51 52 53 54 55 |
#include <asm/byteorder.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <asm/io.h> |
1da177e4c Linux-2.6.12-rc2 |
56 |
|
37245aabf ide: sanitize ide... |
57 |
int ide_end_rq(ide_drive_t *drive, struct request *rq, int error, |
1caf236da ide: add ide_end_... |
58 |
unsigned int nr_bytes) |
1da177e4c Linux-2.6.12-rc2 |
59 |
{ |
1da177e4c Linux-2.6.12-rc2 |
60 61 62 63 |
/* * decide whether to reenable DMA -- 3 is a random magic for now, * if we DMA timeout more than 3 times, just stay in PIO */ |
c39220483 ide: DMA_PIO_RETR... |
64 65 66 |
if ((drive->dev_flags & IDE_DFLAG_DMA_PIO_RETRY) && drive->retry_pio <= 3) { drive->dev_flags &= ~IDE_DFLAG_DMA_PIO_RETRY; |
4a546e046 ide: remove ->ide... |
67 |
ide_dma_on(drive); |
1da177e4c Linux-2.6.12-rc2 |
68 |
} |
1caf236da ide: add ide_end_... |
69 |
return blk_end_request(rq, error, nr_bytes); |
1da177e4c Linux-2.6.12-rc2 |
70 |
} |
1caf236da ide: add ide_end_... |
71 |
EXPORT_SYMBOL_GPL(ide_end_rq); |
1da177e4c Linux-2.6.12-rc2 |
72 |
|
22aa4b32a ide: remove ide_t... |
73 |
void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err) |
e120237c0 ide: factor out c... |
74 |
{ |
35218d1ca ide: move data re... |
75 |
const struct ide_tp_ops *tp_ops = drive->hwif->tp_ops; |
22aa4b32a ide: remove ide_t... |
76 77 |
struct ide_taskfile *tf = &cmd->tf; struct request *rq = cmd->rq; |
e7fedc3ca ide: use ide_comp... |
78 |
u8 tf_cmd = tf->command; |
e120237c0 ide: factor out c... |
79 80 81 |
tf->error = err; tf->status = stat; |
35218d1ca ide: move data re... |
82 83 84 85 |
if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) { u8 data[2]; tp_ops->input_data(drive, cmd, data, 2); |
745483f10 ide: simplify 'st... |
86 87 |
cmd->tf.data = data[0]; cmd->hob.data = data[1]; |
35218d1ca ide: move data re... |
88 |
} |
3153c26b5 ide: refactor tf_... |
89 |
ide_tf_readback(drive, cmd); |
e120237c0 ide: factor out c... |
90 |
|
e7fedc3ca ide: use ide_comp... |
91 92 93 94 95 96 |
if ((cmd->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) && tf_cmd == ATA_CMD_IDLEIMMEDIATE) { if (tf->lbal != 0xc4) { printk(KERN_ERR "%s: head unload failed! ", drive->name); |
745483f10 ide: simplify 'st... |
97 |
ide_tf_dump(drive->name, cmd); |
e7fedc3ca ide: use ide_comp... |
98 99 100 |
} else drive->dev_flags |= IDE_DFLAG_PARKED; } |
f505d49ff ide: fix barriers... |
101 102 |
if (rq && rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { struct ide_cmd *orig_cmd = rq->special; |
a09485df9 ide: move request... |
103 |
|
f505d49ff ide: fix barriers... |
104 105 106 107 108 |
if (cmd->tf_flags & IDE_TFLAG_DYN) kfree(orig_cmd); else memcpy(orig_cmd, cmd, sizeof(*cmd)); } |
e120237c0 ide: factor out c... |
109 |
} |
f974b196f ide: pass number ... |
110 |
int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes) |
1da177e4c Linux-2.6.12-rc2 |
111 |
{ |
b65fac32c ide: merge ide_hw... |
112 113 |
ide_hwif_t *hwif = drive->hwif; struct request *rq = hwif->rq; |
a9587fd8c ide: remove BUG()... |
114 |
int rc; |
1da177e4c Linux-2.6.12-rc2 |
115 |
|
130e88670 ide: remove ide_e... |
116 117 118 119 120 |
/* * if failfast is set on a request, override number of sectors * and complete the whole request right now */ if (blk_noretry_request(rq) && error <= 0) |
5b93629b4 block: implement ... |
121 |
nr_bytes = blk_rq_sectors(rq) << 9; |
130e88670 ide: remove ide_e... |
122 |
|
ba7d479c3 ide: use ide_end_... |
123 |
rc = ide_end_rq(drive, rq, error, nr_bytes); |
a9587fd8c ide: remove BUG()... |
124 125 |
if (rc == 0) hwif->rq = NULL; |
1d0bf587d ide: ide_hwgroup_... |
126 |
|
a9587fd8c ide: remove BUG()... |
127 |
return rc; |
1da177e4c Linux-2.6.12-rc2 |
128 |
} |
a09485df9 ide: move request... |
129 |
EXPORT_SYMBOL(ide_complete_rq); |
1da177e4c Linux-2.6.12-rc2 |
130 |
|
327fa1c29 ide: move error h... |
131 |
void ide_kill_rq(ide_drive_t *drive, struct request *rq) |
1da177e4c Linux-2.6.12-rc2 |
132 |
{ |
33659ebba block: remove wra... |
133 |
u8 drv_req = (rq->cmd_type == REQ_TYPE_SPECIAL) && rq->rq_disk; |
3ee38302f ide: remove ->end... |
134 |
u8 media = drive->media; |
c152cc1a9 ide: use ->end_re... |
135 |
drive->failed_pc = NULL; |
6902a5331 ide: pass error v... |
136 137 |
if ((media == ide_floppy || media == ide_tape) && drv_req) { rq->errors = 0; |
6902a5331 ide: pass error v... |
138 139 140 |
} else { if (media == ide_tape) rq->errors = IDE_DRV_ERROR_GENERAL; |
33659ebba block: remove wra... |
141 |
else if (rq->cmd_type != REQ_TYPE_FS && rq->errors == 0) |
89f78b326 ide: move rq->err... |
142 |
rq->errors = -EIO; |
6902a5331 ide: pass error v... |
143 |
} |
5e955245d ide: always kill ... |
144 145 |
ide_complete_rq(drive, -EIO, blk_rq_bytes(rq)); |
1da177e4c Linux-2.6.12-rc2 |
146 |
} |
57d7366b7 ide: remove 'hand... |
147 |
static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) |
1da177e4c Linux-2.6.12-rc2 |
148 |
{ |
57d7366b7 ide: remove 'hand... |
149 150 151 152 |
tf->nsect = drive->sect; tf->lbal = drive->sect; tf->lbam = drive->cyl; tf->lbah = drive->cyl >> 8; |
7f612f272 ide: remove [ata_... |
153 |
tf->device = (drive->head - 1) | drive->select; |
aaaade3f0 ide: WIN_* -> ATA... |
154 |
tf->command = ATA_CMD_INIT_DEV_PARAMS; |
1da177e4c Linux-2.6.12-rc2 |
155 |
} |
57d7366b7 ide: remove 'hand... |
156 |
static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf) |
1da177e4c Linux-2.6.12-rc2 |
157 |
{ |
57d7366b7 ide: remove 'hand... |
158 |
tf->nsect = drive->sect; |
aaaade3f0 ide: WIN_* -> ATA... |
159 |
tf->command = ATA_CMD_RESTORE; |
1da177e4c Linux-2.6.12-rc2 |
160 |
} |
57d7366b7 ide: remove 'hand... |
161 |
static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf) |
1da177e4c Linux-2.6.12-rc2 |
162 |
{ |
57d7366b7 ide: remove 'hand... |
163 |
tf->nsect = drive->mult_req; |
aaaade3f0 ide: WIN_* -> ATA... |
164 |
tf->command = ATA_CMD_SET_MULTI; |
1da177e4c Linux-2.6.12-rc2 |
165 |
} |
582078ee3 ide: merge ide_di... |
166 167 168 169 170 171 172 173 174 |
/** * do_special - issue some special commands * @drive: drive the command is for * * do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS, * ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive. */ static ide_startstop_t do_special(ide_drive_t *drive) |
1da177e4c Linux-2.6.12-rc2 |
175 |
{ |
22aa4b32a ide: remove ide_t... |
176 |
struct ide_cmd cmd; |
1da177e4c Linux-2.6.12-rc2 |
177 |
|
582078ee3 ide: merge ide_di... |
178 |
#ifdef DEBUG |
ca1b96e00 ide: replace spec... |
179 180 181 |
printk(KERN_DEBUG "%s: %s: 0x%02x ", drive->name, __func__, drive->special_flags); |
582078ee3 ide: merge ide_di... |
182 183 |
#endif if (drive->media != ide_disk) { |
ca1b96e00 ide: replace spec... |
184 |
drive->special_flags = 0; |
582078ee3 ide: merge ide_di... |
185 186 187 |
drive->mult_req = 0; return ide_stopped; } |
22aa4b32a ide: remove ide_t... |
188 |
memset(&cmd, 0, sizeof(cmd)); |
0dfb991c6 ide: use ata_tf_p... |
189 |
cmd.protocol = ATA_PROT_NODATA; |
1da177e4c Linux-2.6.12-rc2 |
190 |
|
ca1b96e00 ide: replace spec... |
191 192 |
if (drive->special_flags & IDE_SFLAG_SET_GEOMETRY) { drive->special_flags &= ~IDE_SFLAG_SET_GEOMETRY; |
22aa4b32a ide: remove ide_t... |
193 |
ide_tf_set_specify_cmd(drive, &cmd.tf); |
ca1b96e00 ide: replace spec... |
194 195 |
} else if (drive->special_flags & IDE_SFLAG_RECALIBRATE) { drive->special_flags &= ~IDE_SFLAG_RECALIBRATE; |
22aa4b32a ide: remove ide_t... |
196 |
ide_tf_set_restore_cmd(drive, &cmd.tf); |
ca1b96e00 ide: replace spec... |
197 198 |
} else if (drive->special_flags & IDE_SFLAG_SET_MULTMODE) { drive->special_flags &= ~IDE_SFLAG_SET_MULTMODE; |
22aa4b32a ide: remove ide_t... |
199 |
ide_tf_set_setmult_cmd(drive, &cmd.tf); |
5f582c8e2 ide: BUG() on unk... |
200 201 |
} else BUG(); |
1da177e4c Linux-2.6.12-rc2 |
202 |
|
60f85019c ide: replace IDE_... |
203 204 205 |
cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; cmd.tf_flags = IDE_TFLAG_CUSTOM_HANDLER; |
74095a91e ide: use do_rw_ta... |
206 |
|
22aa4b32a ide: remove ide_t... |
207 |
do_rw_taskfile(drive, &cmd); |
1da177e4c Linux-2.6.12-rc2 |
208 209 210 |
return ide_started; } |
229816941 ide: pass command... |
211 |
void ide_map_sg(ide_drive_t *drive, struct ide_cmd *cmd) |
1da177e4c Linux-2.6.12-rc2 |
212 213 214 |
{ ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; |
229816941 ide: pass command... |
215 |
struct request *rq = cmd->rq; |
1da177e4c Linux-2.6.12-rc2 |
216 |
|
5ad960fe8 ide: drop rq->dat... |
217 |
cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); |
1da177e4c Linux-2.6.12-rc2 |
218 |
} |
1da177e4c Linux-2.6.12-rc2 |
219 |
EXPORT_SYMBOL_GPL(ide_map_sg); |
bf717c0a2 ide: keep track o... |
220 |
void ide_init_sg_cmd(struct ide_cmd *cmd, unsigned int nr_bytes) |
1da177e4c Linux-2.6.12-rc2 |
221 |
{ |
bf717c0a2 ide: keep track o... |
222 |
cmd->nbytes = cmd->nleft = nr_bytes; |
b6308ee0c ide: move command... |
223 224 |
cmd->cursg_ofs = 0; cmd->cursg = NULL; |
1da177e4c Linux-2.6.12-rc2 |
225 |
} |
1da177e4c Linux-2.6.12-rc2 |
226 227 228 229 |
EXPORT_SYMBOL_GPL(ide_init_sg_cmd); /** * execute_drive_command - issue special drive command |
338cec325 [PATCH] merge som... |
230 |
* @drive: the drive to issue the command on |
1da177e4c Linux-2.6.12-rc2 |
231 232 233 234 235 236 237 238 239 240 241 242 |
* @rq: the request structure holding the command * * execute_drive_cmd() issues a special drive command, usually * initiated by ioctl() from the external hdparm program. The * command can be a drive command, drive task or taskfile * operation. Weirdly you can call it with NULL to wait for * all commands to finish. Don't do this as that is due to change */ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) { |
22aa4b32a ide: remove ide_t... |
243 |
struct ide_cmd *cmd = rq->special; |
1da177e4c Linux-2.6.12-rc2 |
244 |
|
22aa4b32a ide: remove ide_t... |
245 |
if (cmd) { |
0dfb991c6 ide: use ata_tf_p... |
246 |
if (cmd->protocol == ATA_PROT_PIO) { |
9780e2dd8 ide: convert to r... |
247 |
ide_init_sg_cmd(cmd, blk_rq_sectors(rq) << 9); |
229816941 ide: pass command... |
248 |
ide_map_sg(drive, cmd); |
1da177e4c Linux-2.6.12-rc2 |
249 |
} |
74095a91e ide: use do_rw_ta... |
250 |
|
22aa4b32a ide: remove ide_t... |
251 |
return do_rw_taskfile(drive, cmd); |
21d535c91 ide: execute_driv... |
252 |
} |
1da177e4c Linux-2.6.12-rc2 |
253 254 255 256 257 258 259 260 |
/* * NULL is actually a valid way of waiting for * all current requests to be flushed from the queue. */ #ifdef DEBUG printk("%s: DRIVE_CMD (null) ", drive->name); #endif |
6902a5331 ide: pass error v... |
261 |
rq->errors = 0; |
f974b196f ide: pass number ... |
262 |
ide_complete_rq(drive, 0, blk_rq_bytes(rq)); |
64a57fe43 ide: add ide_read... |
263 |
|
1da177e4c Linux-2.6.12-rc2 |
264 |
return ide_stopped; |
1bc6daae4 ide: factor out p... |
265 |
} |
79e36a9f5 IDE: Fix HDIO_DRI... |
266 267 |
static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) { |
4abdc6ee7 ide: Implement di... |
268 |
u8 cmd = rq->cmd[0]; |
4abdc6ee7 ide: Implement di... |
269 |
switch (cmd) { |
1bc6daae4 ide: factor out p... |
270 271 272 |
case REQ_PARK_HEADS: case REQ_UNPARK_HEADS: return ide_do_park_unpark(drive, rq); |
92f1f8fd8 ide: Remove ide_s... |
273 |
case REQ_DEVSET_EXEC: |
1bc6daae4 ide: factor out p... |
274 |
return ide_do_devset(drive, rq); |
79e36a9f5 IDE: Fix HDIO_DRI... |
275 276 277 |
case REQ_DRIVE_RESET: return ide_do_reset(drive); default: |
1713788ff ide: make ide_spe... |
278 |
BUG(); |
79e36a9f5 IDE: Fix HDIO_DRI... |
279 280 |
} } |
1da177e4c Linux-2.6.12-rc2 |
281 282 283 284 |
/** * start_request - start of I/O and command issuing for IDE * * start_request() initiates handling of a new I/O request. It |
3c619ffd4 ide: remove no lo... |
285 |
* accepts commands and I/O (read/write) requests. |
1da177e4c Linux-2.6.12-rc2 |
286 287 288 289 290 291 292 |
* * FIXME: this function needs a rename */ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) { ide_startstop_t startstop; |
1da177e4c Linux-2.6.12-rc2 |
293 |
|
33659ebba block: remove wra... |
294 |
BUG_ON(!(rq->cmd_flags & REQ_STARTED)); |
1da177e4c Linux-2.6.12-rc2 |
295 296 297 298 |
#ifdef DEBUG printk("%s: start_request: current=0x%08lx ", |
898ec223f ide: remove HWIF(... |
299 |
drive->hwif->name, (unsigned long) rq); |
1da177e4c Linux-2.6.12-rc2 |
300 301 302 303 |
#endif /* bail early if we've exceeded max_failures */ if (drive->max_failures && (drive->failures > drive->max_failures)) { |
b5e1a4e28 ide-io: set REQ_F... |
304 |
rq->cmd_flags |= REQ_FAILED; |
1da177e4c Linux-2.6.12-rc2 |
305 306 |
goto kill_rq; } |
ad3caddaa [PATCH] Get rid o... |
307 308 |
if (blk_pm_request(rq)) ide_check_pm_state(drive, rq); |
1da177e4c Linux-2.6.12-rc2 |
309 |
|
fdd88f0af ide: inline SELEC... |
310 |
drive->hwif->tp_ops->dev_select(drive); |
3a7d24841 ide: use ATA_* de... |
311 312 |
if (ide_wait_stat(&startstop, drive, drive->ready_stat, ATA_BUSY | ATA_DRQ, WAIT_READY)) { |
1da177e4c Linux-2.6.12-rc2 |
313 314 315 316 |
printk(KERN_ERR "%s: drive not ready for command ", drive->name); return startstop; } |
ca1b96e00 ide: replace spec... |
317 318 |
if (drive->special_flags == 0) { |
7f3c868ba ide: remove ide_d... |
319 |
struct ide_driver *drv; |
1da177e4c Linux-2.6.12-rc2 |
320 |
|
513daadd1 ide: use correct ... |
321 322 323 324 325 326 |
/* * We reset the drive so we need to issue a SETFEATURES. * Do it _after_ do_special() restored device parameters. */ if (drive->current_speed == 0xff) ide_config_drive_speed(drive, drive->desired_speed); |
7267c3377 ide: remove REQ_T... |
327 |
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) |
1da177e4c Linux-2.6.12-rc2 |
328 329 |
return execute_drive_cmd(drive, rq); else if (blk_pm_request(rq)) { |
765139ef5 ide-pm: don't abu... |
330 |
struct request_pm_state *pm = rq->special; |
1da177e4c Linux-2.6.12-rc2 |
331 332 333 |
#ifdef DEBUG_PM printk("%s: start_power_step(step: %d) ", |
6b7d8fc36 ide: fix build fo... |
334 |
drive->name, pm->pm_step); |
1da177e4c Linux-2.6.12-rc2 |
335 336 337 |
#endif startstop = ide_start_power_step(drive, rq); if (startstop == ide_stopped && |
0d346ba07 ide: sanitize ide... |
338 |
pm->pm_step == IDE_PM_COMPLETED) |
3616b6536 ide: complete pow... |
339 |
ide_complete_pm_rq(drive, rq); |
1da177e4c Linux-2.6.12-rc2 |
340 |
return startstop; |
4c4762d10 block: fix some m... |
341 |
} else if (!rq->rq_disk && rq->cmd_type == REQ_TYPE_SPECIAL) |
79e36a9f5 IDE: Fix HDIO_DRI... |
342 343 344 345 346 347 348 349 350 |
/* * TODO: Once all ULDs have been modified to * check for specific op codes rather than * blindly accepting any special request, the * check for ->rq_disk above may be replaced * by a more suitable mechanism or even * dropped entirely. */ return ide_special_rq(drive, rq); |
1da177e4c Linux-2.6.12-rc2 |
351 |
|
7f3c868ba ide: remove ide_d... |
352 |
drv = *(struct ide_driver **)rq->rq_disk->private_data; |
3c619ffd4 ide: remove no lo... |
353 |
|
9780e2dd8 ide: convert to r... |
354 |
return drv->do_request(drive, rq, blk_rq_pos(rq)); |
1da177e4c Linux-2.6.12-rc2 |
355 356 357 358 359 360 361 362 363 364 365 366 367 |
} return do_special(drive); kill_rq: ide_kill_rq(drive, rq); return ide_stopped; } /** * ide_stall_queue - pause an IDE device * @drive: drive to stall * @timeout: time to stall for (jiffies) * * ide_stall_queue() can be used by a drive to give excess bandwidth back |
b65fac32c ide: merge ide_hw... |
368 |
* to the port by sleeping for timeout jiffies. |
1da177e4c Linux-2.6.12-rc2 |
369 370 371 372 373 374 375 |
*/ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) { if (timeout > WAIT_WORSTCASE) timeout = WAIT_WORSTCASE; drive->sleep = timeout + jiffies; |
97100fc81 ide: add device f... |
376 |
drive->dev_flags |= IDE_DFLAG_SLEEPING; |
1da177e4c Linux-2.6.12-rc2 |
377 |
} |
1da177e4c Linux-2.6.12-rc2 |
378 |
EXPORT_SYMBOL(ide_stall_queue); |
5b31f855f ide: use lock bit... |
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
static inline int ide_lock_port(ide_hwif_t *hwif) { if (hwif->busy) return 1; hwif->busy = 1; return 0; } static inline void ide_unlock_port(ide_hwif_t *hwif) { hwif->busy = 0; } static inline int ide_lock_host(struct ide_host *host, ide_hwif_t *hwif) { int rc = 0; if (host->host_flags & IDE_HFLAG_SERIALIZE) { rc = test_and_set_bit_lock(IDE_HOST_BUSY, &host->host_busy); if (rc == 0) { |
e354c1d80 ide: remove IDE_A... |
401 402 |
if (host->get_lock) host->get_lock(ide_intr, hwif); |
5b31f855f ide: use lock bit... |
403 404 405 406 407 408 409 410 |
} } return rc; } static inline void ide_unlock_host(struct ide_host *host) { if (host->host_flags & IDE_HFLAG_SERIALIZE) { |
e354c1d80 ide: remove IDE_A... |
411 412 |
if (host->release_lock) host->release_lock(); |
5b31f855f ide: use lock bit... |
413 414 415 |
clear_bit_unlock(IDE_HOST_BUSY, &host->host_busy); } } |
782b86e26 ide: always ensur... |
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 |
static void __ide_requeue_and_plug(struct request_queue *q, struct request *rq) { if (rq) blk_requeue_request(q, rq); if (rq || blk_peek_request(q)) { /* Use 3ms as that was the old plug delay */ blk_delay_queue(q, 3); } } void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq) { struct request_queue *q = drive->queue; unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); __ide_requeue_and_plug(q, rq); spin_unlock_irqrestore(q->queue_lock, flags); } |
1da177e4c Linux-2.6.12-rc2 |
435 |
/* |
b65fac32c ide: merge ide_hw... |
436 |
* Issue a new request to a device. |
1da177e4c Linux-2.6.12-rc2 |
437 |
*/ |
295f00042 ide: don't execut... |
438 |
void do_ide_request(struct request_queue *q) |
1da177e4c Linux-2.6.12-rc2 |
439 |
{ |
201bffa46 ide: use per-devi... |
440 441 |
ide_drive_t *drive = q->queuedata; ide_hwif_t *hwif = drive->hwif; |
5b31f855f ide: use lock bit... |
442 |
struct ide_host *host = hwif->host; |
5b31f855f ide: use lock bit... |
443 |
struct request *rq = NULL; |
1da177e4c Linux-2.6.12-rc2 |
444 |
ide_startstop_t startstop; |
9ced0b95b ide: ensure that ... |
445 |
unsigned long queue_run_ms = 3; /* old plug delay */ |
1da177e4c Linux-2.6.12-rc2 |
446 |
|
201bffa46 ide: use per-devi... |
447 |
spin_unlock_irq(q->queue_lock); |
5b31f855f ide: use lock bit... |
448 |
|
02e7cf8f8 ide-cd,atapi: use... |
449 450 |
/* HLD do_request() callback might sleep, make sure it's okay */ might_sleep(); |
5b31f855f ide: use lock bit... |
451 452 |
if (ide_lock_host(host, hwif)) goto plug_device_2; |
b65fac32c ide: merge ide_hw... |
453 |
spin_lock_irq(&hwif->lock); |
295f00042 ide: don't execut... |
454 |
|
5b31f855f ide: use lock bit... |
455 |
if (!ide_lock_port(hwif)) { |
42cf2611b ide: fix setting ... |
456 |
ide_hwif_t *prev_port; |
3503e0acb Revert "ide: impr... |
457 458 |
WARN_ON_ONCE(hwif->rq); |
201bffa46 ide: use per-devi... |
459 |
repeat: |
bd53cbcce ide: add ->cur_po... |
460 |
prev_port = hwif->host->cur_port; |
9010941c5 ide: Fix code dea... |
461 462 |
if (drive->dev_flags & IDE_DFLAG_SLEEPING && time_after(drive->sleep, jiffies)) { |
9ced0b95b ide: ensure that ... |
463 464 465 |
unsigned long left = jiffies - drive->sleep; queue_run_ms = jiffies_to_msecs(left + 1); |
9010941c5 ide: Fix code dea... |
466 467 |
ide_unlock_port(hwif); goto plug_device; |
201bffa46 ide: use per-devi... |
468 |
} |
295f00042 ide: don't execut... |
469 |
|
bd53cbcce ide: add ->cur_po... |
470 471 |
if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) && hwif != prev_port) { |
734affdca ide: add IDE_DFLA... |
472 473 |
ide_drive_t *cur_dev = prev_port ? prev_port->cur_dev : NULL; |
7299a3918 ide: remove hwif-... |
474 |
/* |
42cf2611b ide: fix setting ... |
475 |
* set nIEN for previous port, drives in the |
734affdca ide: add IDE_DFLA... |
476 |
* quirk list may not like intr setups/cleanups |
7299a3918 ide: remove hwif-... |
477 |
*/ |
734affdca ide: add IDE_DFLA... |
478 479 |
if (cur_dev && (cur_dev->dev_flags & IDE_DFLAG_NIEN_QUIRK) == 0) |
ecf3a31d2 ide: turn set_irq... |
480 481 482 |
prev_port->tp_ops->write_devctl(prev_port, ATA_NIEN | ATA_DEVCTL_OBS); |
bd53cbcce ide: add ->cur_po... |
483 484 |
hwif->host->cur_port = hwif; |
1da177e4c Linux-2.6.12-rc2 |
485 |
} |
b65fac32c ide: merge ide_hw... |
486 |
hwif->cur_dev = drive; |
4abdc6ee7 ide: Implement di... |
487 |
drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); |
1da177e4c Linux-2.6.12-rc2 |
488 |
|
3503e0acb Revert "ide: impr... |
489 490 491 492 493 494 495 |
spin_unlock_irq(&hwif->lock); spin_lock_irq(q->queue_lock); /* * we know that the queue isn't empty, but this can happen * if the q->prep_rq_fn() decides to kill a request */ if (!rq) |
9934c8c04 block: implement ... |
496 |
rq = blk_fetch_request(drive->queue); |
8f6205cd5 ide: dequeue in-f... |
497 |
|
3503e0acb Revert "ide: impr... |
498 499 500 501 502 503 |
spin_unlock_irq(q->queue_lock); spin_lock_irq(&hwif->lock); if (!rq) { ide_unlock_port(hwif); goto out; |
1da177e4c Linux-2.6.12-rc2 |
504 505 506 507 |
} /* * Sanity: don't accept a request that isn't a PM request |
3503e0acb Revert "ide: impr... |
508 509 510 511 512 513 514 515 516 517 |
* if we are currently power managed. This is very important as * blk_stop_queue() doesn't prevent the blk_fetch_request() * above to return us whatever is in the queue. Since we call * ide_do_request() ourselves, we end up taking requests while * the queue is blocked... * * We let requests forced at head of queue with ide-preempt * though. I hope that doesn't happen too much, hopefully not * unless the subdriver triggers such a thing in its own PM * state machine. |
1da177e4c Linux-2.6.12-rc2 |
518 |
*/ |
3503e0acb Revert "ide: impr... |
519 520 521 522 523 524 525 |
if ((drive->dev_flags & IDE_DFLAG_BLOCKED) && blk_pm_request(rq) == 0 && (rq->cmd_flags & REQ_PREEMPT) == 0) { /* there should be no pending command at this point */ ide_unlock_port(hwif); goto plug_device; } |
1da177e4c Linux-2.6.12-rc2 |
526 |
|
b65fac32c ide: merge ide_hw... |
527 |
hwif->rq = rq; |
1da177e4c Linux-2.6.12-rc2 |
528 |
|
b65fac32c ide: merge ide_hw... |
529 |
spin_unlock_irq(&hwif->lock); |
1da177e4c Linux-2.6.12-rc2 |
530 |
startstop = start_request(drive, rq); |
b65fac32c ide: merge ide_hw... |
531 |
spin_lock_irq(&hwif->lock); |
295f00042 ide: don't execut... |
532 |
|
8f6205cd5 ide: dequeue in-f... |
533 534 535 |
if (startstop == ide_stopped) { rq = hwif->rq; hwif->rq = NULL; |
201bffa46 ide: use per-devi... |
536 |
goto repeat; |
8f6205cd5 ide: dequeue in-f... |
537 |
} |
201bffa46 ide: use per-devi... |
538 539 540 |
} else goto plug_device; out: |
b65fac32c ide: merge ide_hw... |
541 |
spin_unlock_irq(&hwif->lock); |
5b31f855f ide: use lock bit... |
542 543 |
if (rq == NULL) ide_unlock_host(host); |
201bffa46 ide: use per-devi... |
544 |
spin_lock_irq(q->queue_lock); |
295f00042 ide: don't execut... |
545 |
return; |
1da177e4c Linux-2.6.12-rc2 |
546 |
|
295f00042 ide: don't execut... |
547 |
plug_device: |
b65fac32c ide: merge ide_hw... |
548 |
spin_unlock_irq(&hwif->lock); |
5b31f855f ide: use lock bit... |
549 550 |
ide_unlock_host(host); plug_device_2: |
201bffa46 ide: use per-devi... |
551 |
spin_lock_irq(q->queue_lock); |
782b86e26 ide: always ensur... |
552 |
__ide_requeue_and_plug(q, rq); |
201bffa46 ide: use per-devi... |
553 |
} |
b6a45a0b1 ide: move drive_i... |
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 |
static int drive_is_ready(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; u8 stat = 0; if (drive->waiting_for_dma) return hwif->dma_ops->dma_test_irq(drive); if (hwif->io_ports.ctl_addr && (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) stat = hwif->tp_ops->read_altstatus(hwif); else /* Note: this may clear a pending IRQ!! */ stat = hwif->tp_ops->read_status(hwif); if (stat & ATA_BUSY) /* drive busy: definitely not interrupting */ return 0; /* drive ready: *might* be interrupting */ return 1; } |
1da177e4c Linux-2.6.12-rc2 |
576 577 |
/** * ide_timer_expiry - handle lack of an IDE interrupt |
b65fac32c ide: merge ide_hw... |
578 |
* @data: timer callback magic (hwif) |
1da177e4c Linux-2.6.12-rc2 |
579 580 581 582 583 584 585 586 587 588 589 590 591 |
* * An IDE command has timed out before the expected drive return * occurred. At this point we attempt to clean up the current * mess. If the current handler includes an expiry handler then * we invoke the expiry handler, and providing it is happy the * work is done. If that fails we apply generic recovery rules * invoking the handler and checking the drive DMA status. We * have an excessively incestuous relationship with the DMA * logic that wants cleaning up. */ void ide_timer_expiry (unsigned long data) { |
b65fac32c ide: merge ide_hw... |
592 |
ide_hwif_t *hwif = (ide_hwif_t *)data; |
201bffa46 ide: use per-devi... |
593 |
ide_drive_t *uninitialized_var(drive); |
1da177e4c Linux-2.6.12-rc2 |
594 |
ide_handler_t *handler; |
1da177e4c Linux-2.6.12-rc2 |
595 |
unsigned long flags; |
e0c6dcd8d ide: expiry() ret... |
596 |
int wait = -1; |
201bffa46 ide: use per-devi... |
597 |
int plug_device = 0; |
8f6205cd5 ide: dequeue in-f... |
598 |
struct request *uninitialized_var(rq_in_flight); |
1da177e4c Linux-2.6.12-rc2 |
599 |
|
b65fac32c ide: merge ide_hw... |
600 601 602 |
spin_lock_irqsave(&hwif->lock, flags); handler = hwif->handler; |
1da177e4c Linux-2.6.12-rc2 |
603 |
|
b65fac32c ide: merge ide_hw... |
604 |
if (handler == NULL || hwif->req_gen != hwif->req_gen_timer) { |
1da177e4c Linux-2.6.12-rc2 |
605 606 607 608 609 610 |
/* * Either a marginal timeout occurred * (got the interrupt just as timer expired), * or we were "sleeping" to give other devices a chance. * Either way, we don't really want to complain about anything. */ |
1da177e4c Linux-2.6.12-rc2 |
611 |
} else { |
c38714ed4 ide: remove now r... |
612 613 |
ide_expiry_t *expiry = hwif->expiry; ide_startstop_t startstop = ide_stopped; |
b65fac32c ide: merge ide_hw... |
614 |
drive = hwif->cur_dev; |
c38714ed4 ide: remove now r... |
615 616 617 618 619 620 621 622 623 624 |
if (expiry) { wait = expiry(drive); if (wait > 0) { /* continue */ /* reset timer */ hwif->timer.expires = jiffies + wait; hwif->req_gen_timer = hwif->req_gen; add_timer(&hwif->timer); spin_unlock_irqrestore(&hwif->lock, flags); return; |
295f00042 ide: don't execut... |
625 |
} |
1da177e4c Linux-2.6.12-rc2 |
626 |
} |
c38714ed4 ide: remove now r... |
627 |
hwif->handler = NULL; |
60c0cd02b ide: set hwif->ex... |
628 |
hwif->expiry = NULL; |
c38714ed4 ide: remove now r... |
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 |
/* * We need to simulate a real interrupt when invoking * the handler() function, which means we need to * globally mask the specific IRQ: */ spin_unlock(&hwif->lock); /* disable_irq_nosync ?? */ disable_irq(hwif->irq); /* local CPU only, as if we were handling an interrupt */ local_irq_disable(); if (hwif->polling) { startstop = handler(drive); } else if (drive_is_ready(drive)) { if (drive->waiting_for_dma) hwif->dma_ops->dma_lost_irq(drive); |
53b987d5e ide: call clear_i... |
644 645 |
if (hwif->port_ops && hwif->port_ops->clear_irq) hwif->port_ops->clear_irq(drive); |
c38714ed4 ide: remove now r... |
646 647 648 649 650 651 652 653 654 655 656 657 658 |
printk(KERN_WARNING "%s: lost interrupt ", drive->name); startstop = handler(drive); } else { if (drive->waiting_for_dma) startstop = ide_dma_timeout_retry(drive, wait); else startstop = ide_error(drive, "irq timeout", hwif->tp_ops->read_status(hwif)); } spin_lock_irq(&hwif->lock); enable_irq(hwif->irq); |
e3b29f051 ide: fix OOPS dur... |
659 |
if (startstop == ide_stopped && hwif->polling == 0) { |
8f6205cd5 ide: dequeue in-f... |
660 661 |
rq_in_flight = hwif->rq; hwif->rq = NULL; |
c38714ed4 ide: remove now r... |
662 663 664 |
ide_unlock_port(hwif); plug_device = 1; } |
1da177e4c Linux-2.6.12-rc2 |
665 |
} |
b65fac32c ide: merge ide_hw... |
666 |
spin_unlock_irqrestore(&hwif->lock, flags); |
201bffa46 ide: use per-devi... |
667 |
|
5b31f855f ide: use lock bit... |
668 669 |
if (plug_device) { ide_unlock_host(hwif->host); |
8f6205cd5 ide: dequeue in-f... |
670 |
ide_requeue_and_plug(drive, rq_in_flight); |
5b31f855f ide: use lock bit... |
671 |
} |
1da177e4c Linux-2.6.12-rc2 |
672 673 674 675 676 |
} /** * unexpected_intr - handle an unexpected IDE interrupt * @irq: interrupt line |
bd53cbcce ide: add ->cur_po... |
677 |
* @hwif: port being processed |
1da177e4c Linux-2.6.12-rc2 |
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 |
* * There's nothing really useful we can do with an unexpected interrupt, * other than reading the status register (to clear it), and logging it. * There should be no way that an irq can happen before we're ready for it, * so we needn't worry much about losing an "important" interrupt here. * * On laptops (and "green" PCs), an unexpected interrupt occurs whenever * the drive enters "idle", "standby", or "sleep" mode, so if the status * looks "good", we just ignore the interrupt completely. * * This routine assumes __cli() is in effect when called. * * If an unexpected interrupt happens on irq15 while we are handling irq14 * and if the two interfaces are "serialized" (CMD640), then it looks like * we could screw up by interfering with a new request being set up for * irq15. * * In reality, this is a non-issue. The new command is not sent unless * the drive is ready to accept one, in which case we know the drive is * not trying to interrupt us. And ide_set_handler() is always invoked * before completing the issuance of any new drive command, so we will not * be accidentally invoked as a result of any valid command completion * interrupt. |
1da177e4c Linux-2.6.12-rc2 |
701 |
*/ |
bd53cbcce ide: add ->cur_po... |
702 703 |
static void unexpected_intr(int irq, ide_hwif_t *hwif) |
1da177e4c Linux-2.6.12-rc2 |
704 |
{ |
ae86afaee ide: use per-port... |
705 706 707 708 709 710 711 712 713 714 715 716 717 |
u8 stat = hwif->tp_ops->read_status(hwif); if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) { /* Try to not flood the console with msgs */ static unsigned long last_msgtime, count; ++count; if (time_after(jiffies, last_msgtime + HZ)) { last_msgtime = jiffies; printk(KERN_ERR "%s: unexpected interrupt, " "status=0x%02x, count=%ld ", hwif->name, stat, count); |
1da177e4c Linux-2.6.12-rc2 |
718 |
} |
ae86afaee ide: use per-port... |
719 |
} |
1da177e4c Linux-2.6.12-rc2 |
720 721 722 723 724 |
} /** * ide_intr - default IDE interrupt handler * @irq: interrupt number |
ae86afaee ide: use per-port... |
725 |
* @dev_id: hwif |
1da177e4c Linux-2.6.12-rc2 |
726 727 728 729 730 731 |
* @regs: unused weirdness from the kernel irq layer * * This is the default IRQ handler for the IDE layer. You should * not need to override it. If you do be aware it is subtle in * places * |
bd53cbcce ide: add ->cur_po... |
732 |
* hwif is the interface in the group currently performing |
b65fac32c ide: merge ide_hw... |
733 |
* a command. hwif->cur_dev is the drive and hwif->handler is |
1da177e4c Linux-2.6.12-rc2 |
734 735 736 737 738 739 740 741 742 743 |
* the IRQ handler to call. As we issue a command the handlers * step through multiple states, reassigning the handler to the * next step in the process. Unlike a smart SCSI controller IDE * expects the main processor to sequence the various transfer * stages. We also manage a poll timer to catch up with most * timeout situations. There are still a few where the handlers * don't ever decide to give up. * * The handler eventually returns ide_stopped to indicate the * request completed. At this point we issue the next request |
b65fac32c ide: merge ide_hw... |
744 |
* on the port and the process begins again. |
1da177e4c Linux-2.6.12-rc2 |
745 |
*/ |
b65fac32c ide: merge ide_hw... |
746 |
|
7d12e780e IRQ: Maintain reg... |
747 |
irqreturn_t ide_intr (int irq, void *dev_id) |
1da177e4c Linux-2.6.12-rc2 |
748 |
{ |
ae86afaee ide: use per-port... |
749 |
ide_hwif_t *hwif = (ide_hwif_t *)dev_id; |
255115fb3 ide: allow host d... |
750 |
struct ide_host *host = hwif->host; |
201bffa46 ide: use per-devi... |
751 |
ide_drive_t *uninitialized_var(drive); |
1da177e4c Linux-2.6.12-rc2 |
752 |
ide_handler_t *handler; |
ae86afaee ide: use per-port... |
753 |
unsigned long flags; |
1da177e4c Linux-2.6.12-rc2 |
754 |
ide_startstop_t startstop; |
3e0e29f73 ide: unify ide_in... |
755 |
irqreturn_t irq_ret = IRQ_NONE; |
201bffa46 ide: use per-devi... |
756 |
int plug_device = 0; |
8f6205cd5 ide: dequeue in-f... |
757 |
struct request *uninitialized_var(rq_in_flight); |
1da177e4c Linux-2.6.12-rc2 |
758 |
|
255115fb3 ide: allow host d... |
759 760 |
if (host->host_flags & IDE_HFLAG_SERIALIZE) { if (hwif != host->cur_port) |
ae86afaee ide: use per-port... |
761 762 |
goto out_early; } |
bd53cbcce ide: add ->cur_po... |
763 |
|
b65fac32c ide: merge ide_hw... |
764 |
spin_lock_irqsave(&hwif->lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
765 |
|
f4d3ffa52 ide: move ack_int... |
766 767 |
if (hwif->port_ops && hwif->port_ops->test_irq && hwif->port_ops->test_irq(hwif) == 0) |
3e0e29f73 ide: unify ide_in... |
768 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
769 |
|
b65fac32c ide: merge ide_hw... |
770 771 772 |
handler = hwif->handler; if (handler == NULL || hwif->polling) { |
1da177e4c Linux-2.6.12-rc2 |
773 774 775 776 777 778 779 780 781 782 783 |
/* * Not expecting an interrupt from this drive. * That means this could be: * (1) an interrupt from another PCI device * sharing the same PCI INT# as us. * or (2) a drive just entered sleep or standby mode, * and is interrupting to let us know. * or (3) a spurious interrupt of unknown origin. * * For PCI, we cannot tell the difference, * so in that case we just ignore it and hope it goes away. |
1da177e4c Linux-2.6.12-rc2 |
784 |
*/ |
255115fb3 ide: allow host d... |
785 |
if ((host->irq_flags & IRQF_SHARED) == 0) { |
1da177e4c Linux-2.6.12-rc2 |
786 787 788 789 |
/* * Probably not a shared PCI interrupt, * so we can safely try to do something about it: */ |
bd53cbcce ide: add ->cur_po... |
790 |
unexpected_intr(irq, hwif); |
1da177e4c Linux-2.6.12-rc2 |
791 792 793 794 795 |
} else { /* * Whack the status register, just in case * we have a leftover pending IRQ. */ |
374e042c3 ide: add struct i... |
796 |
(void)hwif->tp_ops->read_status(hwif); |
1da177e4c Linux-2.6.12-rc2 |
797 |
} |
3e0e29f73 ide: unify ide_in... |
798 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
799 |
} |
3e0e29f73 ide: unify ide_in... |
800 |
|
b65fac32c ide: merge ide_hw... |
801 |
drive = hwif->cur_dev; |
3e0e29f73 ide: unify ide_in... |
802 803 |
if (!drive_is_ready(drive)) |
1da177e4c Linux-2.6.12-rc2 |
804 805 806 807 808 809 810 |
/* * This happens regularly when we share a PCI IRQ with * another device. Unfortunately, it can also happen * with some buggy drives that trigger the IRQ before * their status register is up to date. Hopefully we have * enough advance overhead that the latter isn't a problem. */ |
3e0e29f73 ide: unify ide_in... |
811 |
goto out; |
b65fac32c ide: merge ide_hw... |
812 |
hwif->handler = NULL; |
60c0cd02b ide: set hwif->ex... |
813 |
hwif->expiry = NULL; |
b65fac32c ide: merge ide_hw... |
814 815 816 |
hwif->req_gen++; del_timer(&hwif->timer); spin_unlock(&hwif->lock); |
1da177e4c Linux-2.6.12-rc2 |
817 |
|
bfa7d8e55 ide: ->ide_dma_cl... |
818 819 |
if (hwif->port_ops && hwif->port_ops->clear_irq) hwif->port_ops->clear_irq(drive); |
f0dd8712e ide: clear bmdma ... |
820 |
|
97100fc81 ide: add device f... |
821 |
if (drive->dev_flags & IDE_DFLAG_UNMASK) |
366c7f554 [PATCH] lockdep: ... |
822 |
local_irq_enable_in_hardirq(); |
bfa7d8e55 ide: ->ide_dma_cl... |
823 |
|
1da177e4c Linux-2.6.12-rc2 |
824 825 |
/* service this interrupt, may set handler for next interrupt */ startstop = handler(drive); |
1da177e4c Linux-2.6.12-rc2 |
826 |
|
b65fac32c ide: merge ide_hw... |
827 |
spin_lock_irq(&hwif->lock); |
1da177e4c Linux-2.6.12-rc2 |
828 829 830 831 832 833 834 |
/* * Note that handler() may have set things up for another * interrupt to occur soon, but it cannot happen until * we exit from this routine, because it will be the * same irq as is currently being serviced here, and Linux * won't allow another of the same (on any CPU) until we return. */ |
e3b29f051 ide: fix OOPS dur... |
835 |
if (startstop == ide_stopped && hwif->polling == 0) { |
9600dcf13 ide: make "parano... |
836 |
BUG_ON(hwif->handler); |
8f6205cd5 ide: dequeue in-f... |
837 838 |
rq_in_flight = hwif->rq; hwif->rq = NULL; |
9600dcf13 ide: make "parano... |
839 840 |
ide_unlock_port(hwif); plug_device = 1; |
1da177e4c Linux-2.6.12-rc2 |
841 |
} |
3e0e29f73 ide: unify ide_in... |
842 843 |
irq_ret = IRQ_HANDLED; out: |
b65fac32c ide: merge ide_hw... |
844 |
spin_unlock_irqrestore(&hwif->lock, flags); |
ae86afaee ide: use per-port... |
845 |
out_early: |
5b31f855f ide: use lock bit... |
846 847 |
if (plug_device) { ide_unlock_host(hwif->host); |
8f6205cd5 ide: dequeue in-f... |
848 |
ide_requeue_and_plug(drive, rq_in_flight); |
5b31f855f ide: use lock bit... |
849 |
} |
201bffa46 ide: use per-devi... |
850 |
|
3e0e29f73 ide: unify ide_in... |
851 |
return irq_ret; |
1da177e4c Linux-2.6.12-rc2 |
852 |
} |
849d71300 ide: allow to wra... |
853 |
EXPORT_SYMBOL_GPL(ide_intr); |
1da177e4c Linux-2.6.12-rc2 |
854 |
|
9f87abe89 ide: add ide_pad_... |
855 856 857 858 859 860 861 |
void ide_pad_transfer(ide_drive_t *drive, int write, int len) { ide_hwif_t *hwif = drive->hwif; u8 buf[4] = { 0 }; while (len > 0) { if (write) |
374e042c3 ide: add struct i... |
862 |
hwif->tp_ops->output_data(drive, NULL, buf, min(4, len)); |
9f87abe89 ide: add ide_pad_... |
863 |
else |
374e042c3 ide: add struct i... |
864 |
hwif->tp_ops->input_data(drive, NULL, buf, min(4, len)); |
9f87abe89 ide: add ide_pad_... |
865 866 867 868 |
len -= 4; } } EXPORT_SYMBOL_GPL(ide_pad_transfer); |