aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2018-12-19 13:03:24 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2019-01-15 13:20:43 -0500
commit4c98ab550cc624eb94b0cdb32f5deb1ebbb4f593 (patch)
treea98f179de164d41d69855f56d3172a0ff96e4434 /drivers
parent8e151d50a1450350009822b4f705c6caf83383d4 (diff)
ice: Implement support for normal get_eeprom[_len] ethtool ops
Add support for get_eeprom and get_eeprom_len ethtool ops Specification states that PF software accesses NVM (shadow-ram) via AQ commands (e.g. NVM Read, NVM Write) in the range 0x000000-0x00FFFF (64KB), so the get_eeprom_len op should return 64KB. If additional regions of the 16MB NVM must be read, another access method must be used. The ethtool kernel code, by default, will ask for multiple page-size hunks of the NVM not to exceed the value returned by ice_get_eeprom_len(). ice_read_sr_buf() deals with arch page sizes different than 4KB. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/intel/ice/ice_common.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool.c51
-rw-r--r--drivers/net/ethernet/intel/ice/ice_nvm.c81
3 files changed, 134 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h
index b86cfe540045..81c1bb77a9fc 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.h
+++ b/drivers/net/ethernet/intel/ice/ice_common.h
@@ -28,6 +28,8 @@ ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res,
28 enum ice_aq_res_access_type access, u32 timeout); 28 enum ice_aq_res_access_type access, u32 timeout);
29void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res); 29void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res);
30enum ice_status ice_init_nvm(struct ice_hw *hw); 30enum ice_status ice_init_nvm(struct ice_hw *hw);
31enum ice_status ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words,
32 u16 *data);
31enum ice_status 33enum ice_status
32ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq, 34ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq,
33 struct ice_aq_desc *desc, void *buf, u16 buf_size, 35 struct ice_aq_desc *desc, void *buf, u16 buf_size,
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c
index 6facb0a7eed4..2a0bcd460d23 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -203,6 +203,55 @@ static void ice_set_msglevel(struct net_device *netdev, u32 data)
203#endif /* !CONFIG_DYNAMIC_DEBUG */ 203#endif /* !CONFIG_DYNAMIC_DEBUG */
204} 204}
205 205
206static int ice_get_eeprom_len(struct net_device *netdev)
207{
208 struct ice_netdev_priv *np = netdev_priv(netdev);
209 struct ice_pf *pf = np->vsi->back;
210
211 return (int)(pf->hw.nvm.sr_words * sizeof(u16));
212}
213
214static int
215ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
216 u8 *bytes)
217{
218 struct ice_netdev_priv *np = netdev_priv(netdev);
219 u16 first_word, last_word, nwords;
220 struct ice_vsi *vsi = np->vsi;
221 struct ice_pf *pf = vsi->back;
222 struct ice_hw *hw = &pf->hw;
223 enum ice_status status;
224 struct device *dev;
225 int ret = 0;
226 u16 *buf;
227
228 dev = &pf->pdev->dev;
229
230 eeprom->magic = hw->vendor_id | (hw->device_id << 16);
231
232 first_word = eeprom->offset >> 1;
233 last_word = (eeprom->offset + eeprom->len - 1) >> 1;
234 nwords = last_word - first_word + 1;
235
236 buf = devm_kcalloc(dev, nwords, sizeof(u16), GFP_KERNEL);
237 if (!buf)
238 return -ENOMEM;
239
240 status = ice_read_sr_buf(hw, first_word, &nwords, buf);
241 if (status) {
242 dev_err(dev, "ice_read_sr_buf failed, err %d aq_err %d\n",
243 status, hw->adminq.sq_last_status);
244 eeprom->len = sizeof(u16) * nwords;
245 ret = -EIO;
246 goto out;
247 }
248
249 memcpy(bytes, (u8 *)buf + (eeprom->offset & 1), eeprom->len);
250out:
251 devm_kfree(dev, buf);
252 return ret;
253}
254
206static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data) 255static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
207{ 256{
208 struct ice_netdev_priv *np = netdev_priv(netdev); 257 struct ice_netdev_priv *np = netdev_priv(netdev);
@@ -1699,6 +1748,8 @@ static const struct ethtool_ops ice_ethtool_ops = {
1699 .get_msglevel = ice_get_msglevel, 1748 .get_msglevel = ice_get_msglevel,
1700 .set_msglevel = ice_set_msglevel, 1749 .set_msglevel = ice_set_msglevel,
1701 .get_link = ethtool_op_get_link, 1750 .get_link = ethtool_op_get_link,
1751 .get_eeprom_len = ice_get_eeprom_len,
1752 .get_eeprom = ice_get_eeprom,
1702 .get_strings = ice_get_strings, 1753 .get_strings = ice_get_strings,
1703 .set_phys_id = ice_set_phys_id, 1754 .set_phys_id = ice_set_phys_id,
1704 .get_ethtool_stats = ice_get_ethtool_stats, 1755 .get_ethtool_stats = ice_get_ethtool_stats,
diff --git a/drivers/net/ethernet/intel/ice/ice_nvm.c b/drivers/net/ethernet/intel/ice/ice_nvm.c
index 3274c543283c..ce64cecdae9c 100644
--- a/drivers/net/ethernet/intel/ice/ice_nvm.c
+++ b/drivers/net/ethernet/intel/ice/ice_nvm.c
@@ -125,6 +125,62 @@ ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data)
125} 125}
126 126
127/** 127/**
128 * ice_read_sr_buf_aq - Reads Shadow RAM buf via AQ
129 * @hw: pointer to the HW structure
130 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
131 * @words: (in) number of words to read; (out) number of words actually read
132 * @data: words read from the Shadow RAM
133 *
134 * Reads 16 bit words (data buf) from the SR using the ice_read_sr_aq
135 * method. Ownership of the NVM is taken before reading the buffer and later
136 * released.
137 */
138static enum ice_status
139ice_read_sr_buf_aq(struct ice_hw *hw, u16 offset, u16 *words, u16 *data)
140{
141 enum ice_status status;
142 bool last_cmd = false;
143 u16 words_read = 0;
144 u16 i = 0;
145
146 do {
147 u16 read_size, off_w;
148
149 /* Calculate number of bytes we should read in this step.
150 * It's not allowed to read more than one page at a time or
151 * to cross page boundaries.
152 */
153 off_w = offset % ICE_SR_SECTOR_SIZE_IN_WORDS;
154 read_size = off_w ?
155 min(*words,
156 (u16)(ICE_SR_SECTOR_SIZE_IN_WORDS - off_w)) :
157 min((*words - words_read), ICE_SR_SECTOR_SIZE_IN_WORDS);
158
159 /* Check if this is last command, if so set proper flag */
160 if ((words_read + read_size) >= *words)
161 last_cmd = true;
162
163 status = ice_read_sr_aq(hw, offset, read_size,
164 data + words_read, last_cmd);
165 if (status)
166 goto read_nvm_buf_aq_exit;
167
168 /* Increment counter for words already read and move offset to
169 * new read location
170 */
171 words_read += read_size;
172 offset += read_size;
173 } while (words_read < *words);
174
175 for (i = 0; i < *words; i++)
176 data[i] = le16_to_cpu(((__le16 *)data)[i]);
177
178read_nvm_buf_aq_exit:
179 *words = words_read;
180 return status;
181}
182
183/**
128 * ice_acquire_nvm - Generic request for acquiring the NVM ownership 184 * ice_acquire_nvm - Generic request for acquiring the NVM ownership
129 * @hw: pointer to the HW structure 185 * @hw: pointer to the HW structure
130 * @access: NVM access type (read or write) 186 * @access: NVM access type (read or write)
@@ -234,3 +290,28 @@ enum ice_status ice_init_nvm(struct ice_hw *hw)
234 290
235 return status; 291 return status;
236} 292}
293
294/**
295 * ice_read_sr_buf - Reads Shadow RAM buf and acquire lock if necessary
296 * @hw: pointer to the HW structure
297 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
298 * @words: (in) number of words to read; (out) number of words actually read
299 * @data: words read from the Shadow RAM
300 *
301 * Reads 16 bit words (data buf) from the SR using the ice_read_nvm_buf_aq
302 * method. The buf read is preceded by the NVM ownership take
303 * and followed by the release.
304 */
305enum ice_status
306ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data)
307{
308 enum ice_status status;
309
310 status = ice_acquire_nvm(hw, ICE_RES_READ);
311 if (!status) {
312 status = ice_read_sr_buf_aq(hw, offset, words, data);
313 ice_release_nvm(hw);
314 }
315
316 return status;
317}