diff options
Diffstat (limited to 'drivers/mtd/chips')
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0001.c | 87 |
1 files changed, 43 insertions, 44 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 39edb8250fbc..7ea49a0d5ec3 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -908,7 +908,7 @@ static void __xipram xip_enable(struct map_info *map, struct flchip *chip, | |||
908 | 908 | ||
909 | static int __xipram xip_wait_for_operation( | 909 | static int __xipram xip_wait_for_operation( |
910 | struct map_info *map, struct flchip *chip, | 910 | struct map_info *map, struct flchip *chip, |
911 | unsigned long adr, int *chip_op_time ) | 911 | unsigned long adr, unsigned int chip_op_time ) |
912 | { | 912 | { |
913 | struct cfi_private *cfi = map->fldrv_priv; | 913 | struct cfi_private *cfi = map->fldrv_priv; |
914 | struct cfi_pri_intelext *cfip = cfi->cmdset_priv; | 914 | struct cfi_pri_intelext *cfip = cfi->cmdset_priv; |
@@ -917,7 +917,7 @@ static int __xipram xip_wait_for_operation( | |||
917 | flstate_t oldstate, newstate; | 917 | flstate_t oldstate, newstate; |
918 | 918 | ||
919 | start = xip_currtime(); | 919 | start = xip_currtime(); |
920 | usec = *chip_op_time * 8; | 920 | usec = chip_op_time * 8; |
921 | if (usec == 0) | 921 | if (usec == 0) |
922 | usec = 500000; | 922 | usec = 500000; |
923 | done = 0; | 923 | done = 0; |
@@ -1027,8 +1027,8 @@ static int __xipram xip_wait_for_operation( | |||
1027 | #define XIP_INVAL_CACHED_RANGE(map, from, size) \ | 1027 | #define XIP_INVAL_CACHED_RANGE(map, from, size) \ |
1028 | INVALIDATE_CACHED_RANGE(map, from, size) | 1028 | INVALIDATE_CACHED_RANGE(map, from, size) |
1029 | 1029 | ||
1030 | #define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, p_usec) \ | 1030 | #define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \ |
1031 | xip_wait_for_operation(map, chip, cmd_adr, p_usec) | 1031 | xip_wait_for_operation(map, chip, cmd_adr, usec) |
1032 | 1032 | ||
1033 | #else | 1033 | #else |
1034 | 1034 | ||
@@ -1040,64 +1040,64 @@ static int __xipram xip_wait_for_operation( | |||
1040 | static int inval_cache_and_wait_for_operation( | 1040 | static int inval_cache_and_wait_for_operation( |
1041 | struct map_info *map, struct flchip *chip, | 1041 | struct map_info *map, struct flchip *chip, |
1042 | unsigned long cmd_adr, unsigned long inval_adr, int inval_len, | 1042 | unsigned long cmd_adr, unsigned long inval_adr, int inval_len, |
1043 | int *chip_op_time ) | 1043 | unsigned int chip_op_time) |
1044 | { | 1044 | { |
1045 | struct cfi_private *cfi = map->fldrv_priv; | 1045 | struct cfi_private *cfi = map->fldrv_priv; |
1046 | map_word status, status_OK = CMD(0x80); | 1046 | map_word status, status_OK = CMD(0x80); |
1047 | int z, chip_state = chip->state; | 1047 | int chip_state = chip->state; |
1048 | unsigned long timeo; | 1048 | unsigned int timeo, sleep_time; |
1049 | 1049 | ||
1050 | spin_unlock(chip->mutex); | 1050 | spin_unlock(chip->mutex); |
1051 | if (inval_len) | 1051 | if (inval_len) |
1052 | INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len); | 1052 | INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len); |
1053 | if (*chip_op_time) | ||
1054 | cfi_udelay(*chip_op_time); | ||
1055 | spin_lock(chip->mutex); | 1053 | spin_lock(chip->mutex); |
1056 | 1054 | ||
1057 | timeo = *chip_op_time * 8 * HZ / 1000000; | 1055 | /* set our timeout to 8 times the expected delay */ |
1058 | if (timeo < HZ/2) | 1056 | timeo = chip_op_time * 8; |
1059 | timeo = HZ/2; | 1057 | if (!timeo) |
1060 | timeo += jiffies; | 1058 | timeo = 500000; |
1059 | sleep_time = chip_op_time / 2; | ||
1061 | 1060 | ||
1062 | z = 0; | ||
1063 | for (;;) { | 1061 | for (;;) { |
1064 | if (chip->state != chip_state) { | ||
1065 | /* Someone's suspended the operation: sleep */ | ||
1066 | DECLARE_WAITQUEUE(wait, current); | ||
1067 | |||
1068 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1069 | add_wait_queue(&chip->wq, &wait); | ||
1070 | spin_unlock(chip->mutex); | ||
1071 | schedule(); | ||
1072 | remove_wait_queue(&chip->wq, &wait); | ||
1073 | timeo = jiffies + (HZ / 2); /* FIXME */ | ||
1074 | spin_lock(chip->mutex); | ||
1075 | continue; | ||
1076 | } | ||
1077 | |||
1078 | status = map_read(map, cmd_adr); | 1062 | status = map_read(map, cmd_adr); |
1079 | if (map_word_andequal(map, status, status_OK, status_OK)) | 1063 | if (map_word_andequal(map, status, status_OK, status_OK)) |
1080 | break; | 1064 | break; |
1081 | 1065 | ||
1082 | /* OK Still waiting */ | 1066 | if (!timeo) { |
1083 | if (time_after(jiffies, timeo)) { | ||
1084 | map_write(map, CMD(0x70), cmd_adr); | 1067 | map_write(map, CMD(0x70), cmd_adr); |
1085 | chip->state = FL_STATUS; | 1068 | chip->state = FL_STATUS; |
1086 | return -ETIME; | 1069 | return -ETIME; |
1087 | } | 1070 | } |
1088 | 1071 | ||
1089 | /* Latency issues. Drop the lock, wait a while and retry */ | 1072 | /* OK Still waiting. Drop the lock, wait a while and retry. */ |
1090 | z++; | ||
1091 | spin_unlock(chip->mutex); | 1073 | spin_unlock(chip->mutex); |
1092 | cfi_udelay(1); | 1074 | if (sleep_time >= 1000000/HZ) { |
1075 | /* | ||
1076 | * Half of the normal delay still remaining | ||
1077 | * can be performed with a sleeping delay instead | ||
1078 | * of busy waiting. | ||
1079 | */ | ||
1080 | msleep(sleep_time/1000); | ||
1081 | timeo -= sleep_time; | ||
1082 | sleep_time = 1000000/HZ; | ||
1083 | } else { | ||
1084 | udelay(1); | ||
1085 | cond_resched(); | ||
1086 | timeo--; | ||
1087 | } | ||
1093 | spin_lock(chip->mutex); | 1088 | spin_lock(chip->mutex); |
1094 | } | ||
1095 | 1089 | ||
1096 | if (!z) { | 1090 | if (chip->state != chip_state) { |
1097 | if (!--(*chip_op_time)) | 1091 | /* Someone's suspended the operation: sleep */ |
1098 | *chip_op_time = 1; | 1092 | DECLARE_WAITQUEUE(wait, current); |
1099 | } else if (z > 1) | 1093 | set_current_state(TASK_UNINTERRUPTIBLE); |
1100 | ++(*chip_op_time); | 1094 | add_wait_queue(&chip->wq, &wait); |
1095 | spin_unlock(chip->mutex); | ||
1096 | schedule(); | ||
1097 | remove_wait_queue(&chip->wq, &wait); | ||
1098 | spin_lock(chip->mutex); | ||
1099 | } | ||
1100 | } | ||
1101 | 1101 | ||
1102 | /* Done and happy. */ | 1102 | /* Done and happy. */ |
1103 | chip->state = FL_STATUS; | 1103 | chip->state = FL_STATUS; |
@@ -1107,8 +1107,7 @@ static int inval_cache_and_wait_for_operation( | |||
1107 | #endif | 1107 | #endif |
1108 | 1108 | ||
1109 | #define WAIT_TIMEOUT(map, chip, adr, udelay) \ | 1109 | #define WAIT_TIMEOUT(map, chip, adr, udelay) \ |
1110 | ({ int __udelay = (udelay); \ | 1110 | INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay); |
1111 | INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, &__udelay); }) | ||
1112 | 1111 | ||
1113 | 1112 | ||
1114 | static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) | 1113 | static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) |
@@ -1332,7 +1331,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1332 | 1331 | ||
1333 | ret = INVAL_CACHE_AND_WAIT(map, chip, adr, | 1332 | ret = INVAL_CACHE_AND_WAIT(map, chip, adr, |
1334 | adr, map_bankwidth(map), | 1333 | adr, map_bankwidth(map), |
1335 | &chip->word_write_time); | 1334 | chip->word_write_time); |
1336 | if (ret) { | 1335 | if (ret) { |
1337 | xip_enable(map, chip, adr); | 1336 | xip_enable(map, chip, adr); |
1338 | printk(KERN_ERR "%s: word write error (status timeout)\n", map->name); | 1337 | printk(KERN_ERR "%s: word write error (status timeout)\n", map->name); |
@@ -1569,7 +1568,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1569 | 1568 | ||
1570 | ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, | 1569 | ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, |
1571 | adr, len, | 1570 | adr, len, |
1572 | &chip->buffer_write_time); | 1571 | chip->buffer_write_time); |
1573 | if (ret) { | 1572 | if (ret) { |
1574 | map_write(map, CMD(0x70), cmd_adr); | 1573 | map_write(map, CMD(0x70), cmd_adr); |
1575 | chip->state = FL_STATUS; | 1574 | chip->state = FL_STATUS; |
@@ -1704,7 +1703,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, | |||
1704 | 1703 | ||
1705 | ret = INVAL_CACHE_AND_WAIT(map, chip, adr, | 1704 | ret = INVAL_CACHE_AND_WAIT(map, chip, adr, |
1706 | adr, len, | 1705 | adr, len, |
1707 | &chip->erase_time); | 1706 | chip->erase_time); |
1708 | if (ret) { | 1707 | if (ret) { |
1709 | map_write(map, CMD(0x70), adr); | 1708 | map_write(map, CMD(0x70), adr); |
1710 | chip->state = FL_STATUS; | 1709 | chip->state = FL_STATUS; |