@@ -34,7 +34,6 @@ IgbInterruptCreate(
3434 IGB_INTERRUPT* context = IgbGetInterruptContext (wdfInterrupt);
3535 context->Adapter = adapter;
3636 context->Handle = wdfInterrupt;
37- context->IsMsi = translatedDescriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE ? TRUE : FALSE ;
3837 *interrupt = context;
3938
4039Exit:
@@ -43,14 +42,44 @@ IgbInterruptCreate(
4342
4443void
4544IgbInterruptInitialize (
46- _In_ IGB_INTERRUPT* interrupt )
45+ _In_ IGB_ADAPTER* adapter )
4746{
48- // Map RX queues to EICR bits
4947 // TODO: Handle 82575/82576 models
48+
49+ if (adapter->MsiInterrupts > 1 )
50+ {
51+ UINT miscInterrupt = adapter->MsiInterrupts - 1 ;
52+
53+ // Enable MSI-X mode
54+ E1000_WRITE_REG (&adapter->Hw , E1000_GPIE, E1000_GPIE_NSICR | E1000_GPIE_MSIX_MODE | E1000_GPIE_EIAME | E1000_GPIE_PBA);
55+
56+ // Map link & misc interrupts
57+ E1000_WRITE_REG (&adapter->Hw , E1000_IVAR_MISC, ((miscInterrupt | E1000_IVAR_VALID) << 8 ));
58+
59+ // Map the TX queue to the misc interrupt
60+ u32 ivar = E1000_READ_REG_ARRAY (&adapter->Hw , E1000_IVAR0, 0 );
61+ E1000_WRITE_REG_ARRAY (&adapter->Hw , E1000_IVAR0, 0 , (ivar & 0xFFFF00FF ) | ((miscInterrupt | E1000_IVAR_VALID) << 8 ));
62+
63+ // Automatically clear interrupt causes
64+ E1000_WRITE_REG (&adapter->Hw , E1000_EIAC, (1 << adapter->MsiInterrupts ) - 1 );
65+ // Automatically mask RX queues
66+ E1000_WRITE_REG (&adapter->Hw , E1000_EIAM, (1 << (adapter->MsiInterrupts - 1 )) - 1 );
67+ // Enable misc interrupt
68+ E1000_WRITE_REG (&adapter->Hw , E1000_EIMS, (1 << miscInterrupt));
69+
70+ adapter->MiscInterrupt = adapter->Interrupts [miscInterrupt];
71+ }
72+ else
73+ {
74+ E1000_WRITE_REG (&adapter->Hw , E1000_GPIE, adapter->MsiInterrupts == 1 ? E1000_GPIE_NSICR : 0 );
75+ adapter->MiscInterrupt = adapter->Interrupts [0 ];
76+ }
77+
78+ // Map RX queues to EICR bits
5079 for (int i = 0 ; i < IGB_MAX_RX_QUEUES; i++)
5180 {
5281 u32 index = i >> 1 ;
53- u32 ivar = E1000_READ_REG_ARRAY (&interrupt-> Adapter ->Hw , E1000_IVAR0, index);
82+ u32 ivar = E1000_READ_REG_ARRAY (&adapter ->Hw , E1000_IVAR0, index);
5483 if (i & 1 )
5584 {
5685 ivar &= 0xFF00FFFF ;
@@ -61,98 +90,130 @@ IgbInterruptInitialize(
6190 ivar &= 0xFFFFFF00 ;
6291 ivar |= i | E1000_IVAR_VALID;
6392 }
64- E1000_WRITE_REG_ARRAY (&interrupt-> Adapter ->Hw , E1000_IVAR0, index, ivar);
93+ E1000_WRITE_REG_ARRAY (&adapter ->Hw , E1000_IVAR0, index, ivar);
6594 }
6695
67- // TODO: MSI-X
68- if (interrupt->IsMsi )
69- {
70- E1000_WRITE_REG (&interrupt->Adapter ->Hw , E1000_GPIE, E1000_GPIE_NSICR);
71- }
72- else
73- {
74- E1000_WRITE_REG (&interrupt->Adapter ->Hw , E1000_GPIE, 0 );
75- }
96+ E1000_WRITE_FLUSH (&adapter->Hw );
7697}
7798
7899_Use_decl_annotations_
79100BOOLEAN
80101EvtInterruptIsr (
81102 _In_ WDFINTERRUPT wdfInterrupt,
82- ULONG MessageID )
103+ _In_ ULONG messageId )
83104{
84- UNREFERENCED_PARAMETER ((MessageID));
85-
86105 IGB_INTERRUPT* interrupt = IgbGetInterruptContext (wdfInterrupt);
87106 IGB_ADAPTER* adapter = interrupt->Adapter ;
88107 struct e1000_hw * hw = &adapter->Hw ;
89- u32 icr, eicr;
90- BOOLEAN queueDPC = FALSE ;
91-
92- eicr = E1000_READ_REG (hw, E1000_EICR);
93-
94- // Hot eject
95- if (eicr == 0xffffffff )
96- {
97- return TRUE ;
98- }
99108
100- if (eicr != 0 )
109+ if (adapter-> MsiInterrupts > 1 )
101110 {
102- InterlockedOr (&interrupt->EICR , eicr);
103-
104- if ((eicr & E1000_EICR_OTHER) != 0 )
111+ if (interrupt == adapter->MiscInterrupt )
105112 {
106- icr = E1000_READ_REG (hw, E1000_ICR);
113+ // We use MSI-X for RX queues and we are forbidden to read EICR
114+ u32 icr = E1000_READ_REG (hw, E1000_ICR);
115+
116+ // Disarm the TX interrupts for queue where a transfer finished
117+ if ((icr & (E1000_ICR_TXDW | E1000_ICR_TXQE)) != 0 )
118+ {
119+ E1000_WRITE_REG (&interrupt->Adapter ->Hw , E1000_IMC, E1000_IMS_TXDW | E1000_ICR_TXQE);
120+ E1000_WRITE_FLUSH (&interrupt->Adapter ->Hw );
121+ }
122+
107123 InterlockedOr (&interrupt->ICR , icr);
124+ InterlockedOr (&interrupt->EICR , E1000_EICR_OTHER);
125+ }
126+ else
127+ {
128+ // Mark the RX queue
129+ InterlockedOr (&interrupt->EICR , 1 << messageId);
108130 }
109131
110132 WdfInterruptQueueDpcForIsr (wdfInterrupt);
111133 return TRUE ;
112134 }
135+ else
136+ {
137+ u32 eicr = E1000_READ_REG (hw, E1000_EICR);
138+
139+ // Hot eject
140+ if (eicr == 0xffffffff )
141+ {
142+ return TRUE ;
143+ }
144+
145+ if (eicr != 0 )
146+ {
147+ // Disarm the RX interrupts for queues where we received packets
148+ u32 eicrQueueMask = ((1 << IGB_MAX_RX_QUEUES) - 1 );
149+ if ((eicr & eicrQueueMask) != 0 )
150+ {
151+ E1000_WRITE_REG (&interrupt->Adapter ->Hw , E1000_EIMC, eicr & eicrQueueMask);
152+ E1000_WRITE_FLUSH (&interrupt->Adapter ->Hw );
153+ }
154+
155+ if ((eicr & E1000_EICR_OTHER) != 0 )
156+ {
157+ u32 icr = E1000_READ_REG (hw, E1000_ICR);
158+
159+ // Disarm the TX interrupts for queue where a transfer finished
160+ if ((icr & (E1000_ICR_TXDW | E1000_ICR_TXQE)) != 0 )
161+ {
162+ E1000_WRITE_REG (&interrupt->Adapter ->Hw , E1000_IMC, E1000_IMS_TXDW | E1000_ICR_TXQE);
163+ E1000_WRITE_FLUSH (&interrupt->Adapter ->Hw );
164+ }
165+
166+ InterlockedOr (&interrupt->ICR , icr);
167+ }
168+
169+ InterlockedOr (&interrupt->EICR , eicr);
170+
171+ WdfInterruptQueueDpcForIsr (wdfInterrupt);
172+ return TRUE ;
173+ }
113174
114- return interrupt->IsMsi ;
175+ return FALSE ;
176+ }
115177}
116178
117179_Use_decl_annotations_
118180VOID
119181EvtInterruptDpc (
120- _In_ WDFINTERRUPT Interrupt ,
121- _In_ WDFOBJECT AssociatedObject )
182+ _In_ WDFINTERRUPT wdfInterrupt ,
183+ _In_ WDFOBJECT associatedObject )
122184{
123- UNREFERENCED_PARAMETER (AssociatedObject );
185+ UNREFERENCED_PARAMETER (associatedObject );
124186
125- IGB_INTERRUPT* interrupt = IgbGetInterruptContext (Interrupt );
187+ IGB_INTERRUPT* interrupt = IgbGetInterruptContext (wdfInterrupt );
126188 IGB_ADAPTER* adapter = interrupt->Adapter ;
127- struct e1000_hw * hw = &adapter->Hw ;
128- u32 icr = 0 , eicr;
129189
130- eicr = InterlockedExchange (&interrupt->EICR , 0 );
190+ LONG eicr = InterlockedExchange (&interrupt->EICR , 0 );
131191
132- for ( int i = 0 ; i < IGB_MAX_RX_QUEUES; i++ )
192+ if ((eicr & (( 1 << IGB_MAX_RX_QUEUES) - 1 )) != 0 )
133193 {
134- if ((eicr & ( 1 << i)) != 0 )
194+ for ( int i = 0 ; i < IGB_MAX_RX_QUEUES; i++ )
135195 {
136- if (InterlockedExchange (&interrupt->RxNotifyArmed [i], FALSE ))
196+ if ((eicr & (1 << i)) != 0 )
197+ {
137198 NetRxQueueNotifyMoreReceivedPacketsAvailable (adapter->RxQueues [i]);
199+ }
138200 }
139201 }
140202
141203 if ((eicr & E1000_EICR_OTHER) != 0 )
142204 {
143- icr = InterlockedExchange (&interrupt->ICR , 0 );
205+ LONG icr = InterlockedExchange (&interrupt->ICR , 0 );
144206
145- if ((icr & (E1000_ICR_TXDW | E1000_ICR_TXQE)) != 0 &&
146- InterlockedExchange (&interrupt->TxNotifyArmed [0 ], FALSE ))
207+ if ((icr & (E1000_ICR_TXDW | E1000_ICR_TXQE)) != 0 )
147208 {
148209 NetTxQueueNotifyMoreCompletedPacketsAvailable (adapter->TxQueues [0 ]);
149210 }
150211
151212 if ((icr & E1000_ICR_LSC) != 0 )
152213 {
153214 DBGPRINT (" Link Interrupt!\n " );
154- hw-> mac .get_link_status = 1 ;
215+ adapter-> Hw . mac .get_link_status = 1 ;
155216 IgbCheckLinkStatus (adapter);
156217 }
157218 }
158- }
219+ }
0 commit comments