| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_wm.c,v 1.366 2015/10/13 09:03:58 knakahara Exp $ */ | | 1 | /* $NetBSD: if_wm.c,v 1.367 2015/10/13 09:10:01 knakahara Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. | | 4 | * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. | | 7 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
| @@ -73,27 +73,27 @@ | | | @@ -73,27 +73,27 @@ |
73 | * TODO (in order of importance): | | 73 | * TODO (in order of importance): |
74 | * | | 74 | * |
75 | * - Check XXX'ed comments | | 75 | * - Check XXX'ed comments |
76 | * - EEE (Energy Efficiency Ethernet) | | 76 | * - EEE (Energy Efficiency Ethernet) |
77 | * - Multi queue | | 77 | * - Multi queue |
78 | * - Image Unique ID | | 78 | * - Image Unique ID |
79 | * - LPLU other than PCH* | | 79 | * - LPLU other than PCH* |
80 | * - Virtual Function | | 80 | * - Virtual Function |
81 | * - Set LED correctly (based on contents in EEPROM) | | 81 | * - Set LED correctly (based on contents in EEPROM) |
82 | * - Rework how parameters are loaded from the EEPROM. | | 82 | * - Rework how parameters are loaded from the EEPROM. |
83 | */ | | 83 | */ |
84 | | | 84 | |
85 | #include <sys/cdefs.h> | | 85 | #include <sys/cdefs.h> |
86 | __KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.366 2015/10/13 09:03:58 knakahara Exp $"); | | 86 | __KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.367 2015/10/13 09:10:01 knakahara Exp $"); |
87 | | | 87 | |
88 | #ifdef _KERNEL_OPT | | 88 | #ifdef _KERNEL_OPT |
89 | #include "opt_net_mpsafe.h" | | 89 | #include "opt_net_mpsafe.h" |
90 | #endif | | 90 | #endif |
91 | | | 91 | |
92 | #include <sys/param.h> | | 92 | #include <sys/param.h> |
93 | #include <sys/systm.h> | | 93 | #include <sys/systm.h> |
94 | #include <sys/callout.h> | | 94 | #include <sys/callout.h> |
95 | #include <sys/mbuf.h> | | 95 | #include <sys/mbuf.h> |
96 | #include <sys/malloc.h> | | 96 | #include <sys/malloc.h> |
97 | #include <sys/kmem.h> | | 97 | #include <sys/kmem.h> |
98 | #include <sys/kernel.h> | | 98 | #include <sys/kernel.h> |
99 | #include <sys/socket.h> | | 99 | #include <sys/socket.h> |
| @@ -4036,26 +4036,83 @@ wm_rxdrain(struct wm_rxqueue *rxq) | | | @@ -4036,26 +4036,83 @@ wm_rxdrain(struct wm_rxqueue *rxq) |
4036 | KASSERT(WM_RX_LOCKED(rxq)); | | 4036 | KASSERT(WM_RX_LOCKED(rxq)); |
4037 | | | 4037 | |
4038 | for (i = 0; i < WM_NRXDESC; i++) { | | 4038 | for (i = 0; i < WM_NRXDESC; i++) { |
4039 | rxs = &rxq->rxq_soft[i]; | | 4039 | rxs = &rxq->rxq_soft[i]; |
4040 | if (rxs->rxs_mbuf != NULL) { | | 4040 | if (rxs->rxs_mbuf != NULL) { |
4041 | bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); | | 4041 | bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); |
4042 | m_freem(rxs->rxs_mbuf); | | 4042 | m_freem(rxs->rxs_mbuf); |
4043 | rxs->rxs_mbuf = NULL; | | 4043 | rxs->rxs_mbuf = NULL; |
4044 | } | | 4044 | } |
4045 | } | | 4045 | } |
4046 | } | | 4046 | } |
4047 | | | 4047 | |
4048 | /* | | 4048 | /* |
| | | 4049 | * Setup registers for RSS. |
| | | 4050 | * |
| | | 4051 | * XXX not yet VMDq support |
| | | 4052 | */ |
| | | 4053 | static void |
| | | 4054 | wm_init_rss(struct wm_softc *sc) |
| | | 4055 | { |
| | | 4056 | uint32_t mrqc, reta_reg; |
| | | 4057 | int i; |
| | | 4058 | |
| | | 4059 | for (i = 0; i < RETA_NUM_ENTRIES; i++) { |
| | | 4060 | int qid, reta_ent; |
| | | 4061 | |
| | | 4062 | qid = i % sc->sc_nrxqueues; |
| | | 4063 | switch(sc->sc_type) { |
| | | 4064 | case WM_T_82574: |
| | | 4065 | reta_ent = __SHIFTIN(qid, |
| | | 4066 | RETA_ENT_QINDEX_MASK_82574); |
| | | 4067 | break; |
| | | 4068 | case WM_T_82575: |
| | | 4069 | reta_ent = __SHIFTIN(qid, |
| | | 4070 | RETA_ENT_QINDEX1_MASK_82575); |
| | | 4071 | break; |
| | | 4072 | default: |
| | | 4073 | reta_ent = __SHIFTIN(qid, RETA_ENT_QINDEX_MASK); |
| | | 4074 | break; |
| | | 4075 | } |
| | | 4076 | |
| | | 4077 | reta_reg = CSR_READ(sc, WMREG_RETA_Q(i)); |
| | | 4078 | reta_reg &= ~RETA_ENTRY_MASK_Q(i); |
| | | 4079 | reta_reg |= __SHIFTIN(reta_ent, RETA_ENTRY_MASK_Q(i)); |
| | | 4080 | CSR_WRITE(sc, WMREG_RETA_Q(i), reta_reg); |
| | | 4081 | } |
| | | 4082 | |
| | | 4083 | for (i = 0; i < RSSRK_NUM_REGS; i++) |
| | | 4084 | CSR_WRITE(sc, WMREG_RSSRK(i), (uint32_t)random()); |
| | | 4085 | |
| | | 4086 | if (sc->sc_type == WM_T_82574) |
| | | 4087 | mrqc = MRQC_ENABLE_RSS_MQ_82574; |
| | | 4088 | else |
| | | 4089 | mrqc = MRQC_ENABLE_RSS_MQ; |
| | | 4090 | |
| | | 4091 | /* XXXX |
| | | 4092 | * The same as FreeBSD igb. |
| | | 4093 | * Why doesn't use MRQC_RSS_FIELD_IPV6_EX? |
| | | 4094 | */ |
| | | 4095 | mrqc |= (MRQC_RSS_FIELD_IPV4 | MRQC_RSS_FIELD_IPV4_TCP); |
| | | 4096 | mrqc |= (MRQC_RSS_FIELD_IPV6 | MRQC_RSS_FIELD_IPV6_TCP); |
| | | 4097 | mrqc |= (MRQC_RSS_FIELD_IPV4_UDP | MRQC_RSS_FIELD_IPV6_UDP); |
| | | 4098 | mrqc |= (MRQC_RSS_FIELD_IPV6_UDP_EX | MRQC_RSS_FIELD_IPV6_TCP_EX); |
| | | 4099 | |
| | | 4100 | CSR_WRITE(sc, WMREG_MRQC, mrqc); |
| | | 4101 | } |
| | | 4102 | |
| | | 4103 | #ifdef WM_MSI_MSIX |
| | | 4104 | |
| | | 4105 | /* |
4049 | * Adjust TX and RX queue numbers which the system actulally uses. | | 4106 | * Adjust TX and RX queue numbers which the system actulally uses. |
4050 | * | | 4107 | * |
4051 | * The numbers are affected by below parameters. | | 4108 | * The numbers are affected by below parameters. |
4052 | * - The nubmer of hardware queues | | 4109 | * - The nubmer of hardware queues |
4053 | * - The number of MSI-X vectors (= "nvectors" argument) | | 4110 | * - The number of MSI-X vectors (= "nvectors" argument) |
4054 | * - ncpu | | 4111 | * - ncpu |
4055 | */ | | 4112 | */ |
4056 | static void | | 4113 | static void |
4057 | wm_adjust_qnum(struct wm_softc *sc, int nvectors) | | 4114 | wm_adjust_qnum(struct wm_softc *sc, int nvectors) |
4058 | { | | 4115 | { |
4059 | int hw_ntxqueues, hw_nrxqueues; | | 4116 | int hw_ntxqueues, hw_nrxqueues; |
4060 | | | 4117 | |
4061 | if (nvectors < 3) { | | 4118 | if (nvectors < 3) { |
| @@ -4135,82 +4192,26 @@ wm_adjust_qnum(struct wm_softc *sc, int | | | @@ -4135,82 +4192,26 @@ wm_adjust_qnum(struct wm_softc *sc, int |
4135 | * As queues more then cpus cannot improve scaling, we limit | | 4192 | * As queues more then cpus cannot improve scaling, we limit |
4136 | * the number of queues used actually. | | 4193 | * the number of queues used actually. |
4137 | */ | | 4194 | */ |
4138 | if (ncpu < sc->sc_ntxqueues) | | 4195 | if (ncpu < sc->sc_ntxqueues) |
4139 | sc->sc_ntxqueues = ncpu; | | 4196 | sc->sc_ntxqueues = ncpu; |
4140 | if (ncpu < sc->sc_nrxqueues) | | 4197 | if (ncpu < sc->sc_nrxqueues) |
4141 | sc->sc_nrxqueues = ncpu; | | 4198 | sc->sc_nrxqueues = ncpu; |
4142 | | | 4199 | |
4143 | /* XXX Currently, this driver supports RX multiqueue only. */ | | 4200 | /* XXX Currently, this driver supports RX multiqueue only. */ |
4144 | sc->sc_ntxqueues = 1; | | 4201 | sc->sc_ntxqueues = 1; |
4145 | } | | 4202 | } |
4146 | | | 4203 | |
4147 | /* | | 4204 | /* |
4148 | * Setup registers for RSS. | | | |
4149 | * | | | |
4150 | * XXX not yet VMDq support | | | |
4151 | */ | | | |
4152 | static void | | | |
4153 | wm_init_rss(struct wm_softc *sc) | | | |
4154 | { | | | |
4155 | uint32_t mrqc, reta_reg; | | | |
4156 | int i; | | | |
4157 | | | | |
4158 | for (i = 0; i < RETA_NUM_ENTRIES; i++) { | | | |
4159 | int qid, reta_ent; | | | |
4160 | | | | |
4161 | qid = i % sc->sc_nrxqueues; | | | |
4162 | switch(sc->sc_type) { | | | |
4163 | case WM_T_82574: | | | |
4164 | reta_ent = __SHIFTIN(qid, | | | |
4165 | RETA_ENT_QINDEX_MASK_82574); | | | |
4166 | break; | | | |
4167 | case WM_T_82575: | | | |
4168 | reta_ent = __SHIFTIN(qid, | | | |
4169 | RETA_ENT_QINDEX1_MASK_82575); | | | |
4170 | break; | | | |
4171 | default: | | | |
4172 | reta_ent = __SHIFTIN(qid, RETA_ENT_QINDEX_MASK); | | | |
4173 | break; | | | |
4174 | } | | | |
4175 | | | | |
4176 | reta_reg = CSR_READ(sc, WMREG_RETA_Q(i)); | | | |
4177 | reta_reg &= ~RETA_ENTRY_MASK_Q(i); | | | |
4178 | reta_reg |= __SHIFTIN(reta_ent, RETA_ENTRY_MASK_Q(i)); | | | |
4179 | CSR_WRITE(sc, WMREG_RETA_Q(i), reta_reg); | | | |
4180 | } | | | |
4181 | | | | |
4182 | for (i = 0; i < RSSRK_NUM_REGS; i++) | | | |
4183 | CSR_WRITE(sc, WMREG_RSSRK(i), (uint32_t)random()); | | | |
4184 | | | | |
4185 | if (sc->sc_type == WM_T_82574) | | | |
4186 | mrqc = MRQC_ENABLE_RSS_MQ_82574; | | | |
4187 | else | | | |
4188 | mrqc = MRQC_ENABLE_RSS_MQ; | | | |
4189 | | | | |
4190 | /* XXXX | | | |
4191 | * The same as FreeBSD igb. | | | |
4192 | * Why doesn't use MRQC_RSS_FIELD_IPV6_EX? | | | |
4193 | */ | | | |
4194 | mrqc |= (MRQC_RSS_FIELD_IPV4 | MRQC_RSS_FIELD_IPV4_TCP); | | | |
4195 | mrqc |= (MRQC_RSS_FIELD_IPV6 | MRQC_RSS_FIELD_IPV6_TCP); | | | |
4196 | mrqc |= (MRQC_RSS_FIELD_IPV4_UDP | MRQC_RSS_FIELD_IPV6_UDP); | | | |
4197 | mrqc |= (MRQC_RSS_FIELD_IPV6_UDP_EX | MRQC_RSS_FIELD_IPV6_TCP_EX); | | | |
4198 | | | | |
4199 | CSR_WRITE(sc, WMREG_MRQC, mrqc); | | | |
4200 | } | | | |
4201 | | | | |
4202 | #ifdef WM_MSI_MSIX | | | |
4203 | /* | | | |
4204 | * Both single interrupt MSI and INTx can use this function. | | 4205 | * Both single interrupt MSI and INTx can use this function. |
4205 | */ | | 4206 | */ |
4206 | static int | | 4207 | static int |
4207 | wm_setup_legacy(struct wm_softc *sc) | | 4208 | wm_setup_legacy(struct wm_softc *sc) |
4208 | { | | 4209 | { |
4209 | pci_chipset_tag_t pc = sc->sc_pc; | | 4210 | pci_chipset_tag_t pc = sc->sc_pc; |
4210 | const char *intrstr = NULL; | | 4211 | const char *intrstr = NULL; |
4211 | char intrbuf[PCI_INTRSTR_LEN]; | | 4212 | char intrbuf[PCI_INTRSTR_LEN]; |
4212 | | | 4213 | |
4213 | intrstr = pci_intr_string(pc, sc->sc_intrs[0], intrbuf, | | 4214 | intrstr = pci_intr_string(pc, sc->sc_intrs[0], intrbuf, |
4214 | sizeof(intrbuf)); | | 4215 | sizeof(intrbuf)); |
4215 | #ifdef WM_MPSAFE | | 4216 | #ifdef WM_MPSAFE |
4216 | pci_intr_setattr(pc, &sc->sc_intrs[0], PCI_INTR_MPSAFE, true); | | 4217 | pci_intr_setattr(pc, &sc->sc_intrs[0], PCI_INTR_MPSAFE, true); |