Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ath9k: allow to load EEPROM content via firmware API

The calibration data for devices w/o a separate
EEPROM chip can be specified via the 'eeprom_data'
field of 'ath9k_platform_data'. The 'eeprom_data'
is usually filled from board specific setup
functions. It is easy if the EEPROM data is mapped
to the memory, but it can be complicated if it is
stored elsewhere.

The patch adds support for loading of the EEPROM
data via the firmware API to avoid this limitation.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Gabor Juhos and committed by
John W. Linville
ab5c4f71 0e4b9f2f

+82 -2
+18 -1
drivers/net/wireless/ath/ath9k/eeprom.c
··· 113 113 } 114 114 } 115 115 116 + static bool ath9k_hw_nvram_read_blob(struct ath_hw *ah, u32 off, 117 + u16 *data) 118 + { 119 + u16 *blob_data; 120 + 121 + if (off * sizeof(u16) > ah->eeprom_blob->size) 122 + return false; 123 + 124 + blob_data = (u16 *)ah->eeprom_blob->data; 125 + *data = blob_data[off]; 126 + return true; 127 + } 128 + 116 129 bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) 117 130 { 118 131 struct ath_common *common = ath9k_hw_common(ah); 119 132 bool ret; 120 133 121 - ret = common->bus_ops->eeprom_read(common, off, data); 134 + if (ah->eeprom_blob) 135 + ret = ath9k_hw_nvram_read_blob(ah, off, data); 136 + else 137 + ret = common->bus_ops->eeprom_read(common, off, data); 138 + 122 139 if (!ret) 123 140 ath_dbg(common, EEPROM, 124 141 "unable to read eeprom region at offset %u\n", off);
+3
drivers/net/wireless/ath/ath9k/hw.h
··· 20 20 #include <linux/if_ether.h> 21 21 #include <linux/delay.h> 22 22 #include <linux/io.h> 23 + #include <linux/firmware.h> 23 24 24 25 #include "mac.h" 25 26 #include "ani.h" ··· 922 921 bool is_clk_25mhz; 923 922 int (*get_mac_revision)(void); 924 923 int (*external_reset)(void); 924 + 925 + const struct firmware *eeprom_blob; 925 926 }; 926 927 927 928 struct ath_bus_ops {
+59 -1
drivers/net/wireless/ath/ath9k/init.c
··· 23 23 24 24 #include "ath9k.h" 25 25 26 + struct ath9k_eeprom_ctx { 27 + struct completion complete; 28 + struct ath_hw *ah; 29 + }; 30 + 26 31 static char *dev_info = "ath9k"; 27 32 28 33 MODULE_AUTHOR("Atheros Communications"); ··· 511 506 sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; 512 507 } 513 508 509 + static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob, 510 + void *ctx) 511 + { 512 + struct ath9k_eeprom_ctx *ec = ctx; 513 + 514 + if (eeprom_blob) 515 + ec->ah->eeprom_blob = eeprom_blob; 516 + 517 + complete(&ec->complete); 518 + } 519 + 520 + static int ath9k_eeprom_request(struct ath_softc *sc, const char *name) 521 + { 522 + struct ath9k_eeprom_ctx ec; 523 + struct ath_hw *ah = ah = sc->sc_ah; 524 + int err; 525 + 526 + /* try to load the EEPROM content asynchronously */ 527 + init_completion(&ec.complete); 528 + ec.ah = sc->sc_ah; 529 + 530 + err = request_firmware_nowait(THIS_MODULE, 1, name, sc->dev, GFP_KERNEL, 531 + &ec, ath9k_eeprom_request_cb); 532 + if (err < 0) { 533 + ath_err(ath9k_hw_common(ah), 534 + "EEPROM request failed\n"); 535 + return err; 536 + } 537 + 538 + wait_for_completion(&ec.complete); 539 + 540 + if (!ah->eeprom_blob) { 541 + ath_err(ath9k_hw_common(ah), 542 + "Unable to load EEPROM file %s\n", name); 543 + return -EINVAL; 544 + } 545 + 546 + return 0; 547 + } 548 + 549 + static void ath9k_eeprom_release(struct ath_softc *sc) 550 + { 551 + release_firmware(sc->sc_ah->eeprom_blob); 552 + } 553 + 514 554 static int ath9k_init_softc(u16 devid, struct ath_softc *sc, 515 555 const struct ath_bus_ops *bus_ops) 516 556 { ··· 633 583 ath_read_cachesize(common, &csz); 634 584 common->cachelsz = csz << 2; /* convert to bytes */ 635 585 586 + if (pdata->eeprom_name) { 587 + ret = ath9k_eeprom_request(sc, pdata->eeprom_name); 588 + if (ret) 589 + goto err_eeprom; 590 + } 591 + 636 592 /* Initializes the hardware for all supported chipsets */ 637 593 ret = ath9k_hw_init(ah); 638 594 if (ret) ··· 675 619 err_queues: 676 620 ath9k_hw_deinit(ah); 677 621 err_hw: 678 - 622 + ath9k_eeprom_release(sc); 623 + err_eeprom: 679 624 kfree(ah); 680 625 sc->sc_ah = NULL; 681 626 ··· 939 882 if (sc->dfs_detector != NULL) 940 883 sc->dfs_detector->exit(sc->dfs_detector); 941 884 885 + ath9k_eeprom_release(sc); 942 886 kfree(sc->sc_ah); 943 887 sc->sc_ah = NULL; 944 888 }
+2
include/linux/ath9k_platform.h
··· 22 22 #define ATH9K_PLAT_EEP_MAX_WORDS 2048 23 23 24 24 struct ath9k_platform_data { 25 + const char *eeprom_name; 26 + 25 27 u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS]; 26 28 u8 *macaddr; 27 29