xref: /freebsd/sys/dev/aq/aq_irq.c (revision 493d26c58e732dcfcdd87993ef71880adfe9d0cb)
1*493d26c5SEd Maste /*
2*493d26c5SEd Maste  * aQuantia Corporation Network Driver
3*493d26c5SEd Maste  * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
4*493d26c5SEd Maste  *
5*493d26c5SEd Maste  * Redistribution and use in source and binary forms, with or without
6*493d26c5SEd Maste  * modification, are permitted provided that the following conditions
7*493d26c5SEd Maste  * are met:
8*493d26c5SEd Maste  *
9*493d26c5SEd Maste  *   (1) Redistributions of source code must retain the above
10*493d26c5SEd Maste  *   copyright notice, this list of conditions and the following
11*493d26c5SEd Maste  *   disclaimer.
12*493d26c5SEd Maste  *
13*493d26c5SEd Maste  *   (2) Redistributions in binary form must reproduce the above
14*493d26c5SEd Maste  *   copyright notice, this list of conditions and the following
15*493d26c5SEd Maste  *   disclaimer in the documentation and/or other materials provided
16*493d26c5SEd Maste  *   with the distribution.
17*493d26c5SEd Maste  *
18*493d26c5SEd Maste  *   (3)The name of the author may not be used to endorse or promote
19*493d26c5SEd Maste  *   products derived from this software without specific prior
20*493d26c5SEd Maste  *   written permission.
21*493d26c5SEd Maste  *
22*493d26c5SEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23*493d26c5SEd Maste  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24*493d26c5SEd Maste  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*493d26c5SEd Maste  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
26*493d26c5SEd Maste  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27*493d26c5SEd Maste  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28*493d26c5SEd Maste  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29*493d26c5SEd Maste  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30*493d26c5SEd Maste  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31*493d26c5SEd Maste  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32*493d26c5SEd Maste  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*493d26c5SEd Maste  */
34*493d26c5SEd Maste 
35*493d26c5SEd Maste 
36*493d26c5SEd Maste #include <sys/cdefs.h>
37*493d26c5SEd Maste __FBSDID("$FreeBSD$");
38*493d26c5SEd Maste 
39*493d26c5SEd Maste #include <sys/param.h>
40*493d26c5SEd Maste #include <sys/kernel.h>
41*493d26c5SEd Maste #include <sys/socket.h>
42*493d26c5SEd Maste #include <sys/bitstring.h>
43*493d26c5SEd Maste #include <net/if.h>
44*493d26c5SEd Maste #include <net/if_media.h>
45*493d26c5SEd Maste #include <net/if_var.h>
46*493d26c5SEd Maste #include <net/if_dl.h>
47*493d26c5SEd Maste #include <net/ethernet.h>
48*493d26c5SEd Maste #include <net/iflib.h>
49*493d26c5SEd Maste 
50*493d26c5SEd Maste #include "aq_common.h"
51*493d26c5SEd Maste #include "aq_device.h"
52*493d26c5SEd Maste #include "aq_ring.h"
53*493d26c5SEd Maste #include "aq_dbg.h"
54*493d26c5SEd Maste #include "aq_hw.h"
55*493d26c5SEd Maste #include "aq_hw_llh.h"
56*493d26c5SEd Maste 
aq_update_hw_stats(aq_dev_t * aq_dev)57*493d26c5SEd Maste int aq_update_hw_stats(aq_dev_t *aq_dev)
58*493d26c5SEd Maste {
59*493d26c5SEd Maste     struct aq_hw *hw = &aq_dev->hw;
60*493d26c5SEd Maste     struct aq_hw_fw_mbox mbox;
61*493d26c5SEd Maste 
62*493d26c5SEd Maste     aq_hw_mpi_read_stats(hw, &mbox);
63*493d26c5SEd Maste 
64*493d26c5SEd Maste #define AQ_SDELTA(_N_) (aq_dev->curr_stats._N_ += \
65*493d26c5SEd Maste             mbox.stats._N_ - aq_dev->last_stats._N_)
66*493d26c5SEd Maste     if (aq_dev->linkup) {
67*493d26c5SEd Maste         AQ_SDELTA(uprc);
68*493d26c5SEd Maste         AQ_SDELTA(mprc);
69*493d26c5SEd Maste         AQ_SDELTA(bprc);
70*493d26c5SEd Maste         AQ_SDELTA(cprc);
71*493d26c5SEd Maste         AQ_SDELTA(erpt);
72*493d26c5SEd Maste 
73*493d26c5SEd Maste         AQ_SDELTA(uptc);
74*493d26c5SEd Maste         AQ_SDELTA(mptc);
75*493d26c5SEd Maste         AQ_SDELTA(bptc);
76*493d26c5SEd Maste         AQ_SDELTA(erpr);
77*493d26c5SEd Maste 
78*493d26c5SEd Maste         AQ_SDELTA(ubrc);
79*493d26c5SEd Maste         AQ_SDELTA(ubtc);
80*493d26c5SEd Maste         AQ_SDELTA(mbrc);
81*493d26c5SEd Maste         AQ_SDELTA(mbtc);
82*493d26c5SEd Maste         AQ_SDELTA(bbrc);
83*493d26c5SEd Maste         AQ_SDELTA(bbtc);
84*493d26c5SEd Maste 
85*493d26c5SEd Maste         AQ_SDELTA(ptc);
86*493d26c5SEd Maste         AQ_SDELTA(prc);
87*493d26c5SEd Maste 
88*493d26c5SEd Maste         AQ_SDELTA(dpc);
89*493d26c5SEd Maste 
90*493d26c5SEd Maste         aq_dev->curr_stats.brc = aq_dev->curr_stats.ubrc +
91*493d26c5SEd Maste                                  aq_dev->curr_stats.mbrc +
92*493d26c5SEd Maste                                  aq_dev->curr_stats.bbrc;
93*493d26c5SEd Maste         aq_dev->curr_stats.btc = aq_dev->curr_stats.ubtc +
94*493d26c5SEd Maste                                  aq_dev->curr_stats.mbtc +
95*493d26c5SEd Maste                                  aq_dev->curr_stats.bbtc;
96*493d26c5SEd Maste 
97*493d26c5SEd Maste     }
98*493d26c5SEd Maste #undef AQ_SDELTA
99*493d26c5SEd Maste 
100*493d26c5SEd Maste     memcpy(&aq_dev->last_stats, &mbox.stats, sizeof(mbox.stats));
101*493d26c5SEd Maste 
102*493d26c5SEd Maste     return (0);
103*493d26c5SEd Maste }
104*493d26c5SEd Maste 
105*493d26c5SEd Maste 
aq_if_update_admin_status(if_ctx_t ctx)106*493d26c5SEd Maste void aq_if_update_admin_status(if_ctx_t ctx)
107*493d26c5SEd Maste {
108*493d26c5SEd Maste 	aq_dev_t *aq_dev = iflib_get_softc(ctx);
109*493d26c5SEd Maste 	struct aq_hw *hw = &aq_dev->hw;
110*493d26c5SEd Maste 	u32 link_speed;
111*493d26c5SEd Maste 
112*493d26c5SEd Maste 	//	AQ_DBG_ENTER();
113*493d26c5SEd Maste 
114*493d26c5SEd Maste 	struct aq_hw_fc_info fc_neg;
115*493d26c5SEd Maste 	aq_hw_get_link_state(hw, &link_speed, &fc_neg);
116*493d26c5SEd Maste //	AQ_DBG_PRINT(" link_speed=%d aq_dev->linkup=%d", link_speed, aq_dev->linkup);
117*493d26c5SEd Maste 	if (link_speed && !aq_dev->linkup) { /* link was DOWN */
118*493d26c5SEd Maste 		device_printf(aq_dev->dev, "atlantic: link UP: speed=%d\n", link_speed);
119*493d26c5SEd Maste 
120*493d26c5SEd Maste 		aq_dev->linkup = 1;
121*493d26c5SEd Maste 
122*493d26c5SEd Maste #if __FreeBSD__ >= 12
123*493d26c5SEd Maste 		/* Disable TSO if link speed < 1G */
124*493d26c5SEd Maste 		if (link_speed < 1000 && (iflib_get_softc_ctx(ctx)->isc_capabilities & (IFCAP_TSO4 | IFCAP_TSO6))) {
125*493d26c5SEd Maste 		    iflib_get_softc_ctx(ctx)->isc_capabilities &= ~(IFCAP_TSO4 | IFCAP_TSO6);
126*493d26c5SEd Maste 		    device_printf(aq_dev->dev, "atlantic: TSO disabled for link speed < 1G");
127*493d26c5SEd Maste 		}else{
128*493d26c5SEd Maste 		    iflib_get_softc_ctx(ctx)->isc_capabilities |= (IFCAP_TSO4 | IFCAP_TSO6);
129*493d26c5SEd Maste 		}
130*493d26c5SEd Maste #endif
131*493d26c5SEd Maste 		/* turn on/off RX Pause in RPB */
132*493d26c5SEd Maste 		rpb_rx_xoff_en_per_tc_set(hw, fc_neg.fc_rx, 0);
133*493d26c5SEd Maste 
134*493d26c5SEd Maste 
135*493d26c5SEd Maste 		iflib_link_state_change(ctx, LINK_STATE_UP, IF_Mbps(link_speed));
136*493d26c5SEd Maste 		aq_mediastatus_update(aq_dev, link_speed, &fc_neg);
137*493d26c5SEd Maste 
138*493d26c5SEd Maste 		/* update ITR settings according new link speed */
139*493d26c5SEd Maste 		aq_hw_interrupt_moderation_set(hw);
140*493d26c5SEd Maste 	} else if (link_speed == 0U && aq_dev->linkup) { /* link was UP */
141*493d26c5SEd Maste 		device_printf(aq_dev->dev, "atlantic: link DOWN\n");
142*493d26c5SEd Maste 
143*493d26c5SEd Maste 		aq_dev->linkup = 0;
144*493d26c5SEd Maste 
145*493d26c5SEd Maste 		/* turn off RX Pause in RPB */
146*493d26c5SEd Maste 		rpb_rx_xoff_en_per_tc_set(hw, 0, 0);
147*493d26c5SEd Maste 
148*493d26c5SEd Maste 		iflib_link_state_change(ctx, LINK_STATE_DOWN,  0);
149*493d26c5SEd Maste 		aq_mediastatus_update(aq_dev, link_speed, &fc_neg);
150*493d26c5SEd Maste 	}
151*493d26c5SEd Maste 
152*493d26c5SEd Maste 	aq_update_hw_stats(aq_dev);
153*493d26c5SEd Maste //	AQ_DBG_EXIT(0);
154*493d26c5SEd Maste }
155*493d26c5SEd Maste 
156*493d26c5SEd Maste /**************************************************************************/
157*493d26c5SEd Maste /* interrupt service routine  (Top half)                                  */
158*493d26c5SEd Maste /**************************************************************************/
aq_isr_rx(void * arg)159*493d26c5SEd Maste int aq_isr_rx(void *arg)
160*493d26c5SEd Maste {
161*493d26c5SEd Maste 	struct aq_ring  *ring = arg;
162*493d26c5SEd Maste 	struct aq_dev   *aq_dev = ring->dev;
163*493d26c5SEd Maste 	struct aq_hw    *hw = &aq_dev->hw;
164*493d26c5SEd Maste 
165*493d26c5SEd Maste 	/* clear interrupt status */
166*493d26c5SEd Maste 	itr_irq_status_clearlsw_set(hw, BIT(ring->msix));
167*493d26c5SEd Maste 	ring->stats.irq++;
168*493d26c5SEd Maste 	return (FILTER_SCHEDULE_THREAD);
169*493d26c5SEd Maste }
170*493d26c5SEd Maste 
171*493d26c5SEd Maste /**************************************************************************/
172*493d26c5SEd Maste /* interrupt service routine  (Top half)                                  */
173*493d26c5SEd Maste /**************************************************************************/
aq_linkstat_isr(void * arg)174*493d26c5SEd Maste int aq_linkstat_isr(void *arg)
175*493d26c5SEd Maste {
176*493d26c5SEd Maste 	aq_dev_t              *aq_dev = arg;
177*493d26c5SEd Maste 	struct aq_hw          *hw = &aq_dev->hw;
178*493d26c5SEd Maste 
179*493d26c5SEd Maste 	/* clear interrupt status */
180*493d26c5SEd Maste 	itr_irq_status_clearlsw_set(hw, aq_dev->msix);
181*493d26c5SEd Maste 
182*493d26c5SEd Maste 	iflib_admin_intr_deferred(aq_dev->ctx);
183*493d26c5SEd Maste 
184*493d26c5SEd Maste 	return (FILTER_HANDLED);
185*493d26c5SEd Maste }
186