Bug Summary

File:dev/pci/igc_i225.c
Warning:line 1022, column 3
Value stored to 'ret_val' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name igc_i225.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/pci/igc_i225.c
1/* $OpenBSD: igc_i225.c,v 1.1 2021/10/31 14:52:57 patrick Exp $ */
2/*-
3 * Copyright 2021 Intel Corp
4 * Copyright 2021 Rubicon Communications, LLC (Netgate)
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8#include <dev/pci/igc_api.h>
9
10int igc_init_nvm_params_i225(struct igc_hw *);
11int igc_init_mac_params_i225(struct igc_hw *);
12int igc_init_phy_params_i225(struct igc_hw *);
13int igc_reset_hw_i225(struct igc_hw *);
14int igc_acquire_nvm_i225(struct igc_hw *);
15void igc_release_nvm_i225(struct igc_hw *);
16int igc_get_hw_semaphore_i225(struct igc_hw *);
17int __igc_write_nvm_srwr(struct igc_hw *, uint16_t, uint16_t, uint16_t *);
18int igc_pool_flash_update_done_i225(struct igc_hw *);
19
20/**
21 * igc_init_nvm_params_i225 - Init NVM func ptrs.
22 * @hw: pointer to the HW structure
23 **/
24int
25igc_init_nvm_params_i225(struct igc_hw *hw)
26{
27 struct igc_nvm_info *nvm = &hw->nvm;
28 uint32_t eecd = IGC_READ_REG(hw, IGC_EECD)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00010)
))
;
29 uint16_t size;
30
31 DEBUGFUNC("igc_init_nvm_params_i225")do { if (0) printf("igc_init_nvm_params_i225" "\n"); } while (
0)
;
32
33 size = (uint16_t)((eecd & IGC_EECD_SIZE_EX_MASK0x00007800) >>
34 IGC_EECD_SIZE_EX_SHIFT11);
35 /*
36 * Added to a constant, "size" becomes the left-shift value
37 * for setting word_size.
38 */
39 size += NVM_WORD_SIZE_BASE_SHIFT6;
40
41 /* Just in case size is out of range, cap it to the largest
42 * EEPROM size supported.
43 */
44 if (size > 15)
45 size = 15;
46
47 nvm->word_size = 1 << size;
48 nvm->opcode_bits = 8;
49 nvm->delay_usec = 1;
50 nvm->type = igc_nvm_eeprom_spi;
51
52 nvm->page_size = eecd & IGC_EECD_ADDR_BITS0x00000400 ? 32 : 8;
53 nvm->address_bits = eecd & IGC_EECD_ADDR_BITS0x00000400 ? 16 : 8;
54
55 if (nvm->word_size == (1 << 15))
56 nvm->page_size = 128;
57
58 nvm->ops.acquire = igc_acquire_nvm_i225;
59 nvm->ops.release = igc_release_nvm_i225;
60 if (igc_get_flash_presence_i225(hw)) {
61 hw->nvm.type = igc_nvm_flash_hw;
62 nvm->ops.read = igc_read_nvm_srrd_i225;
63 nvm->ops.write = igc_write_nvm_srwr_i225;
64 nvm->ops.validate = igc_validate_nvm_checksum_i225;
65 nvm->ops.update = igc_update_nvm_checksum_i225;
66 } else {
67 hw->nvm.type = igc_nvm_invm;
68 nvm->ops.write = igc_null_write_nvm;
69 nvm->ops.validate = igc_null_ops_generic;
70 nvm->ops.update = igc_null_ops_generic;
71 }
72
73 return IGC_SUCCESS0;
74}
75
76/**
77 * igc_init_mac_params_i225 - Init MAC func ptrs.
78 * @hw: pointer to the HW structure
79 **/
80int
81igc_init_mac_params_i225(struct igc_hw *hw)
82{
83 struct igc_mac_info *mac = &hw->mac;
84 struct igc_dev_spec_i225 *dev_spec = &hw->dev_spec._i225;
85
86 DEBUGFUNC("igc_init_mac_params_i225")do { if (0) printf("igc_init_mac_params_i225" "\n"); } while (
0)
;
87
88 /* Initialize function pointer */
89 igc_init_mac_ops_generic(hw);
90
91 /* Set media type */
92 hw->phy.media_type = igc_media_type_copper;
93 /* Set mta register count */
94 mac->mta_reg_count = 128;
95 /* Set rar entry count */
96 mac->rar_entry_count = IGC_RAR_ENTRIES_BASE16;
97
98 /* reset */
99 mac->ops.reset_hw = igc_reset_hw_i225;
100 /* hw initialization */
101 mac->ops.init_hw = igc_init_hw_i225;
102 /* link setup */
103 mac->ops.setup_link = igc_setup_link_generic;
104 /* check for link */
105 mac->ops.check_for_link = igc_check_for_link_i225;
106 /* link info */
107 mac->ops.get_link_up_info = igc_get_speed_and_duplex_copper_generic;
108 /* acquire SW_FW sync */
109 mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225;
110 /* release SW_FW sync */
111 mac->ops.release_swfw_sync = igc_release_swfw_sync_i225;
112
113 /* Allow a single clear of the SW semaphore on I225 */
114 dev_spec->clear_semaphore_once = true1;
115 mac->ops.setup_physical_interface = igc_setup_copper_link_i225;
116
117 /* Set if part includes ASF firmware */
118 mac->asf_firmware_present = true1;
119
120 /* multicast address update */
121 mac->ops.update_mc_addr_list = igc_update_mc_addr_list_generic;
122
123 mac->ops.write_vfta = igc_write_vfta_generic;
124
125 return IGC_SUCCESS0;
126}
127
128/**
129 * igc_init_phy_params_i225 - Init PHY func ptrs.
130 * @hw: pointer to the HW structure
131 **/
132int
133igc_init_phy_params_i225(struct igc_hw *hw)
134{
135 struct igc_phy_info *phy = &hw->phy;
136 uint32_t ctrl_ext;
137 int ret_val = IGC_SUCCESS0;
138
139 DEBUGFUNC("igc_init_phy_params_i225")do { if (0) printf("igc_init_phy_params_i225" "\n"); } while (
0)
;
140
141 if (hw->phy.media_type != igc_media_type_copper) {
142 phy->type = igc_phy_none;
143 goto out;
144 }
145
146 phy->ops.power_up = igc_power_up_phy_copper;
147 phy->ops.power_down = igc_power_down_phy_copper_base;
148 phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT_2500( 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0020 | 0x0080);
149 phy->reset_delay_us = 100;
150 phy->ops.acquire = igc_acquire_phy_base;
151 phy->ops.check_reset_block = igc_check_reset_block_generic;
152 phy->ops.commit = igc_phy_sw_reset_generic;
153 phy->ops.release = igc_release_phy_base;
154
155 ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00018)
))
;
156
157 /* Make sure the PHY is in a good state. Several people have reported
158 * firmware leaving the PHY's page select register set to something
159 * other than the default of zero, which causes the PHY ID read to
160 * access something other than the intended register.
161 */
162 ret_val = hw->phy.ops.reset(hw);
163 if (ret_val)
164 goto out;
165
166 IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00018)
, (ctrl_ext)))
;
167 phy->ops.read_reg = igc_read_phy_reg_gpy;
168 phy->ops.write_reg = igc_write_phy_reg_gpy;
169
170 ret_val = igc_get_phy_id(hw);
171 /* Verify phy id and set remaining function pointers */
172 switch (phy->id) {
173 case I225_I_PHY_ID0x67C9DC00:
174 phy->type = igc_phy_i225;
175 phy->ops.set_d0_lplu_state = igc_set_d0_lplu_state_i225;
176 phy->ops.set_d3_lplu_state = igc_set_d3_lplu_state_i225;
177 /* TODO - complete with GPY PHY information */
178 break;
179 default:
180 ret_val = -IGC_ERR_PHY2;
181 goto out;
182 }
183
184out:
185 return ret_val;
186}
187
188/**
189 * igc_reset_hw_i225 - Reset hardware
190 * @hw: pointer to the HW structure
191 *
192 * This resets the hardware into a known state.
193 **/
194int
195igc_reset_hw_i225(struct igc_hw *hw)
196{
197 uint32_t ctrl;
198 int ret_val;
199
200 DEBUGFUNC("igc_reset_hw_i225")do { if (0) printf("igc_reset_hw_i225" "\n"); } while (0);
201
202 /*
203 * Prevent the PCI-E bus from sticking if there is no TLP connection
204 * on the last TLP read/write transaction when MAC is reset.
205 */
206 ret_val = igc_disable_pcie_master_generic(hw);
207 if (ret_val)
208 DEBUGOUT("PCI-E Master disable polling has failed.\n")do { if (0) printf("PCI-E Master disable polling has failed.\n"
); } while (0)
;
209
210 DEBUGOUT("Masking off all interrupts\n")do { if (0) printf("Masking off all interrupts\n"); } while (
0)
;
211 IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0150C)
, (0xffffffff)))
;
212
213 IGC_WRITE_REG(hw, IGC_RCTL, 0)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00100)
, (0)))
;
214 IGC_WRITE_REG(hw, IGC_TCTL, IGC_TCTL_PSP)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00400)
, (0x00000008)))
;
215 IGC_WRITE_FLUSH(hw)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00008)
))
;
216
217 msec_delay(10)(*delay_func)(1000 * (10));
218
219 ctrl = IGC_READ_REG(hw, IGC_CTRL)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00000)
))
;
220
221 DEBUGOUT("Issuing a global reset to MAC\n")do { if (0) printf("Issuing a global reset to MAC\n"); } while
(0)
;
222 IGC_WRITE_REG(hw, IGC_CTRL, ctrl | IGC_CTRL_DEV_RST)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00000)
, (ctrl | 0x20000000)))
;
223
224 ret_val = igc_get_auto_rd_done_generic(hw);
225 if (ret_val) {
226 /*
227 * When auto config read does not complete, do not
228 * return with an error. This can happen in situations
229 * where there is no eeprom and prevents getting link.
230 */
231 DEBUGOUT("Auto Read Done did not complete\n")do { if (0) printf("Auto Read Done did not complete\n"); } while
(0)
;
232 }
233
234 /* Clear any pending interrupt events. */
235 IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0150C)
, (0xffffffff)))
;
236 IGC_READ_REG(hw, IGC_ICR)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x01500)
))
;
237
238 /* Install any alternate MAC address into RAR0 */
239 ret_val = igc_check_alt_mac_addr_generic(hw);
240
241 return ret_val;
242}
243
244/* igc_acquire_nvm_i225 - Request for access to EEPROM
245 * @hw: pointer to the HW structure
246 *
247 * Acquire the necessary semaphores for exclusive access to the EEPROM.
248 * Set the EEPROM access request bit and wait for EEPROM access grant bit.
249 * Return successful if access grant bit set, else clear the request for
250 * EEPROM access and return -IGC_ERR_NVM (-1).
251 */
252int
253igc_acquire_nvm_i225(struct igc_hw *hw)
254{
255 int ret_val;
256
257 DEBUGFUNC("igc_acquire_nvm_i225")do { if (0) printf("igc_acquire_nvm_i225" "\n"); } while (0);
258
259 ret_val = igc_acquire_swfw_sync_i225(hw, IGC_SWFW_EEP_SM0x01);
260
261 return ret_val;
262}
263
264/* igc_release_nvm_i225 - Release exclusive access to EEPROM
265 * @hw: pointer to the HW structure
266 *
267 * Stop any current commands to the EEPROM and clear the EEPROM request bit,
268 * then release the semaphores acquired.
269 */
270void
271igc_release_nvm_i225(struct igc_hw *hw)
272{
273 DEBUGFUNC("igc_release_nvm_i225")do { if (0) printf("igc_release_nvm_i225" "\n"); } while (0);
274
275 igc_release_swfw_sync_i225(hw, IGC_SWFW_EEP_SM0x01);
276}
277
278/* igc_acquire_swfw_sync_i225 - Acquire SW/FW semaphore
279 * @hw: pointer to the HW structure
280 * @mask: specifies which semaphore to acquire
281 *
282 * Acquire the SW/FW semaphore to access the PHY or NVM. The mask
283 * will also specify which port we're acquiring the lock for.
284 */
285int
286igc_acquire_swfw_sync_i225(struct igc_hw *hw, uint16_t mask)
287{
288 uint32_t swfw_sync;
289 uint32_t swmask = mask;
290 uint32_t fwmask = mask << 16;
291 int ret_val = IGC_SUCCESS0;
292 int i = 0, timeout = 200; /* FIXME: find real value to use here */
293
294 DEBUGFUNC("igc_acquire_swfw_sync_i225")do { if (0) printf("igc_acquire_swfw_sync_i225" "\n"); } while
(0)
;
295
296 while (i < timeout) {
297 if (igc_get_hw_semaphore_i225(hw)) {
298 ret_val = -IGC_ERR_SWFW_SYNC13;
299 goto out;
300 }
301
302 swfw_sync = IGC_READ_REG(hw, IGC_SW_FW_SYNC)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x05B5C)
))
;
303 if (!(swfw_sync & (fwmask | swmask)))
304 break;
305
306 /* Firmware currently using resource (fwmask)
307 * or other software thread using resource (swmask)
308 */
309 igc_put_hw_semaphore_generic(hw);
310 msec_delay(5)(*delay_func)(1000 * (5));
311 i++;
312 }
313
314 if (i == timeout) {
315 DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n")do { if (0) printf("Driver can't access resource, SW_FW_SYNC timeout.\n"
); } while (0)
;
316 ret_val = -IGC_ERR_SWFW_SYNC13;
317 goto out;
318 }
319
320 swfw_sync |= swmask;
321 IGC_WRITE_REG(hw, IGC_SW_FW_SYNC, swfw_sync)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x05B5C)
, (swfw_sync)))
;
322
323 igc_put_hw_semaphore_generic(hw);
324
325out:
326 return ret_val;
327}
328
329/* igc_release_swfw_sync_i225 - Release SW/FW semaphore
330 * @hw: pointer to the HW structure
331 * @mask: specifies which semaphore to acquire
332 *
333 * Release the SW/FW semaphore used to access the PHY or NVM. The mask
334 * will also specify which port we're releasing the lock for.
335 */
336void
337igc_release_swfw_sync_i225(struct igc_hw *hw, uint16_t mask)
338{
339 uint32_t swfw_sync;
340
341 DEBUGFUNC("igc_release_swfw_sync_i225")do { if (0) printf("igc_release_swfw_sync_i225" "\n"); } while
(0)
;
342
343 while (igc_get_hw_semaphore_i225(hw) != IGC_SUCCESS0)
344 ; /* Empty */
345
346 swfw_sync = IGC_READ_REG(hw, IGC_SW_FW_SYNC)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x05B5C)
))
;
347 swfw_sync &= ~mask;
348 IGC_WRITE_REG(hw, IGC_SW_FW_SYNC, swfw_sync)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x05B5C)
, (swfw_sync)))
;
349
350 igc_put_hw_semaphore_generic(hw);
351}
352
353/*
354 * igc_setup_copper_link_i225 - Configure copper link settings
355 * @hw: pointer to the HW structure
356 *
357 * Configures the link for auto-neg or forced speed and duplex. Then we check
358 * for link, once link is established calls to configure collision distance
359 * and flow control are called.
360 */
361int
362igc_setup_copper_link_i225(struct igc_hw *hw)
363{
364 uint32_t ctrl, phpm_reg;
365 int ret_val;
366
367 DEBUGFUNC("igc_setup_copper_link_i225")do { if (0) printf("igc_setup_copper_link_i225" "\n"); } while
(0)
;
368
369 ctrl = IGC_READ_REG(hw, IGC_CTRL)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00000)
))
;
370 ctrl |= IGC_CTRL_SLU0x00000040;
371 ctrl &= ~(IGC_CTRL_FRCSPD0x00000800 | IGC_CTRL_FRCDPX0x00001000);
372 IGC_WRITE_REG(hw, IGC_CTRL, ctrl)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00000)
, (ctrl)))
;
373
374 phpm_reg = IGC_READ_REG(hw, IGC_I225_PHPM)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E14))
)
;
375 phpm_reg &= ~IGC_I225_PHPM_GO_LINKD0x0020;
376 IGC_WRITE_REG(hw, IGC_I225_PHPM, phpm_reg)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E14),
(phpm_reg)))
;
377
378 ret_val = igc_setup_copper_link_generic(hw);
379
380 return ret_val;
381}
382
383/* igc_get_hw_semaphore_i225 - Acquire hardware semaphore
384 * @hw: pointer to the HW structure
385 *
386 * Acquire the HW semaphore to access the PHY or NVM
387 */
388int
389igc_get_hw_semaphore_i225(struct igc_hw *hw)
390{
391 uint32_t swsm;
392 int timeout = hw->nvm.word_size + 1;
393 int i = 0;
394
395 DEBUGFUNC("igc_get_hw_semaphore_i225")do { if (0) printf("igc_get_hw_semaphore_i225" "\n"); } while
(0)
;
396
397 /* Get the SW semaphore */
398 while (i < timeout) {
399 swsm = IGC_READ_REG(hw, IGC_SWSM)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x05B50)
))
;
400 if (!(swsm & IGC_SWSM_SMBI0x00000001))
401 break;
402
403 DELAY(50)(*delay_func)(50);
404 i++;
405 }
406
407 if (i == timeout) {
408 /* In rare circumstances, the SW semaphore may already be held
409 * unintentionally. Clear the semaphore once before giving up.
410 */
411 if (hw->dev_spec._i225.clear_semaphore_once) {
412 hw->dev_spec._i225.clear_semaphore_once = false0;
413 igc_put_hw_semaphore_generic(hw);
414 for (i = 0; i < timeout; i++) {
415 swsm = IGC_READ_REG(hw, IGC_SWSM)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x05B50)
))
;
416 if (!(swsm & IGC_SWSM_SMBI0x00000001))
417 break;
418
419 DELAY(50)(*delay_func)(50);
420 }
421 }
422
423 /* If we do not have the semaphore here, we have to give up. */
424 if (i == timeout) {
425 DEBUGOUT("Driver can't access device -\n")do { if (0) printf("Driver can't access device -\n"); } while
(0)
;
426 DEBUGOUT("SMBI bit is set.\n")do { if (0) printf("SMBI bit is set.\n"); } while (0);
427 return -IGC_ERR_NVM1;
428 }
429 }
430
431 /* Get the FW semaphore. */
432 for (i = 0; i < timeout; i++) {
433 swsm = IGC_READ_REG(hw, IGC_SWSM)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x05B50)
))
;
434 IGC_WRITE_REG(hw, IGC_SWSM, swsm | IGC_SWSM_SWESMBI)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x05B50)
, (swsm | 0x00000002)))
;
435
436 /* Semaphore acquired if bit latched */
437 if (IGC_READ_REG(hw, IGC_SWSM)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x05B50)
))
& IGC_SWSM_SWESMBI0x00000002)
438 break;
439
440 DELAY(50)(*delay_func)(50);
441 }
442
443 if (i == timeout) {
444 /* Release semaphores */
445 igc_put_hw_semaphore_generic(hw);
446 DEBUGOUT("Driver can't access the NVM\n")do { if (0) printf("Driver can't access the NVM\n"); } while (
0)
;
447 return -IGC_ERR_NVM1;
448 }
449
450 return IGC_SUCCESS0;
451}
452
453/* igc_read_nvm_srrd_i225 - Reads Shadow Ram using EERD register
454 * @hw: pointer to the HW structure
455 * @offset: offset of word in the Shadow Ram to read
456 * @words: number of words to read
457 * @data: word read from the Shadow Ram
458 *
459 * Reads a 16 bit word from the Shadow Ram using the EERD register.
460 * Uses necessary synchronization semaphores.
461 */
462int
463igc_read_nvm_srrd_i225(struct igc_hw *hw, uint16_t offset, uint16_t words,
464 uint16_t *data)
465{
466 uint16_t i, count;
467 int status = IGC_SUCCESS0;
468
469 DEBUGFUNC("igc_read_nvm_srrd_i225")do { if (0) printf("igc_read_nvm_srrd_i225" "\n"); } while (0
)
;
470
471 /* We cannot hold synchronization semaphores for too long,
472 * because of forceful takeover procedure. However it is more efficient
473 * to read in bursts than synchronizing access for each word.
474 */
475 for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT512) {
476 count = (words - i) / IGC_EERD_EEWR_MAX_COUNT512 > 0 ?
477 IGC_EERD_EEWR_MAX_COUNT512 : (words - i);
478 if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS0) {
479 status = igc_read_nvm_eerd(hw, offset, count, data + i);
480 hw->nvm.ops.release(hw);
481 } else {
482 status = IGC_ERR_SWFW_SYNC13;
483 }
484
485 if (status != IGC_SUCCESS0)
486 break;
487 }
488
489 return status;
490}
491
492/* igc_write_nvm_srwr_i225 - Write to Shadow RAM using EEWR
493 * @hw: pointer to the HW structure
494 * @offset: offset within the Shadow RAM to be written to
495 * @words: number of words to write
496 * @data: 16 bit word(s) to be written to the Shadow RAM
497 *
498 * Writes data to Shadow RAM at offset using EEWR register.
499 *
500 * If igc_update_nvm_checksum is not called after this function , the
501 * data will not be committed to FLASH and also Shadow RAM will most likely
502 * contain an invalid checksum.
503 *
504 * If error code is returned, data and Shadow RAM may be inconsistent - buffer
505 * partially written.
506 */
507int
508igc_write_nvm_srwr_i225(struct igc_hw *hw, uint16_t offset, uint16_t words,
509 uint16_t *data)
510{
511 uint16_t i, count;
512 int status = IGC_SUCCESS0;
513
514 DEBUGFUNC("igc_write_nvm_srwr_i225")do { if (0) printf("igc_write_nvm_srwr_i225" "\n"); } while (
0)
;
515
516 /* We cannot hold synchronization semaphores for too long,
517 * because of forceful takeover procedure. However it is more efficient
518 * to write in bursts than synchronizing access for each word.
519 */
520 for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT512) {
521 count = (words - i) / IGC_EERD_EEWR_MAX_COUNT512 > 0 ?
522 IGC_EERD_EEWR_MAX_COUNT512 : (words - i);
523 if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS0) {
524 status = __igc_write_nvm_srwr(hw, offset, count,
525 data + i);
526 hw->nvm.ops.release(hw);
527 } else
528 status = IGC_ERR_SWFW_SYNC13;
529
530 if (status != IGC_SUCCESS0)
531 break;
532 }
533
534 return status;
535}
536
537/* __igc_write_nvm_srwr - Write to Shadow Ram using EEWR
538 * @hw: pointer to the HW structure
539 * @offset: offset within the Shadow Ram to be written to
540 * @words: number of words to write
541 * @data: 16 bit word(s) to be written to the Shadow Ram
542 *
543 * Writes data to Shadow Ram at offset using EEWR register.
544 *
545 * If igc_update_nvm_checksum is not called after this function , the
546 * Shadow Ram will most likely contain an invalid checksum.
547 */
548int
549__igc_write_nvm_srwr(struct igc_hw *hw, uint16_t offset, uint16_t words,
550 uint16_t *data)
551{
552 struct igc_nvm_info *nvm = &hw->nvm;
553 uint32_t i, k, eewr = 0;
554 uint32_t attempts = 100000;
555 int ret_val = IGC_SUCCESS0;
556
557 DEBUGFUNC("__igc_write_nvm_srwr")do { if (0) printf("__igc_write_nvm_srwr" "\n"); } while (0);
558
559 /* A check for invalid values: offset too large, too many words,
560 * too many words for the offset, and not enough words.
561 */
562 if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
563 (words == 0)) {
564 DEBUGOUT("nvm parameter(s) out of bounds\n")do { if (0) printf("nvm parameter(s) out of bounds\n"); } while
(0)
;
565 ret_val = -IGC_ERR_NVM1;
566 goto out;
567 }
568
569 for (i = 0; i < words; i++) {
570 eewr = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT2) |
571 (data[i] << IGC_NVM_RW_REG_DATA16) | IGC_NVM_RW_REG_START1;
572
573 IGC_WRITE_REG(hw, IGC_SRWR, eewr)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x12018)
, (eewr)))
;
574
575 for (k = 0; k < attempts; k++) {
576 if (IGC_NVM_RW_REG_DONE2 & IGC_READ_REG(hw, IGC_SRWR)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x12018)
))
) {
577 ret_val = IGC_SUCCESS0;
578 break;
579 }
580 DELAY(5)(*delay_func)(5);
581 }
582
583 if (ret_val != IGC_SUCCESS0) {
584 DEBUGOUT("Shadow RAM write EEWR timed out\n")do { if (0) printf("Shadow RAM write EEWR timed out\n"); } while
(0)
;
585 break;
586 }
587 }
588
589out:
590 return ret_val;
591}
592
593/* igc_validate_nvm_checksum_i225 - Validate EEPROM checksum
594 * @hw: pointer to the HW structure
595 *
596 * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
597 * and then verifies that the sum of the EEPROM is equal to 0xBABA.
598 */
599int
600igc_validate_nvm_checksum_i225(struct igc_hw *hw)
601{
602 int status = IGC_SUCCESS0;
603 int (*read_op_ptr)(struct igc_hw *, uint16_t, uint16_t, uint16_t *);
604
605 DEBUGFUNC("igc_validate_nvm_checksum_i225")do { if (0) printf("igc_validate_nvm_checksum_i225" "\n"); } while
(0)
;
606
607 if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS0) {
608 /* Replace the read function with semaphore grabbing with
609 * the one that skips this for a while.
610 * We have semaphore taken already here.
611 */
612 read_op_ptr = hw->nvm.ops.read;
613 hw->nvm.ops.read = igc_read_nvm_eerd;
614
615 status = igc_validate_nvm_checksum_generic(hw);
616
617 /* Revert original read operation. */
618 hw->nvm.ops.read = read_op_ptr;
619
620 hw->nvm.ops.release(hw);
621 } else {
622 status = IGC_ERR_SWFW_SYNC13;
623 }
624
625 return status;
626}
627
628/* igc_update_nvm_checksum_i225 - Update EEPROM checksum
629 * @hw: pointer to the HW structure
630 *
631 * Updates the EEPROM checksum by reading/adding each word of the EEPROM
632 * up to the checksum. Then calculates the EEPROM checksum and writes the
633 * value to the EEPROM. Next commit EEPROM data onto the Flash.
634 */
635int
636igc_update_nvm_checksum_i225(struct igc_hw *hw)
637{
638 uint16_t checksum = 0;
639 uint16_t i, nvm_data;
640 int ret_val;
641
642 DEBUGFUNC("igc_update_nvm_checksum_i225")do { if (0) printf("igc_update_nvm_checksum_i225" "\n"); } while
(0)
;
643
644 /* Read the first word from the EEPROM. If this times out or fails, do
645 * not continue or we could be in for a very long wait while every
646 * EEPROM read fails
647 */
648 ret_val = igc_read_nvm_eerd(hw, 0, 1, &nvm_data);
649 if (ret_val != IGC_SUCCESS0) {
650 DEBUGOUT("EEPROM read failed\n")do { if (0) printf("EEPROM read failed\n"); } while (0);
651 goto out;
652 }
653
654 if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS0) {
655 /* Do not use hw->nvm.ops.write, hw->nvm.ops.read
656 * because we do not want to take the synchronization
657 * semaphores twice here.
658 */
659
660 for (i = 0; i < NVM_CHECKSUM_REG0x003F; i++) {
661 ret_val = igc_read_nvm_eerd(hw, i, 1, &nvm_data);
662 if (ret_val) {
663 hw->nvm.ops.release(hw);
664 DEBUGOUT("NVM Read Error while updating\n")do { if (0) printf("NVM Read Error while updating\n"); } while
(0)
;
665 DEBUGOUT("checksum.\n")do { if (0) printf("checksum.\n"); } while (0);
666 goto out;
667 }
668 checksum += nvm_data;
669 }
670 checksum = (uint16_t)NVM_SUM0xBABA - checksum;
671 ret_val = __igc_write_nvm_srwr(hw, NVM_CHECKSUM_REG0x003F, 1,
672 &checksum);
673 if (ret_val != IGC_SUCCESS0) {
674 hw->nvm.ops.release(hw);
675 DEBUGOUT("NVM Write Error while updating checksum.\n")do { if (0) printf("NVM Write Error while updating checksum.\n"
); } while (0)
;
676 goto out;
677 }
678
679 hw->nvm.ops.release(hw);
680
681 ret_val = igc_update_flash_i225(hw);
682 } else {
683 ret_val = IGC_ERR_SWFW_SYNC13;
684 }
685out:
686 return ret_val;
687}
688
689/* igc_get_flash_presence_i225 - Check if flash device is detected.
690 * @hw: pointer to the HW structure
691 */
692bool_Bool
693igc_get_flash_presence_i225(struct igc_hw *hw)
694{
695 uint32_t eec = 0;
696 bool_Bool ret_val = false0;
697
698 DEBUGFUNC("igc_get_flash_presence_i225")do { if (0) printf("igc_get_flash_presence_i225" "\n"); } while
(0)
;
699
700 eec = IGC_READ_REG(hw, IGC_EECD)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00010)
))
;
701
702 if (eec & IGC_EECD_FLASH_DETECTED_I2250x00080000)
703 ret_val = true1;
704
705 return ret_val;
706}
707
708/* igc_set_flsw_flash_burst_counter_i225 - sets FLSW NVM Burst
709 * Counter in FLSWCNT register.
710 *
711 * @hw: pointer to the HW structure
712 * @burst_counter: size in bytes of the Flash burst to read or write
713 */
714int
715igc_set_flsw_flash_burst_counter_i225(struct igc_hw *hw, uint32_t burst_counter)
716{
717 int ret_val = IGC_SUCCESS0;
718
719 DEBUGFUNC("igc_set_flsw_flash_burst_counter_i225")do { if (0) printf("igc_set_flsw_flash_burst_counter_i225" "\n"
); } while (0)
;
720
721 /* Validate input data */
722 if (burst_counter < IGC_I225_SHADOW_RAM_SIZE4096) {
723 /* Write FLSWCNT - burst counter */
724 IGC_WRITE_REG(hw, IGC_I225_FLSWCNT, burst_counter)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x12050)
, (burst_counter)))
;
725 } else {
726 ret_val = IGC_ERR_INVALID_ARGUMENT16;
727 }
728
729 return ret_val;
730}
731
732
733/* igc_write_erase_flash_command_i225 - write/erase to a sector
734 * region on a given address.
735 *
736 * @hw: pointer to the HW structure
737 * @opcode: opcode to be used for the write command
738 * @address: the offset to write into the FLASH image
739 */
740int
741igc_write_erase_flash_command_i225(struct igc_hw *hw, uint32_t opcode,
742 uint32_t address)
743{
744 uint32_t flswctl = 0;
745 int timeout = IGC_NVM_GRANT_ATTEMPTS1000;
746 int ret_val = IGC_SUCCESS0;
747
748 DEBUGFUNC("igc_write_erase_flash_command_i225")do { if (0) printf("igc_write_erase_flash_command_i225" "\n")
; } while (0)
;
749
750 flswctl = IGC_READ_REG(hw, IGC_I225_FLSWCTL)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x12048)
))
;
751 /* Polling done bit on FLSWCTL register */
752 while (timeout) {
753 if (flswctl & IGC_FLSWCTL_DONE0x40000000)
754 break;
755 DELAY(5)(*delay_func)(5);
756 flswctl = IGC_READ_REG(hw, IGC_I225_FLSWCTL)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x12048)
))
;
757 timeout--;
758 }
759
760 if (!timeout) {
761 DEBUGOUT("Flash transaction was not done\n")do { if (0) printf("Flash transaction was not done\n"); } while
(0)
;
762 return -IGC_ERR_NVM1;
763 }
764
765 /* Build and issue command on FLSWCTL register */
766 flswctl = address | opcode;
767 IGC_WRITE_REG(hw, IGC_I225_FLSWCTL, flswctl)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x12048)
, (flswctl)))
;
768
769 /* Check if issued command is valid on FLSWCTL register */
770 flswctl = IGC_READ_REG(hw, IGC_I225_FLSWCTL)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x12048)
))
;
771 if (!(flswctl & IGC_FLSWCTL_CMDV0x10000000)) {
772 DEBUGOUT("Write flash command failed\n")do { if (0) printf("Write flash command failed\n"); } while (
0)
;
773 ret_val = IGC_ERR_INVALID_ARGUMENT16;
774 }
775
776 return ret_val;
777}
778
779/* igc_update_flash_i225 - Commit EEPROM to the flash
780 * if fw_valid_bit is set, FW is active. setting FLUPD bit in EEC
781 * register makes the FW load the internal shadow RAM into the flash.
782 * Otherwise, fw_valid_bit is 0. if FL_SECU.block_prtotected_sw = 0
783 * then FW is not active so the SW is responsible shadow RAM dump.
784 *
785 * @hw: pointer to the HW structure
786 */
787int
788igc_update_flash_i225(struct igc_hw *hw)
789{
790 uint32_t block_sw_protect = 1;
791 uint32_t i, flup, fw_valid_bit;
792 uint16_t current_offset;
793 uint16_t base_address = 0x0;
794 uint16_t current_offset_data = 0;
795 int ret_val = 0;
796
797 DEBUGFUNC("igc_update_flash_i225")do { if (0) printf("igc_update_flash_i225" "\n"); } while (0);
798
799 block_sw_protect = IGC_READ_REG(hw, IGC_I225_FLSECU)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x12114)
))
&
800 IGC_FLSECU_BLK_SW_ACCESS_I2250x00000004;
801
802 fw_valid_bit = IGC_READ_REG(hw, IGC_FWSM)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x05B54)
))
& IGC_FWSM_FW_VALID_I2250x8000;
803 if (fw_valid_bit) {
804 ret_val = igc_pool_flash_update_done_i225(hw);
805 if (ret_val == -IGC_ERR_NVM1) {
806 DEBUGOUT("Flash update time out\n")do { if (0) printf("Flash update time out\n"); } while (0);
807 goto out;
808 }
809
810 flup = IGC_READ_REG(hw, IGC_EECD)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00010)
))
| IGC_EECD_FLUPD_I2250x00800000;
811 IGC_WRITE_REG(hw, IGC_EECD, flup)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00010)
, (flup)))
;
812
813 ret_val = igc_pool_flash_update_done_i225(hw);
814 if (ret_val == IGC_SUCCESS0)
815 DEBUGOUT("Flash update complete\n")do { if (0) printf("Flash update complete\n"); } while (0);
816 else
817 DEBUGOUT("Flash update time out\n")do { if (0) printf("Flash update time out\n"); } while (0);
818 } else if (!block_sw_protect) {
819 /* FW is not active and security protection is disabled.
820 * therefore, SW is in charge of shadow RAM dump.
821 * Check which sector is valid. if sector 0 is valid,
822 * base address remains 0x0. otherwise, sector 1 is
823 * valid and it's base address is 0x1000
824 */
825 if (IGC_READ_REG(hw, IGC_EECD)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00010)
))
& IGC_EECD_SEC1VAL_I2250x02000000)
826 base_address = 0x1000;
827
828 /* Valid sector erase */
829 ret_val = igc_write_erase_flash_command_i225(hw,
830 IGC_I225_ERASE_CMD_OPCODE0x02000000, base_address);
831 if (!ret_val) {
832 DEBUGOUT("Sector erase failed\n")do { if (0) printf("Sector erase failed\n"); } while (0);
833 goto out;
834 }
835
836 current_offset = base_address;
837
838 /* Write */
839 for (i = 0; i < IGC_I225_SHADOW_RAM_SIZE4096 / 2; i++) {
840 /* Set burst write length */
841 ret_val = igc_set_flsw_flash_burst_counter_i225(hw,
842 0x2);
843 if (ret_val != IGC_SUCCESS0)
844 break;
845
846 /* Set address and opcode */
847 ret_val = igc_write_erase_flash_command_i225(hw,
848 IGC_I225_WRITE_CMD_OPCODE0x01000000, 2 * current_offset);
849 if (ret_val != IGC_SUCCESS0)
850 break;
851
852 ret_val = igc_read_nvm_eerd(hw, current_offset, 1,
853 &current_offset_data);
854 if (ret_val) {
855 DEBUGOUT("Failed to read from EEPROM\n")do { if (0) printf("Failed to read from EEPROM\n"); } while (
0)
;
856 goto out;
857 }
858
859 /* Write CurrentOffseData to FLSWDATA register */
860 IGC_WRITE_REG(hw, IGC_I225_FLSWDATA,((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x1204C)
, (current_offset_data)))
861 current_offset_data)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x1204C)
, (current_offset_data)))
;
862 current_offset++;
863
864 /* Wait till operation has finished */
865 ret_val = igc_poll_eerd_eewr_done(hw,
866 IGC_NVM_POLL_READ0);
867 if (ret_val)
868 break;
869
870 DELAY(1000)(*delay_func)(1000);
871 }
872 }
873out:
874 return ret_val;
875}
876
877/* igc_pool_flash_update_done_i225 - Pool FLUDONE status.
878 * @hw: pointer to the HW structure
879 */
880int
881igc_pool_flash_update_done_i225(struct igc_hw *hw)
882{
883 uint32_t i, reg;
884 int ret_val = -IGC_ERR_NVM1;
885
886 DEBUGFUNC("igc_pool_flash_update_done_i225")do { if (0) printf("igc_pool_flash_update_done_i225" "\n"); }
while (0)
;
887
888 for (i = 0; i < IGC_FLUDONE_ATTEMPTS20000; i++) {
889 reg = IGC_READ_REG(hw, IGC_EECD)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x00010)
))
;
890 if (reg & IGC_EECD_FLUDONE_I2250x04000000) {
891 ret_val = IGC_SUCCESS0;
892 break;
893 }
894 DELAY(5)(*delay_func)(5);
895 }
896
897 return ret_val;
898}
899
900/* igc_set_ltr_i225 - Set Latency Tolerance Reporting thresholds.
901 * @hw: pointer to the HW structure
902 * @link: bool indicating link status
903 *
904 * Set the LTR thresholds based on the link speed (Mbps), EEE, and DMAC
905 * settings, otherwise specify that there is no LTR requirement.
906 */
907int
908igc_set_ltr_i225(struct igc_hw *hw, bool_Bool link)
909{
910 uint16_t speed, duplex;
911 uint32_t tw_system, ltrc, ltrv, ltr_min, ltr_max, scale_min, scale_max;
912 int size;
913
914 DEBUGFUNC("igc_set_ltr_i225")do { if (0) printf("igc_set_ltr_i225" "\n"); } while (0);
915
916 /* If we do not have link, LTR thresholds are zero. */
917 if (link) {
918 hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
919
920 /* Check if using copper interface with EEE enabled or if the
921 * link speed is 10 Mbps.
922 */
923 if ((hw->phy.media_type == igc_media_type_copper) &&
924 !(hw->dev_spec._i225.eee_disable) &&
925 (speed != SPEED_1010)) {
926 /* EEE enabled, so send LTRMAX threshold. */
927 ltrc = IGC_READ_REG(hw, IGC_LTRC)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x01A0))
)
| IGC_LTRC_EEEMS_EN0x00000020;
928 IGC_WRITE_REG(hw, IGC_LTRC, ltrc)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x01A0),
(ltrc)))
;
929
930 /* Calculate tw_system (nsec). */
931 if (speed == SPEED_100100) {
932 tw_system = ((IGC_READ_REG(hw, IGC_EEE_SU)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E34))
)
&
933 IGC_TW_SYSTEM_100_MASK0x0000FF00) >>
934 IGC_TW_SYSTEM_100_SHIFT8) * 500;
935 } else {
936 tw_system = (IGC_READ_REG(hw, IGC_EEE_SU)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E34))
)
&
937 IGC_TW_SYSTEM_1000_MASK0x000000FF) * 500;
938 }
939 } else {
940 tw_system = 0;
941 }
942
943 /* Get the Rx packet buffer size. */
944 size = IGC_READ_REG(hw, IGC_RXPBS)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x02404)
))
& IGC_RXPBS_SIZE_I225_MASK0x0000003F;
945
946 /* Calculations vary based on DMAC settings. */
947 if (IGC_READ_REG(hw, IGC_DMACR)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x02508)
))
& IGC_DMACR_DMAC_EN0x80000000) {
948 size -= (IGC_READ_REG(hw, IGC_DMACR)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x02508)
))
&
949 IGC_DMACR_DMACTHR_MASK0x00FF0000) >> IGC_DMACR_DMACTHR_SHIFT16;
950 /* Convert size to bits. */
951 size *= 1024 * 8;
952 } else {
953 /* Convert size to bytes, subtract the MTU, and then
954 * convert the size to bits.
955 */
956 size *= 1024;
957 size -= hw->dev_spec._i225.mtu;
958 size *= 8;
959 }
960
961 if (size < 0) {
962 DEBUGOUT1("Invalid effective Rx buffer size %d\n",do { if (0) printf("Invalid effective Rx buffer size %d\n", size
); } while (0)
963 size)do { if (0) printf("Invalid effective Rx buffer size %d\n", size
); } while (0)
;
964 return -IGC_ERR_CONFIG3;
965 }
966
967 /* Calculate the thresholds. Since speed is in Mbps, simplify
968 * the calculation by multiplying size/speed by 1000 for result
969 * to be in nsec before dividing by the scale in nsec. Set the
970 * scale such that the LTR threshold fits in the register.
971 */
972 ltr_min = (1000 * size) / speed;
973 ltr_max = ltr_min + tw_system;
974 scale_min = (ltr_min / 1024) < 1024 ? IGC_LTRMINV_SCALE_10242 :
975 IGC_LTRMINV_SCALE_327683;
976 scale_max = (ltr_max / 1024) < 1024 ? IGC_LTRMAXV_SCALE_10242 :
977 IGC_LTRMAXV_SCALE_327683;
978 ltr_min /= scale_min == IGC_LTRMINV_SCALE_10242 ? 1024 : 32768;
979 ltr_max /= scale_max == IGC_LTRMAXV_SCALE_10242 ? 1024 : 32768;
980
981 /* Only write the LTR thresholds if they differ from before. */
982 ltrv = IGC_READ_REG(hw, IGC_LTRMINV)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x5BB0))
)
;
983 if (ltr_min != (ltrv & IGC_LTRMINV_LTRV_MASK0x000003FF)) {
984 ltrv = IGC_LTRMINV_LSNP_REQ0x00008000 | ltr_min |
985 (scale_min << IGC_LTRMINV_SCALE_SHIFT10);
986 IGC_WRITE_REG(hw, IGC_LTRMINV, ltrv)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x5BB0),
(ltrv)))
;
987 }
988
989 ltrv = IGC_READ_REG(hw, IGC_LTRMAXV)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x5BB4))
)
;
990 if (ltr_max != (ltrv & IGC_LTRMAXV_LTRV_MASK0x000003FF)) {
991 ltrv = IGC_LTRMAXV_LSNP_REQ0x00008000 | ltr_max |
992 (scale_min << IGC_LTRMAXV_SCALE_SHIFT10);
993 IGC_WRITE_REG(hw, IGC_LTRMAXV, ltrv)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x5BB4),
(ltrv)))
;
994 }
995 }
996
997 return IGC_SUCCESS0;
998}
999
1000/* igc_check_for_link_i225 - Check for link
1001 * @hw: pointer to the HW structure
1002 *
1003 * Checks to see of the link status of the hardware has changed. If a
1004 * change in link status has been detected, then we read the PHY registers
1005 * to get the current speed/duplex if link exists.
1006 */
1007int
1008igc_check_for_link_i225(struct igc_hw *hw)
1009{
1010 struct igc_mac_info *mac = &hw->mac;
1011 int ret_val;
1012 bool_Bool link = false0;
1013
1014 DEBUGFUNC("igc_check_for_link_i225")do { if (0) printf("igc_check_for_link_i225" "\n"); } while (
0)
;
1015
1016 /* We only want to go out to the PHY registers to see if
1017 * Auto-Neg has completed and/or if our link status has
1018 * changed. The get_link_status flag is set upon receiving
1019 * a Link Status Change or Rx Sequence Error interrupt.
1020 */
1021 if (!mac->get_link_status) {
1022 ret_val = IGC_SUCCESS0;
Value stored to 'ret_val' is never read
1023 goto out;
1024 }
1025
1026 /* First we want to see if the MII Status Register reports
1027 * link. If so, then we want to get the current speed/duplex
1028 * of the PHY.
1029 */
1030 ret_val = igc_phy_has_link_generic(hw, 1, 0, &link);
1031 if (ret_val)
1032 goto out;
1033
1034 if (!link)
1035 goto out; /* No link detected */
1036
1037 /* First we want to see if the MII Status Register reports
1038 * link. If so, then we want to get the current speed/duplex
1039 * of the PHY.
1040 */
1041 ret_val = igc_phy_has_link_generic(hw, 1, 0, &link);
1042 if (ret_val)
1043 goto out;
1044
1045 if (!link)
1046 goto out; /* No link detected */
1047
1048 mac->get_link_status = false0;
1049
1050 /* Check if there was DownShift, must be checked
1051 * immediately after link-up
1052 */
1053 igc_check_downshift_generic(hw);
1054
1055 /* If we are forcing speed/duplex, then we simply return since
1056 * we have already determined whether we have link or not.
1057 */
1058 if (!mac->autoneg)
1059 goto out;
1060
1061 /* Auto-Neg is enabled. Auto Speed Detection takes care
1062 * of MAC speed/duplex configuration. So we only need to
1063 * configure Collision Distance in the MAC.
1064 */
1065 mac->ops.config_collision_dist(hw);
1066
1067 /* Configure Flow Control now that Auto-Neg has completed.
1068 * First, we need to restore the desired flow control
1069 * settings because we may have had to re-autoneg with a
1070 * different link partner.
1071 */
1072 ret_val = igc_config_fc_after_link_up_generic(hw);
1073 if (ret_val)
1074 DEBUGOUT("Error configuring flow control\n")do { if (0) printf("Error configuring flow control\n"); } while
(0)
;
1075out:
1076 /* Now that we are aware of our link settings, we can set the LTR
1077 * thresholds.
1078 */
1079 ret_val = igc_set_ltr_i225(hw, link);
1080
1081 return ret_val;
1082}
1083
1084/* igc_init_function_pointers_i225 - Init func ptrs.
1085 * @hw: pointer to the HW structure
1086 *
1087 * Called to initialize all function pointers and parameters.
1088 */
1089void
1090igc_init_function_pointers_i225(struct igc_hw *hw)
1091{
1092 igc_init_mac_ops_generic(hw);
1093 igc_init_phy_ops_generic(hw);
1094 igc_init_nvm_ops_generic(hw);
1095 hw->mac.ops.init_params = igc_init_mac_params_i225;
1096 hw->nvm.ops.init_params = igc_init_nvm_params_i225;
1097 hw->phy.ops.init_params = igc_init_phy_params_i225;
1098}
1099
1100/* igc_init_hw_i225 - Init hw for I225
1101 * @hw: pointer to the HW structure
1102 *
1103 * Called to initialize hw for i225 hw family.
1104 */
1105int
1106igc_init_hw_i225(struct igc_hw *hw)
1107{
1108 int ret_val;
1109
1110 DEBUGFUNC("igc_init_hw_i225")do { if (0) printf("igc_init_hw_i225" "\n"); } while (0);
1111
1112 ret_val = igc_init_hw_base(hw);
1113 return ret_val;
1114}
1115
1116/*
1117 * igc_set_d0_lplu_state_i225 - Set Low-Power-Link-Up (LPLU) D0 state
1118 * @hw: pointer to the HW structure
1119 * @active: true to enable LPLU, false to disable
1120 *
1121 * Note: since I225 does not actually support LPLU, this function
1122 * simply enables/disables 1G and 2.5G speeds in D0.
1123 */
1124int
1125igc_set_d0_lplu_state_i225(struct igc_hw *hw, bool_Bool active)
1126{
1127 uint32_t data;
1128
1129 DEBUGFUNC("igc_set_d0_lplu_state_i225")do { if (0) printf("igc_set_d0_lplu_state_i225" "\n"); } while
(0)
;
1130
1131 data = IGC_READ_REG(hw, IGC_I225_PHPM)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E14))
)
;
1132
1133 if (active) {
1134 data |= IGC_I225_PHPM_DIS_10000x0040;
1135 data |= IGC_I225_PHPM_DIS_25000x0800;
1136 } else {
1137 data &= ~IGC_I225_PHPM_DIS_10000x0040;
1138 data &= ~IGC_I225_PHPM_DIS_25000x0800;
1139 }
1140
1141 IGC_WRITE_REG(hw, IGC_I225_PHPM, data)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E14),
(data)))
;
1142 return IGC_SUCCESS0;
1143}
1144
1145/*
1146 * igc_set_d3_lplu_state_i225 - Set Low-Power-Link-Up (LPLU) D3 state
1147 * @hw: pointer to the HW structure
1148 * @active: true to enable LPLU, false to disable
1149 *
1150 * Note: since I225 does not actually support LPLU, this function
1151 * simply enables/disables 100M, 1G and 2.5G speeds in D3.
1152 */
1153int
1154igc_set_d3_lplu_state_i225(struct igc_hw *hw, bool_Bool active)
1155{
1156 uint32_t data;
1157
1158 DEBUGFUNC("igc_set_d3_lplu_state_i225")do { if (0) printf("igc_set_d3_lplu_state_i225" "\n"); } while
(0)
;
1159
1160 data = IGC_READ_REG(hw, IGC_I225_PHPM)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E14))
)
;
1161
1162 if (active) {
1163 data |= IGC_I225_PHPM_DIS_100_D30x0200;
1164 data |= IGC_I225_PHPM_DIS_1000_D30x0008;
1165 data |= IGC_I225_PHPM_DIS_2500_D30x1000;
1166 } else {
1167 data &= ~IGC_I225_PHPM_DIS_100_D30x0200;
1168 data &= ~IGC_I225_PHPM_DIS_1000_D30x0008;
1169 data &= ~IGC_I225_PHPM_DIS_2500_D30x1000;
1170 }
1171
1172 IGC_WRITE_REG(hw, IGC_I225_PHPM, data)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E14),
(data)))
;
1173 return IGC_SUCCESS0;
1174}
1175
1176/**
1177 * igc_set_eee_i225 - Enable/disable EEE support
1178 * @hw: pointer to the HW structure
1179 * @adv2p5G: boolean flag enabling 2.5G EEE advertisement
1180 * @adv1G: boolean flag enabling 1G EEE advertisement
1181 * @adv100M: boolean flag enabling 100M EEE advertisement
1182 *
1183 * Enable/disable EEE based on setting in dev_spec structure.
1184 *
1185 **/
1186int
1187igc_set_eee_i225(struct igc_hw *hw, bool_Bool adv2p5G, bool_Bool adv1G,
1188 bool_Bool adv100M)
1189{
1190 uint32_t ipcnfg, eeer;
1191
1192 DEBUGFUNC("igc_set_eee_i225")do { if (0) printf("igc_set_eee_i225" "\n"); } while (0);
1193
1194 if (hw->mac.type != igc_i225 ||
1195 hw->phy.media_type != igc_media_type_copper)
1196 goto out;
1197 ipcnfg = IGC_READ_REG(hw, IGC_IPCNFG)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E38))
)
;
1198 eeer = IGC_READ_REG(hw, IGC_EEER)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E30))
)
;
1199
1200 /* enable or disable per user setting */
1201 if (!(hw->dev_spec._i225.eee_disable)) {
1202 uint32_t eee_su = IGC_READ_REG(hw, IGC_EEE_SU)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E34))
)
;
1203
1204 if (adv100M)
1205 ipcnfg |= IGC_IPCNFG_EEE_100M_AN0x00000004;
1206 else
1207 ipcnfg &= ~IGC_IPCNFG_EEE_100M_AN0x00000004;
1208
1209 if (adv1G)
1210 ipcnfg |= IGC_IPCNFG_EEE_1G_AN0x00000008;
1211 else
1212 ipcnfg &= ~IGC_IPCNFG_EEE_1G_AN0x00000008;
1213
1214 if (adv2p5G)
1215 ipcnfg |= IGC_IPCNFG_EEE_2_5G_AN0x00000010;
1216 else
1217 ipcnfg &= ~IGC_IPCNFG_EEE_2_5G_AN0x00000010;
1218
1219 eeer |= (IGC_EEER_TX_LPI_EN0x00010000 | IGC_EEER_RX_LPI_EN0x00020000 |
1220 IGC_EEER_LPI_FC0x00040000);
1221
1222 /* This bit should not be set in normal operation. */
1223 if (eee_su & IGC_EEE_SU_LPI_CLK_STP0x00800000)
1224 DEBUGOUT("LPI Clock Stop Bit should not be set!\n")do { if (0) printf("LPI Clock Stop Bit should not be set!\n")
; } while (0)
;
1225 } else {
1226 ipcnfg &= ~(IGC_IPCNFG_EEE_2_5G_AN0x00000010 | IGC_IPCNFG_EEE_1G_AN0x00000008 |
1227 IGC_IPCNFG_EEE_100M_AN0x00000004);
1228 eeer &= ~(IGC_EEER_TX_LPI_EN0x00010000 | IGC_EEER_RX_LPI_EN0x00020000 |
1229 IGC_EEER_LPI_FC0x00040000);
1230 }
1231 IGC_WRITE_REG(hw, IGC_IPCNFG, ipcnfg)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E38),
(ipcnfg)))
;
1232 IGC_WRITE_REG(hw, IGC_EEER, eeer)((((struct igc_osdep *)(hw)->back)->os_memt)->write_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E30),
(eeer)))
;
1233 IGC_READ_REG(hw, IGC_IPCNFG)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E38))
)
;
1234 IGC_READ_REG(hw, IGC_EEER)((((struct igc_osdep *)(hw)->back)->os_memt)->read_4
((((struct igc_osdep *)(hw)->back)->os_memh), (0x0E30))
)
;
1235out:
1236
1237 return IGC_SUCCESS0;
1238}