xref: /illumos-gate/usr/src/uts/common/io/igc/igc.c (revision 6bbbd442)
1*6bbbd442SRobert Mustacchi /*
2*6bbbd442SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*6bbbd442SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*6bbbd442SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*6bbbd442SRobert Mustacchi  * 1.0 of the CDDL.
6*6bbbd442SRobert Mustacchi  *
7*6bbbd442SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*6bbbd442SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*6bbbd442SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*6bbbd442SRobert Mustacchi  */
11*6bbbd442SRobert Mustacchi 
12*6bbbd442SRobert Mustacchi /*
13*6bbbd442SRobert Mustacchi  * Copyright 2024 Oxide Computer Company
14*6bbbd442SRobert Mustacchi  */
15*6bbbd442SRobert Mustacchi 
16*6bbbd442SRobert Mustacchi /*
17*6bbbd442SRobert Mustacchi  * Intel I225/226 Ethernet Driver
18*6bbbd442SRobert Mustacchi  * ------------------------------
19*6bbbd442SRobert Mustacchi  *
20*6bbbd442SRobert Mustacchi  * This driver implements support for the Intel I225 and I226 Ethernet
21*6bbbd442SRobert Mustacchi  * controllers which support up to 2.5 GbE and generally only supports BASE-T
22*6bbbd442SRobert Mustacchi  * copper phys. This device is yet another variant on the venerable Intel 1 GbE
23*6bbbd442SRobert Mustacchi  * devices that are found in e1000g(4D) and igb(4D). This is its own driver in
24*6bbbd442SRobert Mustacchi  * part because that's how Intel did things and refactored their common code
25*6bbbd442SRobert Mustacchi  * which we import and is found in the 'core' directory.
26*6bbbd442SRobert Mustacchi  *
27*6bbbd442SRobert Mustacchi  * There is not a good datasheet for the MAC that we've been able to find for
28*6bbbd442SRobert Mustacchi  * this part. It's not clear that Intel even has a doc for this in their
29*6bbbd442SRobert Mustacchi  * Resource and Design Center. The primary datasheet documents the NVM and other
30*6bbbd442SRobert Mustacchi  * parts of it, but not the software interface. Based on observations from the
31*6bbbd442SRobert Mustacchi  * common code we describe this as somewhat of an evolution of the I217 and
32*6bbbd442SRobert Mustacchi  * I210, with less features than the I210, which comes from the server world
33*6bbbd442SRobert Mustacchi  * (which ws itself a more stripped down I350).
34*6bbbd442SRobert Mustacchi  *
35*6bbbd442SRobert Mustacchi  * The result of all this is us trying to focus on what we know about this part
36*6bbbd442SRobert Mustacchi  * and making some assumptions along the way. This includes things like:
37*6bbbd442SRobert Mustacchi  *
38*6bbbd442SRobert Mustacchi  * 1) We believe that the device only supports up to 4 RX and TX queues.
39*6bbbd442SRobert Mustacchi  * 2) There is only one TX context for each TX queue and it is mapped to the
40*6bbbd442SRobert Mustacchi  * queue.
41*6bbbd442SRobert Mustacchi  * 3) There is no support for the head writeback modes that we've found.
42*6bbbd442SRobert Mustacchi  * 4) This does otherwise support both the MSI-X and MSI/INTx interrupt
43*6bbbd442SRobert Mustacchi  * management which are shaped very differently in the device.
44*6bbbd442SRobert Mustacchi  * 5) The 2500BASE-T PHY support is unique, but the other PHY settings are
45*6bbbd442SRobert Mustacchi  * roughly the same as far as we can tell.
46*6bbbd442SRobert Mustacchi  *
47*6bbbd442SRobert Mustacchi  * There are certainly more differences than the points up above, but the above
48*6bbbd442SRobert Mustacchi  * are ones that generally influence our design.
49*6bbbd442SRobert Mustacchi  *
50*6bbbd442SRobert Mustacchi  * ------------
51*6bbbd442SRobert Mustacchi  * Organization
52*6bbbd442SRobert Mustacchi  * ------------
53*6bbbd442SRobert Mustacchi  *
54*6bbbd442SRobert Mustacchi  * This driver is first broken into two different pieces. There is the 'core'
55*6bbbd442SRobert Mustacchi  * code which we import from Intel via FreeBSD. All of these sources are in the
56*6bbbd442SRobert Mustacchi  * 'uts/common/io/igc/core' directory and we try our hardest to avoid modifying
57*6bbbd442SRobert Mustacchi  * them (hence the smatch gags). The core code can be thought of as abstracting
58*6bbbd442SRobert Mustacchi  * the MAC, NVM, and PHY across different chipsets (right now it's all the I225)
59*6bbbd442SRobert Mustacchi  * and providing us with a series of library calls that we can do to manage the
60*6bbbd442SRobert Mustacchi  * chip.
61*6bbbd442SRobert Mustacchi  *
62*6bbbd442SRobert Mustacchi  * The remaining files that sit alongside this one implement different portions
63*6bbbd442SRobert Mustacchi  * of functionality related to the device. In particular:
64*6bbbd442SRobert Mustacchi  *
65*6bbbd442SRobert Mustacchi  *  igc.[ch]:		This is the main entry point for the driver and the
66*6bbbd442SRobert Mustacchi  *			source of this block comment. It implements all of the
67*6bbbd442SRobert Mustacchi  *			basic DDI entry points: attach and detach, interrupts,
68*6bbbd442SRobert Mustacchi  *			PCI config space and register set up and tear down.
69*6bbbd442SRobert Mustacchi  *
70*6bbbd442SRobert Mustacchi  *			The header file contains all of the structure
71*6bbbd442SRobert Mustacchi  *			definitions that we use throughout this and the basic
72*6bbbd442SRobert Mustacchi  *			constants we use for sizing.
73*6bbbd442SRobert Mustacchi  *
74*6bbbd442SRobert Mustacchi  *  igc_gld.c		This file implements all of the major GLDv3 required
75*6bbbd442SRobert Mustacchi  *			entry points that are found in mac(9E). The guts of the
76*6bbbd442SRobert Mustacchi  *			actual I/O are in igc_ring.c, but getting and setting
77*6bbbd442SRobert Mustacchi  *			all of the various MAC properties and other bits is
78*6bbbd442SRobert Mustacchi  *			here.
79*6bbbd442SRobert Mustacchi  *
80*6bbbd442SRobert Mustacchi  *  igc_osdep.[ch]	The osdep (OS dependent) files, are used to define and
81*6bbbd442SRobert Mustacchi  *			implement the functionality required by the common code.
82*6bbbd442SRobert Mustacchi  *			igc_osdep.h is included in the build of each file.
83*6bbbd442SRobert Mustacchi  *
84*6bbbd442SRobert Mustacchi  *			We have a second use for igc_osdep.h which is where we
85*6bbbd442SRobert Mustacchi  *			put missing hardware definitions that apply. This is for
86*6bbbd442SRobert Mustacchi  *			cases where the core code doesn't have it and it should
87*6bbbd442SRobert Mustacchi  *			really live in igc_defines.h or igc_regs.h, but we keep
88*6bbbd442SRobert Mustacchi  *			it here to avoid modifying those.
89*6bbbd442SRobert Mustacchi  *
90*6bbbd442SRobert Mustacchi  *  igc_ring.c		This implements the core I/O routines of the device
91*6bbbd442SRobert Mustacchi  *			driver, starting with the descriptor ring setup and tear
92*6bbbd442SRobert Mustacchi  *			down as well as DMA, descriptor ring, and per-frame
93*6bbbd442SRobert Mustacchi  *			memory. It also implements all of the primary logic for
94*6bbbd442SRobert Mustacchi  *			transmitting and receiving frames.
95*6bbbd442SRobert Mustacchi  *
96*6bbbd442SRobert Mustacchi  *  igc_stat.c		This file deals with kstat creation and destruction as
97*6bbbd442SRobert Mustacchi  *			well as reading and fetching all of the registers that
98*6bbbd442SRobert Mustacchi  *			exist in hardware.
99*6bbbd442SRobert Mustacchi  *
100*6bbbd442SRobert Mustacchi  * There are a few primary data structures to be aware of. Their relationships
101*6bbbd442SRobert Mustacchi  * are shown in the following image and then described. Note, each structure has
102*6bbbd442SRobert Mustacchi  * many more fields than those pictured:
103*6bbbd442SRobert Mustacchi  *
104*6bbbd442SRobert Mustacchi  * +---------------+
105*6bbbd442SRobert Mustacchi  * | dev_info_t *  |
106*6bbbd442SRobert Mustacchi  * |              -|-+
107*6bbbd442SRobert Mustacchi  * | private data  | |
108*6bbbd442SRobert Mustacchi  * +---------------+ v
109*6bbbd442SRobert Mustacchi  *   +------------------------------+        +---------------------+
110*6bbbd442SRobert Mustacchi  *   | igc_t                        |        | igc_addr_t          |
111*6bbbd442SRobert Mustacchi  *   | per-instance primary         |  +---->|                     |
112*6bbbd442SRobert Mustacchi  *   | structure                    |  |+--->| Notes a MAC address | ...
113*6bbbd442SRobert Mustacchi  *   |                              |  ||    | stored in hardware  |
114*6bbbd442SRobert Mustacchi  *   | igc_addr_t    *igc_ucast    -|--+|    +---------------------+
115*6bbbd442SRobert Mustacchi  *   | igc_addr_t    *igc_mcast    -|---+      +---------------------------+
116*6bbbd442SRobert Mustacchi  *   | struct igc_hw *igc_hw       -|--------->| struct igc_hw (core code) |
117*6bbbd442SRobert Mustacchi  *   | igc_tx_ring_t *igc_tx_rings -|--+       |                           |
118*6bbbd442SRobert Mustacchi  *   | igc_rx_ring_t *igc_rx_rings -|--|---+   | igc_mac_info mac          |
119*6bbbd442SRobert Mustacchi  *   +------------------------------+  |   |   | igc_fc_info  fc           |
120*6bbbd442SRobert Mustacchi  *                                     |   |   | igc_phy_info phy          |
121*6bbbd442SRobert Mustacchi  *  +----------------------------------+   |   | igc_nvm_info nvm          |
122*6bbbd442SRobert Mustacchi  *  |                                      v   +---------------------------+
123*6bbbd442SRobert Mustacchi  *  |  +--------------------------------------+
124*6bbbd442SRobert Mustacchi  *  |  | igc_rx_ring_t                        |
125*6bbbd442SRobert Mustacchi  *  |  |                                      |
126*6bbbd442SRobert Mustacchi  *  |  | igc_adv_rx_desc *irr_ring         ---|--> rx hw descriptor ring
127*6bbbd442SRobert Mustacchi  *  |  | uint32_t        irr_next          ---|--> next entry to look for data
128*6bbbd442SRobert Mustacchi  *  |  | igc_rx_buffer_t **irr_work_list   ---|--> corresponds to ring entries
129*6bbbd442SRobert Mustacchi  *  |  | uint32_t        irr_nfree         ---|--> number of free list entries
130*6bbbd442SRobert Mustacchi  *  |  | igc_rx_buffer_t **irr_free_list   ---|--> set of buffers free for bind
131*6bbbd442SRobert Mustacchi  *  |  | igc_rx_buffer_t *irr_arena        ---|-+> array of all rx buffers
132*6bbbd442SRobert Mustacchi  *  |  +--------------------------------------+ |
133*6bbbd442SRobert Mustacchi  *  |                                           |
134*6bbbd442SRobert Mustacchi  *  |          +----------------------------+   |
135*6bbbd442SRobert Mustacchi  *  |          | igc_rx_buffer_t            |<--+
136*6bbbd442SRobert Mustacchi  *  |          |                            |
137*6bbbd442SRobert Mustacchi  *  |          | mblk_t            *igb_mp -|---> mblk_t for rx buffer
138*6bbbd442SRobert Mustacchi  *  |          | igc_dma_buffer_t  irb_dma -|---> DMA memory for rx buffer
139*6bbbd442SRobert Mustacchi  *  |          +----------------------------+
140*6bbbd442SRobert Mustacchi  *  |
141*6bbbd442SRobert Mustacchi  *  |   +------------------------------------+
142*6bbbd442SRobert Mustacchi  *  +-->| igc_tx_ring_t                      |
143*6bbbd442SRobert Mustacchi  *      |                                    |
144*6bbbd442SRobert Mustacchi  *      | icc_adv_tx_desc   *itr_ring      --|--> tx hw descriptor ring
145*6bbbd442SRobert Mustacchi  *      | uin32_t           itr_ring_head  --|--> next descriptor to recycle
146*6bbbd442SRobert Mustacchi  *      | uin32_t           itr_ring_fail  --|--> next descriptor to place
147*6bbbd442SRobert Mustacchi  *      | uin32_t           itr_ring_free  --|--> free descriptors in ring
148*6bbbd442SRobert Mustacchi  *      | igc_tx_buffer_t   **itr_work_list  |--> corresponds to ring entries
149*6bbbd442SRobert Mustacchi  *      | list_t            itr_free_list  --|--> available tx buffers
150*6bbbd442SRobert Mustacchi  *      | igc_tx_buffer_t   *itr_arena     --|-+> array of all tx buffers
151*6bbbd442SRobert Mustacchi  *      +------------------------------------+ |
152*6bbbd442SRobert Mustacchi  *                                             |
153*6bbbd442SRobert Mustacchi  *        +---------------------------------+  |
154*6bbbd442SRobert Mustacchi  *        | igc_tx_buffer_t                 |<-+
155*6bbbd442SRobert Mustacchi  *        |                                 |
156*6bbbd442SRobert Mustacchi  *        | mblk_t           *itb_mp      --|--> mblk to tx (only in first)
157*6bbbd442SRobert Mustacchi  *        | igc_dma_buffer_t itb_dma      --|--> tx DMA buffer for copy
158*6bbbd442SRobert Mustacchi  *        | ddi_dma_handle_t itb_bind_hdl --|--> DMA handle for bind
159*6bbbd442SRobert Mustacchi  *        +---------------------------------+
160*6bbbd442SRobert Mustacchi  *
161*6bbbd442SRobert Mustacchi  * igc_t		This is the primary data structure that exists for each
162*6bbbd442SRobert Mustacchi  *			instance of the driver. There is generally a 1:1
163*6bbbd442SRobert Mustacchi  *			relationship between a physical port, an instance of the
164*6bbbd442SRobert Mustacchi  *			driver, and a PCI function. This structure provides
165*6bbbd442SRobert Mustacchi  *			access to the device's registers and it embeds the
166*6bbbd442SRobert Mustacchi  *			common code's struct igc_hw.
167*6bbbd442SRobert Mustacchi  *
168*6bbbd442SRobert Mustacchi  * struct igc_hw	This structure is used by the core code and it contains
169*6bbbd442SRobert Mustacchi  *			information related to the MAC, PHY, NVM, and related
170*6bbbd442SRobert Mustacchi  *			information that the device uses. In general, this
171*6bbbd442SRobert Mustacchi  *			structure is used when performing API calls to the
172*6bbbd442SRobert Mustacchi  *			common code. The common code calls back into us in the
173*6bbbd442SRobert Mustacchi  *			igc_osdep.c interfaces.
174*6bbbd442SRobert Mustacchi  *
175*6bbbd442SRobert Mustacchi  * igc_tx_ring_t	This structure represents a single transmit ring in
176*6bbbd442SRobert Mustacchi  *			hardware, its associated software state, and
177*6bbbd442SRobert Mustacchi  *			miscellaneous data like statistics, MAC handles, etc.
178*6bbbd442SRobert Mustacchi  *			See the 'TX Data Path Design' section for more
179*6bbbd442SRobert Mustacchi  *			information.
180*6bbbd442SRobert Mustacchi  *
181*6bbbd442SRobert Mustacchi  * igc_rx_ring_t	This is the receive variant of a ring. It represents and
182*6bbbd442SRobert Mustacchi  *			tracks the hardware state along with all our metadata.
183*6bbbd442SRobert Mustacchi  *			One of these exists for each receive ring that we've
184*6bbbd442SRobert Mustacchi  *			enabled (currently one). See the 'RX Data Path Design'
185*6bbbd442SRobert Mustacchi  *			section for more information.
186*6bbbd442SRobert Mustacchi  *
187*6bbbd442SRobert Mustacchi  * igc_tx_buffer_t	This represents a single tx buffer in the driver. A tx
188*6bbbd442SRobert Mustacchi  *			buffer contains DMA based storage that it can use to
189*6bbbd442SRobert Mustacchi  *			transmit a packet and contains a second DMA handle that
190*6bbbd442SRobert Mustacchi  *			can be used to bind a specific mblk_t to it. tx buffers
191*6bbbd442SRobert Mustacchi  *			are capped at the current page size and can be smaller
192*6bbbd442SRobert Mustacchi  *			if the maximum packet size is smaller. A 1500 byte MTU
193*6bbbd442SRobert Mustacchi  *			will end up with a 2 KiB buffer due to the device's
194*6bbbd442SRobert Mustacchi  *			internal alignment requirements.
195*6bbbd442SRobert Mustacchi  *
196*6bbbd442SRobert Mustacchi  * igc_rx_buffer_t	This represents a single rx buffer in the driver. These
197*6bbbd442SRobert Mustacchi  *			buffers may be loaned up to MAC and then returned to us
198*6bbbd442SRobert Mustacchi  *			later. They contain a single DMA buffer which right now
199*6bbbd442SRobert Mustacchi  *			is a single contiguous buffer that fits the maximum
200*6bbbd442SRobert Mustacchi  *			packet size. Each buffer has a corresponding mblk_t that
201*6bbbd442SRobert Mustacchi  *			it is mapped to.
202*6bbbd442SRobert Mustacchi  *
203*6bbbd442SRobert Mustacchi  * igc_dma_buffer_t	This represent a DMA buffer in the system. DMA buffers
204*6bbbd442SRobert Mustacchi  *			are used for transmit buffers, receive buffers, or
205*6bbbd442SRobert Mustacchi  *			various ring descriptor entries. The DMA buffer
206*6bbbd442SRobert Mustacchi  *			structure is not inherently limited to a specific number
207*6bbbd442SRobert Mustacchi  *			of cookies. It is always mapped in our virtual address
208*6bbbd442SRobert Mustacchi  *			space and encapsulates the various DDI functions. In
209*6bbbd442SRobert Mustacchi  *			general, one expects to interface with the idb_va member
210*6bbbd442SRobert Mustacchi  *			when needing to access the memory, the idb_size member
211*6bbbd442SRobert Mustacchi  *			when wanting to understand how much memory is in the
212*6bbbd442SRobert Mustacchi  *			buffer, and the idb_hdl member when needing to access
213*6bbbd442SRobert Mustacchi  *			the DMA cookies.
214*6bbbd442SRobert Mustacchi  *
215*6bbbd442SRobert Mustacchi  * igc_addr_t		This represents a 48-bit Ethernet MAC address slot in
216*6bbbd442SRobert Mustacchi  *			the hardware that may or may not be used at any given
217*6bbbd442SRobert Mustacchi  *			point in time.
218*6bbbd442SRobert Mustacchi  *
219*6bbbd442SRobert Mustacchi  * --------------------
220*6bbbd442SRobert Mustacchi  * Rings and Interrupts
221*6bbbd442SRobert Mustacchi  * --------------------
222*6bbbd442SRobert Mustacchi  *
223*6bbbd442SRobert Mustacchi  * The I225/226 controller like the I210 supports up to 4 rx and tx rings. Due
224*6bbbd442SRobert Mustacchi  * to the long history of this controller and its tradition from the e1000g/igb
225*6bbbd442SRobert Mustacchi  * days and much older parts like the 8254x series, it has two entirely
226*6bbbd442SRobert Mustacchi  * different sets of interrupt modes. One where MSI-X is used and a mode where
227*6bbbd442SRobert Mustacchi  * a single MSI or INTx interrupt is used. Currently the driver only supports
228*6bbbd442SRobert Mustacchi  * the MSI-X mode as that gives us more flexibility and due to the fact that the
229*6bbbd442SRobert Mustacchi  * interrupt modes and register handling are different, reduces the complexity
230*6bbbd442SRobert Mustacchi  * in the driver.
231*6bbbd442SRobert Mustacchi  *
232*6bbbd442SRobert Mustacchi  * The hardware uses its IVAR registers to map specific queues to interrupts.
233*6bbbd442SRobert Mustacchi  * Each rx queue and tx queue is mapped to a specific bit position in the IVAR
234*6bbbd442SRobert Mustacchi  * and there is an additional IVAR register for miscellaneous causes like link
235*6bbbd442SRobert Mustacchi  * state changes. While the IVAR register allows for several bits for MSI-X
236*6bbbd442SRobert Mustacchi  * entries, for the most part, it appears that there is only support for values
237*6bbbd442SRobert Mustacchi  * in the range [0, 4] based on the I210 which we believe extends to the I225/6.
238*6bbbd442SRobert Mustacchi  *
239*6bbbd442SRobert Mustacchi  * MSI-X mode causes the device's various interrupt registers to be split into
240*6bbbd442SRobert Mustacchi  * two groups the 'legacy' and 'extended' (sometimes called advanced) ones. The
241*6bbbd442SRobert Mustacchi  * extended ones all start with 'E'. When in MSI-X mode, the EICR (cause), EICS
242*6bbbd442SRobert Mustacchi  * (cause set), EIAC (auto-clear), EIMS (mask set) registers all operate with
243*6bbbd442SRobert Mustacchi  * indexes that refer to the MSI-X. The primary way to temporarily disable
244*6bbbd442SRobert Mustacchi  * interrupts for polling is to remove the given MSI-X from the auto-clear set
245*6bbbd442SRobert Mustacchi  * and to clear it from the enabled mask set.
246*6bbbd442SRobert Mustacchi  *
247*6bbbd442SRobert Mustacchi  * The implication of all of this is that we can only really disable interrupts
248*6bbbd442SRobert Mustacchi  * for polling on a per-MSI-X basis. This generally means that the design for
249*6bbbd442SRobert Mustacchi  * interrupts and rings is that all the tx rings and the link state change
250*6bbbd442SRobert Mustacchi  * events share interrupt 0, while rx rings use interrupts 1-4. Because the x86
251*6bbbd442SRobert Mustacchi  * 'apix' modules end up defaulting to two interrupts to a driver, we end up
252*6bbbd442SRobert Mustacchi  * only supporting a single rx and tx ring for the time being, though the driver
253*6bbbd442SRobert Mustacchi  * is phrased in terms of a variable number of such rings.
254*6bbbd442SRobert Mustacchi  *
255*6bbbd442SRobert Mustacchi  * -------------------
256*6bbbd442SRobert Mustacchi  * RX Data Path Design
257*6bbbd442SRobert Mustacchi  * -------------------
258*6bbbd442SRobert Mustacchi  *
259*6bbbd442SRobert Mustacchi  * The rx data path is based around allocating a fixed number of receive buffers
260*6bbbd442SRobert Mustacchi  * for each ring. We have two goals in the allocation buffer and ring design:
261*6bbbd442SRobert Mustacchi  *
262*6bbbd442SRobert Mustacchi  * 1) We want to make sure that the ring is always full of valid descriptors for
263*6bbbd442SRobert Mustacchi  *    rx to prevent stalls. One implication of this is that we will always
264*6bbbd442SRobert Mustacchi  *    refill a received buffer with a new one and notify the hardware that the
265*6bbbd442SRobert Mustacchi  *    buffer is usable again.
266*6bbbd442SRobert Mustacchi  *
267*6bbbd442SRobert Mustacchi  * 2) We would prefer to not have to copy received memory and instead bind the
268*6bbbd442SRobert Mustacchi  *    DMA memory directly into an mblk_t.
269*6bbbd442SRobert Mustacchi  *
270*6bbbd442SRobert Mustacchi  * To satisfy (1) we need to allocate at least as many rx buffers as there are
271*6bbbd442SRobert Mustacchi  * ring entries. The ring is sized by default to 512 entries, which is a
272*6bbbd442SRobert Mustacchi  * somewhat arbitrary, but common, size. We then say that we want to be able to
273*6bbbd442SRobert Mustacchi  * loan half of our entries up the stack at any given time. This leads to us
274*6bbbd442SRobert Mustacchi  * allocating 1.5x the ring size rx buffers.
275*6bbbd442SRobert Mustacchi  *
276*6bbbd442SRobert Mustacchi  * All of the rx buffers are stored in the irr_arena array. They are then split
277*6bbbd442SRobert Mustacchi  * between the free list and the ring's work list. The work list is an array
278*6bbbd442SRobert Mustacchi  * that is a 1:1 mapping to a location in the descriptor ring. That is index 4
279*6bbbd442SRobert Mustacchi  * of the work list (irr_work_list[4]) corresponds to index 4 of the descriptor
280*6bbbd442SRobert Mustacchi  * ring (irr_ring[4]). However, this may refer to any of the rx descriptors that
281*6bbbd442SRobert Mustacchi  * is in the irr_arena. When we start up the ring, the first ring size entries
282*6bbbd442SRobert Mustacchi  * are all inserted into the work list and then the remaining entries are
283*6bbbd442SRobert Mustacchi  * inserted into the free list.
284*6bbbd442SRobert Mustacchi  *
285*6bbbd442SRobert Mustacchi  * Entries that are in the work list are always given to hardware. We track the
286*6bbbd442SRobert Mustacchi  * next place for us to scan for received packets through the 'irr_next' index
287*6bbbd442SRobert Mustacchi  * into the descriptor ring. When an interrupt fires, we start at irr_next and
288*6bbbd442SRobert Mustacchi  * iterate through the descriptor ring continuing while we find valid, received
289*6bbbd442SRobert Mustacchi  * packets. When we process a packet, we look at two things to consider whether
290*6bbbd442SRobert Mustacchi  * we bind it or copy it to a new mblk_t. The first piece is the received
291*6bbbd442SRobert Mustacchi  * packet's length. If the packet is small, there is not much value in binding
292*6bbbd442SRobert Mustacchi  * it and instead we just allocate and copy a new buffer for the packet.
293*6bbbd442SRobert Mustacchi  *
294*6bbbd442SRobert Mustacchi  * The second is if there are free rx descriptors. To keep goal (1) valid, we
295*6bbbd442SRobert Mustacchi  * only will loan a packet up if there is an entry on the free list that can
296*6bbbd442SRobert Mustacchi  * replace the rx buffer, as otherwise we'd want to make sure we don't stall the
297*6bbbd442SRobert Mustacchi  * ring. If an rx buffer is loaned, the entry on the free list takes its place
298*6bbbd442SRobert Mustacchi  * in the descriptor ring and when the networking stack is finally done with the
299*6bbbd442SRobert Mustacchi  * mblk_t, it'll be returned to us as part of the freemsg()/freeb() destructor.
300*6bbbd442SRobert Mustacchi  * This lifetime is illustrated in the following diagram:
301*6bbbd442SRobert Mustacchi  *
302*6bbbd442SRobert Mustacchi  *
303*6bbbd442SRobert Mustacchi  *    +-------------+                        +-----------+
304*6bbbd442SRobert Mustacchi  *    | Work List   |<---*-------------------| Free List |
305*6bbbd442SRobert Mustacchi  *    | Owned by HW |    . . Used to replace |   Idle    |
306*6bbbd442SRobert Mustacchi  *    +-------------+        loaned buffers  +-----------+
307*6bbbd442SRobert Mustacchi  *      |     | ^                                  ^
308*6bbbd442SRobert Mustacchi  *      |     | . . . Reused if a                  |
309*6bbbd442SRobert Mustacchi  *      |     +-+     copy is done                 . . . Returned to driver via
310*6bbbd442SRobert Mustacchi  *      |                                          |     freemsg() which calls
311*6bbbd442SRobert Mustacchi  *      |                                          |     igc_rx_recycle().
312*6bbbd442SRobert Mustacchi  *      v                                          |
313*6bbbd442SRobert Mustacchi  *    +-------------------+                        |
314*6bbbd442SRobert Mustacchi  *    | Loaned            |------------------------+
315*6bbbd442SRobert Mustacchi  *    | Owned by netstack |
316*6bbbd442SRobert Mustacchi  *    +-------------------+
317*6bbbd442SRobert Mustacchi  *
318*6bbbd442SRobert Mustacchi  * Currently the rx data path uses rx buffers that are equal to the maximum size
319*6bbbd442SRobert Mustacchi  * of a packet (rounded up based on hardware's 1 KiB alignment requirement).
320*6bbbd442SRobert Mustacchi  * This was mostly done for initial simplicity, though it comes at a memory
321*6bbbd442SRobert Mustacchi  * cost. It is possible to design this to be more like the tx subsystem where we
322*6bbbd442SRobert Mustacchi  * use fixed page size buffers and just cons up an mblk_t chain with b_cont
323*6bbbd442SRobert Mustacchi  * pointers.
324*6bbbd442SRobert Mustacchi  *
325*6bbbd442SRobert Mustacchi  * -------------------
326*6bbbd442SRobert Mustacchi  * TX Data Path Design
327*6bbbd442SRobert Mustacchi  * -------------------
328*6bbbd442SRobert Mustacchi  *
329*6bbbd442SRobert Mustacchi  * The tx data path is a bit different in design from the rx data path. When the
330*6bbbd442SRobert Mustacchi  * system wants to tx data there are two fundamental building blocks that we
331*6bbbd442SRobert Mustacchi  * use, both of which leverage the igc_tx_buffer_t:
332*6bbbd442SRobert Mustacchi  *
333*6bbbd442SRobert Mustacchi  * 1) We use the DMA memory that is allocated with the buffer and copy the
334*6bbbd442SRobert Mustacchi  *    mblk_t data into it. This is used when we have small mblk_t's.
335*6bbbd442SRobert Mustacchi  *
336*6bbbd442SRobert Mustacchi  * 2) We utilize the DMA handle that is in the tx buffer (but not the buffer's
337*6bbbd442SRobert Mustacchi  *    DMA memory) to perform DMA binding. This can result in multiple cookies
338*6bbbd442SRobert Mustacchi  *    and therefore descriptors mapping to the single buffer.
339*6bbbd442SRobert Mustacchi  *
340*6bbbd442SRobert Mustacchi  * Because a given tx buffer may end up using more than one descriptor and we
341*6bbbd442SRobert Mustacchi  * have to account for transmit context descriptors, which are used for
342*6bbbd442SRobert Mustacchi  * indicating checksum and segmentation offloads, we end up only allocating a
343*6bbbd442SRobert Mustacchi  * number of transmit buffers equal to the ring size. In addition, the tx data
344*6bbbd442SRobert Mustacchi  * buffer's maximum size is capped at the size of a single page. This is done
345*6bbbd442SRobert Mustacchi  * because we often aren't going to be copying and if we are, we don't need that
346*6bbbd442SRobert Mustacchi  * much more memory. The actual size may be smaller depending on the MTU.
347*6bbbd442SRobert Mustacchi  *
348*6bbbd442SRobert Mustacchi  * The tx descriptor ring is used in a bit of a different way. While part of the
349*6bbbd442SRobert Mustacchi  * reason for this is that we are filling it based on the stack's demands and
350*6bbbd442SRobert Mustacchi  * therefore only need to fill in descriptors when there's a need, the second
351*6bbbd442SRobert Mustacchi  * reason is because of how the hardware reports back events. There are two
352*6bbbd442SRobert Mustacchi  * major kinds of descriptors that can be entered into the ring. There are the
353*6bbbd442SRobert Mustacchi  * aforementioned context descriptors and then data descriptors. While data
354*6bbbd442SRobert Mustacchi  * descriptors support an interrupt on completion, context descriptors do not.
355*6bbbd442SRobert Mustacchi  *
356*6bbbd442SRobert Mustacchi  * When an mblk_t comes in to be transmitted, we walk all of the mblk_t's
357*6bbbd442SRobert Mustacchi  * associated with it via the b_cont pointer. For each one, we look at the size
358*6bbbd442SRobert Mustacchi  * of the data and determine whether or not to perform DMA binding or to copy it
359*6bbbd442SRobert Mustacchi  * into the current tx buffer. A given tx buffer can be used to copy multiple
360*6bbbd442SRobert Mustacchi  * different mblk_t's. Imagine a pathological case where we had a 500 byte
361*6bbbd442SRobert Mustacchi  * packet split into 125 byte chunks, this would end up using a single tx data
362*6bbbd442SRobert Mustacchi  * buffer.  However, if you imagine a large chunk of TCP data, this may be
363*6bbbd442SRobert Mustacchi  * spread across several mblk_t's so we may end up leveraging multiple tx data
364*6bbbd442SRobert Mustacchi  * buffers.
365*6bbbd442SRobert Mustacchi  *
366*6bbbd442SRobert Mustacchi  * The transmit buffers that are available are stored on a free list. This is
367*6bbbd442SRobert Mustacchi  * managed as a list_t as we end up needing to often track groups of descriptors
368*6bbbd442SRobert Mustacchi  * to allocate and free across packet transmit and recycling. We don't count the
369*6bbbd442SRobert Mustacchi  * number of transmit buffers that are free per se, but it generally tracks the
370*6bbbd442SRobert Mustacchi  * number of free descriptors which do track as in the worst case there is a 1:1
371*6bbbd442SRobert Mustacchi  * relationship between buffers and descriptors and more generally it's 1:n,
372*6bbbd442SRobert Mustacchi  * that is there are multiple descriptors used for a single buffer.
373*6bbbd442SRobert Mustacchi  *
374*6bbbd442SRobert Mustacchi  * The transmit ring is managed through a combination of three integers, the
375*6bbbd442SRobert Mustacchi  * itr_ring_head, the itr_ring_tail, and the itr_ring_free. The ring's tail
376*6bbbd442SRobert Mustacchi  * represents the place where the driver will place new data to transmit. The
377*6bbbd442SRobert Mustacchi  * ring's head represents the first place that we should check for a packet's
378*6bbbd442SRobert Mustacchi  * completion when we're performing recycling (the act of acknowledging what
379*6bbbd442SRobert Mustacchi  * hardware has processed internal to the driver) due to a tx interrupt or
380*6bbbd442SRobert Mustacchi  * manual recycling in the transmit path.
381*6bbbd442SRobert Mustacchi  *
382*6bbbd442SRobert Mustacchi  * When placing a packet as a series of descriptor rings we'll end up doing the
383*6bbbd442SRobert Mustacchi  * following:
384*6bbbd442SRobert Mustacchi  *
385*6bbbd442SRobert Mustacchi  * 1) First we determine how to map each mblk_t as mentioned above.
386*6bbbd442SRobert Mustacchi  * 2) This will then be turned into descriptors in the ring. Each tx data buffer
387*6bbbd442SRobert Mustacchi  *    that is used is placed in the itr_work_list at the corresponding index
388*6bbbd442SRobert Mustacchi  *    that they are used in the ring. There is one special case here, if a
389*6bbbd442SRobert Mustacchi  *    context descriptor is used, the first transmit buffer will refer to the
390*6bbbd442SRobert Mustacchi  *    context descriptor's entry (which always comes before data).
391*6bbbd442SRobert Mustacchi  * 3) We'll ensure that there are enough descriptors for this packet to fit into
392*6bbbd442SRobert Mustacchi  *    the ring or if it would exceed our mandatory gap threshold. If so, then
393*6bbbd442SRobert Mustacchi  *    we'll undo all the work we just did and return the mblk_t to MAC and
394*6bbbd442SRobert Mustacchi  *    indicate that the ring is blocked. MAC will be notified later when we free
395*6bbbd442SRobert Mustacchi  *    up transmit descriptors.
396*6bbbd442SRobert Mustacchi  * 4) In the first transmit data buffer we'll store both the mblk_t and then
397*6bbbd442SRobert Mustacchi  *    we'll store what the index of the last descriptor that's used is. This is
398*6bbbd442SRobert Mustacchi  *    important for recycling. We also indicate that the last descriptor should
399*6bbbd442SRobert Mustacchi  *    be the one that reports its status on interrupt completion.
400*6bbbd442SRobert Mustacchi  * 5) We'll notify hardware that there is data for it to transmit by writing to
401*6bbbd442SRobert Mustacchi  *    the ring's tail pointer.
402*6bbbd442SRobert Mustacchi  *
403*6bbbd442SRobert Mustacchi  * This all works reasonably okay, except for the small problem of the bill,
404*6bbbd442SRobert Mustacchi  * which we pay off in the form of recycling. Recycling is going through the
405*6bbbd442SRobert Mustacchi  * ring and seeing which descriptors are free. While the transmit path described
406*6bbbd442SRobert Mustacchi  * above is the only path that is allowed to move the tail, the recycling path
407*6bbbd442SRobert Mustacchi  * is the only one that's allowed to adjust the head.
408*6bbbd442SRobert Mustacchi  *
409*6bbbd442SRobert Mustacchi  * When we perform recycling we look at the current head and its corresponding
410*6bbbd442SRobert Mustacchi  * tx buffer. There will always be a tx buffer in the same index in the
411*6bbbd442SRobert Mustacchi  * itr_work_list[] unless a serious programmer error has occurred. This buffer
412*6bbbd442SRobert Mustacchi  * will tell us what the index to check for completion is via its itb_last_desc
413*6bbbd442SRobert Mustacchi  * member (only valid when itb_first is set to true). If this index indicates
414*6bbbd442SRobert Mustacchi  * that it has been processed by hardware, then we process all entries between
415*6bbbd442SRobert Mustacchi  * here and there.
416*6bbbd442SRobert Mustacchi  *
417*6bbbd442SRobert Mustacchi  * When we process descriptors, we bunch up the transmit descriptors and
418*6bbbd442SRobert Mustacchi  * mblk_t's. We'll reset the transmit descriptor (freeing any DMA binding if
419*6bbbd442SRobert Mustacchi  * used) and append the mblk_t if it exists to be freed in one large
420*6bbbd442SRobert Mustacchi  * freemsgchain() at the end. The fact that we won't free any tx buffers
421*6bbbd442SRobert Mustacchi  * associated with a packet until they're all done is important. This makes
422*6bbbd442SRobert Mustacchi  * sure that any memory that we have bound from the mblk_t remains valid the
423*6bbbd442SRobert Mustacchi  * entire time.
424*6bbbd442SRobert Mustacchi  *
425*6bbbd442SRobert Mustacchi  * If we have freed enough descriptors as part of this to allow mac to send data
426*6bbbd442SRobert Mustacchi  * again, then once we have finished all processing and dropped the lock, we
427*6bbbd442SRobert Mustacchi  * will notify MAC.
428*6bbbd442SRobert Mustacchi  *
429*6bbbd442SRobert Mustacchi  * When we are processing descriptors here we try to avoid holding the itr_lock
430*6bbbd442SRobert Mustacchi  * except for the start and end of the process. This is an important way to
431*6bbbd442SRobert Mustacchi  * ensure that we don't block transmits. Because of this, there can only be one
432*6bbbd442SRobert Mustacchi  * thread performing a recycle at any given time between the interrupt path and
433*6bbbd442SRobert Mustacchi  * the transmit path trying to clean up. This is maintained using the
434*6bbbd442SRobert Mustacchi  * 'itr_recycle' boolean. If a recycle is already in progress then there's
435*6bbbd442SRobert Mustacchi  * generally not much reason to perform one simultaneously and so the caller
436*6bbbd442SRobert Mustacchi  * will just return. This is why the head (and thus returning descriptors) is
437*6bbbd442SRobert Mustacchi  * only used by the recycle path.
438*6bbbd442SRobert Mustacchi  *
439*6bbbd442SRobert Mustacchi  * -------
440*6bbbd442SRobert Mustacchi  * Locking
441*6bbbd442SRobert Mustacchi  * -------
442*6bbbd442SRobert Mustacchi  *
443*6bbbd442SRobert Mustacchi  * Mutexes exist on three different structures in the driver:
444*6bbbd442SRobert Mustacchi  *
445*6bbbd442SRobert Mustacchi  * 1) igc_t (igc_lock)
446*6bbbd442SRobert Mustacchi  * 2) igc_rx_ring_t (irr_lock, irr_free_lock)
447*6bbbd442SRobert Mustacchi  * 3) igc_tx_ring_t (itr_lock)
448*6bbbd442SRobert Mustacchi  *
449*6bbbd442SRobert Mustacchi  * The following rules hold for locking in the driver:
450*6bbbd442SRobert Mustacchi  *
451*6bbbd442SRobert Mustacchi  * 1) One should not hold locks for both the rx rings and tx rings at the same
452*6bbbd442SRobert Mustacchi  *    time. If this is required, please determine if it is absolutely necessary.
453*6bbbd442SRobert Mustacchi  * 2) You should always take the controller's lock ahead of any ring's locks.
454*6bbbd442SRobert Mustacchi  * 3) The general rx ring lock (irr_lock) should be taken ahead of the free list
455*6bbbd442SRobert Mustacchi  *    lock (irr_free_lock) if both are required.
456*6bbbd442SRobert Mustacchi  *
457*6bbbd442SRobert Mustacchi  * -------------------
458*6bbbd442SRobert Mustacchi  * Future Improvements
459*6bbbd442SRobert Mustacchi  * -------------------
460*6bbbd442SRobert Mustacchi  *
461*6bbbd442SRobert Mustacchi  * This driver was initially written with an eye towards getting something that
462*6bbbd442SRobert Mustacchi  * had broad use for folks with this hardware and not towards enabling every
463*6bbbd442SRobert Mustacchi  * feature immediately. Here are some areas that can be improved upon in the
464*6bbbd442SRobert Mustacchi  * driver.
465*6bbbd442SRobert Mustacchi  *
466*6bbbd442SRobert Mustacchi  *  - Multiple ring, RSS support: As the OS changes towards offering more
467*6bbbd442SRobert Mustacchi  *    interrupts or opting to participate in IRM, then you can more easily
468*6bbbd442SRobert Mustacchi  *    offer RSS and related features. This should likely show up as a single
469*6bbbd442SRobert Mustacchi  *    rx group with multiple rings and leverage the tx pseudo-group support.
470*6bbbd442SRobert Mustacchi  *
471*6bbbd442SRobert Mustacchi  *  - TCP segmentation offload support: Right now the driver does not support
472*6bbbd442SRobert Mustacchi  *    TSO. It'd potentially be a useful addition and help out folks. Fetching
473*6bbbd442SRobert Mustacchi  *    information for TSO is in the tx data path right now.
474*6bbbd442SRobert Mustacchi  *
475*6bbbd442SRobert Mustacchi  *  - FMA Support: Currently the driver does not rig up support for FMA.
476*6bbbd442SRobert Mustacchi  *    Participating in that and more generally being able to reset the device
477*6bbbd442SRobert Mustacchi  *    while it is operating in the face of fatal errors would be good.
478*6bbbd442SRobert Mustacchi  *
479*6bbbd442SRobert Mustacchi  *  - TX stall detection: Related to the above, carefully designing a tx stall
480*6bbbd442SRobert Mustacchi  *    detection and resetting the device when that happens would probably be
481*6bbbd442SRobert Mustacchi  *    useful.
482*6bbbd442SRobert Mustacchi  *
483*6bbbd442SRobert Mustacchi  *  - UFM support: Exposing the NVM and PBA (printed board assembly) through the
484*6bbbd442SRobert Mustacchi  *    UFM subsystem would be a good thing to do.
485*6bbbd442SRobert Mustacchi  *
486*6bbbd442SRobert Mustacchi  *  - Dynamic MTU changing: Right now the driver takes advantage of the
487*6bbbd442SRobert Mustacchi  *    simplification of not allowing the MTU to change once the device has been
488*6bbbd442SRobert Mustacchi  *    started. This isn't great, but it is far from the first (igb, e1000g,
489*6bbbd442SRobert Mustacchi  *    ixgbe, etc.) to do this. It would be nice if this was lifted.
490*6bbbd442SRobert Mustacchi  */
491*6bbbd442SRobert Mustacchi 
492*6bbbd442SRobert Mustacchi #include <sys/ddi.h>
493*6bbbd442SRobert Mustacchi #include <sys/sunddi.h>
494*6bbbd442SRobert Mustacchi #include <sys/conf.h>
495*6bbbd442SRobert Mustacchi #include <sys/devops.h>
496*6bbbd442SRobert Mustacchi #include <sys/modctl.h>
497*6bbbd442SRobert Mustacchi #include <sys/cmn_err.h>
498*6bbbd442SRobert Mustacchi #include <sys/pci.h>
499*6bbbd442SRobert Mustacchi #include <sys/sysmacros.h>
500*6bbbd442SRobert Mustacchi #include <sys/debug.h>
501*6bbbd442SRobert Mustacchi #include <sys/bitext.h>
502*6bbbd442SRobert Mustacchi 
503*6bbbd442SRobert Mustacchi #include "igc.h"
504*6bbbd442SRobert Mustacchi 
505*6bbbd442SRobert Mustacchi /*
506*6bbbd442SRobert Mustacchi  * The core code expects the igc_mcast_raw to be a uint8_t packed array. We use
507*6bbbd442SRobert Mustacchi  * the ether_addr_t to make this a little more explicit and easy to reason
508*6bbbd442SRobert Mustacchi  * about, but that means we are relying on this size.
509*6bbbd442SRobert Mustacchi  */
510*6bbbd442SRobert Mustacchi CTASSERT(sizeof (ether_addr_t) == 6);
511*6bbbd442SRobert Mustacchi 
512*6bbbd442SRobert Mustacchi uint32_t
igc_read32(igc_t * igc,uint32_t reg)513*6bbbd442SRobert Mustacchi igc_read32(igc_t *igc, uint32_t reg)
514*6bbbd442SRobert Mustacchi {
515*6bbbd442SRobert Mustacchi 	uint32_t *addr;
516*6bbbd442SRobert Mustacchi 	ASSERT3U(reg, <, igc->igc_regs_size);
517*6bbbd442SRobert Mustacchi 	addr = (uint32_t *)(igc->igc_regs_base + reg);
518*6bbbd442SRobert Mustacchi 	return (ddi_get32(igc->igc_regs_hdl, addr));
519*6bbbd442SRobert Mustacchi }
520*6bbbd442SRobert Mustacchi 
521*6bbbd442SRobert Mustacchi void
igc_write32(igc_t * igc,uint32_t reg,uint32_t val)522*6bbbd442SRobert Mustacchi igc_write32(igc_t *igc, uint32_t reg, uint32_t val)
523*6bbbd442SRobert Mustacchi {
524*6bbbd442SRobert Mustacchi 	uint32_t *addr;
525*6bbbd442SRobert Mustacchi 	ASSERT3U(reg, <, igc->igc_regs_size);
526*6bbbd442SRobert Mustacchi 	addr = (uint32_t *)(igc->igc_regs_base + reg);
527*6bbbd442SRobert Mustacchi 	ddi_put32(igc->igc_regs_hdl, addr, val);
528*6bbbd442SRobert Mustacchi }
529*6bbbd442SRobert Mustacchi 
530*6bbbd442SRobert Mustacchi /*
531*6bbbd442SRobert Mustacchi  * Ask hardware if the link is up and ready. Note, this assumes that we're on a
532*6bbbd442SRobert Mustacchi  * copper phy and short circuits a few things. See igb_is_link_up() for what
533*6bbbd442SRobert Mustacchi  * this looks like for non-copper PHYs if that ever becomes relevant.
534*6bbbd442SRobert Mustacchi  */
535*6bbbd442SRobert Mustacchi static bool
igc_link_up(igc_t * igc)536*6bbbd442SRobert Mustacchi igc_link_up(igc_t *igc)
537*6bbbd442SRobert Mustacchi {
538*6bbbd442SRobert Mustacchi 	ASSERT(MUTEX_HELD(&igc->igc_lock));
539*6bbbd442SRobert Mustacchi 
540*6bbbd442SRobert Mustacchi 	/*
541*6bbbd442SRobert Mustacchi 	 * When the link is up, then the core code will clear the value below.
542*6bbbd442SRobert Mustacchi 	 * Otherwise we likely need to assume it's down.
543*6bbbd442SRobert Mustacchi 	 */
544*6bbbd442SRobert Mustacchi 	(void) igc_check_for_link(&igc->igc_hw);
545*6bbbd442SRobert Mustacchi 	return (!igc->igc_hw.mac.get_link_status);
546*6bbbd442SRobert Mustacchi }
547*6bbbd442SRobert Mustacchi 
548*6bbbd442SRobert Mustacchi static void
igc_intr_lsc(igc_t * igc)549*6bbbd442SRobert Mustacchi igc_intr_lsc(igc_t *igc)
550*6bbbd442SRobert Mustacchi {
551*6bbbd442SRobert Mustacchi 	link_state_t orig_state, new_state;
552*6bbbd442SRobert Mustacchi 	uint32_t mmd_base;
553*6bbbd442SRobert Mustacchi 
554*6bbbd442SRobert Mustacchi 	mutex_enter(&igc->igc_lock);
555*6bbbd442SRobert Mustacchi 	orig_state = igc->igc_link_state;
556*6bbbd442SRobert Mustacchi 
557*6bbbd442SRobert Mustacchi 	/*
558*6bbbd442SRobert Mustacchi 	 * Always force a check of the link.
559*6bbbd442SRobert Mustacchi 	 */
560*6bbbd442SRobert Mustacchi 	igc->igc_hw.mac.get_link_status = true;
561*6bbbd442SRobert Mustacchi 	if (igc_link_up(igc)) {
562*6bbbd442SRobert Mustacchi 		uint16_t duplex = 0;
563*6bbbd442SRobert Mustacchi 
564*6bbbd442SRobert Mustacchi 		(void) igc_get_speed_and_duplex(&igc->igc_hw,
565*6bbbd442SRobert Mustacchi 		    &igc->igc_link_speed, &duplex);
566*6bbbd442SRobert Mustacchi 
567*6bbbd442SRobert Mustacchi 		switch (duplex) {
568*6bbbd442SRobert Mustacchi 		case HALF_DUPLEX:
569*6bbbd442SRobert Mustacchi 			igc->igc_link_duplex = LINK_DUPLEX_HALF;
570*6bbbd442SRobert Mustacchi 			break;
571*6bbbd442SRobert Mustacchi 		case FULL_DUPLEX:
572*6bbbd442SRobert Mustacchi 			igc->igc_link_duplex = LINK_DUPLEX_FULL;
573*6bbbd442SRobert Mustacchi 			break;
574*6bbbd442SRobert Mustacchi 		default:
575*6bbbd442SRobert Mustacchi 			igc->igc_link_duplex = LINK_DUPLEX_UNKNOWN;
576*6bbbd442SRobert Mustacchi 			break;
577*6bbbd442SRobert Mustacchi 		}
578*6bbbd442SRobert Mustacchi 		igc->igc_link_state = LINK_STATE_UP;
579*6bbbd442SRobert Mustacchi 	} else {
580*6bbbd442SRobert Mustacchi 		igc->igc_link_state = LINK_STATE_DOWN;
581*6bbbd442SRobert Mustacchi 		igc->igc_link_speed = 0;
582*6bbbd442SRobert Mustacchi 		igc->igc_link_duplex = LINK_DUPLEX_UNKNOWN;
583*6bbbd442SRobert Mustacchi 	}
584*6bbbd442SRobert Mustacchi 	new_state = igc->igc_link_state;
585*6bbbd442SRobert Mustacchi 
586*6bbbd442SRobert Mustacchi 	/*
587*6bbbd442SRobert Mustacchi 	 * Next, grab a bunch of information from the PHY for future us.
588*6bbbd442SRobert Mustacchi 	 */
589*6bbbd442SRobert Mustacchi 	(void) igc_read_phy_reg(&igc->igc_hw, PHY_CONTROL, &igc->igc_phy_ctrl);
590*6bbbd442SRobert Mustacchi 	(void) igc_read_phy_reg(&igc->igc_hw, PHY_STATUS, &igc->igc_phy_status);
591*6bbbd442SRobert Mustacchi 	(void) igc_read_phy_reg(&igc->igc_hw, PHY_AUTONEG_ADV,
592*6bbbd442SRobert Mustacchi 	    &igc->igc_phy_an_adv);
593*6bbbd442SRobert Mustacchi 	(void) igc_read_phy_reg(&igc->igc_hw, PHY_LP_ABILITY,
594*6bbbd442SRobert Mustacchi 	    &igc->igc_phy_lp);
595*6bbbd442SRobert Mustacchi 	(void) igc_read_phy_reg(&igc->igc_hw, PHY_AUTONEG_EXP,
596*6bbbd442SRobert Mustacchi 	    &igc->igc_phy_an_exp);
597*6bbbd442SRobert Mustacchi 	(void) igc_read_phy_reg(&igc->igc_hw, PHY_1000T_CTRL,
598*6bbbd442SRobert Mustacchi 	    &igc->igc_phy_1000t_ctrl);
599*6bbbd442SRobert Mustacchi 	(void) igc_read_phy_reg(&igc->igc_hw, PHY_1000T_STATUS,
600*6bbbd442SRobert Mustacchi 	    &igc->igc_phy_1000t_status);
601*6bbbd442SRobert Mustacchi 	(void) igc_read_phy_reg(&igc->igc_hw, PHY_EXT_STATUS,
602*6bbbd442SRobert Mustacchi 	    &igc->igc_phy_ext_status);
603*6bbbd442SRobert Mustacchi 	(void) igc_read_phy_reg(&igc->igc_hw, PHY_EXT_STATUS,
604*6bbbd442SRobert Mustacchi 	    &igc->igc_phy_ext_status);
605*6bbbd442SRobert Mustacchi 
606*6bbbd442SRobert Mustacchi 	mmd_base = STANDARD_AN_REG_MASK << MMD_DEVADDR_SHIFT;
607*6bbbd442SRobert Mustacchi 	(void) igc_read_phy_reg(&igc->igc_hw, mmd_base | ANEG_MULTIGBT_AN_CTRL,
608*6bbbd442SRobert Mustacchi 	    &igc->igc_phy_mmd_ctrl);
609*6bbbd442SRobert Mustacchi 	(void) igc_read_phy_reg(&igc->igc_hw, mmd_base | ANEG_MULTIGBT_AN_STS1,
610*6bbbd442SRobert Mustacchi 	    &igc->igc_phy_mmd_sts);
611*6bbbd442SRobert Mustacchi 	mutex_exit(&igc->igc_lock);
612*6bbbd442SRobert Mustacchi 
613*6bbbd442SRobert Mustacchi 	if (orig_state != new_state) {
614*6bbbd442SRobert Mustacchi 		mac_link_update(igc->igc_mac_hdl, new_state);
615*6bbbd442SRobert Mustacchi 	}
616*6bbbd442SRobert Mustacchi }
617*6bbbd442SRobert Mustacchi 
618*6bbbd442SRobert Mustacchi static uint_t
igc_intr_rx_queue(caddr_t arg1,caddr_t arg2)619*6bbbd442SRobert Mustacchi igc_intr_rx_queue(caddr_t arg1, caddr_t arg2)
620*6bbbd442SRobert Mustacchi {
621*6bbbd442SRobert Mustacchi 	igc_t *igc = (igc_t *)arg1;
622*6bbbd442SRobert Mustacchi 	uintptr_t queue = (uintptr_t)arg2;
623*6bbbd442SRobert Mustacchi 	igc_rx_ring_t *ring;
624*6bbbd442SRobert Mustacchi 	mblk_t *mp = NULL;
625*6bbbd442SRobert Mustacchi 
626*6bbbd442SRobert Mustacchi 	ASSERT3U(queue, <, igc->igc_nrx_rings);
627*6bbbd442SRobert Mustacchi 	ring = &igc->igc_rx_rings[queue];
628*6bbbd442SRobert Mustacchi 
629*6bbbd442SRobert Mustacchi 	mutex_enter(&ring->irr_lock);
630*6bbbd442SRobert Mustacchi 	if ((ring->irr_flags & IGC_RXR_F_POLL) == 0) {
631*6bbbd442SRobert Mustacchi 		mp = igc_ring_rx(ring, IGC_RX_POLL_INTR);
632*6bbbd442SRobert Mustacchi 	}
633*6bbbd442SRobert Mustacchi 	mutex_exit(&ring->irr_lock);
634*6bbbd442SRobert Mustacchi 
635*6bbbd442SRobert Mustacchi 	if (mp != NULL) {
636*6bbbd442SRobert Mustacchi 		mac_rx_ring(igc->igc_mac_hdl, ring->irr_rh, mp, ring->irr_gen);
637*6bbbd442SRobert Mustacchi 	}
638*6bbbd442SRobert Mustacchi 
639*6bbbd442SRobert Mustacchi 	return (DDI_INTR_CLAIMED);
640*6bbbd442SRobert Mustacchi }
641*6bbbd442SRobert Mustacchi 
642*6bbbd442SRobert Mustacchi static uint_t
igc_intr_tx_other(caddr_t arg1,caddr_t arg2)643*6bbbd442SRobert Mustacchi igc_intr_tx_other(caddr_t arg1, caddr_t arg2)
644*6bbbd442SRobert Mustacchi {
645*6bbbd442SRobert Mustacchi 	igc_t *igc = (igc_t *)arg1;
646*6bbbd442SRobert Mustacchi 	uint32_t icr = igc_read32(igc, IGC_ICR);
647*6bbbd442SRobert Mustacchi 
648*6bbbd442SRobert Mustacchi 	igc_tx_recycle(igc, &igc->igc_tx_rings[0]);
649*6bbbd442SRobert Mustacchi 
650*6bbbd442SRobert Mustacchi 	if ((icr & IGC_ICR_LSC) != 0) {
651*6bbbd442SRobert Mustacchi 		igc_intr_lsc(igc);
652*6bbbd442SRobert Mustacchi 	}
653*6bbbd442SRobert Mustacchi 
654*6bbbd442SRobert Mustacchi 	return (DDI_INTR_CLAIMED);
655*6bbbd442SRobert Mustacchi }
656*6bbbd442SRobert Mustacchi 
657*6bbbd442SRobert Mustacchi static bool
igc_setup_regs(igc_t * igc)658*6bbbd442SRobert Mustacchi igc_setup_regs(igc_t *igc)
659*6bbbd442SRobert Mustacchi {
660*6bbbd442SRobert Mustacchi 	int ret;
661*6bbbd442SRobert Mustacchi 	ddi_device_acc_attr_t da;
662*6bbbd442SRobert Mustacchi 
663*6bbbd442SRobert Mustacchi 	if (pci_config_setup(igc->igc_dip, &igc->igc_cfgspace) != DDI_SUCCESS) {
664*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to map config space");
665*6bbbd442SRobert Mustacchi 		return (false);
666*6bbbd442SRobert Mustacchi 	}
667*6bbbd442SRobert Mustacchi 
668*6bbbd442SRobert Mustacchi 	if (ddi_dev_regsize(igc->igc_dip, IGC_PCI_BAR, &igc->igc_regs_size) !=
669*6bbbd442SRobert Mustacchi 	    DDI_SUCCESS) {
670*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to get BAR %u size",
671*6bbbd442SRobert Mustacchi 		    IGC_PCI_BAR - 1);
672*6bbbd442SRobert Mustacchi 		return (false);
673*6bbbd442SRobert Mustacchi 	}
674*6bbbd442SRobert Mustacchi 
675*6bbbd442SRobert Mustacchi 	bzero(&da, sizeof (ddi_device_acc_attr_t));
676*6bbbd442SRobert Mustacchi 	da.devacc_attr_version = DDI_DEVICE_ATTR_V1;
677*6bbbd442SRobert Mustacchi 	da.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
678*6bbbd442SRobert Mustacchi 	da.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
679*6bbbd442SRobert Mustacchi 	da.devacc_attr_access = DDI_DEFAULT_ACC;
680*6bbbd442SRobert Mustacchi 
681*6bbbd442SRobert Mustacchi 	if ((ret = ddi_regs_map_setup(igc->igc_dip, IGC_PCI_BAR,
682*6bbbd442SRobert Mustacchi 	    &igc->igc_regs_base, 0, igc->igc_regs_size, &da,
683*6bbbd442SRobert Mustacchi 	    &igc->igc_regs_hdl)) != DDI_SUCCESS) {
684*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to map registers: %d",
685*6bbbd442SRobert Mustacchi 		    ret);
686*6bbbd442SRobert Mustacchi 		return (false);
687*6bbbd442SRobert Mustacchi 	}
688*6bbbd442SRobert Mustacchi 
689*6bbbd442SRobert Mustacchi 	return (true);
690*6bbbd442SRobert Mustacchi }
691*6bbbd442SRobert Mustacchi 
692*6bbbd442SRobert Mustacchi /*
693*6bbbd442SRobert Mustacchi  * Go through the process of initializing the igc core code. First we have to
694*6bbbd442SRobert Mustacchi  * fill in the information that the common code requires to identify the
695*6bbbd442SRobert Mustacchi  * hardware and set the mac type. After that we can go through and set up all of
696*6bbbd442SRobert Mustacchi  * the function initialization.
697*6bbbd442SRobert Mustacchi  */
698*6bbbd442SRobert Mustacchi static bool
igc_core_code_init(igc_t * igc)699*6bbbd442SRobert Mustacchi igc_core_code_init(igc_t *igc)
700*6bbbd442SRobert Mustacchi {
701*6bbbd442SRobert Mustacchi 	int ret;
702*6bbbd442SRobert Mustacchi 	int *regs;
703*6bbbd442SRobert Mustacchi 	uint_t nprop;
704*6bbbd442SRobert Mustacchi 
705*6bbbd442SRobert Mustacchi 	igc->igc_hw.back = igc;
706*6bbbd442SRobert Mustacchi 	igc->igc_hw.vendor_id = pci_config_get16(igc->igc_cfgspace,
707*6bbbd442SRobert Mustacchi 	    PCI_CONF_VENID);
708*6bbbd442SRobert Mustacchi 	igc->igc_hw.device_id = pci_config_get16(igc->igc_cfgspace,
709*6bbbd442SRobert Mustacchi 	    PCI_CONF_DEVID);
710*6bbbd442SRobert Mustacchi 	igc->igc_hw.revision_id = pci_config_get8(igc->igc_cfgspace,
711*6bbbd442SRobert Mustacchi 	    PCI_CONF_REVID);
712*6bbbd442SRobert Mustacchi 	igc->igc_hw.subsystem_vendor_id = pci_config_get16(igc->igc_cfgspace,
713*6bbbd442SRobert Mustacchi 	    PCI_CONF_SUBVENID);
714*6bbbd442SRobert Mustacchi 	igc->igc_hw.subsystem_device_id = pci_config_get16(igc->igc_cfgspace,
715*6bbbd442SRobert Mustacchi 	    PCI_CONF_SUBSYSID);
716*6bbbd442SRobert Mustacchi 
717*6bbbd442SRobert Mustacchi 	if ((ret = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, igc->igc_dip,
718*6bbbd442SRobert Mustacchi 	    DDI_PROP_DONTPASS, "reg", &regs, &nprop)) != DDI_PROP_SUCCESS) {
719*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to look up 'reg' "
720*6bbbd442SRobert Mustacchi 		    "property: %d", ret);
721*6bbbd442SRobert Mustacchi 		return (false);
722*6bbbd442SRobert Mustacchi 	}
723*6bbbd442SRobert Mustacchi 
724*6bbbd442SRobert Mustacchi 	/*
725*6bbbd442SRobert Mustacchi 	 * We fill out the function and command word. We currently don't fill
726*6bbbd442SRobert Mustacchi 	 * out the bus type, speed, and width as it's not used by the common
727*6bbbd442SRobert Mustacchi 	 * code, leaving it all at unknown. We can grab that information when it
728*6bbbd442SRobert Mustacchi 	 * needs it. We do fill out the function and command word as the former
729*6bbbd442SRobert Mustacchi 	 * is important and the latter is easy to grab.
730*6bbbd442SRobert Mustacchi 	 */
731*6bbbd442SRobert Mustacchi 	igc->igc_hw.bus.func = PCI_REG_FUNC_G(regs[0]);
732*6bbbd442SRobert Mustacchi 	igc->igc_hw.bus.pci_cmd_word = pci_config_get16(igc->igc_cfgspace,
733*6bbbd442SRobert Mustacchi 	    PCI_CONF_COMM);
734*6bbbd442SRobert Mustacchi 	ddi_prop_free(regs);
735*6bbbd442SRobert Mustacchi 
736*6bbbd442SRobert Mustacchi 	/*
737*6bbbd442SRobert Mustacchi 	 * The common code asks for the memory mapped address to be set in its
738*6bbbd442SRobert Mustacchi 	 * structure. Though in theory it promises not to use it.
739*6bbbd442SRobert Mustacchi 	 */
740*6bbbd442SRobert Mustacchi 	igc->igc_hw.hw_addr = (uint8_t *)igc->igc_regs_base;
741*6bbbd442SRobert Mustacchi 
742*6bbbd442SRobert Mustacchi 	if ((ret = igc_set_mac_type(&igc->igc_hw)) != IGC_SUCCESS) {
743*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to set mac type: %d",
744*6bbbd442SRobert Mustacchi 		    ret);
745*6bbbd442SRobert Mustacchi 		return (false);
746*6bbbd442SRobert Mustacchi 	}
747*6bbbd442SRobert Mustacchi 
748*6bbbd442SRobert Mustacchi 	if ((ret = igc_setup_init_funcs(&igc->igc_hw, true)) != IGC_SUCCESS) {
749*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to setup core code "
750*6bbbd442SRobert Mustacchi 		    "function pointers: %d", ret);
751*6bbbd442SRobert Mustacchi 		return (false);
752*6bbbd442SRobert Mustacchi 	}
753*6bbbd442SRobert Mustacchi 
754*6bbbd442SRobert Mustacchi 	/*
755*6bbbd442SRobert Mustacchi 	 * Go ahead and attempt to get the bus information even though this
756*6bbbd442SRobert Mustacchi 	 * doesn't actually do anything right now.
757*6bbbd442SRobert Mustacchi 	 */
758*6bbbd442SRobert Mustacchi 	if ((ret = igc_get_bus_info(&igc->igc_hw)) != IGC_SUCCESS) {
759*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "core code failed to get bus "
760*6bbbd442SRobert Mustacchi 		    "info: %d", ret);
761*6bbbd442SRobert Mustacchi 		return (false);
762*6bbbd442SRobert Mustacchi 	}
763*6bbbd442SRobert Mustacchi 
764*6bbbd442SRobert Mustacchi 	return (true);
765*6bbbd442SRobert Mustacchi }
766*6bbbd442SRobert Mustacchi 
767*6bbbd442SRobert Mustacchi static bool
igc_limits_init(igc_t * igc)768*6bbbd442SRobert Mustacchi igc_limits_init(igc_t *igc)
769*6bbbd442SRobert Mustacchi {
770*6bbbd442SRobert Mustacchi 	switch (igc->igc_hw.mac.type) {
771*6bbbd442SRobert Mustacchi 	case igc_i225:
772*6bbbd442SRobert Mustacchi 		igc->igc_limits.il_max_rx_rings = IGC_MAX_RX_RINGS_I225;
773*6bbbd442SRobert Mustacchi 		igc->igc_limits.il_max_tx_rings = IGC_MAX_RX_RINGS_I225;
774*6bbbd442SRobert Mustacchi 		igc->igc_limits.il_max_mtu = IGC_MAX_MTU_I225;
775*6bbbd442SRobert Mustacchi 		break;
776*6bbbd442SRobert Mustacchi 	default:
777*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "unknown MAC type: %u",
778*6bbbd442SRobert Mustacchi 		    igc->igc_hw.mac.type);
779*6bbbd442SRobert Mustacchi 		return (false);
780*6bbbd442SRobert Mustacchi 	}
781*6bbbd442SRobert Mustacchi 
782*6bbbd442SRobert Mustacchi 	return (true);
783*6bbbd442SRobert Mustacchi }
784*6bbbd442SRobert Mustacchi 
785*6bbbd442SRobert Mustacchi /*
786*6bbbd442SRobert Mustacchi  * Determine the hardware buffer sizes that are required for the given MTU.
787*6bbbd442SRobert Mustacchi  * There are a few different constraints that we try to enforce here that come
788*6bbbd442SRobert Mustacchi  * from the hardware and others that come from us:
789*6bbbd442SRobert Mustacchi  *
790*6bbbd442SRobert Mustacchi  * 1) The hardware requires that the rx and tx sizes all be 1 KiB (0x400) byte
791*6bbbd442SRobert Mustacchi  * aligned.
792*6bbbd442SRobert Mustacchi  * 2) Our tx engine can handle copying across multiple descriptors, so we cap
793*6bbbd442SRobert Mustacchi  * the maximum tx buffer size at one page.
794*6bbbd442SRobert Mustacchi  * 3) Right now our rx engine does not handle scanning multiple buffers for rx
795*6bbbd442SRobert Mustacchi  * (see the theory statement), so we end up making the rx buffer have to fix the
796*6bbbd442SRobert Mustacchi  * maximum frame size.
797*6bbbd442SRobert Mustacchi  * 4) rx buffers need to also account for IP alignment, so we make sure to
798*6bbbd442SRobert Mustacchi  * allocate extra bytes for that.
799*6bbbd442SRobert Mustacchi  */
800*6bbbd442SRobert Mustacchi void
igc_hw_buf_update(igc_t * igc)801*6bbbd442SRobert Mustacchi igc_hw_buf_update(igc_t *igc)
802*6bbbd442SRobert Mustacchi {
803*6bbbd442SRobert Mustacchi 	unsigned long pagesize = ddi_ptob(igc->igc_dip, 1);
804*6bbbd442SRobert Mustacchi 	uint32_t tx_mtu;
805*6bbbd442SRobert Mustacchi 
806*6bbbd442SRobert Mustacchi 	igc->igc_max_frame = igc->igc_mtu + sizeof (struct ether_vlan_header) +
807*6bbbd442SRobert Mustacchi 	    ETHERFCSL;
808*6bbbd442SRobert Mustacchi 	igc->igc_rx_buf_size = P2ROUNDUP_TYPED(igc->igc_max_frame +
809*6bbbd442SRobert Mustacchi 	    IGC_RX_BUF_IP_ALIGN, IGC_BUF_ALIGN, uint32_t);
810*6bbbd442SRobert Mustacchi 	tx_mtu = P2ROUNDUP_TYPED(igc->igc_max_frame, IGC_BUF_ALIGN, uint32_t);
811*6bbbd442SRobert Mustacchi 	igc->igc_tx_buf_size = MIN(tx_mtu, pagesize);
812*6bbbd442SRobert Mustacchi }
813*6bbbd442SRobert Mustacchi 
814*6bbbd442SRobert Mustacchi static bool
igc_intr_init(igc_t * igc)815*6bbbd442SRobert Mustacchi igc_intr_init(igc_t *igc)
816*6bbbd442SRobert Mustacchi {
817*6bbbd442SRobert Mustacchi 	int ret, types, nintrs, navail, req;
818*6bbbd442SRobert Mustacchi 	const int min_nintrs = 2;
819*6bbbd442SRobert Mustacchi 
820*6bbbd442SRobert Mustacchi 	if ((ret = ddi_intr_get_supported_types(igc->igc_dip, &types)) !=
821*6bbbd442SRobert Mustacchi 	    DDI_SUCCESS) {
822*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to get supported "
823*6bbbd442SRobert Mustacchi 		    "interrupts: %d", ret);
824*6bbbd442SRobert Mustacchi 		return (false);
825*6bbbd442SRobert Mustacchi 	}
826*6bbbd442SRobert Mustacchi 
827*6bbbd442SRobert Mustacchi 	/*
828*6bbbd442SRobert Mustacchi 	 * For now, we simplify our lives and device support by only supporting
829*6bbbd442SRobert Mustacchi 	 * MSI-X interrupts. When we find versions of this without MSI-X
830*6bbbd442SRobert Mustacchi 	 * support, we can go and add what we need.
831*6bbbd442SRobert Mustacchi 	 */
832*6bbbd442SRobert Mustacchi 	if ((types & DDI_INTR_TYPE_MSIX) == 0) {
833*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "device does not support MSI-X, "
834*6bbbd442SRobert Mustacchi 		    "found %d", types);
835*6bbbd442SRobert Mustacchi 		return (false);
836*6bbbd442SRobert Mustacchi 	}
837*6bbbd442SRobert Mustacchi 
838*6bbbd442SRobert Mustacchi 	if ((ret = ddi_intr_get_nintrs(igc->igc_dip, DDI_INTR_TYPE_MSIX,
839*6bbbd442SRobert Mustacchi 	    &nintrs)) != DDI_SUCCESS) {
840*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to get number of "
841*6bbbd442SRobert Mustacchi 		    "supported MSI-X interrupts: %d", ret);
842*6bbbd442SRobert Mustacchi 		return (false);
843*6bbbd442SRobert Mustacchi 	}
844*6bbbd442SRobert Mustacchi 
845*6bbbd442SRobert Mustacchi 	if (nintrs < min_nintrs) {
846*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "igc driver currently requires "
847*6bbbd442SRobert Mustacchi 		    "%d MSI-X interrupts be supported, found %d", min_nintrs,
848*6bbbd442SRobert Mustacchi 		    nintrs);
849*6bbbd442SRobert Mustacchi 		return (false);
850*6bbbd442SRobert Mustacchi 	}
851*6bbbd442SRobert Mustacchi 
852*6bbbd442SRobert Mustacchi 	if ((ret = ddi_intr_get_navail(igc->igc_dip, DDI_INTR_TYPE_MSIX,
853*6bbbd442SRobert Mustacchi 	    &navail)) != DDI_SUCCESS) {
854*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to get number of "
855*6bbbd442SRobert Mustacchi 		    "available MSI-X interrupts: %d", ret);
856*6bbbd442SRobert Mustacchi 		return (false);
857*6bbbd442SRobert Mustacchi 	}
858*6bbbd442SRobert Mustacchi 
859*6bbbd442SRobert Mustacchi 	if (navail < min_nintrs) {
860*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "igc driver currently requires "
861*6bbbd442SRobert Mustacchi 		    "%d MSI-X interrupts be available, found %d", min_nintrs,
862*6bbbd442SRobert Mustacchi 		    navail);
863*6bbbd442SRobert Mustacchi 		return (false);
864*6bbbd442SRobert Mustacchi 	}
865*6bbbd442SRobert Mustacchi 
866*6bbbd442SRobert Mustacchi 	/*
867*6bbbd442SRobert Mustacchi 	 * In the future this could be based upon the multiple queues that the
868*6bbbd442SRobert Mustacchi 	 * device supports, but for now it's limited to two. See 'Rings and
869*6bbbd442SRobert Mustacchi 	 * Interrupts' in the theory statement for more background.
870*6bbbd442SRobert Mustacchi 	 */
871*6bbbd442SRobert Mustacchi 	req = min_nintrs;
872*6bbbd442SRobert Mustacchi 	req = MIN(req, navail);
873*6bbbd442SRobert Mustacchi 	igc->igc_intr_size = req * sizeof (ddi_intr_handle_t);
874*6bbbd442SRobert Mustacchi 	igc->igc_intr_handles = kmem_alloc(igc->igc_intr_size, KM_SLEEP);
875*6bbbd442SRobert Mustacchi 
876*6bbbd442SRobert Mustacchi 	if ((ret = ddi_intr_alloc(igc->igc_dip, igc->igc_intr_handles,
877*6bbbd442SRobert Mustacchi 	    DDI_INTR_TYPE_MSIX, 0, req, &igc->igc_nintrs,
878*6bbbd442SRobert Mustacchi 	    DDI_INTR_ALLOC_NORMAL)) != DDI_SUCCESS) {
879*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to allocate interrupts: "
880*6bbbd442SRobert Mustacchi 		    "%d", ret);
881*6bbbd442SRobert Mustacchi 		return (false);
882*6bbbd442SRobert Mustacchi 	}
883*6bbbd442SRobert Mustacchi 
884*6bbbd442SRobert Mustacchi 	igc->igc_intr_type = DDI_INTR_TYPE_MSIX;
885*6bbbd442SRobert Mustacchi 	igc->igc_attach |= IGC_ATTACH_INTR_ALLOC;
886*6bbbd442SRobert Mustacchi 	if (igc->igc_nintrs < min_nintrs) {
887*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "received %d interrupts, but "
888*6bbbd442SRobert Mustacchi 		    "needed at least %d", igc->igc_nintrs, min_nintrs);
889*6bbbd442SRobert Mustacchi 		return (false);
890*6bbbd442SRobert Mustacchi 	}
891*6bbbd442SRobert Mustacchi 
892*6bbbd442SRobert Mustacchi 	if ((ret = ddi_intr_get_pri(igc->igc_intr_handles[0],
893*6bbbd442SRobert Mustacchi 	    &igc->igc_intr_pri)) != DDI_SUCCESS) {
894*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to get interrupt "
895*6bbbd442SRobert Mustacchi 		    "priority: %d", ret);
896*6bbbd442SRobert Mustacchi 		return (false);
897*6bbbd442SRobert Mustacchi 	}
898*6bbbd442SRobert Mustacchi 
899*6bbbd442SRobert Mustacchi 	if ((ret = ddi_intr_get_cap(igc->igc_intr_handles[0],
900*6bbbd442SRobert Mustacchi 	    &igc->igc_intr_cap)) != DDI_SUCCESS) {
901*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to get interrupt "
902*6bbbd442SRobert Mustacchi 		    "capabilities: %d", ret);
903*6bbbd442SRobert Mustacchi 		return (false);
904*6bbbd442SRobert Mustacchi 	}
905*6bbbd442SRobert Mustacchi 
906*6bbbd442SRobert Mustacchi 	return (true);
907*6bbbd442SRobert Mustacchi }
908*6bbbd442SRobert Mustacchi 
909*6bbbd442SRobert Mustacchi /*
910*6bbbd442SRobert Mustacchi  * As part of allocating our rings we make the following assumptions about
911*6bbbd442SRobert Mustacchi  * interrupt assignments. All tx rings share interrupt 0. All rx rings have
912*6bbbd442SRobert Mustacchi  * separate interrupts starting from interrupt 1. This design may likely change
913*6bbbd442SRobert Mustacchi  * in the face of actual multi-ring support
914*6bbbd442SRobert Mustacchi  */
915*6bbbd442SRobert Mustacchi static bool
igc_rings_alloc(igc_t * igc)916*6bbbd442SRobert Mustacchi igc_rings_alloc(igc_t *igc)
917*6bbbd442SRobert Mustacchi {
918*6bbbd442SRobert Mustacchi 	uint32_t intr = 0;
919*6bbbd442SRobert Mustacchi 	igc->igc_tx_rings = kmem_zalloc(sizeof (igc_tx_ring_t) *
920*6bbbd442SRobert Mustacchi 	    igc->igc_ntx_rings, KM_SLEEP);
921*6bbbd442SRobert Mustacchi 
922*6bbbd442SRobert Mustacchi 	for (uint32_t i = 0; i < igc->igc_ntx_rings; i++) {
923*6bbbd442SRobert Mustacchi 		igc->igc_tx_rings[i].itr_igc = igc;
924*6bbbd442SRobert Mustacchi 		igc->igc_tx_rings[i].itr_idx = i;
925*6bbbd442SRobert Mustacchi 		igc->igc_tx_rings[i].itr_intr_idx = intr;
926*6bbbd442SRobert Mustacchi 		mutex_init(&igc->igc_tx_rings[i].itr_lock, NULL, MUTEX_DRIVER,
927*6bbbd442SRobert Mustacchi 		    DDI_INTR_PRI(igc->igc_intr_pri));
928*6bbbd442SRobert Mustacchi 		if (!igc_tx_ring_stats_init(igc, &igc->igc_tx_rings[i])) {
929*6bbbd442SRobert Mustacchi 			return (false);
930*6bbbd442SRobert Mustacchi 		}
931*6bbbd442SRobert Mustacchi 	}
932*6bbbd442SRobert Mustacchi 
933*6bbbd442SRobert Mustacchi 	igc->igc_rx_rings = kmem_zalloc(sizeof (igc_rx_ring_t) *
934*6bbbd442SRobert Mustacchi 	    igc->igc_nrx_rings, KM_SLEEP);
935*6bbbd442SRobert Mustacchi 	intr = 1;
936*6bbbd442SRobert Mustacchi 
937*6bbbd442SRobert Mustacchi 	for (uint32_t i = 0; i < igc->igc_nrx_rings; i++, intr++) {
938*6bbbd442SRobert Mustacchi 		igc->igc_rx_rings[i].irr_igc = igc;
939*6bbbd442SRobert Mustacchi 		igc->igc_rx_rings[i].irr_idx = i;
940*6bbbd442SRobert Mustacchi 		igc->igc_rx_rings[i].irr_intr_idx = intr;
941*6bbbd442SRobert Mustacchi 		mutex_init(&igc->igc_rx_rings[i].irr_lock, NULL, MUTEX_DRIVER,
942*6bbbd442SRobert Mustacchi 		    DDI_INTR_PRI(igc->igc_intr_pri));
943*6bbbd442SRobert Mustacchi 		mutex_init(&igc->igc_rx_rings[i].irr_free_lock, NULL,
944*6bbbd442SRobert Mustacchi 		    MUTEX_DRIVER, DDI_INTR_PRI(igc->igc_intr_pri));
945*6bbbd442SRobert Mustacchi 		cv_init(&igc->igc_rx_rings[i].irr_free_cv, NULL, CV_DRIVER,
946*6bbbd442SRobert Mustacchi 		    NULL);
947*6bbbd442SRobert Mustacchi 		if (!igc_rx_ring_stats_init(igc, &igc->igc_rx_rings[i])) {
948*6bbbd442SRobert Mustacchi 			return (false);
949*6bbbd442SRobert Mustacchi 		}
950*6bbbd442SRobert Mustacchi 	}
951*6bbbd442SRobert Mustacchi 
952*6bbbd442SRobert Mustacchi 	ASSERT3U(intr, ==, igc->igc_nintrs);
953*6bbbd442SRobert Mustacchi 
954*6bbbd442SRobert Mustacchi 	return (true);
955*6bbbd442SRobert Mustacchi }
956*6bbbd442SRobert Mustacchi 
957*6bbbd442SRobert Mustacchi /*
958*6bbbd442SRobert Mustacchi  * Allocate our interrupts. Note, we have more or less constrained the device
959*6bbbd442SRobert Mustacchi  * right now to only request two interrupts which we use in a fixed way. If we
960*6bbbd442SRobert Mustacchi  * end up with more varied queue support then this should be changed around.
961*6bbbd442SRobert Mustacchi  */
962*6bbbd442SRobert Mustacchi static bool
igc_intr_hdlr_init(igc_t * igc)963*6bbbd442SRobert Mustacchi igc_intr_hdlr_init(igc_t *igc)
964*6bbbd442SRobert Mustacchi {
965*6bbbd442SRobert Mustacchi 	int ret;
966*6bbbd442SRobert Mustacchi 
967*6bbbd442SRobert Mustacchi 	if ((ret = ddi_intr_add_handler(igc->igc_intr_handles[0],
968*6bbbd442SRobert Mustacchi 	    igc_intr_tx_other, igc, NULL)) != DDI_SUCCESS) {
969*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to add tx/other "
970*6bbbd442SRobert Mustacchi 		    "interrupt handler: %d", ret);
971*6bbbd442SRobert Mustacchi 		return (false);
972*6bbbd442SRobert Mustacchi 	}
973*6bbbd442SRobert Mustacchi 
974*6bbbd442SRobert Mustacchi 	if ((ret = ddi_intr_add_handler(igc->igc_intr_handles[1],
975*6bbbd442SRobert Mustacchi 	    igc_intr_rx_queue, igc, (uintptr_t)0)) != DDI_SUCCESS) {
976*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to add rx interrupt "
977*6bbbd442SRobert Mustacchi 		    "handler: %d", ret);
978*6bbbd442SRobert Mustacchi 		if ((ret = ddi_intr_remove_handler(igc->igc_intr_handles[0])) !=
979*6bbbd442SRobert Mustacchi 		    DDI_SUCCESS) {
980*6bbbd442SRobert Mustacchi 			dev_err(igc->igc_dip, CE_WARN, "failed to remove "
981*6bbbd442SRobert Mustacchi 			    "tx/other interrupt handler");
982*6bbbd442SRobert Mustacchi 		}
983*6bbbd442SRobert Mustacchi 		return (false);
984*6bbbd442SRobert Mustacchi 	}
985*6bbbd442SRobert Mustacchi 
986*6bbbd442SRobert Mustacchi 	return (true);
987*6bbbd442SRobert Mustacchi }
988*6bbbd442SRobert Mustacchi 
989*6bbbd442SRobert Mustacchi static void
igc_hw_control(igc_t * igc,bool take)990*6bbbd442SRobert Mustacchi igc_hw_control(igc_t *igc, bool take)
991*6bbbd442SRobert Mustacchi {
992*6bbbd442SRobert Mustacchi 	uint32_t ctrl = igc_read32(igc, IGC_CTRL_EXT);
993*6bbbd442SRobert Mustacchi 
994*6bbbd442SRobert Mustacchi 	if (take) {
995*6bbbd442SRobert Mustacchi 		ctrl |= IGC_CTRL_EXT_DRV_LOAD;
996*6bbbd442SRobert Mustacchi 	} else {
997*6bbbd442SRobert Mustacchi 		ctrl &= ~IGC_CTRL_EXT_DRV_LOAD;
998*6bbbd442SRobert Mustacchi 	}
999*6bbbd442SRobert Mustacchi 
1000*6bbbd442SRobert Mustacchi 	igc_write32(igc, IGC_CTRL_EXT, ctrl);
1001*6bbbd442SRobert Mustacchi }
1002*6bbbd442SRobert Mustacchi 
1003*6bbbd442SRobert Mustacchi /*
1004*6bbbd442SRobert Mustacchi  * Basic device initialization and sanity check. This covers that we can
1005*6bbbd442SRobert Mustacchi  * properly reset the device, validate its checksum, and get a valid MAC
1006*6bbbd442SRobert Mustacchi  * address.
1007*6bbbd442SRobert Mustacchi  */
1008*6bbbd442SRobert Mustacchi static bool
igc_hw_init(igc_t * igc)1009*6bbbd442SRobert Mustacchi igc_hw_init(igc_t *igc)
1010*6bbbd442SRobert Mustacchi {
1011*6bbbd442SRobert Mustacchi 	int ret;
1012*6bbbd442SRobert Mustacchi 	uint32_t eecd;
1013*6bbbd442SRobert Mustacchi 
1014*6bbbd442SRobert Mustacchi 	if ((ret = igc_reset_hw(&igc->igc_hw)) != IGC_SUCCESS) {
1015*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to reset device: %d",
1016*6bbbd442SRobert Mustacchi 		    ret);
1017*6bbbd442SRobert Mustacchi 		return (false);
1018*6bbbd442SRobert Mustacchi 	}
1019*6bbbd442SRobert Mustacchi 
1020*6bbbd442SRobert Mustacchi 	/*
1021*6bbbd442SRobert Mustacchi 	 * Goodbye firmware.
1022*6bbbd442SRobert Mustacchi 	 */
1023*6bbbd442SRobert Mustacchi 	igc_hw_control(igc, true);
1024*6bbbd442SRobert Mustacchi 
1025*6bbbd442SRobert Mustacchi 	/*
1026*6bbbd442SRobert Mustacchi 	 * Check the NVM validiity if a device is present.
1027*6bbbd442SRobert Mustacchi 	 */
1028*6bbbd442SRobert Mustacchi 	eecd = igc_read32(igc, IGC_EECD);
1029*6bbbd442SRobert Mustacchi 	if ((eecd & IGC_EECD_EE_DET) != 0) {
1030*6bbbd442SRobert Mustacchi 		if ((ret = igc_validate_nvm_checksum(&igc->igc_hw)) !=
1031*6bbbd442SRobert Mustacchi 		    IGC_SUCCESS) {
1032*6bbbd442SRobert Mustacchi 			dev_err(igc->igc_dip, CE_WARN, "failed to validate "
1033*6bbbd442SRobert Mustacchi 			    "igc NVM checksum: %d", ret);
1034*6bbbd442SRobert Mustacchi 			return (false);
1035*6bbbd442SRobert Mustacchi 		}
1036*6bbbd442SRobert Mustacchi 	}
1037*6bbbd442SRobert Mustacchi 
1038*6bbbd442SRobert Mustacchi 	if ((ret = igc_read_mac_addr(&igc->igc_hw)) != IGC_SUCCESS) {
1039*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to read MAC address: %d",
1040*6bbbd442SRobert Mustacchi 		    ret);
1041*6bbbd442SRobert Mustacchi 		return (false);
1042*6bbbd442SRobert Mustacchi 	}
1043*6bbbd442SRobert Mustacchi 
1044*6bbbd442SRobert Mustacchi 	if ((ret = igc_get_phy_id(&igc->igc_hw)) != IGC_SUCCESS) {
1045*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to get PHY id: %d", ret);
1046*6bbbd442SRobert Mustacchi 		return (false);
1047*6bbbd442SRobert Mustacchi 	}
1048*6bbbd442SRobert Mustacchi 
1049*6bbbd442SRobert Mustacchi 	return (true);
1050*6bbbd442SRobert Mustacchi }
1051*6bbbd442SRobert Mustacchi 
1052*6bbbd442SRobert Mustacchi /*
1053*6bbbd442SRobert Mustacchi  * In case the user has modified the LED state through MAC_CAPAB_LED, restore
1054*6bbbd442SRobert Mustacchi  * that back to the defaults we got when we started up the device.
1055*6bbbd442SRobert Mustacchi  */
1056*6bbbd442SRobert Mustacchi static void
igc_led_fini(igc_t * igc)1057*6bbbd442SRobert Mustacchi igc_led_fini(igc_t *igc)
1058*6bbbd442SRobert Mustacchi {
1059*6bbbd442SRobert Mustacchi 	igc_write32(igc, IGC_LEDCTL, igc->igc_ledctl);
1060*6bbbd442SRobert Mustacchi }
1061*6bbbd442SRobert Mustacchi 
1062*6bbbd442SRobert Mustacchi /*
1063*6bbbd442SRobert Mustacchi  * Traditionally the Intel NIC drivers avoid touching activity pins as part of
1064*6bbbd442SRobert Mustacchi  * their behavior for what we use. We also don't touch a pin if it's in SDP mode
1065*6bbbd442SRobert Mustacchi  * and not being used to drive an LED as it means it's likely not for us.
1066*6bbbd442SRobert Mustacchi  */
1067*6bbbd442SRobert Mustacchi static bool
igc_led_ignore(i225_led_mode_t mode)1068*6bbbd442SRobert Mustacchi igc_led_ignore(i225_led_mode_t mode)
1069*6bbbd442SRobert Mustacchi {
1070*6bbbd442SRobert Mustacchi 	switch (mode) {
1071*6bbbd442SRobert Mustacchi 	case I225_LED_M_FILTER_ACT:
1072*6bbbd442SRobert Mustacchi 	case I225_LED_M_LINK_ACT:
1073*6bbbd442SRobert Mustacchi 	case I225_LED_M_SDP:
1074*6bbbd442SRobert Mustacchi 	case I225_LED_M_PAUSE:
1075*6bbbd442SRobert Mustacchi 	case I225_LED_M_ACT:
1076*6bbbd442SRobert Mustacchi 		return (true);
1077*6bbbd442SRobert Mustacchi 	default:
1078*6bbbd442SRobert Mustacchi 		return (false);
1079*6bbbd442SRobert Mustacchi 	}
1080*6bbbd442SRobert Mustacchi }
1081*6bbbd442SRobert Mustacchi 
1082*6bbbd442SRobert Mustacchi static inline uint32_t
igc_led_bitoff(uint32_t led)1083*6bbbd442SRobert Mustacchi igc_led_bitoff(uint32_t led)
1084*6bbbd442SRobert Mustacchi {
1085*6bbbd442SRobert Mustacchi 	VERIFY3U(led, <, 3);
1086*6bbbd442SRobert Mustacchi 	return (led * 8);
1087*6bbbd442SRobert Mustacchi }
1088*6bbbd442SRobert Mustacchi 
1089*6bbbd442SRobert Mustacchi static inline uint32_t
igc_led_get_mode(uint32_t led,uint32_t reg)1090*6bbbd442SRobert Mustacchi igc_led_get_mode(uint32_t led, uint32_t reg)
1091*6bbbd442SRobert Mustacchi {
1092*6bbbd442SRobert Mustacchi 	uint32_t off = igc_led_bitoff(led);
1093*6bbbd442SRobert Mustacchi 	return (bitx32(reg, 3 + off, off));
1094*6bbbd442SRobert Mustacchi }
1095*6bbbd442SRobert Mustacchi 
1096*6bbbd442SRobert Mustacchi static inline uint32_t
igc_led_set_mode(uint32_t led,uint32_t reg,i225_led_mode_t mode)1097*6bbbd442SRobert Mustacchi igc_led_set_mode(uint32_t led, uint32_t reg, i225_led_mode_t mode)
1098*6bbbd442SRobert Mustacchi {
1099*6bbbd442SRobert Mustacchi 	uint32_t off = igc_led_bitoff(led);
1100*6bbbd442SRobert Mustacchi 	return (bitset32(reg, 3 + off, off, mode));
1101*6bbbd442SRobert Mustacchi }
1102*6bbbd442SRobert Mustacchi 
1103*6bbbd442SRobert Mustacchi static inline uint32_t
igc_led_get_ivrt(uint32_t led,uint32_t reg)1104*6bbbd442SRobert Mustacchi igc_led_get_ivrt(uint32_t led, uint32_t reg)
1105*6bbbd442SRobert Mustacchi {
1106*6bbbd442SRobert Mustacchi 	uint32_t off = igc_led_bitoff(led) + 6;
1107*6bbbd442SRobert Mustacchi 	return (bitx32(reg, off, off));
1108*6bbbd442SRobert Mustacchi }
1109*6bbbd442SRobert Mustacchi 
1110*6bbbd442SRobert Mustacchi static inline uint32_t
igc_led_set_blink(uint32_t led,uint32_t reg,bool en)1111*6bbbd442SRobert Mustacchi igc_led_set_blink(uint32_t led, uint32_t reg, bool en)
1112*6bbbd442SRobert Mustacchi {
1113*6bbbd442SRobert Mustacchi 	uint32_t off = igc_led_bitoff(led) + 7;
1114*6bbbd442SRobert Mustacchi 	return (bitset32(reg, off, off, en));
1115*6bbbd442SRobert Mustacchi }
1116*6bbbd442SRobert Mustacchi 
1117*6bbbd442SRobert Mustacchi /*
1118*6bbbd442SRobert Mustacchi  * There are three LEDs on the chip. The reference defines LED0 for 1 GbE link
1119*6bbbd442SRobert Mustacchi  * up, LED1 for a 2.5GbE link up, and LED 2 for activity. However, this is all
1120*6bbbd442SRobert Mustacchi  * controllable in the NVM so we shouldn't assume that these have any of their
1121*6bbbd442SRobert Mustacchi  * default values. We instead read the LEDCTL register to see how it was set up
1122*6bbbd442SRobert Mustacchi  * by default (though the NVM would likely be better). We then create pre-canned
1123*6bbbd442SRobert Mustacchi  * LEDCTL register values for on, off, and default. See igc_osdep.h for some of
1124*6bbbd442SRobert Mustacchi  * the caveats in definitions here. Note, we only tweak the non-activity LEDs
1125*6bbbd442SRobert Mustacchi  * and if an LED has been indicated that it's being used for SDP, we don't touch
1126*6bbbd442SRobert Mustacchi  * it.
1127*6bbbd442SRobert Mustacchi  */
1128*6bbbd442SRobert Mustacchi static void
igc_led_init(igc_t * igc)1129*6bbbd442SRobert Mustacchi igc_led_init(igc_t *igc)
1130*6bbbd442SRobert Mustacchi {
1131*6bbbd442SRobert Mustacchi 	uint32_t led = igc_read32(igc, IGC_LEDCTL);
1132*6bbbd442SRobert Mustacchi 
1133*6bbbd442SRobert Mustacchi 	igc->igc_ledctl = led;
1134*6bbbd442SRobert Mustacchi 	igc->igc_ledctl_on = led;
1135*6bbbd442SRobert Mustacchi 	igc->igc_ledctl_off = led;
1136*6bbbd442SRobert Mustacchi 	igc->igc_ledctl_blink = led;
1137*6bbbd442SRobert Mustacchi 
1138*6bbbd442SRobert Mustacchi 	for (uint32_t i = 0; i < IGC_I225_NLEDS; i++) {
1139*6bbbd442SRobert Mustacchi 		i225_led_mode_t mode = igc_led_get_mode(i, led);
1140*6bbbd442SRobert Mustacchi 		if (!igc_led_ignore(mode)) {
1141*6bbbd442SRobert Mustacchi 			/*
1142*6bbbd442SRobert Mustacchi 			 * If the inversion logic is on, that changes what the
1143*6bbbd442SRobert Mustacchi 			 * on and off modes mean, so we need to change how we
1144*6bbbd442SRobert Mustacchi 			 * set that appropriately.
1145*6bbbd442SRobert Mustacchi 			 */
1146*6bbbd442SRobert Mustacchi 			if (igc_led_get_ivrt(i, led) != 0) {
1147*6bbbd442SRobert Mustacchi 				igc->igc_ledctl_on = igc_led_set_mode(i,
1148*6bbbd442SRobert Mustacchi 				    igc->igc_ledctl_on, I225_LED_M_OFF);
1149*6bbbd442SRobert Mustacchi 				igc->igc_ledctl_off = igc_led_set_mode(i,
1150*6bbbd442SRobert Mustacchi 				    igc->igc_ledctl_off, I225_LED_M_ON);
1151*6bbbd442SRobert Mustacchi 				igc->igc_ledctl_blink = igc_led_set_mode(i,
1152*6bbbd442SRobert Mustacchi 				    igc->igc_ledctl_blink, I225_LED_M_OFF);
1153*6bbbd442SRobert Mustacchi 			} else {
1154*6bbbd442SRobert Mustacchi 				igc->igc_ledctl_on = igc_led_set_mode(i,
1155*6bbbd442SRobert Mustacchi 				    igc->igc_ledctl_on, I225_LED_M_ON);
1156*6bbbd442SRobert Mustacchi 				igc->igc_ledctl_off = igc_led_set_mode(i,
1157*6bbbd442SRobert Mustacchi 				    igc->igc_ledctl_off, I225_LED_M_OFF);
1158*6bbbd442SRobert Mustacchi 				igc->igc_ledctl_blink = igc_led_set_mode(i,
1159*6bbbd442SRobert Mustacchi 				    igc->igc_ledctl_blink, I225_LED_M_ON);
1160*6bbbd442SRobert Mustacchi 			}
1161*6bbbd442SRobert Mustacchi 		}
1162*6bbbd442SRobert Mustacchi 
1163*6bbbd442SRobert Mustacchi 		igc->igc_ledctl_blink = igc_led_set_blink(i,
1164*6bbbd442SRobert Mustacchi 		    igc->igc_ledctl_blink, true);
1165*6bbbd442SRobert Mustacchi 	}
1166*6bbbd442SRobert Mustacchi 
1167*6bbbd442SRobert Mustacchi 	igc->igc_led_mode = MAC_LED_DEFAULT;
1168*6bbbd442SRobert Mustacchi }
1169*6bbbd442SRobert Mustacchi 
1170*6bbbd442SRobert Mustacchi static void
igc_write_ivar(igc_t * igc,uint32_t queue,bool rx,uint32_t msix)1171*6bbbd442SRobert Mustacchi igc_write_ivar(igc_t *igc, uint32_t queue, bool rx, uint32_t msix)
1172*6bbbd442SRobert Mustacchi {
1173*6bbbd442SRobert Mustacchi 	const uint32_t ivarno = queue >> 1;
1174*6bbbd442SRobert Mustacchi 	const uint32_t reg = IGC_IVAR0 + ivarno * 4;
1175*6bbbd442SRobert Mustacchi 	const uint32_t val = msix | IGC_IVAR_VALID;
1176*6bbbd442SRobert Mustacchi 	uint32_t bitoff, bitend, ivar;
1177*6bbbd442SRobert Mustacchi 
1178*6bbbd442SRobert Mustacchi 	if (rx) {
1179*6bbbd442SRobert Mustacchi 		if ((queue % 2) == 0) {
1180*6bbbd442SRobert Mustacchi 			bitoff = IGC_IVAR_RX0_START;
1181*6bbbd442SRobert Mustacchi 		} else {
1182*6bbbd442SRobert Mustacchi 			bitoff = IGC_IVAR_RX1_START;
1183*6bbbd442SRobert Mustacchi 		}
1184*6bbbd442SRobert Mustacchi 	} else {
1185*6bbbd442SRobert Mustacchi 		if ((queue % 2) == 0) {
1186*6bbbd442SRobert Mustacchi 			bitoff = IGC_IVAR_TX0_START;
1187*6bbbd442SRobert Mustacchi 		} else {
1188*6bbbd442SRobert Mustacchi 			bitoff = IGC_IVAR_TX1_START;
1189*6bbbd442SRobert Mustacchi 		}
1190*6bbbd442SRobert Mustacchi 	}
1191*6bbbd442SRobert Mustacchi 	bitend = bitoff + IGC_IVAR_ENT_LEN - 1;
1192*6bbbd442SRobert Mustacchi 
1193*6bbbd442SRobert Mustacchi 	ivar = igc_read32(igc, reg);
1194*6bbbd442SRobert Mustacchi 	ivar = bitset32(ivar, bitend, bitoff, val);
1195*6bbbd442SRobert Mustacchi 	igc_write32(igc, reg, ivar);
1196*6bbbd442SRobert Mustacchi 	igc->igc_eims |= 1 << msix;
1197*6bbbd442SRobert Mustacchi }
1198*6bbbd442SRobert Mustacchi 
1199*6bbbd442SRobert Mustacchi /*
1200*6bbbd442SRobert Mustacchi  * Here we need to go through and initialize the hardware's notion of how
1201*6bbbd442SRobert Mustacchi  * interrupts are mapped to causes. The device must be specifically enabled for
1202*6bbbd442SRobert Mustacchi  * MSI-X and then this is also where we go ensure that all of our interrupt
1203*6bbbd442SRobert Mustacchi  * coalescing is properly enabled. Note, we must first touch the GPIE register
1204*6bbbd442SRobert Mustacchi  * to enable MSI-X settings otherwise later settings won't do anything.
1205*6bbbd442SRobert Mustacchi  */
1206*6bbbd442SRobert Mustacchi static void
igc_hw_intr_init(igc_t * igc)1207*6bbbd442SRobert Mustacchi igc_hw_intr_init(igc_t *igc)
1208*6bbbd442SRobert Mustacchi {
1209*6bbbd442SRobert Mustacchi 	uint32_t gpie, ivar;
1210*6bbbd442SRobert Mustacchi 
1211*6bbbd442SRobert Mustacchi 	gpie = IGC_GPIE_NSICR | IGC_GPIE_MSIX_MODE | IGC_GPIE_EIAME |
1212*6bbbd442SRobert Mustacchi 	    IGC_GPIE_PBA;
1213*6bbbd442SRobert Mustacchi 	igc_write32(igc, IGC_GPIE, gpie);
1214*6bbbd442SRobert Mustacchi 
1215*6bbbd442SRobert Mustacchi 	/*
1216*6bbbd442SRobert Mustacchi 	 * Other causes are always explicitly mapped to cause 0. Each ring then
1217*6bbbd442SRobert Mustacchi 	 * has its own mapping. In the MISC IVAR, these start at bit 8. We leave
1218*6bbbd442SRobert Mustacchi 	 * the '0 |' out below just to avoid a compiler complaining. We also
1219*6bbbd442SRobert Mustacchi 	 * must unamsk this interrupt cause, which is in bit 0.
1220*6bbbd442SRobert Mustacchi 	 */
1221*6bbbd442SRobert Mustacchi 	ivar = IGC_IVAR_VALID << 8;
1222*6bbbd442SRobert Mustacchi 	igc_write32(igc, IGC_IVAR_MISC, ivar);
1223*6bbbd442SRobert Mustacchi 	igc->igc_eims = 1;
1224*6bbbd442SRobert Mustacchi 
1225*6bbbd442SRobert Mustacchi 	/*
1226*6bbbd442SRobert Mustacchi 	 * There are a few IVAR registers available in hardware. Each IVAR
1227*6bbbd442SRobert Mustacchi 	 * register handles mapping a given queue to an MSI-X. Each IVAR handles
1228*6bbbd442SRobert Mustacchi 	 * two queues.
1229*6bbbd442SRobert Mustacchi 	 */
1230*6bbbd442SRobert Mustacchi 	for (uint32_t i = 0; i < igc->igc_ntx_rings; i++) {
1231*6bbbd442SRobert Mustacchi 		igc_write_ivar(igc, i, false,
1232*6bbbd442SRobert Mustacchi 		    igc->igc_tx_rings[i].itr_intr_idx);
1233*6bbbd442SRobert Mustacchi 	}
1234*6bbbd442SRobert Mustacchi 
1235*6bbbd442SRobert Mustacchi 	for (uint32_t i = 0; i < igc->igc_nrx_rings; i++) {
1236*6bbbd442SRobert Mustacchi 		igc_write_ivar(igc, i, true, igc->igc_rx_rings[i].irr_intr_idx);
1237*6bbbd442SRobert Mustacchi 	}
1238*6bbbd442SRobert Mustacchi 
1239*6bbbd442SRobert Mustacchi 	for (uint32_t i = 0; i < igc->igc_nintrs; i++) {
1240*6bbbd442SRobert Mustacchi 		igc_write32(igc, IGC_EITR(i), igc->igc_eitr);
1241*6bbbd442SRobert Mustacchi 	}
1242*6bbbd442SRobert Mustacchi }
1243*6bbbd442SRobert Mustacchi 
1244*6bbbd442SRobert Mustacchi /*
1245*6bbbd442SRobert Mustacchi  * Synchronize our sense of the unicast table over to the device. If this is the
1246*6bbbd442SRobert Mustacchi  * first time that we're here due to attach, we need to go through and allocate
1247*6bbbd442SRobert Mustacchi  * the tracking table.
1248*6bbbd442SRobert Mustacchi  */
1249*6bbbd442SRobert Mustacchi static void
igc_unicast_sync(igc_t * igc)1250*6bbbd442SRobert Mustacchi igc_unicast_sync(igc_t *igc)
1251*6bbbd442SRobert Mustacchi {
1252*6bbbd442SRobert Mustacchi 	ASSERT(MUTEX_HELD(&igc->igc_lock));
1253*6bbbd442SRobert Mustacchi 
1254*6bbbd442SRobert Mustacchi 	if (igc->igc_ucast == NULL) {
1255*6bbbd442SRobert Mustacchi 		igc->igc_nucast = igc->igc_hw.mac.rar_entry_count;
1256*6bbbd442SRobert Mustacchi 		igc->igc_ucast = kmem_zalloc(sizeof (igc_addr_t) *
1257*6bbbd442SRobert Mustacchi 		    igc->igc_nucast, KM_SLEEP);
1258*6bbbd442SRobert Mustacchi 	}
1259*6bbbd442SRobert Mustacchi 
1260*6bbbd442SRobert Mustacchi 	for (uint16_t i = 0; i < igc->igc_nucast; i++) {
1261*6bbbd442SRobert Mustacchi 		int ret = igc_rar_set(&igc->igc_hw, igc->igc_ucast[i].ia_mac,
1262*6bbbd442SRobert Mustacchi 		    i);
1263*6bbbd442SRobert Mustacchi 		/*
1264*6bbbd442SRobert Mustacchi 		 * Common code today guarantees this can't fail. Put this here
1265*6bbbd442SRobert Mustacchi 		 * to ensure to guard against future updates.
1266*6bbbd442SRobert Mustacchi 		 */
1267*6bbbd442SRobert Mustacchi 		VERIFY3S(ret, ==, IGC_SUCCESS);
1268*6bbbd442SRobert Mustacchi 	}
1269*6bbbd442SRobert Mustacchi 
1270*6bbbd442SRobert Mustacchi }
1271*6bbbd442SRobert Mustacchi 
1272*6bbbd442SRobert Mustacchi /*
1273*6bbbd442SRobert Mustacchi  * The core code interface to the multicast table requires us to give them a
1274*6bbbd442SRobert Mustacchi  * packed uint8_t array that they manually walk through in ETHERADDRL (6 byte)
1275*6bbbd442SRobert Mustacchi  * chunks. This must be packed. To deal with this we opt to preserve a normal
1276*6bbbd442SRobert Mustacchi  * list of multicast addresses and then a secondary version that's serialized as
1277*6bbbd442SRobert Mustacchi  * the core code wants it. We allocate the memory for this secondary version at
1278*6bbbd442SRobert Mustacchi  * the start.
1279*6bbbd442SRobert Mustacchi  */
1280*6bbbd442SRobert Mustacchi void
igc_multicast_sync(igc_t * igc)1281*6bbbd442SRobert Mustacchi igc_multicast_sync(igc_t *igc)
1282*6bbbd442SRobert Mustacchi {
1283*6bbbd442SRobert Mustacchi 	uint16_t nvalid;
1284*6bbbd442SRobert Mustacchi 
1285*6bbbd442SRobert Mustacchi 	ASSERT(MUTEX_HELD(&igc->igc_lock));
1286*6bbbd442SRobert Mustacchi 
1287*6bbbd442SRobert Mustacchi 	if (igc->igc_mcast == NULL) {
1288*6bbbd442SRobert Mustacchi 		igc->igc_nmcast = igc->igc_hw.mac.mta_reg_count;
1289*6bbbd442SRobert Mustacchi 		igc->igc_mcast = kmem_zalloc(sizeof (igc_addr_t) *
1290*6bbbd442SRobert Mustacchi 		    igc->igc_nmcast, KM_SLEEP);
1291*6bbbd442SRobert Mustacchi 		igc->igc_mcast_raw = kmem_alloc(sizeof (ether_addr_t) *
1292*6bbbd442SRobert Mustacchi 		    igc->igc_nmcast, KM_SLEEP);
1293*6bbbd442SRobert Mustacchi 	}
1294*6bbbd442SRobert Mustacchi 
1295*6bbbd442SRobert Mustacchi 	bzero(igc->igc_mcast_raw, sizeof (ether_addr_t) * igc->igc_nmcast);
1296*6bbbd442SRobert Mustacchi 	nvalid = 0;
1297*6bbbd442SRobert Mustacchi 	for (uint16_t i = 0; i < igc->igc_nmcast; i++) {
1298*6bbbd442SRobert Mustacchi 		ether_addr_t *targ = &igc->igc_mcast_raw[nvalid];
1299*6bbbd442SRobert Mustacchi 
1300*6bbbd442SRobert Mustacchi 		if (!igc->igc_mcast[i].ia_valid)
1301*6bbbd442SRobert Mustacchi 			continue;
1302*6bbbd442SRobert Mustacchi 		bcopy(igc->igc_mcast[i].ia_mac, targ, sizeof (ether_addr_t));
1303*6bbbd442SRobert Mustacchi 		nvalid++;
1304*6bbbd442SRobert Mustacchi 	}
1305*6bbbd442SRobert Mustacchi 
1306*6bbbd442SRobert Mustacchi 	igc_update_mc_addr_list(&igc->igc_hw, (uint8_t *)igc->igc_mcast_raw,
1307*6bbbd442SRobert Mustacchi 	    nvalid);
1308*6bbbd442SRobert Mustacchi }
1309*6bbbd442SRobert Mustacchi 
1310*6bbbd442SRobert Mustacchi /*
1311*6bbbd442SRobert Mustacchi  * This function is used to reinitialize the PBA, our various flow control
1312*6bbbd442SRobert Mustacchi  * settings, reset hardware, ensure that the EEE, DPLU, and related power modes
1313*6bbbd442SRobert Mustacchi  * are in the correct state.
1314*6bbbd442SRobert Mustacchi  */
1315*6bbbd442SRobert Mustacchi bool
igc_hw_common_init(igc_t * igc)1316*6bbbd442SRobert Mustacchi igc_hw_common_init(igc_t *igc)
1317*6bbbd442SRobert Mustacchi {
1318*6bbbd442SRobert Mustacchi 	int ret;
1319*6bbbd442SRobert Mustacchi 	uint32_t pba, hwm, hwmp, hwm2x;
1320*6bbbd442SRobert Mustacchi 	struct igc_hw *hw = &igc->igc_hw;
1321*6bbbd442SRobert Mustacchi 
1322*6bbbd442SRobert Mustacchi 	/*
1323*6bbbd442SRobert Mustacchi 	 * The PBA register determines which portion is used for the receive
1324*6bbbd442SRobert Mustacchi 	 * buffers and which is used for the transmit buffers. This follows from
1325*6bbbd442SRobert Mustacchi 	 * the I210 and reference drivers which use 34K as the default. We
1326*6bbbd442SRobert Mustacchi 	 * currently leave the RXPBS and TXPBS at their power-on-reset defaults.
1327*6bbbd442SRobert Mustacchi 	 *
1328*6bbbd442SRobert Mustacchi 	 * We set the watermark based settings similar to igb, ensuring that we
1329*6bbbd442SRobert Mustacchi 	 * have 16-byte granularity. The general guidelines from there was that
1330*6bbbd442SRobert Mustacchi 	 * when it comes to automatic Ethernet PAUSE frame generation we should:
1331*6bbbd442SRobert Mustacchi 	 *
1332*6bbbd442SRobert Mustacchi 	 * - After an XOFF, you want to receive at least two frames. We use
1333*6bbbd442SRobert Mustacchi 	 *   whichever is smaller of 9/10ths and two frames.
1334*6bbbd442SRobert Mustacchi 	 * - The low water mark apparently wants to be closer to the high water
1335*6bbbd442SRobert Mustacchi 	 *   mark.
1336*6bbbd442SRobert Mustacchi 	 *
1337*6bbbd442SRobert Mustacchi 	 * See igb_init_adapter() for more information. We basically use the
1338*6bbbd442SRobert Mustacchi 	 * same calculation it did, given that the MAC is basically the same.
1339*6bbbd442SRobert Mustacchi 	 */
1340*6bbbd442SRobert Mustacchi 	pba = IGC_PBA_34K;
1341*6bbbd442SRobert Mustacchi 	hwmp = (pba << 10) * 9 / 10;
1342*6bbbd442SRobert Mustacchi 	hwm2x = (pba << 10) - 2 * igc->igc_max_frame;
1343*6bbbd442SRobert Mustacchi 	hwm = MIN(hwmp, hwm2x);
1344*6bbbd442SRobert Mustacchi 
1345*6bbbd442SRobert Mustacchi 	hw->fc.high_water = hwm & 0xfffffff0;
1346*6bbbd442SRobert Mustacchi 	hw->fc.low_water = igc->igc_hw.fc.high_water - 16;
1347*6bbbd442SRobert Mustacchi 
1348*6bbbd442SRobert Mustacchi 	/*
1349*6bbbd442SRobert Mustacchi 	 * Use the suggested default pause time.
1350*6bbbd442SRobert Mustacchi 	 */
1351*6bbbd442SRobert Mustacchi 	hw->fc.pause_time = IGC_FC_PAUSE_TIME;
1352*6bbbd442SRobert Mustacchi 	hw->fc.send_xon = true;
1353*6bbbd442SRobert Mustacchi 
1354*6bbbd442SRobert Mustacchi 	if ((ret = igc_reset_hw(hw)) != IGC_SUCCESS) {
1355*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to reset device: %d",
1356*6bbbd442SRobert Mustacchi 		    ret);
1357*6bbbd442SRobert Mustacchi 		return (false);
1358*6bbbd442SRobert Mustacchi 	}
1359*6bbbd442SRobert Mustacchi 
1360*6bbbd442SRobert Mustacchi 	if ((ret = igc_init_hw(hw)) != IGC_SUCCESS) {
1361*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to init hardware: %d",
1362*6bbbd442SRobert Mustacchi 		    ret);
1363*6bbbd442SRobert Mustacchi 		return (false);
1364*6bbbd442SRobert Mustacchi 	}
1365*6bbbd442SRobert Mustacchi 
1366*6bbbd442SRobert Mustacchi 	/*
1367*6bbbd442SRobert Mustacchi 	 * Clear wake on LAN and set other power states. In addition, disable
1368*6bbbd442SRobert Mustacchi 	 * EEE for now.
1369*6bbbd442SRobert Mustacchi 	 */
1370*6bbbd442SRobert Mustacchi 	igc_write32(igc, IGC_WUC, 0);
1371*6bbbd442SRobert Mustacchi 
1372*6bbbd442SRobert Mustacchi 	if ((ret = igc_set_d0_lplu_state(hw, false)) != IGC_SUCCESS) {
1373*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to set D0 LPLU mode: %d",
1374*6bbbd442SRobert Mustacchi 		    ret);
1375*6bbbd442SRobert Mustacchi 		return (false);
1376*6bbbd442SRobert Mustacchi 	}
1377*6bbbd442SRobert Mustacchi 
1378*6bbbd442SRobert Mustacchi 	/*
1379*6bbbd442SRobert Mustacchi 	 * There have been reports that enabling EEE for some 2.5G devices has
1380*6bbbd442SRobert Mustacchi 	 * led to issues with the I225/226. It's not entirely clear, but we
1381*6bbbd442SRobert Mustacchi 	 * default to disabling this like in igb/e1000g for now.
1382*6bbbd442SRobert Mustacchi 	 */
1383*6bbbd442SRobert Mustacchi 	if ((ret = igc_set_eee_i225(hw, false, false, false)) != IGC_SUCCESS) {
1384*6bbbd442SRobert Mustacchi 		dev_err(igc->igc_dip, CE_WARN, "failed to set EEE mode: %d",
1385*6bbbd442SRobert Mustacchi 		    ret);
1386*6bbbd442SRobert Mustacchi 		return (false);
1387*6bbbd442SRobert Mustacchi 	}
1388*6bbbd442SRobert Mustacchi 
1389*6bbbd442SRobert Mustacchi 	igc_hw_intr_init(igc);
1390*6bbbd442SRobert Mustacchi 
1391*6bbbd442SRobert Mustacchi 	mutex_enter(&igc->igc_lock);
1392*6bbbd442SRobert Mustacchi 	igc_unicast_sync(igc);
1393*6bbbd442SRobert Mustacchi 	igc_multicast_sync(igc);
1394*6bbbd442SRobert Mustacchi 
1395*6bbbd442SRobert Mustacchi 	igc->igc_hw.mac.get_link_status = true;
1396*6bbbd442SRobert Mustacchi 	(void) igc_get_phy_info(hw);
1397*6bbbd442SRobert Mustacchi 	(void) igc_check_for_link(hw);
1398*6bbbd442SRobert Mustacchi 	mutex_exit(&igc->igc_lock);
1399*6bbbd442SRobert Mustacchi 
1400*6bbbd442SRobert Mustacchi 	return (true);
1401*6bbbd442SRobert Mustacchi }
1402*6bbbd442SRobert Mustacchi 
1403*6bbbd442SRobert Mustacchi static bool
igc_intr_en(igc_t * igc)1404*6bbbd442SRobert Mustacchi igc_intr_en(igc_t *igc)
1405*6bbbd442SRobert Mustacchi {
1406*6bbbd442SRobert Mustacchi 	int ret;
1407*6bbbd442SRobert Mustacchi 
1408*6bbbd442SRobert Mustacchi 	if ((igc->igc_intr_cap & DDI_INTR_FLAG_BLOCK) != 0) {
1409*6bbbd442SRobert Mustacchi 		ret = ddi_intr_block_enable(igc->igc_intr_handles,
1410*6bbbd442SRobert Mustacchi 		    igc->igc_nintrs);
1411*6bbbd442SRobert Mustacchi 		if (ret != DDI_SUCCESS) {
1412*6bbbd442SRobert Mustacchi 			dev_err(igc->igc_dip, CE_WARN, "failed to block "
1413*6bbbd442SRobert Mustacchi 			    "enable interrupts: %d", ret);
1414*6bbbd442SRobert Mustacchi 			return (false);
1415*6bbbd442SRobert Mustacchi 		}
1416*6bbbd442SRobert Mustacchi 	} else {
1417*6bbbd442SRobert Mustacchi 		for (int i = 0; i < igc->igc_nintrs; i++) {
1418*6bbbd442SRobert Mustacchi 			ret = ddi_intr_enable(igc->igc_intr_handles[i]);
1419*6bbbd442SRobert Mustacchi 			if (ret != DDI_SUCCESS) {
1420*6bbbd442SRobert Mustacchi 				dev_err(igc->igc_dip, CE_WARN, "failed to "
1421*6bbbd442SRobert Mustacchi 				    "enable interrupt %d: %d", i, ret);
1422*6bbbd442SRobert Mustacchi 				for (int clean = 0; clean < i; clean++) {
1423*6bbbd442SRobert Mustacchi 					ret = ddi_intr_disable(
1424*6bbbd442SRobert Mustacchi 					    igc->igc_intr_handles[clean]);
1425*6bbbd442SRobert Mustacchi 					if (ret != DDI_SUCCESS) {
1426*6bbbd442SRobert Mustacchi 						dev_err(igc->igc_dip, CE_WARN,
1427*6bbbd442SRobert Mustacchi 						    "failed to disable "
1428*6bbbd442SRobert Mustacchi 						    "interrupt %d while "
1429*6bbbd442SRobert Mustacchi 						    "unwinding: %d", i, ret);
1430*6bbbd442SRobert Mustacchi 					}
1431*6bbbd442SRobert Mustacchi 				}
1432*6bbbd442SRobert Mustacchi 				return (false);
1433*6bbbd442SRobert Mustacchi 			}
1434*6bbbd442SRobert Mustacchi 		}
1435*6bbbd442SRobert Mustacchi 	}
1436*6bbbd442SRobert Mustacchi 
1437*6bbbd442SRobert Mustacchi 	/*
1438*6bbbd442SRobert Mustacchi 	 * Now that we've enabled interrupts here, clear any pending interrupts
1439*6bbbd442SRobert Mustacchi 	 * and make sure hardware interrupts are enabled.
1440*6bbbd442SRobert Mustacchi 	 */
1441*6bbbd442SRobert Mustacchi 	(void) igc_read32(igc, IGC_ICR);
1442*6bbbd442SRobert Mustacchi 
1443*6bbbd442SRobert Mustacchi 	return (true);
1444*6bbbd442SRobert Mustacchi }
1445*6bbbd442SRobert Mustacchi 
1446*6bbbd442SRobert Mustacchi /*
1447*6bbbd442SRobert Mustacchi  * Undo interrupt enablement.
1448*6bbbd442SRobert Mustacchi  */
1449*6bbbd442SRobert Mustacchi void
igc_hw_intr_disable(igc_t * igc)1450*6bbbd442SRobert Mustacchi igc_hw_intr_disable(igc_t *igc)
1451*6bbbd442SRobert Mustacchi {
1452*6bbbd442SRobert Mustacchi 	igc_write32(igc, IGC_EIMC, UINT32_MAX);
1453*6bbbd442SRobert Mustacchi 	igc_write32(igc, IGC_EIAC, 0);
1454*6bbbd442SRobert Mustacchi 	igc_write32(igc, IGC_IMC, UINT32_MAX);
1455*6bbbd442SRobert Mustacchi }
1456*6bbbd442SRobert Mustacchi 
1457*6bbbd442SRobert Mustacchi /*
1458*6bbbd442SRobert Mustacchi  * This is used during the GLDv3 mc_start(9E) entry point to enable interrupts
1459*6bbbd442SRobert Mustacchi  * on the device itself.
1460*6bbbd442SRobert Mustacchi  */
1461*6bbbd442SRobert Mustacchi void
igc_hw_intr_enable(igc_t * igc)1462*6bbbd442SRobert Mustacchi igc_hw_intr_enable(igc_t *igc)
1463*6bbbd442SRobert Mustacchi {
1464*6bbbd442SRobert Mustacchi 	uint32_t ims;
1465*6bbbd442SRobert Mustacchi 
1466*6bbbd442SRobert Mustacchi 	/*
1467*6bbbd442SRobert Mustacchi 	 * First we clear pending interrupts.
1468*6bbbd442SRobert Mustacchi 	 */
1469*6bbbd442SRobert Mustacchi 	(void) igc_read32(igc, IGC_ICR);
1470*6bbbd442SRobert Mustacchi 
1471*6bbbd442SRobert Mustacchi 	/*
1472*6bbbd442SRobert Mustacchi 	 * The hardware has extended and non-extended interrupt masks and
1473*6bbbd442SRobert Mustacchi 	 * auto-clear registers. We always disable auto-clear for the
1474*6bbbd442SRobert Mustacchi 	 * non-extended portions. See the I210 datasheet 'Setting Interrupt
1475*6bbbd442SRobert Mustacchi 	 * Registers' for a better sense of what's going on here.
1476*6bbbd442SRobert Mustacchi 	 *
1477*6bbbd442SRobert Mustacchi 	 * In the IMS register we always register link status change events and
1478*6bbbd442SRobert Mustacchi 	 * device reset assertions.
1479*6bbbd442SRobert Mustacchi 	 */
1480*6bbbd442SRobert Mustacchi 	ims = IGC_IMS_LSC | IGC_IMS_DRSTA;
1481*6bbbd442SRobert Mustacchi 
1482*6bbbd442SRobert Mustacchi 	igc_write32(igc, IGC_EIAC, igc->igc_eims);
1483*6bbbd442SRobert Mustacchi 	igc_write32(igc, IGC_EIMS, igc->igc_eims);
1484*6bbbd442SRobert Mustacchi 	igc_write32(igc, IGC_IMS, ims);
1485*6bbbd442SRobert Mustacchi 	igc_write32(igc, IGC_IAM, 0);
1486*6bbbd442SRobert Mustacchi }
1487*6bbbd442SRobert Mustacchi 
1488*6bbbd442SRobert Mustacchi static void
igc_cleanup(igc_t * igc)1489*6bbbd442SRobert Mustacchi igc_cleanup(igc_t *igc)
1490*6bbbd442SRobert Mustacchi {
1491*6bbbd442SRobert Mustacchi 	if (igc->igc_mcast != NULL) {
1492*6bbbd442SRobert Mustacchi 		ASSERT3U(igc->igc_nmcast, !=, 0);
1493*6bbbd442SRobert Mustacchi 		kmem_free(igc->igc_mcast_raw, sizeof (ether_addr_t) *
1494*6bbbd442SRobert Mustacchi 		    igc->igc_nmcast);
1495*6bbbd442SRobert Mustacchi 		kmem_free(igc->igc_mcast, sizeof (igc_addr_t) *
1496*6bbbd442SRobert Mustacchi 		    igc->igc_nmcast);
1497*6bbbd442SRobert Mustacchi 		igc->igc_nmcast = 0;
1498*6bbbd442SRobert Mustacchi 		igc->igc_mcast = NULL;
1499*6bbbd442SRobert Mustacchi 	}
1500*6bbbd442SRobert Mustacchi 
1501*6bbbd442SRobert Mustacchi 	if (igc->igc_ucast != NULL) {
1502*6bbbd442SRobert Mustacchi 		ASSERT3U(igc->igc_nucast, !=, 0);
1503*6bbbd442SRobert Mustacchi 		kmem_free(igc->igc_ucast, sizeof (igc_addr_t) *
1504*6bbbd442SRobert Mustacchi 		    igc->igc_nucast);
1505*6bbbd442SRobert Mustacchi 		igc->igc_nucast = 0;
1506*6bbbd442SRobert Mustacchi 		igc->igc_ucast = NULL;
1507*6bbbd442SRobert Mustacchi 	}
1508*6bbbd442SRobert Mustacchi 
1509*6bbbd442SRobert Mustacchi 	if ((igc->igc_attach & IGC_ATTACH_INTR_EN) != 0) {
1510*6bbbd442SRobert Mustacchi 		int ret;
1511*6bbbd442SRobert Mustacchi 		if ((igc->igc_intr_cap & DDI_INTR_FLAG_BLOCK) != 0) {
1512*6bbbd442SRobert Mustacchi 			ret = ddi_intr_block_disable(igc->igc_intr_handles,
1513*6bbbd442SRobert Mustacchi 			    igc->igc_nintrs);
1514*6bbbd442SRobert Mustacchi 			if (ret != DDI_SUCCESS) {
1515*6bbbd442SRobert Mustacchi 				dev_err(igc->igc_dip, CE_WARN, "failed to "
1516*6bbbd442SRobert Mustacchi 				    "block disable interrupts: %d", ret);
1517*6bbbd442SRobert Mustacchi 			}
1518*6bbbd442SRobert Mustacchi 		} else {
1519*6bbbd442SRobert Mustacchi 			for (int i = 0; i < igc->igc_nintrs; i++) {
1520*6bbbd442SRobert Mustacchi 				ret = ddi_intr_disable(
1521*6bbbd442SRobert Mustacchi 				    igc->igc_intr_handles[i]);
1522*6bbbd442SRobert Mustacchi 				if (ret != DDI_SUCCESS) {
1523*6bbbd442SRobert Mustacchi 					dev_err(igc->igc_dip, CE_WARN, "failed "
1524*6bbbd442SRobert Mustacchi 					    "to disable interrupt %d: %d", i,
1525*6bbbd442SRobert Mustacchi 					    ret);
1526*6bbbd442SRobert Mustacchi 				}
1527*6bbbd442SRobert Mustacchi 			}
1528*6bbbd442SRobert Mustacchi 		}
1529*6bbbd442SRobert Mustacchi 		igc->igc_attach &= ~IGC_ATTACH_INTR_EN;
1530*6bbbd442SRobert Mustacchi 	}
1531*6bbbd442SRobert Mustacchi 
1532*6bbbd442SRobert Mustacchi 	if ((igc->igc_attach & IGC_ATTACH_MAC) != 0) {
1533*6bbbd442SRobert Mustacchi 		int ret = mac_unregister(igc->igc_mac_hdl);
1534*6bbbd442SRobert Mustacchi 		if (ret != 0) {
1535*6bbbd442SRobert Mustacchi 			dev_err(igc->igc_dip, CE_WARN, "failed to unregister "
1536*6bbbd442SRobert Mustacchi 			    "MAC handle: %d", ret);
1537*6bbbd442SRobert Mustacchi 		}
1538*6bbbd442SRobert Mustacchi 		igc->igc_attach &= ~IGC_ATTACH_MAC;
1539*6bbbd442SRobert Mustacchi 	}
1540*6bbbd442SRobert Mustacchi 
1541*6bbbd442SRobert Mustacchi 	if ((igc->igc_attach & IGC_ATTACH_STATS) != 0) {
1542*6bbbd442SRobert Mustacchi 		igc_stats_fini(igc);
1543*6bbbd442SRobert Mustacchi 		igc->igc_attach &= ~IGC_ATTACH_STATS;
1544*6bbbd442SRobert Mustacchi 	}
1545*6bbbd442SRobert Mustacchi 
1546*6bbbd442SRobert Mustacchi 	if ((igc->igc_attach & IGC_ATTACH_LED) != 0) {
1547*6bbbd442SRobert Mustacchi 		igc_led_fini(igc);
1548*6bbbd442SRobert Mustacchi 		igc->igc_attach &= ~IGC_ATTACH_LED;
1549*6bbbd442SRobert Mustacchi 	}
1550*6bbbd442SRobert Mustacchi 
1551*6bbbd442SRobert Mustacchi 	if ((igc->igc_attach & IGC_ATTACH_INTR_HANDLER) != 0) {
1552*6bbbd442SRobert Mustacchi 		for (int i = 0; i < igc->igc_nintrs; i++) {
1553*6bbbd442SRobert Mustacchi 			int ret =
1554*6bbbd442SRobert Mustacchi 			    ddi_intr_remove_handler(igc->igc_intr_handles[i]);
1555*6bbbd442SRobert Mustacchi 			if (ret != 0) {
1556*6bbbd442SRobert Mustacchi 				dev_err(igc->igc_dip, CE_WARN, "failed to "
1557*6bbbd442SRobert Mustacchi 				    "remove interrupt %d handler: %d", i, ret);
1558*6bbbd442SRobert Mustacchi 			}
1559*6bbbd442SRobert Mustacchi 		}
1560*6bbbd442SRobert Mustacchi 		igc->igc_attach &= ~IGC_ATTACH_INTR_HANDLER;
1561*6bbbd442SRobert Mustacchi 	}
1562*6bbbd442SRobert Mustacchi 
1563*6bbbd442SRobert Mustacchi 	if (igc->igc_tx_rings != NULL) {
1564*6bbbd442SRobert Mustacchi 		for (uint32_t i = 0; i < igc->igc_ntx_rings; i++) {
1565*6bbbd442SRobert Mustacchi 			igc_tx_ring_stats_fini(&igc->igc_tx_rings[i]);
1566*6bbbd442SRobert Mustacchi 			mutex_destroy(&igc->igc_tx_rings[i].itr_lock);
1567*6bbbd442SRobert Mustacchi 		}
1568*6bbbd442SRobert Mustacchi 		kmem_free(igc->igc_tx_rings, sizeof (igc_tx_ring_t) *
1569*6bbbd442SRobert Mustacchi 		    igc->igc_ntx_rings);
1570*6bbbd442SRobert Mustacchi 		igc->igc_tx_rings = NULL;
1571*6bbbd442SRobert Mustacchi 	}
1572*6bbbd442SRobert Mustacchi 
1573*6bbbd442SRobert Mustacchi 	if (igc->igc_rx_rings != NULL) {
1574*6bbbd442SRobert Mustacchi 		for (uint32_t i = 0; i < igc->igc_nrx_rings; i++) {
1575*6bbbd442SRobert Mustacchi 			igc_rx_ring_stats_fini(&igc->igc_rx_rings[i]);
1576*6bbbd442SRobert Mustacchi 			cv_destroy(&igc->igc_rx_rings[i].irr_free_cv);
1577*6bbbd442SRobert Mustacchi 			mutex_destroy(&igc->igc_rx_rings[i].irr_free_lock);
1578*6bbbd442SRobert Mustacchi 			mutex_destroy(&igc->igc_rx_rings[i].irr_lock);
1579*6bbbd442SRobert Mustacchi 		}
1580*6bbbd442SRobert Mustacchi 		kmem_free(igc->igc_rx_rings, sizeof (igc_rx_ring_t) *
1581*6bbbd442SRobert Mustacchi 		    igc->igc_nrx_rings);
1582*6bbbd442SRobert Mustacchi 		igc->igc_rx_rings = NULL;
1583*6bbbd442SRobert Mustacchi 	}
1584*6bbbd442SRobert Mustacchi 
1585*6bbbd442SRobert Mustacchi 	if ((igc->igc_attach & IGC_ATTACH_MUTEX) != 0) {
1586*6bbbd442SRobert Mustacchi 		mutex_destroy(&igc->igc_lock);
1587*6bbbd442SRobert Mustacchi 		igc->igc_attach &= ~IGC_ATTACH_MUTEX;
1588*6bbbd442SRobert Mustacchi 	}
1589*6bbbd442SRobert Mustacchi 
1590*6bbbd442SRobert Mustacchi 	if ((igc->igc_attach & IGC_ATTACH_INTR_ALLOC) != 0) {
1591*6bbbd442SRobert Mustacchi 		for (int i = 0; i < igc->igc_nintrs; i++) {
1592*6bbbd442SRobert Mustacchi 			int ret = ddi_intr_free(igc->igc_intr_handles[i]);
1593*6bbbd442SRobert Mustacchi 			if (ret != DDI_SUCCESS) {
1594*6bbbd442SRobert Mustacchi 				dev_err(igc->igc_dip, CE_WARN, "unexpected "
1595*6bbbd442SRobert Mustacchi 				    "failure freeing interrupt %d: %d", i, ret);
1596*6bbbd442SRobert Mustacchi 			}
1597*6bbbd442SRobert Mustacchi 		}
1598*6bbbd442SRobert Mustacchi 		igc->igc_attach &= ~IGC_ATTACH_INTR_ALLOC;
1599*6bbbd442SRobert Mustacchi 	}
1600*6bbbd442SRobert Mustacchi 
1601*6bbbd442SRobert Mustacchi 	if (igc->igc_intr_handles != NULL) {
1602*6bbbd442SRobert Mustacchi 		ASSERT3U(igc->igc_intr_size, !=, 0);
1603*6bbbd442SRobert Mustacchi 		kmem_free(igc->igc_intr_handles, igc->igc_intr_size);
1604*6bbbd442SRobert Mustacchi 	}
1605*6bbbd442SRobert Mustacchi 
1606*6bbbd442SRobert Mustacchi 	/*
1607*6bbbd442SRobert Mustacchi 	 * Now that we're almost done, begrudgingly let firmware know we're
1608*6bbbd442SRobert Mustacchi 	 * done.
1609*6bbbd442SRobert Mustacchi 	 */
1610*6bbbd442SRobert Mustacchi 	igc_hw_control(igc, false);
1611*6bbbd442SRobert Mustacchi 
1612*6bbbd442SRobert Mustacchi 	if (igc->igc_regs_hdl != NULL) {
1613*6bbbd442SRobert Mustacchi 		ddi_regs_map_free(&igc->igc_regs_hdl);
1614*6bbbd442SRobert Mustacchi 		igc->igc_regs_base = NULL;
1615*6bbbd442SRobert Mustacchi 	}
1616*6bbbd442SRobert Mustacchi 
1617*6bbbd442SRobert Mustacchi 	if (igc->igc_cfgspace != NULL) {
1618*6bbbd442SRobert Mustacchi 		pci_config_teardown(&igc->igc_cfgspace);
1619*6bbbd442SRobert Mustacchi 	}
1620*6bbbd442SRobert Mustacchi 	igc->igc_attach &= ~IGC_ATTACH_REGS;
1621*6bbbd442SRobert Mustacchi 
1622*6bbbd442SRobert Mustacchi 	ddi_set_driver_private(igc->igc_dip, NULL);
1623*6bbbd442SRobert Mustacchi 	igc->igc_dip = NULL;
1624*6bbbd442SRobert Mustacchi 
1625*6bbbd442SRobert Mustacchi 	VERIFY0(igc->igc_attach);
1626*6bbbd442SRobert Mustacchi 
1627*6bbbd442SRobert Mustacchi 	kmem_free(igc, sizeof (igc_t));
1628*6bbbd442SRobert Mustacchi }
1629*6bbbd442SRobert Mustacchi 
1630*6bbbd442SRobert Mustacchi static int
igc_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)1631*6bbbd442SRobert Mustacchi igc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1632*6bbbd442SRobert Mustacchi {
1633*6bbbd442SRobert Mustacchi 	igc_t *igc;
1634*6bbbd442SRobert Mustacchi 
1635*6bbbd442SRobert Mustacchi 	if (cmd != DDI_ATTACH) {
1636*6bbbd442SRobert Mustacchi 		return (DDI_FAILURE);
1637*6bbbd442SRobert Mustacchi 	}
1638*6bbbd442SRobert Mustacchi 
1639*6bbbd442SRobert Mustacchi 	igc = kmem_zalloc(sizeof (igc_t), KM_SLEEP);
1640*6bbbd442SRobert Mustacchi 	ddi_set_driver_private(dip, igc);
1641*6bbbd442SRobert Mustacchi 	igc->igc_dip = dip;
1642*6bbbd442SRobert Mustacchi 
1643*6bbbd442SRobert Mustacchi 	/*
1644*6bbbd442SRobert Mustacchi 	 * Initialize a few members that are not zero-based.
1645*6bbbd442SRobert Mustacchi 	 */
1646*6bbbd442SRobert Mustacchi 	igc->igc_link_duplex = LINK_DUPLEX_UNKNOWN;
1647*6bbbd442SRobert Mustacchi 	igc->igc_link_state = LINK_STATE_UNKNOWN;
1648*6bbbd442SRobert Mustacchi 
1649*6bbbd442SRobert Mustacchi 	/*
1650*6bbbd442SRobert Mustacchi 	 * Set up all the register spaces that hardware requires.
1651*6bbbd442SRobert Mustacchi 	 */
1652*6bbbd442SRobert Mustacchi 	if (!igc_setup_regs(igc)) {
1653*6bbbd442SRobert Mustacchi 		goto err;
1654*6bbbd442SRobert Mustacchi 	}
1655*6bbbd442SRobert Mustacchi 	igc->igc_attach |= IGC_ATTACH_REGS;
1656*6bbbd442SRobert Mustacchi 
1657*6bbbd442SRobert Mustacchi 	/*
1658*6bbbd442SRobert Mustacchi 	 * Setup the common code.
1659*6bbbd442SRobert Mustacchi 	 */
1660*6bbbd442SRobert Mustacchi 	if (!igc_core_code_init(igc)) {
1661*6bbbd442SRobert Mustacchi 		goto err;
1662*6bbbd442SRobert Mustacchi 	}
1663*6bbbd442SRobert Mustacchi 
1664*6bbbd442SRobert Mustacchi 	if (!igc_limits_init(igc)) {
1665*6bbbd442SRobert Mustacchi 		goto err;
1666*6bbbd442SRobert Mustacchi 	}
1667*6bbbd442SRobert Mustacchi 
1668*6bbbd442SRobert Mustacchi 	/*
1669*6bbbd442SRobert Mustacchi 	 * Go allocate and set up all of our interrupts.
1670*6bbbd442SRobert Mustacchi 	 */
1671*6bbbd442SRobert Mustacchi 	if (!igc_intr_init(igc)) {
1672*6bbbd442SRobert Mustacchi 		goto err;
1673*6bbbd442SRobert Mustacchi 	}
1674*6bbbd442SRobert Mustacchi 
1675*6bbbd442SRobert Mustacchi 	/*
1676*6bbbd442SRobert Mustacchi 	 * Initialize our main mutex for the device now that we have an
1677*6bbbd442SRobert Mustacchi 	 * interrupt priority.
1678*6bbbd442SRobert Mustacchi 	 */
1679*6bbbd442SRobert Mustacchi 	mutex_init(&igc->igc_lock, NULL, MUTEX_DRIVER,
1680*6bbbd442SRobert Mustacchi 	    DDI_INTR_PRI(igc->igc_intr_pri));
1681*6bbbd442SRobert Mustacchi 	igc->igc_attach |= IGC_ATTACH_MUTEX;
1682*6bbbd442SRobert Mustacchi 
1683*6bbbd442SRobert Mustacchi 	/*
1684*6bbbd442SRobert Mustacchi 	 * We now want to determine the total number of rx and tx rings that we
1685*6bbbd442SRobert Mustacchi 	 * have based on our interrupt allocation so we can go through and
1686*6bbbd442SRobert Mustacchi 	 * perform the rest of the device setup that is required. The various
1687*6bbbd442SRobert Mustacchi 	 * queues that we have are mapped to a given MSI-X through the IVAR
1688*6bbbd442SRobert Mustacchi 	 * registers in the device. There is also an IVAR_MISC register that
1689*6bbbd442SRobert Mustacchi 	 * maps link state change events and other issues up to two vectors.
1690*6bbbd442SRobert Mustacchi 	 *
1691*6bbbd442SRobert Mustacchi 	 * There isn't strictly per-queue interrupt generation control. Instead,
1692*6bbbd442SRobert Mustacchi 	 * when in MSI-X mode, the device has an extended interrupt cause and
1693*6bbbd442SRobert Mustacchi 	 * mask register. The mask register allows us to mask the five bits
1694*6bbbd442SRobert Mustacchi 	 * described above.
1695*6bbbd442SRobert Mustacchi 	 *
1696*6bbbd442SRobert Mustacchi 	 * Because of all this we end up limiting the number of queues that we
1697*6bbbd442SRobert Mustacchi 	 * use to 2 for now: 1 for tx and 1 for rx. Interrupt 0 is for tx/other
1698*6bbbd442SRobert Mustacchi 	 * and 1 for rx.
1699*6bbbd442SRobert Mustacchi 	 */
1700*6bbbd442SRobert Mustacchi 	igc->igc_nrx_rings = 1;
1701*6bbbd442SRobert Mustacchi 	igc->igc_ntx_rings = 1;
1702*6bbbd442SRobert Mustacchi 
1703*6bbbd442SRobert Mustacchi 	/*
1704*6bbbd442SRobert Mustacchi 	 * Default to a 1500 byte MTU.
1705*6bbbd442SRobert Mustacchi 	 */
1706*6bbbd442SRobert Mustacchi 	igc->igc_mtu = ETHERMTU;
1707*6bbbd442SRobert Mustacchi 	igc_hw_buf_update(igc);
1708*6bbbd442SRobert Mustacchi 
1709*6bbbd442SRobert Mustacchi 	/*
1710*6bbbd442SRobert Mustacchi 	 * Initialize default descriptor limits and thresholds. We allocate 1.5
1711*6bbbd442SRobert Mustacchi 	 * times the number of rx descriptors so that way we can loan up to
1712*6bbbd442SRobert Mustacchi 	 * 1/3rd of them. We allocate an even number of tx descriptors.
1713*6bbbd442SRobert Mustacchi 	 */
1714*6bbbd442SRobert Mustacchi 	igc->igc_rx_ndesc = IGC_DEF_RX_RING_SIZE;
1715*6bbbd442SRobert Mustacchi 	igc->igc_tx_ndesc = IGC_DEF_TX_RING_SIZE;
1716*6bbbd442SRobert Mustacchi 	igc->igc_rx_nbuf = igc->igc_rx_ndesc + (igc->igc_rx_ndesc >> 1);
1717*6bbbd442SRobert Mustacchi 	igc->igc_tx_nbuf = igc->igc_tx_ndesc;
1718*6bbbd442SRobert Mustacchi 	igc->igc_rx_nfree = igc->igc_rx_nbuf - igc->igc_rx_ndesc;
1719*6bbbd442SRobert Mustacchi 	igc->igc_rx_intr_nframes = IGC_DEF_RX_RING_INTR_LIMIT;
1720*6bbbd442SRobert Mustacchi 	igc->igc_rx_bind_thresh = IGC_DEF_RX_BIND;
1721*6bbbd442SRobert Mustacchi 	igc->igc_tx_bind_thresh = IGC_DEF_TX_BIND;
1722*6bbbd442SRobert Mustacchi 	igc->igc_tx_notify_thresh = IGC_DEF_TX_NOTIFY_MIN;
1723*6bbbd442SRobert Mustacchi 	igc->igc_tx_recycle_thresh = IGC_DEF_TX_RECYCLE_MIN;
1724*6bbbd442SRobert Mustacchi 	igc->igc_tx_gap = IGC_DEF_TX_GAP;
1725*6bbbd442SRobert Mustacchi 	igc->igc_eitr = IGC_DEF_EITR;
1726*6bbbd442SRobert Mustacchi 
1727*6bbbd442SRobert Mustacchi 	if (!igc_rings_alloc(igc)) {
1728*6bbbd442SRobert Mustacchi 		goto err;
1729*6bbbd442SRobert Mustacchi 	}
1730*6bbbd442SRobert Mustacchi 
1731*6bbbd442SRobert Mustacchi 	if (!igc_intr_hdlr_init(igc)) {
1732*6bbbd442SRobert Mustacchi 		goto err;
1733*6bbbd442SRobert Mustacchi 	}
1734*6bbbd442SRobert Mustacchi 	igc->igc_attach |= IGC_ATTACH_INTR_HANDLER;
1735*6bbbd442SRobert Mustacchi 
1736*6bbbd442SRobert Mustacchi 	/*
1737*6bbbd442SRobert Mustacchi 	 * Next reset the device before we begin initializing anything else. As
1738*6bbbd442SRobert Mustacchi 	 * part of this, validate the flash checksum if present. This is all
1739*6bbbd442SRobert Mustacchi 	 * initialization that we would only do once per device. Other
1740*6bbbd442SRobert Mustacchi 	 * initialization that we want to do after any reset is done is
1741*6bbbd442SRobert Mustacchi 	 * igc_hw_common_init().
1742*6bbbd442SRobert Mustacchi 	 */
1743*6bbbd442SRobert Mustacchi 	if (!igc_hw_init(igc)) {
1744*6bbbd442SRobert Mustacchi 		goto err;
1745*6bbbd442SRobert Mustacchi 	}
1746*6bbbd442SRobert Mustacchi 
1747*6bbbd442SRobert Mustacchi 	igc_led_init(igc);
1748*6bbbd442SRobert Mustacchi 	igc->igc_attach |= IGC_ATTACH_LED;
1749*6bbbd442SRobert Mustacchi 
1750*6bbbd442SRobert Mustacchi 	/*
1751*6bbbd442SRobert Mustacchi 	 * Snapshot our basic settings that users can eventually control in the
1752*6bbbd442SRobert Mustacchi 	 * device. We start with always enabling auto-negotiation and
1753*6bbbd442SRobert Mustacchi 	 * advertising the basic supported speeds. The I225v1 does have
1754*6bbbd442SRobert Mustacchi 	 * substantial problems with enabling 2.5G due to the fact that it
1755*6bbbd442SRobert Mustacchi 	 * doesn't maintain a proper inter-packet gap. Despite that, we default
1756*6bbbd442SRobert Mustacchi 	 * to enabling 2.5G for now as its supposedly not broken with all link
1757*6bbbd442SRobert Mustacchi 	 * partners and the NVM. We also don't have a way of actually
1758*6bbbd442SRobert Mustacchi 	 * identifying and mapping that to something in the driver today,
1759*6bbbd442SRobert Mustacchi 	 * unfortunately.
1760*6bbbd442SRobert Mustacchi 	 */
1761*6bbbd442SRobert Mustacchi 	igc->igc_hw.mac.autoneg = true;
1762*6bbbd442SRobert Mustacchi 	igc->igc_hw.phy.autoneg_wait_to_complete = false;
1763*6bbbd442SRobert Mustacchi 	igc->igc_hw.phy.autoneg_advertised = IGC_DEFAULT_ADV;
1764*6bbbd442SRobert Mustacchi 	igc->igc_hw.fc.requested_mode = igc_fc_default;
1765*6bbbd442SRobert Mustacchi 	igc->igc_hw.fc.current_mode = igc_fc_default;
1766*6bbbd442SRobert Mustacchi 
1767*6bbbd442SRobert Mustacchi 	if (!igc_hw_common_init(igc)) {
1768*6bbbd442SRobert Mustacchi 		goto err;
1769*6bbbd442SRobert Mustacchi 	}
1770*6bbbd442SRobert Mustacchi 
1771*6bbbd442SRobert Mustacchi 	if (!igc_stats_init(igc)) {
1772*6bbbd442SRobert Mustacchi 		goto err;
1773*6bbbd442SRobert Mustacchi 	}
1774*6bbbd442SRobert Mustacchi 	igc->igc_attach |= IGC_ATTACH_STATS;
1775*6bbbd442SRobert Mustacchi 
1776*6bbbd442SRobert Mustacchi 	/*
1777*6bbbd442SRobert Mustacchi 	 * Register with MAC
1778*6bbbd442SRobert Mustacchi 	 */
1779*6bbbd442SRobert Mustacchi 	if (!igc_mac_register(igc)) {
1780*6bbbd442SRobert Mustacchi 		goto err;
1781*6bbbd442SRobert Mustacchi 	}
1782*6bbbd442SRobert Mustacchi 	igc->igc_attach |= IGC_ATTACH_MAC;
1783*6bbbd442SRobert Mustacchi 
1784*6bbbd442SRobert Mustacchi 	/*
1785*6bbbd442SRobert Mustacchi 	 * Enable interrupts and get going.
1786*6bbbd442SRobert Mustacchi 	 */
1787*6bbbd442SRobert Mustacchi 	if (!igc_intr_en(igc)) {
1788*6bbbd442SRobert Mustacchi 		goto err;
1789*6bbbd442SRobert Mustacchi 	}
1790*6bbbd442SRobert Mustacchi 	igc->igc_attach |= IGC_ATTACH_INTR_EN;
1791*6bbbd442SRobert Mustacchi 
1792*6bbbd442SRobert Mustacchi 	return (DDI_SUCCESS);
1793*6bbbd442SRobert Mustacchi 
1794*6bbbd442SRobert Mustacchi err:
1795*6bbbd442SRobert Mustacchi 	igc_cleanup(igc);
1796*6bbbd442SRobert Mustacchi 	return (DDI_FAILURE);
1797*6bbbd442SRobert Mustacchi }
1798*6bbbd442SRobert Mustacchi 
1799*6bbbd442SRobert Mustacchi static int
igc_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)1800*6bbbd442SRobert Mustacchi igc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1801*6bbbd442SRobert Mustacchi {
1802*6bbbd442SRobert Mustacchi 	igc_t *igc;
1803*6bbbd442SRobert Mustacchi 
1804*6bbbd442SRobert Mustacchi 	if (cmd != DDI_DETACH) {
1805*6bbbd442SRobert Mustacchi 		return (DDI_FAILURE);
1806*6bbbd442SRobert Mustacchi 	}
1807*6bbbd442SRobert Mustacchi 
1808*6bbbd442SRobert Mustacchi 	igc = ddi_get_driver_private(dip);
1809*6bbbd442SRobert Mustacchi 	if (igc == NULL) {
1810*6bbbd442SRobert Mustacchi 		dev_err(dip, CE_WARN, "asked to detach, but missing igc_t");
1811*6bbbd442SRobert Mustacchi 		return (DDI_FAILURE);
1812*6bbbd442SRobert Mustacchi 	}
1813*6bbbd442SRobert Mustacchi 
1814*6bbbd442SRobert Mustacchi 	igc_cleanup(igc);
1815*6bbbd442SRobert Mustacchi 	return (DDI_SUCCESS);
1816*6bbbd442SRobert Mustacchi }
1817*6bbbd442SRobert Mustacchi 
1818*6bbbd442SRobert Mustacchi static struct cb_ops igc_cb_ops = {
1819*6bbbd442SRobert Mustacchi 	.cb_open = nulldev,
1820*6bbbd442SRobert Mustacchi 	.cb_close = nulldev,
1821*6bbbd442SRobert Mustacchi 	.cb_strategy = nodev,
1822*6bbbd442SRobert Mustacchi 	.cb_print = nodev,
1823*6bbbd442SRobert Mustacchi 	.cb_dump = nodev,
1824*6bbbd442SRobert Mustacchi 	.cb_read = nodev,
1825*6bbbd442SRobert Mustacchi 	.cb_write = nodev,
1826*6bbbd442SRobert Mustacchi 	.cb_ioctl = nodev,
1827*6bbbd442SRobert Mustacchi 	.cb_devmap = nodev,
1828*6bbbd442SRobert Mustacchi 	.cb_mmap = nodev,
1829*6bbbd442SRobert Mustacchi 	.cb_segmap = nodev,
1830*6bbbd442SRobert Mustacchi 	.cb_chpoll = nochpoll,
1831*6bbbd442SRobert Mustacchi 	.cb_prop_op = ddi_prop_op,
1832*6bbbd442SRobert Mustacchi 	.cb_flag = D_MP,
1833*6bbbd442SRobert Mustacchi 	.cb_rev = CB_REV,
1834*6bbbd442SRobert Mustacchi 	.cb_aread = nodev,
1835*6bbbd442SRobert Mustacchi 	.cb_awrite = nodev
1836*6bbbd442SRobert Mustacchi };
1837*6bbbd442SRobert Mustacchi 
1838*6bbbd442SRobert Mustacchi static struct dev_ops igc_dev_ops = {
1839*6bbbd442SRobert Mustacchi 	.devo_rev = DEVO_REV,
1840*6bbbd442SRobert Mustacchi 	.devo_refcnt = 0,
1841*6bbbd442SRobert Mustacchi 	.devo_getinfo = NULL,
1842*6bbbd442SRobert Mustacchi 	.devo_identify = nulldev,
1843*6bbbd442SRobert Mustacchi 	.devo_probe = nulldev,
1844*6bbbd442SRobert Mustacchi 	.devo_attach = igc_attach,
1845*6bbbd442SRobert Mustacchi 	.devo_detach = igc_detach,
1846*6bbbd442SRobert Mustacchi 	.devo_reset = nodev,
1847*6bbbd442SRobert Mustacchi 	.devo_quiesce = ddi_quiesce_not_supported,
1848*6bbbd442SRobert Mustacchi 	.devo_cb_ops = &igc_cb_ops
1849*6bbbd442SRobert Mustacchi };
1850*6bbbd442SRobert Mustacchi 
1851*6bbbd442SRobert Mustacchi static struct modldrv igc_modldrv = {
1852*6bbbd442SRobert Mustacchi 	.drv_modops = &mod_driverops,
1853*6bbbd442SRobert Mustacchi 	.drv_linkinfo = "Intel I226/226 Ethernet Controller",
1854*6bbbd442SRobert Mustacchi 	.drv_dev_ops = &igc_dev_ops
1855*6bbbd442SRobert Mustacchi };
1856*6bbbd442SRobert Mustacchi 
1857*6bbbd442SRobert Mustacchi static struct modlinkage igc_modlinkage = {
1858*6bbbd442SRobert Mustacchi 	.ml_rev = MODREV_1,
1859*6bbbd442SRobert Mustacchi 	.ml_linkage = { &igc_modldrv, NULL }
1860*6bbbd442SRobert Mustacchi };
1861*6bbbd442SRobert Mustacchi 
1862*6bbbd442SRobert Mustacchi int
_init(void)1863*6bbbd442SRobert Mustacchi _init(void)
1864*6bbbd442SRobert Mustacchi {
1865*6bbbd442SRobert Mustacchi 	int ret;
1866*6bbbd442SRobert Mustacchi 
1867*6bbbd442SRobert Mustacchi 	mac_init_ops(&igc_dev_ops, IGC_MOD_NAME);
1868*6bbbd442SRobert Mustacchi 
1869*6bbbd442SRobert Mustacchi 	if ((ret = mod_install(&igc_modlinkage)) != 0) {
1870*6bbbd442SRobert Mustacchi 		mac_fini_ops(&igc_dev_ops);
1871*6bbbd442SRobert Mustacchi 	}
1872*6bbbd442SRobert Mustacchi 
1873*6bbbd442SRobert Mustacchi 	return (ret);
1874*6bbbd442SRobert Mustacchi }
1875*6bbbd442SRobert Mustacchi 
1876*6bbbd442SRobert Mustacchi int
_info(struct modinfo * modinfop)1877*6bbbd442SRobert Mustacchi _info(struct modinfo *modinfop)
1878*6bbbd442SRobert Mustacchi {
1879*6bbbd442SRobert Mustacchi 	return (mod_info(&igc_modlinkage, modinfop));
1880*6bbbd442SRobert Mustacchi }
1881*6bbbd442SRobert Mustacchi 
1882*6bbbd442SRobert Mustacchi int
_fini(void)1883*6bbbd442SRobert Mustacchi _fini(void)
1884*6bbbd442SRobert Mustacchi {
1885*6bbbd442SRobert Mustacchi 	int ret;
1886*6bbbd442SRobert Mustacchi 
1887*6bbbd442SRobert Mustacchi 	if ((ret = mod_remove(&igc_modlinkage)) == 0) {
1888*6bbbd442SRobert Mustacchi 		mac_fini_ops(&igc_dev_ops);
1889*6bbbd442SRobert Mustacchi 	}
1890*6bbbd442SRobert Mustacchi 
1891*6bbbd442SRobert Mustacchi 	return (ret);
1892*6bbbd442SRobert Mustacchi }
1893