On 14 April 2015 at 20:10, Arend van Spriel <arend@xxxxxxxxxxxx> wrote: > @@ -23,6 +23,10 @@ > #include "debug.h" > #include "firmware.h" > > +#define BRCMF_FW_MAX_NVRAM_SIZE 64000 > +#define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */ > +#define BRCMF_FW_NVRAM_PCIEDEV_LEN 9 /* pcie/1/4/ */ You most likely know what you're doing, but just for sure: are there any devices using "pcie/" prefix *without* a devpath? I got an impression that Broadcom first started using devpath-s and then (later) started using "pcie/" prefix (instead of "pci/"). > @@ -192,12 +214,136 @@ static int brcmf_init_nvram_parser(struct nvram_parser *nvp, > return 0; > } > > +/* brcmf_fw_strip_multi_v1 :Some nvram files contain settings for multiple > + * devices. Strip it down for one device, use domain_nr/bus_nr to determine > + * which data is to be returned. v1 is the version where nvram is stored > + * compressed and "devpath" maps to index for valid entries. > + */ > +static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr, > + u16 bus_nr) > +{ > + u32 i, j; > + bool found; > + u8 *nvram; > + u8 id; > + > + nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL); > + if (!nvram) > + goto fail; > + > + /* min length: devpath0=pcie/1/4/ + 0:x=y */ > + if (nvp->nvram_len < BRCMF_FW_NVRAM_DEVPATH_LEN + 6) > + goto fail; > + > + /* First search for the devpathX and see if it is the configuration > + * for domain_nr/bus_nr. Search complete nvp > + */ > + found = false; > + i = 0; > + while (i < nvp->nvram_len - BRCMF_FW_NVRAM_DEVPATH_LEN) { > + /* Format: devpathX=pcie/Y/Z/ > + * Y = domain_nr, Z = bus_nr, X = virtual ID > + */ > + if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) && > + (strncmp(&nvp->nvram[i + 8], "=pcie/", 6) == 0)) { > + if (((nvp->nvram[i + 14] - '0') == domain_nr) && > + ((nvp->nvram[i + 16] - '0') == bus_nr)) { > + id = nvp->nvram[i + 7] - '0'; > + found = true; > + break; > + } > + } > + while (nvp->nvram[i] != 0) > + i++; I guess while should also check nvp->nvram_len to avoid crashing with malformed NVRAM content. Same in _v2 function. > + i++; > + } > + if (!found) > + goto fail; > + > + /* Now copy all valid entries, release old nvram and assign new one */ > + i = 0; > + j = 0; > + while (i < nvp->nvram_len) { > + if ((nvp->nvram[i] - '0' == id) && (nvp->nvram[i + 1] == ':')) { > + i += 2; > + while (nvp->nvram[i] != 0) { > + nvram[j] = nvp->nvram[i]; > + i++; > + j++; > + } > + nvram[j] = 0; > + j++; > + } > + while (nvp->nvram[i] != 0) > + i++; Same here. > +/* brcmf_fw_strip_multi_v2 :Some nvram files contain settings for multiple > + * devices. Strip it down for one device, use domain_nr/bus_nr to determine > + * which data is to be returned. v2 is the version where nvram is stored > + * uncompressed, all relevant valid entries are identified by > + * pcie/domain_nr/bus_nr: > + */ > +static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr, > + u16 bus_nr) > +{ > + u32 i, j; > + u8 *nvram; > + > + nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL); > + if (!nvram) > + goto fail; > + > + /* Copy all valid entries, release old nvram and assign new one. > + * Valid entries are of type pcie/X/Y/ where X = domain_nr and > + * Y = bus_nr. > + */ > + i = 0; > + j = 0; > + while (i < nvp->nvram_len - BRCMF_FW_NVRAM_PCIEDEV_LEN) { > + if ((strncmp(&nvp->nvram[i], "pcie/", 5) == 0) && > + (nvp->nvram[i + 6] == '/') && (nvp->nvram[i + 8] == '/') && > + ((nvp->nvram[i + 5] - '0') == domain_nr) && > + ((nvp->nvram[i + 7] - '0') == bus_nr)) { > + i += BRCMF_FW_NVRAM_PCIEDEV_LEN; > + while (nvp->nvram[i] != 0) { > + nvram[j] = nvp->nvram[i]; > + i++; > + j++; > + } > + nvram[j] = 0; > + j++; > + } > + while (nvp->nvram[i] != 0) > + i++; > + i++; > + } > + kfree(nvp->nvram); > + nvp->nvram = nvram; > + nvp->nvram_len = j; > + return; > +fail: > + kfree(nvram); > + nvp->nvram_len = 0; > +} I guess you could consider implementing a one generic function that will accept sth like a "char *prefix" argument. First check for a devpathX=$prefix entry and use X: instead of prefix: or not. -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html