Skip to content

Commit 84a2479

Browse files
jbrandebJeff Kirsher
authored andcommitted
ice: implement full NVM read from ETHTOOL_GEEPROM
The current implementation of .get_eeprom only enables reading from the Shadow RAM portion of the NVM contents. Implement support for reading the entire flash contents instead of only the initial portion contained in the Shadow RAM. A complete dump can take several seconds, but the ETHTOOL_GEEPROM ioctl is capable of reading only a limited portion at a time by specifying the offset and length to read. In order to perform the reads directly, several functions are made non static. Additionally, the unused ice_read_sr_buf_aq and ice_read_sr_buf functions are removed. Signed-off-by: Jesse Brandeburg <[email protected]> Signed-off-by: Jacob Keller <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 81f0749 commit 84a2479

File tree

4 files changed

+26
-164
lines changed

4 files changed

+26
-164
lines changed

drivers/net/ethernet/intel/ice/ice_common.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ enum ice_status
3838
ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res);
3939
enum ice_status
4040
ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res);
41-
enum ice_status ice_init_nvm(struct ice_hw *hw);
42-
enum ice_status
43-
ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data);
4441
enum ice_status
4542
ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries,
4643
struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,

drivers/net/ethernet/intel/ice/ice_ethtool.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -245,47 +245,54 @@ static int ice_get_eeprom_len(struct net_device *netdev)
245245
struct ice_netdev_priv *np = netdev_priv(netdev);
246246
struct ice_pf *pf = np->vsi->back;
247247

248-
return (int)(pf->hw.nvm.sr_words * sizeof(u16));
248+
return (int)pf->hw.nvm.flash_size;
249249
}
250250

251251
static int
252252
ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
253253
u8 *bytes)
254254
{
255255
struct ice_netdev_priv *np = netdev_priv(netdev);
256-
u16 first_word, last_word, nwords;
257256
struct ice_vsi *vsi = np->vsi;
258257
struct ice_pf *pf = vsi->back;
259258
struct ice_hw *hw = &pf->hw;
260259
enum ice_status status;
261260
struct device *dev;
262261
int ret = 0;
263-
u16 *buf;
262+
u8 *buf;
264263

265264
dev = ice_pf_to_dev(pf);
266265

267266
eeprom->magic = hw->vendor_id | (hw->device_id << 16);
267+
netdev_dbg(netdev, "GEEPROM cmd 0x%08x, offset 0x%08x, len 0x%08x\n",
268+
eeprom->cmd, eeprom->offset, eeprom->len);
268269

269-
first_word = eeprom->offset >> 1;
270-
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
271-
nwords = last_word - first_word + 1;
272-
273-
buf = devm_kcalloc(dev, nwords, sizeof(u16), GFP_KERNEL);
270+
buf = kzalloc(eeprom->len, GFP_KERNEL);
274271
if (!buf)
275272
return -ENOMEM;
276273

277-
status = ice_read_sr_buf(hw, first_word, &nwords, buf);
274+
status = ice_acquire_nvm(hw, ICE_RES_READ);
278275
if (status) {
279-
dev_err(dev, "ice_read_sr_buf failed, err %d aq_err %d\n",
276+
dev_err(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
280277
status, hw->adminq.sq_last_status);
281-
eeprom->len = sizeof(u16) * nwords;
282278
ret = -EIO;
283279
goto out;
284280
}
285281

286-
memcpy(bytes, (u8 *)buf + (eeprom->offset & 1), eeprom->len);
282+
status = ice_read_flat_nvm(hw, eeprom->offset, &eeprom->len, buf,
283+
false);
284+
if (status) {
285+
dev_err(dev, "ice_read_flat_nvm failed, err %d aq_err %d\n",
286+
status, hw->adminq.sq_last_status);
287+
ret = -EIO;
288+
goto release;
289+
}
290+
291+
memcpy(bytes, buf, eeprom->len);
292+
release:
293+
ice_release_nvm(hw);
287294
out:
288-
devm_kfree(dev, buf);
295+
kfree(buf);
289296
return ret;
290297
}
291298

drivers/net/ethernet/intel/ice/ice_nvm.c

Lines changed: 2 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -107,70 +107,6 @@ ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data,
107107
return status;
108108
}
109109

110-
/**
111-
* ice_check_sr_access_params - verify params for Shadow RAM R/W operations.
112-
* @hw: pointer to the HW structure
113-
* @offset: offset in words from module start
114-
* @words: number of words to access
115-
*/
116-
static enum ice_status
117-
ice_check_sr_access_params(struct ice_hw *hw, u32 offset, u16 words)
118-
{
119-
if ((offset + words) > hw->nvm.sr_words) {
120-
ice_debug(hw, ICE_DBG_NVM,
121-
"NVM error: offset beyond SR lmt.\n");
122-
return ICE_ERR_PARAM;
123-
}
124-
125-
if (words > ICE_SR_SECTOR_SIZE_IN_WORDS) {
126-
/* We can access only up to 4KB (one sector), in one AQ write */
127-
ice_debug(hw, ICE_DBG_NVM,
128-
"NVM error: tried to access %d words, limit is %d.\n",
129-
words, ICE_SR_SECTOR_SIZE_IN_WORDS);
130-
return ICE_ERR_PARAM;
131-
}
132-
133-
if (((offset + (words - 1)) / ICE_SR_SECTOR_SIZE_IN_WORDS) !=
134-
(offset / ICE_SR_SECTOR_SIZE_IN_WORDS)) {
135-
/* A single access cannot spread over two sectors */
136-
ice_debug(hw, ICE_DBG_NVM,
137-
"NVM error: cannot spread over two sectors.\n");
138-
return ICE_ERR_PARAM;
139-
}
140-
141-
return 0;
142-
}
143-
144-
/**
145-
* ice_read_sr_aq - Read Shadow RAM.
146-
* @hw: pointer to the HW structure
147-
* @offset: offset in words from module start
148-
* @words: number of words to read
149-
* @data: storage for the words read from Shadow RAM (Little Endian)
150-
* @last_command: tells the AdminQ that this is the last command
151-
*
152-
* Reads 16-bit Little Endian word buffers from the Shadow RAM using the admin
153-
* command.
154-
*/
155-
static enum ice_status
156-
ice_read_sr_aq(struct ice_hw *hw, u32 offset, u16 words, __le16 *data,
157-
bool last_command)
158-
{
159-
enum ice_status status;
160-
161-
status = ice_check_sr_access_params(hw, offset, words);
162-
163-
/* values in "offset" and "words" parameters are sized as words
164-
* (16 bits) but ice_aq_read_nvm expects these values in bytes.
165-
* So do this conversion while calling ice_aq_read_nvm.
166-
*/
167-
if (!status)
168-
status = ice_aq_read_nvm(hw, 0, 2 * offset, 2 * words, data,
169-
last_command, true, NULL);
170-
171-
return status;
172-
}
173-
174110
/**
175111
* ice_read_sr_word_aq - Reads Shadow RAM via AQ
176112
* @hw: pointer to the HW structure
@@ -198,71 +134,14 @@ ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data)
198134
return 0;
199135
}
200136

201-
/**
202-
* ice_read_sr_buf_aq - Reads Shadow RAM buf via AQ
203-
* @hw: pointer to the HW structure
204-
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
205-
* @words: (in) number of words to read; (out) number of words actually read
206-
* @data: words read from the Shadow RAM
207-
*
208-
* Reads 16 bit words (data buf) from the SR using the ice_read_sr_aq
209-
* method. Ownership of the NVM is taken before reading the buffer and later
210-
* released.
211-
*/
212-
static enum ice_status
213-
ice_read_sr_buf_aq(struct ice_hw *hw, u16 offset, u16 *words, u16 *data)
214-
{
215-
enum ice_status status;
216-
bool last_cmd = false;
217-
u16 words_read = 0;
218-
u16 i = 0;
219-
220-
do {
221-
u16 read_size, off_w;
222-
223-
/* Calculate number of bytes we should read in this step.
224-
* It's not allowed to read more than one page at a time or
225-
* to cross page boundaries.
226-
*/
227-
off_w = offset % ICE_SR_SECTOR_SIZE_IN_WORDS;
228-
read_size = off_w ?
229-
min_t(u16, *words,
230-
(ICE_SR_SECTOR_SIZE_IN_WORDS - off_w)) :
231-
min_t(u16, (*words - words_read),
232-
ICE_SR_SECTOR_SIZE_IN_WORDS);
233-
234-
/* Check if this is last command, if so set proper flag */
235-
if ((words_read + read_size) >= *words)
236-
last_cmd = true;
237-
238-
status = ice_read_sr_aq(hw, offset, read_size,
239-
data + words_read, last_cmd);
240-
if (status)
241-
goto read_nvm_buf_aq_exit;
242-
243-
/* Increment counter for words already read and move offset to
244-
* new read location
245-
*/
246-
words_read += read_size;
247-
offset += read_size;
248-
} while (words_read < *words);
249-
250-
for (i = 0; i < *words; i++)
251-
data[i] = le16_to_cpu(((__force __le16 *)data)[i]);
252-
253-
read_nvm_buf_aq_exit:
254-
*words = words_read;
255-
return status;
256-
}
257-
258137
/**
259138
* ice_acquire_nvm - Generic request for acquiring the NVM ownership
260139
* @hw: pointer to the HW structure
261140
* @access: NVM access type (read or write)
262141
*
263142
* This function will request NVM ownership.
264143
*/
265-
static enum ice_status
144+
enum ice_status
266145
ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access)
267146
{
268147
if (hw->nvm.blank_nvm_mode)
@@ -277,7 +156,7 @@ ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access)
277156
*
278157
* This function will release NVM ownership.
279158
*/
280-
static void ice_release_nvm(struct ice_hw *hw)
159+
void ice_release_nvm(struct ice_hw *hw)
281160
{
282161
if (hw->nvm.blank_nvm_mode)
283162
return;
@@ -514,31 +393,6 @@ enum ice_status ice_init_nvm(struct ice_hw *hw)
514393
return 0;
515394
}
516395

517-
/**
518-
* ice_read_sr_buf - Reads Shadow RAM buf and acquire lock if necessary
519-
* @hw: pointer to the HW structure
520-
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
521-
* @words: (in) number of words to read; (out) number of words actually read
522-
* @data: words read from the Shadow RAM
523-
*
524-
* Reads 16 bit words (data buf) from the SR using the ice_read_nvm_buf_aq
525-
* method. The buf read is preceded by the NVM ownership take
526-
* and followed by the release.
527-
*/
528-
enum ice_status
529-
ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data)
530-
{
531-
enum ice_status status;
532-
533-
status = ice_acquire_nvm(hw, ICE_RES_READ);
534-
if (!status) {
535-
status = ice_read_sr_buf_aq(hw, offset, words, data);
536-
ice_release_nvm(hw);
537-
}
538-
539-
return status;
540-
}
541-
542396
/**
543397
* ice_nvm_validate_checksum
544398
* @hw: pointer to the HW struct

drivers/net/ethernet/intel/ice/ice_nvm.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44
#ifndef _ICE_NVM_H_
55
#define _ICE_NVM_H_
66

7+
enum ice_status
8+
ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access);
9+
void ice_release_nvm(struct ice_hw *hw);
710
enum ice_status
811
ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data,
912
bool read_shadow_ram);
13+
enum ice_status ice_init_nvm(struct ice_hw *hw);
1014
enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data);
1115
#endif /* _ICE_NVM_H_ */

0 commit comments

Comments
 (0)