kernel: add some debloat patches, strip down procfs and make O_DIRECT support optiona...
[oweals/openwrt.git] / package / mac80211 / patches / 305-pending-ath9k-allow-to-load-EEPROM-content-via-firmware-API.patch
1 From ee4581f2f024c601a5e247ec6acab3e7df538f88 Mon Sep 17 00:00:00 2001
2 From: Gabor Juhos <juhosg@openwrt.org>
3 Date: Sun, 9 Dec 2012 17:31:54 +0100
4 Subject: [PATCH 4/4] ath9k: allow to load EEPROM content via firmware API
5
6 The calibration data for devices w/o a separate
7 EEPROM chip can be specified via the 'eeprom_data'
8 field of 'ath9k_platform_data'. The 'eeprom_data'
9 is usually filled from board specific setup
10 functions. It is easy if the EEPROM data is mapped
11 to the memory, but it can be complicated if it is
12 stored elsewhere.
13
14 The patch adds support for loading of the EEPROM
15 data via the firmware API to avoid this limitation.
16
17 Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
18 ---
19  drivers/net/wireless/ath/ath9k/eeprom.c |   19 +++++++++-
20  drivers/net/wireless/ath/ath9k/hw.h     |    3 ++
21  drivers/net/wireless/ath/ath9k/init.c   |   60 ++++++++++++++++++++++++++++++-
22  include/linux/ath9k_platform.h          |    2 ++
23  4 files changed, 82 insertions(+), 2 deletions(-)
24
25 --- a/drivers/net/wireless/ath/ath9k/eeprom.c
26 +++ b/drivers/net/wireless/ath/ath9k/eeprom.c
27 @@ -113,12 +113,29 @@ void ath9k_hw_usb_gen_fill_eeprom(struct
28         }
29  }
30  
31 +static bool ath9k_hw_nvram_read_blob(struct ath_hw *ah, u32 off,
32 +                                    u16 *data)
33 +{
34 +       u16 *blob_data;
35 +
36 +       if (off * sizeof(u16) > ah->eeprom_blob->size)
37 +               return false;
38 +
39 +       blob_data = (u16 *)ah->eeprom_blob->data;
40 +       *data =  blob_data[off];
41 +       return true;
42 +}
43 +
44  bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
45  {
46         struct ath_common *common = ath9k_hw_common(ah);
47         bool ret;
48  
49 -       ret = common->bus_ops->eeprom_read(common, off, data);
50 +       if (ah->eeprom_blob)
51 +               ret = ath9k_hw_nvram_read_blob(ah, off, data);
52 +       else
53 +               ret = common->bus_ops->eeprom_read(common, off, data);
54 +
55         if (!ret)
56                 ath_dbg(common, EEPROM,
57                         "unable to read eeprom region at offset %u\n", off);
58 --- a/drivers/net/wireless/ath/ath9k/hw.h
59 +++ b/drivers/net/wireless/ath/ath9k/hw.h
60 @@ -20,6 +20,7 @@
61  #include <linux/if_ether.h>
62  #include <linux/delay.h>
63  #include <linux/io.h>
64 +#include <linux/firmware.h>
65  
66  #include "mac.h"
67  #include "ani.h"
68 @@ -920,6 +921,8 @@ struct ath_hw {
69         bool is_clk_25mhz;
70         int (*get_mac_revision)(void);
71         int (*external_reset)(void);
72 +
73 +       const struct firmware *eeprom_blob;
74  };
75  
76  struct ath_bus_ops {
77 --- a/drivers/net/wireless/ath/ath9k/init.c
78 +++ b/drivers/net/wireless/ath/ath9k/init.c
79 @@ -25,6 +25,11 @@
80  
81  #include "ath9k.h"
82  
83 +struct ath9k_eeprom_ctx {
84 +       struct completion complete;
85 +       struct ath_hw *ah;
86 +};
87 +
88  static char *dev_info = "ath9k";
89  
90  MODULE_AUTHOR("Atheros Communications");
91 @@ -508,6 +513,51 @@ static void ath9k_init_misc(struct ath_s
92                 sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
93  }
94  
95 +static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob,
96 +                                   void *ctx)
97 +{
98 +       struct ath9k_eeprom_ctx *ec = ctx;
99 +
100 +       if (eeprom_blob)
101 +               ec->ah->eeprom_blob = eeprom_blob;
102 +
103 +       complete(&ec->complete);
104 +}
105 +
106 +static int ath9k_eeprom_request(struct ath_softc *sc, const char *name)
107 +{
108 +       struct ath9k_eeprom_ctx ec;
109 +       struct ath_hw *ah = ah = sc->sc_ah;
110 +       int err;
111 +
112 +       /* try to load the EEPROM content asynchronously */
113 +       init_completion(&ec.complete);
114 +       ec.ah = sc->sc_ah;
115 +
116 +       err = request_firmware_nowait(THIS_MODULE, 1, name, sc->dev, GFP_KERNEL,
117 +                                     &ec, ath9k_eeprom_request_cb);
118 +       if (err < 0) {
119 +               ath_err(ath9k_hw_common(ah),
120 +                       "EEPROM request failed\n");
121 +               return err;
122 +       }
123 +
124 +       wait_for_completion(&ec.complete);
125 +
126 +       if (!ah->eeprom_blob) {
127 +               ath_err(ath9k_hw_common(ah),
128 +                       "Unable to load EEPROM file %s\n", name);
129 +               return -EINVAL;
130 +       }
131 +
132 +       return 0;
133 +}
134 +
135 +static void ath9k_eeprom_release(struct ath_softc *sc)
136 +{
137 +       release_firmware(sc->sc_ah->eeprom_blob);
138 +}
139 +
140  static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
141                             const struct ath_bus_ops *bus_ops)
142  {
143 @@ -585,6 +635,12 @@ static int ath9k_init_softc(u16 devid, s
144         ath_read_cachesize(common, &csz);
145         common->cachelsz = csz << 2; /* convert to bytes */
146  
147 +       if (pdata && pdata->eeprom_name) {
148 +               ret = ath9k_eeprom_request(sc, pdata->eeprom_name);
149 +               if (ret)
150 +                       goto err_eeprom;
151 +       }
152 +
153         /* Initializes the hardware for all supported chipsets */
154         ret = ath9k_hw_init(ah);
155         if (ret)
156 @@ -621,7 +677,8 @@ err_btcoex:
157  err_queues:
158         ath9k_hw_deinit(ah);
159  err_hw:
160 -
161 +       ath9k_eeprom_release(sc);
162 +err_eeprom:
163         kfree(ah);
164         sc->sc_ah = NULL;
165  
166 @@ -884,6 +941,7 @@ static void ath9k_deinit_softc(struct at
167         if (sc->dfs_detector != NULL)
168                 sc->dfs_detector->exit(sc->dfs_detector);
169  
170 +       ath9k_eeprom_release(sc);
171         kfree(sc->sc_ah);
172         sc->sc_ah = NULL;
173  }
174 --- a/include/linux/ath9k_platform.h
175 +++ b/include/linux/ath9k_platform.h
176 @@ -22,6 +22,8 @@
177  #define ATH9K_PLAT_EEP_MAX_WORDS       2048
178  
179  struct ath9k_platform_data {
180 +       const char *eeprom_name;
181 +
182         u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS];
183         u8 *macaddr;
184