Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / iwlwifi / mvm / nvm.c
1 /******************************************************************************
2  *
3  * This file is provided under a dual BSD/GPLv2 license.  When using or
4  * redistributing this file, you may do so under either license.
5  *
6  * GPL LICENSE SUMMARY
7  *
8  * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of version 2 of the GNU General Public License as
12  * published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22  * USA
23  *
24  * The full GNU General Public License is included in this distribution
25  * in the file called COPYING.
26  *
27  * Contact Information:
28  *  Intel Linux Wireless <ilw@linux.intel.com>
29  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30  *
31  * BSD LICENSE
32  *
33  * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  *
40  *  * Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  *  * Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in
44  *    the documentation and/or other materials provided with the
45  *    distribution.
46  *  * Neither the name Intel Corporation nor the names of its
47  *    contributors may be used to endorse or promote products derived
48  *    from this software without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61  *
62  *****************************************************************************/
63 #include "iwl-trans.h"
64 #include "mvm.h"
65 #include "iwl-eeprom-parse.h"
66 #include "iwl-eeprom-read.h"
67 #include "iwl-nvm-parse.h"
68
69 /* list of NVM sections we are allowed/need to read */
70 static const int nvm_to_read[] = {
71         NVM_SECTION_TYPE_HW,
72         NVM_SECTION_TYPE_SW,
73         NVM_SECTION_TYPE_CALIBRATION,
74         NVM_SECTION_TYPE_PRODUCTION,
75 };
76
77 /* Default NVM size to read */
78 #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024);
79
80 static inline void iwl_nvm_fill_read(struct iwl_nvm_access_cmd *cmd,
81                                      u16 offset, u16 length, u16 section)
82 {
83         cmd->offset = cpu_to_le16(offset);
84         cmd->length = cpu_to_le16(length);
85         cmd->type = cpu_to_le16(section);
86 }
87
88 static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
89                               u16 offset, u16 length, u8 *data)
90 {
91         struct iwl_nvm_access_cmd nvm_access_cmd = {};
92         struct iwl_nvm_access_resp *nvm_resp;
93         struct iwl_rx_packet *pkt;
94         struct iwl_host_cmd cmd = {
95                 .id = NVM_ACCESS_CMD,
96                 .flags = CMD_SYNC | CMD_WANT_SKB,
97                 .data = { &nvm_access_cmd, },
98         };
99         int ret, bytes_read, offset_read;
100         u8 *resp_data;
101
102         iwl_nvm_fill_read(&nvm_access_cmd, offset, length, section);
103         cmd.len[0] = sizeof(struct iwl_nvm_access_cmd);
104
105         ret = iwl_mvm_send_cmd(mvm, &cmd);
106         if (ret)
107                 return ret;
108
109         pkt = cmd.resp_pkt;
110         if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
111                 IWL_ERR(mvm, "Bad return from NVM_ACCES_COMMAND (0x%08X)\n",
112                         pkt->hdr.flags);
113                 ret = -EIO;
114                 goto exit;
115         }
116
117         /* Extract NVM response */
118         nvm_resp = (void *)pkt->data;
119         ret = le16_to_cpu(nvm_resp->status);
120         bytes_read = le16_to_cpu(nvm_resp->length);
121         offset_read = le16_to_cpu(nvm_resp->offset);
122         resp_data = nvm_resp->data;
123         if (ret) {
124                 IWL_ERR(mvm,
125                         "NVM access command failed with status %d (device: %s)\n",
126                         ret, mvm->cfg->name);
127                 ret = -EINVAL;
128                 goto exit;
129         }
130
131         if (offset_read != offset) {
132                 IWL_ERR(mvm, "NVM ACCESS response with invalid offset %d\n",
133                         offset_read);
134                 ret = -EINVAL;
135                 goto exit;
136         }
137
138         /* Write data to NVM */
139         memcpy(data + offset, resp_data, bytes_read);
140         ret = bytes_read;
141
142 exit:
143         iwl_free_resp(&cmd);
144         return ret;
145 }
146
147 /*
148  * Reads an NVM section completely.
149  * NICs prior to 7000 family doesn't have a real NVM, but just read
150  * section 0 which is the EEPROM. Because the EEPROM reading is unlimited
151  * by uCode, we need to manually check in this case that we don't
152  * overflow and try to read more than the EEPROM size.
153  * For 7000 family NICs, we supply the maximal size we can read, and
154  * the uCode fills the response with as much data as we can,
155  * without overflowing, so no check is needed.
156  */
157 static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
158                                 u8 *data)
159 {
160         u16 length, offset = 0;
161         int ret;
162
163         /* Set nvm section read length */
164         length = IWL_NVM_DEFAULT_CHUNK_SIZE;
165
166         ret = length;
167
168         /* Read the NVM until exhausted (reading less than requested) */
169         while (ret == length) {
170                 ret = iwl_nvm_read_chunk(mvm, section, offset, length, data);
171                 if (ret < 0) {
172                         IWL_ERR(mvm,
173                                 "Cannot read NVM from section %d offset %d, length %d\n",
174                                 section, offset, length);
175                         return ret;
176                 }
177                 offset += ret;
178         }
179
180         IWL_INFO(mvm, "NVM section %d read completed\n", section);
181         return offset;
182 }
183
184 static struct iwl_nvm_data *
185 iwl_parse_nvm_sections(struct iwl_mvm *mvm)
186 {
187         struct iwl_nvm_section *sections = mvm->nvm_sections;
188         const __le16 *hw, *sw, *calib;
189
190         /* Checking for required sections */
191         if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
192             !mvm->nvm_sections[NVM_SECTION_TYPE_HW].data) {
193                 IWL_ERR(mvm, "Can't parse empty NVM sections\n");
194                 return NULL;
195         }
196
197         if (WARN_ON(!mvm->cfg))
198                 return NULL;
199
200         hw = (const __le16 *)sections[NVM_SECTION_TYPE_HW].data;
201         sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data;
202         calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data;
203         return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib);
204 }
205
206 int iwl_nvm_init(struct iwl_mvm *mvm)
207 {
208         int ret, i, section;
209         u8 *nvm_buffer, *temp;
210
211         /* TODO: find correct NVM max size for a section */
212         nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
213                              GFP_KERNEL);
214         if (!nvm_buffer)
215                 return -ENOMEM;
216         for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
217                 section = nvm_to_read[i];
218                 /* we override the constness for initial read */
219                 ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
220                 if (ret < 0)
221                         break;
222                 temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
223                 if (!temp) {
224                         ret = -ENOMEM;
225                         break;
226                 }
227                 mvm->nvm_sections[section].data = temp;
228                 mvm->nvm_sections[section].length = ret;
229         }
230         kfree(nvm_buffer);
231         if (ret < 0)
232                 return ret;
233
234         ret = 0;
235         mvm->nvm_data = iwl_parse_nvm_sections(mvm);
236
237         return ret;
238 }