mtd: cfi_cmdset_0002: do not fail on no extended query table as they are both optional

After looking at AMD's CFI specification [1], both of the extended query
tables are optional. Thus, it looks like relying that at least one of
those tables exist is a bug in cfi_cmdset_0002.

This patch inverts the logic and checks for unlock function pointers before
exiting on error. This approach leaves place to add a call to a fixup
function to try to handle chips compatible with the early AMD specification
from 1995 [2].

[1] http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_r20.pdf
[2] http://noel.feld.cvut.cz/hw/amd/20158a.pdf

Signed-off-by: Guillaume LECERF <glecerf@gmail.com>
Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
Guillaume LECERF 2010-04-24 17:58:17 +02:00 коммит произвёл David Woodhouse
Родитель 5859886122
Коммит 564b84978d
1 изменённых файлов: 47 добавлений и 46 удалений

Просмотреть файл

@ -357,20 +357,15 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
if (cfi->cfi_mode==CFI_MODE_CFI){ if (cfi->cfi_mode==CFI_MODE_CFI){
unsigned char bootloc; unsigned char bootloc;
/*
* It's a real CFI chip, not one for which the probe
* routine faked a CFI structure. So we read the feature
* table from it.
*/
__u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR; __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
struct cfi_pri_amdstd *extp; struct cfi_pri_amdstd *extp;
extp = (struct cfi_pri_amdstd*)cfi_read_pri(map, adr, sizeof(*extp), "Amd/Fujitsu"); extp = (struct cfi_pri_amdstd*)cfi_read_pri(map, adr, sizeof(*extp), "Amd/Fujitsu");
if (!extp) { if (extp) {
kfree(mtd); /*
return NULL; * It's a real CFI chip, not one for which the probe
} * routine faked a CFI structure.
*/
cfi_fixup_major_minor(cfi, extp); cfi_fixup_major_minor(cfi, extp);
if (extp->MajorVersion != '1' || if (extp->MajorVersion != '1' ||
@ -416,6 +411,12 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
/* Set the default CFI lock/unlock addresses */ /* Set the default CFI lock/unlock addresses */
cfi->addr_unlock1 = 0x555; cfi->addr_unlock1 = 0x555;
cfi->addr_unlock2 = 0x2aa; cfi->addr_unlock2 = 0x2aa;
}
if (!cfi->addr_unlock1 || !cfi->addr_unlock2) {
kfree(mtd);
return NULL;
}
} /* CFI mode */ } /* CFI mode */
else if (cfi->cfi_mode == CFI_MODE_JEDEC) { else if (cfi->cfi_mode == CFI_MODE_JEDEC) {