ppc32: Update PowerMac mediabay driver

Fix timings with HZ != 100, fix resource management
parent de46dd7e
...@@ -106,6 +106,11 @@ int media_bay_count = 0; ...@@ -106,6 +106,11 @@ int media_bay_count = 0;
*/ */
#define MS_TO_HZ(ms) ((ms * HZ + 999) / 1000) #define MS_TO_HZ(ms) ((ms * HZ + 999) / 1000)
/*
* Wait that number of ms between each step in normal polling mode
*/
#define MB_POLL_DELAY 25
/* /*
* Consider the media-bay ID value stable if it is the same for * Consider the media-bay ID value stable if it is the same for
* this number of milliseconds * this number of milliseconds
...@@ -121,7 +126,7 @@ int media_bay_count = 0; ...@@ -121,7 +126,7 @@ int media_bay_count = 0;
* Hold the media-bay reset signal true for this many ticks * Hold the media-bay reset signal true for this many ticks
* after a device is inserted before releasing it. * after a device is inserted before releasing it.
*/ */
#define MB_RESET_DELAY 40 #define MB_RESET_DELAY 50
/* /*
* Wait this long after the reset signal is released and before doing * Wait this long after the reset signal is released and before doing
...@@ -390,24 +395,28 @@ static void __pmac poll_media_bay(struct media_bay_info* bay) ...@@ -390,24 +395,28 @@ static void __pmac poll_media_bay(struct media_bay_info* bay)
int id = bay->ops->content(bay); int id = bay->ops->content(bay);
if (id == bay->last_value) { if (id == bay->last_value) {
if (id != bay->content_id if (id != bay->content_id) {
&& ++bay->value_count >= MS_TO_HZ(MB_STABLE_DELAY)) { bay->value_count += MS_TO_HZ(MB_POLL_DELAY);
/* If the device type changes without going thru "MB_NO", we force if (bay->value_count >= MS_TO_HZ(MB_STABLE_DELAY)) {
a pass by "MB_NO" to make sure things are properly reset */ /* If the device type changes without going thru
if ((id != MB_NO) && (bay->content_id != MB_NO)) { * "MB_NO", we force a pass by "MB_NO" to make sure
id = MB_NO; * things are properly reset
MBDBG("mediabay%d: forcing MB_NO\n", bay->index); */
} if ((id != MB_NO) && (bay->content_id != MB_NO)) {
MBDBG("mediabay%d: switching to %d\n", bay->index, id); id = MB_NO;
set_mb_power(bay, id != MB_NO); MBDBG("mediabay%d: forcing MB_NO\n", bay->index);
bay->content_id = id; }
if (id == MB_NO) { MBDBG("mediabay%d: switching to %d\n", bay->index, id);
set_mb_power(bay, id != MB_NO);
bay->content_id = id;
if (id == MB_NO) {
#ifdef CONFIG_BLK_DEV_IDE #ifdef CONFIG_BLK_DEV_IDE
bay->cd_retry = 0; bay->cd_retry = 0;
#endif #endif
printk(KERN_INFO "media bay %d is empty\n", bay->index); printk(KERN_INFO "media bay %d is empty\n", bay->index);
}
}
} }
}
} else { } else {
bay->last_value = id; bay->last_value = id;
bay->value_count = 0; bay->value_count = 0;
...@@ -496,8 +505,12 @@ static void __pmac media_bay_step(int i) ...@@ -496,8 +505,12 @@ static void __pmac media_bay_step(int i)
poll_media_bay(bay); poll_media_bay(bay);
/* If timer expired or polling IDE busy, run state machine */ /* If timer expired or polling IDE busy, run state machine */
if ((bay->state != mb_ide_waiting) && (bay->timer != 0) && ((--bay->timer) != 0)) if ((bay->state != mb_ide_waiting) && (bay->timer != 0)) {
return; bay->timer -= MS_TO_HZ(MB_POLL_DELAY);
if (bay->timer > 0)
return;
bay->timer = 0;
}
switch(bay->state) { switch(bay->state) {
case mb_powering_up: case mb_powering_up:
...@@ -572,12 +585,13 @@ static void __pmac media_bay_step(int i) ...@@ -572,12 +585,13 @@ static void __pmac media_bay_step(int i)
} }
break; break;
} else if (bay->timer > 0) } else if (bay->timer > 0)
bay->timer--; bay->timer -= MS_TO_HZ(MB_POLL_DELAY);
if (bay->timer == 0) { if (bay->timer <= 0) {
printk("\nIDE Timeout in bay %d !, IDE state is: 0x%02x\n", printk("\nIDE Timeout in bay %d !, IDE state is: 0x%02x\n",
i, readb(bay->cd_base + 0x70)); i, readb(bay->cd_base + 0x70));
MBDBG("mediabay%d: nIDE Timeout !\n", i); MBDBG("mediabay%d: nIDE Timeout !\n", i);
set_mb_power(bay, 0); set_mb_power(bay, 0);
bay->timer = 0;
} }
break; break;
#endif /* CONFIG_BLK_DEV_IDE */ #endif /* CONFIG_BLK_DEV_IDE */
...@@ -630,7 +644,7 @@ static int __pmac media_bay_task(void *x) ...@@ -630,7 +644,7 @@ static int __pmac media_bay_task(void *x)
} }
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule_timeout(MS_TO_HZ(10)); schedule_timeout(MS_TO_HZ(MB_POLL_DELAY));
if (signal_pending(current)) if (signal_pending(current))
return 0; return 0;
} }
...@@ -645,17 +659,16 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_ma ...@@ -645,17 +659,16 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_ma
ofnode = mdev->ofdev.node; ofnode = mdev->ofdev.node;
if (!request_OF_resource(ofnode, 0, NULL)) if (macio_resource_count(mdev) < 1)
return -ENXIO; return -ENODEV;
if (macio_request_resources(mdev, "media-bay"))
return -EBUSY;
/* Media bay registers are located at the beginning of the /* Media bay registers are located at the beginning of the
* mac-io chip, we get the parent address for now (hrm...) * mac-io chip, we get the parent address for now (hrm...)
*/ */
if (ofnode->parent->n_addrs == 0)
return -ENODEV;
regbase = (volatile u32 *)ioremap(ofnode->parent->addrs[0].address, 0x100); regbase = (volatile u32 *)ioremap(ofnode->parent->addrs[0].address, 0x100);
if (regbase == NULL) { if (regbase == NULL) {
release_OF_resource(ofnode, 0); macio_release_resources(mdev);
return -ENOMEM; return -ENOMEM;
} }
...@@ -684,13 +697,13 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_ma ...@@ -684,13 +697,13 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_ma
bay->state = mb_empty; bay->state = mb_empty;
do { do {
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(MS_TO_HZ(10)); schedule_timeout(MS_TO_HZ(MB_POLL_DELAY));
media_bay_step(i); media_bay_step(i);
} while((bay->state != mb_empty) && } while((bay->state != mb_empty) &&
(bay->state != mb_up)); (bay->state != mb_up));
/* Mark us ready by filling our mdev data */ /* Mark us ready by filling our mdev data */
dev_set_drvdata(&mdev->ofdev.dev, bay); macio_set_drvdata(mdev, bay);
/* Startup kernel thread */ /* Startup kernel thread */
if (i == 0) if (i == 0)
...@@ -702,7 +715,7 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_ma ...@@ -702,7 +715,7 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_ma
static int __pmac media_bay_suspend(struct macio_dev *mdev, u32 state) static int __pmac media_bay_suspend(struct macio_dev *mdev, u32 state)
{ {
struct media_bay_info *bay = dev_get_drvdata(&mdev->ofdev.dev); struct media_bay_info *bay = macio_get_drvdata(mdev);
if (state != mdev->ofdev.dev.power_state && state >= 2) { if (state != mdev->ofdev.dev.power_state && state >= 2) {
down(&bay->lock); down(&bay->lock);
...@@ -710,7 +723,7 @@ static int __pmac media_bay_suspend(struct macio_dev *mdev, u32 state) ...@@ -710,7 +723,7 @@ static int __pmac media_bay_suspend(struct macio_dev *mdev, u32 state)
set_mb_power(bay, 0); set_mb_power(bay, 0);
up(&bay->lock); up(&bay->lock);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(MS_TO_HZ(10)); schedule_timeout(MS_TO_HZ(MB_POLL_DELAY));
mdev->ofdev.dev.power_state = state; mdev->ofdev.dev.power_state = state;
} }
return 0; return 0;
...@@ -718,7 +731,7 @@ static int __pmac media_bay_suspend(struct macio_dev *mdev, u32 state) ...@@ -718,7 +731,7 @@ static int __pmac media_bay_suspend(struct macio_dev *mdev, u32 state)
static int __pmac media_bay_resume(struct macio_dev *mdev) static int __pmac media_bay_resume(struct macio_dev *mdev)
{ {
struct media_bay_info *bay = dev_get_drvdata(&mdev->ofdev.dev); struct media_bay_info *bay = macio_get_drvdata(mdev);
if (mdev->ofdev.dev.power_state != 0) { if (mdev->ofdev.dev.power_state != 0) {
mdev->ofdev.dev.power_state = 0; mdev->ofdev.dev.power_state = 0;
...@@ -746,7 +759,7 @@ static int __pmac media_bay_resume(struct macio_dev *mdev) ...@@ -746,7 +759,7 @@ static int __pmac media_bay_resume(struct macio_dev *mdev)
#endif #endif
do { do {
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(MS_TO_HZ(10)); schedule_timeout(MS_TO_HZ(MB_POLL_DELAY));
media_bay_step(bay->index); media_bay_step(bay->index);
} while((bay->state != mb_empty) && } while((bay->state != mb_empty) &&
(bay->state != mb_up)); (bay->state != mb_up));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment