aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-06-23 07:29:11 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-07 13:42:59 -0400
commitfa56d4cb4022c8b313c3b99236e1b87effc3655b (patch)
treeb51b1e66ac75b1412f57f7e41e3aff4bc8f0f0f7
parent2d5abcedeb41f4af9582c60cef70749c3ab90a3b (diff)
ide: allow ide_dev_read_id() to be called from the IRQ context
* Un-static __ide_wait_stat(). * Allow ide_dev_read_id() helper to be called from the IRQ context by adding irq_ctx flag and using mdelay()/__ide_wait_stat() when needed. * Switch ide_driveid_update() to set irq_ctx flag. This change is needed for the consecutive patch which fixes races in handling of user-space SET XFER commands but for improved bisectability and clarity it is better to do it in a separate patch. Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/ide/ide-iops.c6
-rw-r--r--drivers/ide/ide-probe.c31
-rw-r--r--include/linux/ide.h3
3 files changed, 26 insertions, 14 deletions
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 2892b242bbe1..b99873845d21 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -102,8 +102,8 @@ EXPORT_SYMBOL(ide_fixstring);
102 * setting a timer to wake up at half second intervals thereafter, 102 * setting a timer to wake up at half second intervals thereafter,
103 * until timeout is achieved, before timing out. 103 * until timeout is achieved, before timing out.
104 */ 104 */
105static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, 105int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad,
106 unsigned long timeout, u8 *rstat) 106 unsigned long timeout, u8 *rstat)
107{ 107{
108 ide_hwif_t *hwif = drive->hwif; 108 ide_hwif_t *hwif = drive->hwif;
109 const struct ide_tp_ops *tp_ops = hwif->tp_ops; 109 const struct ide_tp_ops *tp_ops = hwif->tp_ops;
@@ -316,7 +316,7 @@ int ide_driveid_update(ide_drive_t *drive)
316 return 0; 316 return 0;
317 317
318 SELECT_MASK(drive, 1); 318 SELECT_MASK(drive, 1);
319 rc = ide_dev_read_id(drive, ATA_CMD_ID_ATA, id); 319 rc = ide_dev_read_id(drive, ATA_CMD_ID_ATA, id, 1);
320 SELECT_MASK(drive, 0); 320 SELECT_MASK(drive, 0);
321 321
322 if (rc) 322 if (rc)
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 1bb106f6221a..8de442cbee94 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -238,6 +238,7 @@ static void do_identify(ide_drive_t *drive, u8 cmd, u16 *id)
238 * @drive: drive to identify 238 * @drive: drive to identify
239 * @cmd: command to use 239 * @cmd: command to use
240 * @id: buffer for IDENTIFY data 240 * @id: buffer for IDENTIFY data
241 * @irq_ctx: flag set when called from the IRQ context
241 * 242 *
242 * Sends an ATA(PI) IDENTIFY request to a drive and waits for a response. 243 * Sends an ATA(PI) IDENTIFY request to a drive and waits for a response.
243 * 244 *
@@ -246,7 +247,7 @@ static void do_identify(ide_drive_t *drive, u8 cmd, u16 *id)
246 * 2 device aborted the command (refused to identify itself) 247 * 2 device aborted the command (refused to identify itself)
247 */ 248 */
248 249
249int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id) 250int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id, int irq_ctx)
250{ 251{
251 ide_hwif_t *hwif = drive->hwif; 252 ide_hwif_t *hwif = drive->hwif;
252 struct ide_io_ports *io_ports = &hwif->io_ports; 253 struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -263,7 +264,10 @@ int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id)
263 tp_ops->write_devctl(hwif, ATA_NIEN | ATA_DEVCTL_OBS); 264 tp_ops->write_devctl(hwif, ATA_NIEN | ATA_DEVCTL_OBS);
264 265
265 /* take a deep breath */ 266 /* take a deep breath */
266 msleep(50); 267 if (irq_ctx)
268 mdelay(50);
269 else
270 msleep(50);
267 271
268 if (io_ports->ctl_addr && 272 if (io_ports->ctl_addr &&
269 (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) { 273 (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) {
@@ -295,12 +299,19 @@ int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id)
295 299
296 timeout = ((cmd == ATA_CMD_ID_ATA) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; 300 timeout = ((cmd == ATA_CMD_ID_ATA) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
297 301
298 if (ide_busy_sleep(drive, timeout, use_altstatus))
299 return 1;
300
301 /* wait for IRQ and ATA_DRQ */ 302 /* wait for IRQ and ATA_DRQ */
302 msleep(50); 303 if (irq_ctx) {
303 s = tp_ops->read_status(hwif); 304 rc = __ide_wait_stat(drive, ATA_DRQ, BAD_R_STAT, timeout, &s);
305 if (rc)
306 return 1;
307 } else {
308 rc = ide_busy_sleep(drive, timeout, use_altstatus);
309 if (rc)
310 return 1;
311
312 msleep(50);
313 s = tp_ops->read_status(hwif);
314 }
304 315
305 if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) { 316 if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) {
306 /* drive returned ID */ 317 /* drive returned ID */
@@ -406,10 +417,10 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
406 417
407 if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) || 418 if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) ||
408 present || cmd == ATA_CMD_ID_ATAPI) { 419 present || cmd == ATA_CMD_ID_ATAPI) {
409 rc = ide_dev_read_id(drive, cmd, id); 420 rc = ide_dev_read_id(drive, cmd, id, 0);
410 if (rc) 421 if (rc)
411 /* failed: try again */ 422 /* failed: try again */
412 rc = ide_dev_read_id(drive, cmd, id); 423 rc = ide_dev_read_id(drive, cmd, id, 0);
413 424
414 stat = tp_ops->read_status(hwif); 425 stat = tp_ops->read_status(hwif);
415 426
@@ -424,7 +435,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
424 msleep(50); 435 msleep(50);
425 tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); 436 tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
426 (void)ide_busy_sleep(drive, WAIT_WORSTCASE, 0); 437 (void)ide_busy_sleep(drive, WAIT_WORSTCASE, 0);
427 rc = ide_dev_read_id(drive, cmd, id); 438 rc = ide_dev_read_id(drive, cmd, id, 0);
428 } 439 }
429 440
430 /* ensure drive IRQ is clear */ 441 /* ensure drive IRQ is clear */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index edc93a6d931d..cb6cd0459a5e 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1081,6 +1081,7 @@ extern void ide_fixstring(u8 *, const int, const int);
1081 1081
1082int ide_busy_sleep(ide_drive_t *, unsigned long, int); 1082int ide_busy_sleep(ide_drive_t *, unsigned long, int);
1083 1083
1084int __ide_wait_stat(ide_drive_t *, u8, u8, unsigned long, u8 *);
1084int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long); 1085int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long);
1085 1086
1086ide_startstop_t ide_do_park_unpark(ide_drive_t *, struct request *); 1087ide_startstop_t ide_do_park_unpark(ide_drive_t *, struct request *);
@@ -1169,7 +1170,7 @@ int ide_no_data_taskfile(ide_drive_t *, struct ide_cmd *);
1169 1170
1170int ide_taskfile_ioctl(ide_drive_t *, unsigned long); 1171int ide_taskfile_ioctl(ide_drive_t *, unsigned long);
1171 1172
1172int ide_dev_read_id(ide_drive_t *, u8, u16 *); 1173int ide_dev_read_id(ide_drive_t *, u8, u16 *, int);
1173 1174
1174extern int ide_driveid_update(ide_drive_t *); 1175extern int ide_driveid_update(ide_drive_t *);
1175extern int ide_config_drive_speed(ide_drive_t *, u8); 1176extern int ide_config_drive_speed(ide_drive_t *, u8);