diff options
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r-- | drivers/ide/ide.c | 81 |
1 files changed, 15 insertions, 66 deletions
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 349d7fa75585..9dcf5aed92cb 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -250,42 +250,9 @@ void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw) | |||
250 | 250 | ||
251 | DEFINE_MUTEX(ide_setting_mtx); | 251 | DEFINE_MUTEX(ide_setting_mtx); |
252 | 252 | ||
253 | /** | ||
254 | * ide_spin_wait_hwgroup - wait for group | ||
255 | * @drive: drive in the group | ||
256 | * | ||
257 | * Wait for an IDE device group to go non busy and then return | ||
258 | * holding the ide_lock which guards the hwgroup->busy status | ||
259 | * and right to use it. | ||
260 | */ | ||
261 | |||
262 | int ide_spin_wait_hwgroup (ide_drive_t *drive) | ||
263 | { | ||
264 | ide_hwgroup_t *hwgroup = HWGROUP(drive); | ||
265 | unsigned long timeout = jiffies + (3 * HZ); | ||
266 | |||
267 | spin_lock_irq(&ide_lock); | ||
268 | |||
269 | while (hwgroup->busy) { | ||
270 | unsigned long lflags; | ||
271 | spin_unlock_irq(&ide_lock); | ||
272 | local_irq_set(lflags); | ||
273 | if (time_after(jiffies, timeout)) { | ||
274 | local_irq_restore(lflags); | ||
275 | printk(KERN_ERR "%s: channel busy\n", drive->name); | ||
276 | return -EBUSY; | ||
277 | } | ||
278 | local_irq_restore(lflags); | ||
279 | spin_lock_irq(&ide_lock); | ||
280 | } | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | EXPORT_SYMBOL(ide_spin_wait_hwgroup); | ||
285 | |||
286 | ide_devset_get(io_32bit, io_32bit); | 253 | ide_devset_get(io_32bit, io_32bit); |
287 | 254 | ||
288 | int set_io_32bit(ide_drive_t *drive, int arg) | 255 | static int set_io_32bit(ide_drive_t *drive, int arg) |
289 | { | 256 | { |
290 | if (drive->no_io_32bit) | 257 | if (drive->no_io_32bit) |
291 | return -EPERM; | 258 | return -EPERM; |
@@ -293,37 +260,28 @@ int set_io_32bit(ide_drive_t *drive, int arg) | |||
293 | if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) | 260 | if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) |
294 | return -EINVAL; | 261 | return -EINVAL; |
295 | 262 | ||
296 | if (ide_spin_wait_hwgroup(drive)) | ||
297 | return -EBUSY; | ||
298 | |||
299 | drive->io_32bit = arg; | 263 | drive->io_32bit = arg; |
300 | 264 | ||
301 | spin_unlock_irq(&ide_lock); | ||
302 | |||
303 | return 0; | 265 | return 0; |
304 | } | 266 | } |
305 | 267 | ||
306 | ide_devset_get(ksettings, keep_settings); | 268 | ide_devset_get(ksettings, keep_settings); |
307 | 269 | ||
308 | int set_ksettings(ide_drive_t *drive, int arg) | 270 | static int set_ksettings(ide_drive_t *drive, int arg) |
309 | { | 271 | { |
310 | if (arg < 0 || arg > 1) | 272 | if (arg < 0 || arg > 1) |
311 | return -EINVAL; | 273 | return -EINVAL; |
312 | 274 | ||
313 | if (ide_spin_wait_hwgroup(drive)) | ||
314 | return -EBUSY; | ||
315 | drive->keep_settings = arg; | 275 | drive->keep_settings = arg; |
316 | spin_unlock_irq(&ide_lock); | ||
317 | 276 | ||
318 | return 0; | 277 | return 0; |
319 | } | 278 | } |
320 | 279 | ||
321 | ide_devset_get(using_dma, using_dma); | 280 | ide_devset_get(using_dma, using_dma); |
322 | 281 | ||
323 | int set_using_dma(ide_drive_t *drive, int arg) | 282 | static int set_using_dma(ide_drive_t *drive, int arg) |
324 | { | 283 | { |
325 | #ifdef CONFIG_BLK_DEV_IDEDMA | 284 | #ifdef CONFIG_BLK_DEV_IDEDMA |
326 | ide_hwif_t *hwif = drive->hwif; | ||
327 | int err = -EPERM; | 285 | int err = -EPERM; |
328 | 286 | ||
329 | if (arg < 0 || arg > 1) | 287 | if (arg < 0 || arg > 1) |
@@ -332,18 +290,9 @@ int set_using_dma(ide_drive_t *drive, int arg) | |||
332 | if (ata_id_has_dma(drive->id) == 0) | 290 | if (ata_id_has_dma(drive->id) == 0) |
333 | goto out; | 291 | goto out; |
334 | 292 | ||
335 | if (hwif->dma_ops == NULL) | 293 | if (drive->hwif->dma_ops == NULL) |
336 | goto out; | 294 | goto out; |
337 | 295 | ||
338 | err = -EBUSY; | ||
339 | if (ide_spin_wait_hwgroup(drive)) | ||
340 | goto out; | ||
341 | /* | ||
342 | * set ->busy flag, unlock and let it ride | ||
343 | */ | ||
344 | hwif->hwgroup->busy = 1; | ||
345 | spin_unlock_irq(&ide_lock); | ||
346 | |||
347 | err = 0; | 296 | err = 0; |
348 | 297 | ||
349 | if (arg) { | 298 | if (arg) { |
@@ -352,12 +301,6 @@ int set_using_dma(ide_drive_t *drive, int arg) | |||
352 | } else | 301 | } else |
353 | ide_dma_off(drive); | 302 | ide_dma_off(drive); |
354 | 303 | ||
355 | /* | ||
356 | * lock, clear ->busy flag and unlock before leaving | ||
357 | */ | ||
358 | spin_lock_irq(&ide_lock); | ||
359 | hwif->hwgroup->busy = 0; | ||
360 | spin_unlock_irq(&ide_lock); | ||
361 | out: | 304 | out: |
362 | return err; | 305 | return err; |
363 | #else | 306 | #else |
@@ -368,7 +311,7 @@ out: | |||
368 | #endif | 311 | #endif |
369 | } | 312 | } |
370 | 313 | ||
371 | int set_pio_mode(ide_drive_t *drive, int arg) | 314 | static int set_pio_mode(ide_drive_t *drive, int arg) |
372 | { | 315 | { |
373 | struct request *rq; | 316 | struct request *rq; |
374 | ide_hwif_t *hwif = drive->hwif; | 317 | ide_hwif_t *hwif = drive->hwif; |
@@ -398,7 +341,7 @@ int set_pio_mode(ide_drive_t *drive, int arg) | |||
398 | 341 | ||
399 | ide_devset_get(unmaskirq, unmask); | 342 | ide_devset_get(unmaskirq, unmask); |
400 | 343 | ||
401 | int set_unmaskirq(ide_drive_t *drive, int arg) | 344 | static int set_unmaskirq(ide_drive_t *drive, int arg) |
402 | { | 345 | { |
403 | if (drive->no_unmask) | 346 | if (drive->no_unmask) |
404 | return -EPERM; | 347 | return -EPERM; |
@@ -406,14 +349,20 @@ int set_unmaskirq(ide_drive_t *drive, int arg) | |||
406 | if (arg < 0 || arg > 1) | 349 | if (arg < 0 || arg > 1) |
407 | return -EINVAL; | 350 | return -EINVAL; |
408 | 351 | ||
409 | if (ide_spin_wait_hwgroup(drive)) | ||
410 | return -EBUSY; | ||
411 | drive->unmask = arg; | 352 | drive->unmask = arg; |
412 | spin_unlock_irq(&ide_lock); | ||
413 | 353 | ||
414 | return 0; | 354 | return 0; |
415 | } | 355 | } |
416 | 356 | ||
357 | #define ide_gen_devset_rw(_name, _func) \ | ||
358 | __IDE_DEVSET(_name, DS_SYNC, get_##_func, set_##_func) | ||
359 | |||
360 | ide_gen_devset_rw(io_32bit, io_32bit); | ||
361 | ide_gen_devset_rw(keepsettings, ksettings); | ||
362 | ide_gen_devset_rw(unmaskirq, unmaskirq); | ||
363 | ide_gen_devset_rw(using_dma, using_dma); | ||
364 | __IDE_DEVSET(pio_mode, 0, NULL, set_pio_mode); | ||
365 | |||
417 | static int generic_ide_suspend(struct device *dev, pm_message_t mesg) | 366 | static int generic_ide_suspend(struct device *dev, pm_message_t mesg) |
418 | { | 367 | { |
419 | ide_drive_t *drive = dev->driver_data; | 368 | ide_drive_t *drive = dev->driver_data; |