Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'bng_en-add-link-management-and-statistics-support'

Bhargava Marreddy says:

====================
bng_en: add link management and statistics support

This series enhances the bng_en driver by adding:
1. Link/PHY support
a. Link query
b. Async Link events
c. Ethtool link set/get functionality
2. Hardware statistics reporting via ethtool -S

This version incorporates feedback received prior to splitting the
original series into two parts.
====================

Link: https://patch.msgid.link/20260406180420.279470-1-bhargava.marreddy@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+3229 -19
+2 -1
drivers/net/ethernet/broadcom/bnge/Makefile
··· 11 11 bnge_netdev.o \ 12 12 bnge_ethtool.o \ 13 13 bnge_auxr.o \ 14 - bnge_txrx.o 14 + bnge_txrx.o \ 15 + bnge_link.o
+10
drivers/net/ethernet/broadcom/bnge/bnge.h
··· 94 94 u8 queue_profile; 95 95 }; 96 96 97 + #define BNGE_PHY_FLAGS2_SHIFT 8 98 + #define BNGE_PHY_FL_NO_FCS PORT_PHY_QCAPS_RESP_FLAGS_NO_FCS 99 + #define BNGE_PHY_FL_NO_PAUSE \ 100 + (PORT_PHY_QCAPS_RESP_FLAGS2_PAUSE_UNSUPPORTED << 8) 101 + 97 102 struct bnge_dev { 98 103 struct device *dev; 99 104 struct pci_dev *pdev; ··· 212 207 213 208 struct bnge_auxr_priv *aux_priv; 214 209 struct bnge_auxr_dev *auxr_dev; 210 + 211 + struct bnge_link_info link_info; 212 + 213 + /* Copied from flags and flags2 in hwrm_port_phy_qcaps_output */ 214 + u32 phy_flags; 215 215 }; 216 216 217 217 static inline bool bnge_is_roce_en(struct bnge_dev *bd)
+1
drivers/net/ethernet/broadcom/bnge/bnge_core.c
··· 10 10 #include "bnge_devlink.h" 11 11 #include "bnge_hwrm.h" 12 12 #include "bnge_hwrm_lib.h" 13 + #include "bnge_link.h" 13 14 14 15 MODULE_LICENSE("GPL"); 15 16 MODULE_DESCRIPTION(DRV_SUMMARY);
+732
drivers/net/ethernet/broadcom/bnge/bnge_ethtool.c
··· 11 11 12 12 #include "bnge.h" 13 13 #include "bnge_ethtool.h" 14 + #include "bnge_hwrm_lib.h" 15 + 16 + static int bnge_nway_reset(struct net_device *dev) 17 + { 18 + struct bnge_net *bn = netdev_priv(dev); 19 + struct bnge_dev *bd = bn->bd; 20 + bool set_pause = false; 21 + int rc = 0; 22 + 23 + if (!BNGE_PHY_CFG_ABLE(bd)) 24 + return -EOPNOTSUPP; 25 + 26 + if (!(bn->eth_link_info.autoneg & BNGE_AUTONEG_SPEED)) 27 + return -EINVAL; 28 + 29 + if (!(bd->phy_flags & BNGE_PHY_FL_NO_PAUSE)) 30 + set_pause = true; 31 + 32 + if (netif_running(dev)) 33 + rc = bnge_hwrm_set_link_setting(bn, set_pause); 34 + 35 + return rc; 36 + } 37 + 38 + static const char * const bnge_ring_q_stats_str[] = { 39 + "ucast_packets", 40 + "mcast_packets", 41 + "bcast_packets", 42 + "ucast_bytes", 43 + "mcast_bytes", 44 + "bcast_bytes", 45 + }; 46 + 47 + static const char * const bnge_ring_tpa2_stats_str[] = { 48 + "tpa_eligible_pkt", 49 + "tpa_eligible_bytes", 50 + "tpa_pkt", 51 + "tpa_bytes", 52 + "tpa_errors", 53 + "tpa_events", 54 + }; 55 + 56 + #define BNGE_RX_PORT_STATS_ENTRY(suffix) \ 57 + { BNGE_RX_STATS_OFFSET(rx_##suffix), "rxp_" __stringify(suffix) } 58 + 59 + #define BNGE_TX_PORT_STATS_ENTRY(suffix) \ 60 + { BNGE_TX_STATS_OFFSET(tx_##suffix), "txp_" __stringify(suffix) } 61 + 62 + #define BNGE_RX_STATS_EXT_ENTRY(counter) \ 63 + { BNGE_RX_STATS_EXT_OFFSET(counter), __stringify(counter) } 64 + 65 + #define BNGE_TX_STATS_EXT_ENTRY(counter) \ 66 + { BNGE_TX_STATS_EXT_OFFSET(counter), __stringify(counter) } 67 + 68 + #define BNGE_RX_STATS_EXT_PFC_ENTRY(n) \ 69 + BNGE_RX_STATS_EXT_ENTRY(pfc_pri##n##_rx_duration_us), \ 70 + BNGE_RX_STATS_EXT_ENTRY(pfc_pri##n##_rx_transitions) 71 + 72 + #define BNGE_TX_STATS_EXT_PFC_ENTRY(n) \ 73 + BNGE_TX_STATS_EXT_ENTRY(pfc_pri##n##_tx_duration_us), \ 74 + BNGE_TX_STATS_EXT_ENTRY(pfc_pri##n##_tx_transitions) 75 + 76 + #define BNGE_RX_STATS_EXT_PFC_ENTRIES \ 77 + BNGE_RX_STATS_EXT_PFC_ENTRY(0), \ 78 + BNGE_RX_STATS_EXT_PFC_ENTRY(1), \ 79 + BNGE_RX_STATS_EXT_PFC_ENTRY(2), \ 80 + BNGE_RX_STATS_EXT_PFC_ENTRY(3), \ 81 + BNGE_RX_STATS_EXT_PFC_ENTRY(4), \ 82 + BNGE_RX_STATS_EXT_PFC_ENTRY(5), \ 83 + BNGE_RX_STATS_EXT_PFC_ENTRY(6), \ 84 + BNGE_RX_STATS_EXT_PFC_ENTRY(7) 85 + 86 + #define BNGE_TX_STATS_EXT_PFC_ENTRIES \ 87 + BNGE_TX_STATS_EXT_PFC_ENTRY(0), \ 88 + BNGE_TX_STATS_EXT_PFC_ENTRY(1), \ 89 + BNGE_TX_STATS_EXT_PFC_ENTRY(2), \ 90 + BNGE_TX_STATS_EXT_PFC_ENTRY(3), \ 91 + BNGE_TX_STATS_EXT_PFC_ENTRY(4), \ 92 + BNGE_TX_STATS_EXT_PFC_ENTRY(5), \ 93 + BNGE_TX_STATS_EXT_PFC_ENTRY(6), \ 94 + BNGE_TX_STATS_EXT_PFC_ENTRY(7) 95 + 96 + #define BNGE_RX_STATS_EXT_COS_ENTRY(n) \ 97 + BNGE_RX_STATS_EXT_ENTRY(rx_bytes_cos##n), \ 98 + BNGE_RX_STATS_EXT_ENTRY(rx_packets_cos##n) 99 + 100 + #define BNGE_TX_STATS_EXT_COS_ENTRY(n) \ 101 + BNGE_TX_STATS_EXT_ENTRY(tx_bytes_cos##n), \ 102 + BNGE_TX_STATS_EXT_ENTRY(tx_packets_cos##n) 103 + 104 + #define BNGE_RX_STATS_EXT_COS_ENTRIES \ 105 + BNGE_RX_STATS_EXT_COS_ENTRY(0), \ 106 + BNGE_RX_STATS_EXT_COS_ENTRY(1), \ 107 + BNGE_RX_STATS_EXT_COS_ENTRY(2), \ 108 + BNGE_RX_STATS_EXT_COS_ENTRY(3), \ 109 + BNGE_RX_STATS_EXT_COS_ENTRY(4), \ 110 + BNGE_RX_STATS_EXT_COS_ENTRY(5), \ 111 + BNGE_RX_STATS_EXT_COS_ENTRY(6), \ 112 + BNGE_RX_STATS_EXT_COS_ENTRY(7) \ 113 + 114 + #define BNGE_TX_STATS_EXT_COS_ENTRIES \ 115 + BNGE_TX_STATS_EXT_COS_ENTRY(0), \ 116 + BNGE_TX_STATS_EXT_COS_ENTRY(1), \ 117 + BNGE_TX_STATS_EXT_COS_ENTRY(2), \ 118 + BNGE_TX_STATS_EXT_COS_ENTRY(3), \ 119 + BNGE_TX_STATS_EXT_COS_ENTRY(4), \ 120 + BNGE_TX_STATS_EXT_COS_ENTRY(5), \ 121 + BNGE_TX_STATS_EXT_COS_ENTRY(6), \ 122 + BNGE_TX_STATS_EXT_COS_ENTRY(7) \ 123 + 124 + #define BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(n) \ 125 + BNGE_RX_STATS_EXT_ENTRY(rx_discard_bytes_cos##n), \ 126 + BNGE_RX_STATS_EXT_ENTRY(rx_discard_packets_cos##n) 127 + 128 + #define BNGE_RX_STATS_EXT_DISCARD_COS_ENTRIES \ 129 + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(0), \ 130 + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(1), \ 131 + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(2), \ 132 + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(3), \ 133 + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(4), \ 134 + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(5), \ 135 + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(6), \ 136 + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRY(7) 137 + 138 + #define BNGE_RX_STATS_PRI_ENTRY(counter, n) \ 139 + { BNGE_RX_STATS_EXT_OFFSET(counter##_cos0), \ 140 + __stringify(counter##_pri##n) } 141 + 142 + #define BNGE_TX_STATS_PRI_ENTRY(counter, n) \ 143 + { BNGE_TX_STATS_EXT_OFFSET(counter##_cos0), \ 144 + __stringify(counter##_pri##n) } 145 + 146 + #define BNGE_RX_STATS_PRI_ENTRIES(counter) \ 147 + BNGE_RX_STATS_PRI_ENTRY(counter, 0), \ 148 + BNGE_RX_STATS_PRI_ENTRY(counter, 1), \ 149 + BNGE_RX_STATS_PRI_ENTRY(counter, 2), \ 150 + BNGE_RX_STATS_PRI_ENTRY(counter, 3), \ 151 + BNGE_RX_STATS_PRI_ENTRY(counter, 4), \ 152 + BNGE_RX_STATS_PRI_ENTRY(counter, 5), \ 153 + BNGE_RX_STATS_PRI_ENTRY(counter, 6), \ 154 + BNGE_RX_STATS_PRI_ENTRY(counter, 7) 155 + 156 + #define BNGE_TX_STATS_PRI_ENTRIES(counter) \ 157 + BNGE_TX_STATS_PRI_ENTRY(counter, 0), \ 158 + BNGE_TX_STATS_PRI_ENTRY(counter, 1), \ 159 + BNGE_TX_STATS_PRI_ENTRY(counter, 2), \ 160 + BNGE_TX_STATS_PRI_ENTRY(counter, 3), \ 161 + BNGE_TX_STATS_PRI_ENTRY(counter, 4), \ 162 + BNGE_TX_STATS_PRI_ENTRY(counter, 5), \ 163 + BNGE_TX_STATS_PRI_ENTRY(counter, 6), \ 164 + BNGE_TX_STATS_PRI_ENTRY(counter, 7) 165 + 166 + #define NUM_RING_Q_HW_STATS ARRAY_SIZE(bnge_ring_q_stats_str) 167 + 168 + static const struct { 169 + long offset; 170 + char string[ETH_GSTRING_LEN]; 171 + } bnge_tx_port_stats_ext_arr[] = { 172 + BNGE_TX_STATS_EXT_COS_ENTRIES, 173 + BNGE_TX_STATS_EXT_PFC_ENTRIES, 174 + }; 175 + 176 + static const struct { 177 + long base_off; 178 + char string[ETH_GSTRING_LEN]; 179 + } bnge_rx_bytes_pri_arr[] = { 180 + BNGE_RX_STATS_PRI_ENTRIES(rx_bytes), 181 + }; 182 + 183 + static const struct { 184 + long base_off; 185 + char string[ETH_GSTRING_LEN]; 186 + } bnge_rx_pkts_pri_arr[] = { 187 + BNGE_RX_STATS_PRI_ENTRIES(rx_packets), 188 + }; 189 + 190 + static const struct { 191 + long base_off; 192 + char string[ETH_GSTRING_LEN]; 193 + } bnge_tx_bytes_pri_arr[] = { 194 + BNGE_TX_STATS_PRI_ENTRIES(tx_bytes), 195 + }; 196 + 197 + static const struct { 198 + long base_off; 199 + char string[ETH_GSTRING_LEN]; 200 + } bnge_tx_pkts_pri_arr[] = { 201 + BNGE_TX_STATS_PRI_ENTRIES(tx_packets), 202 + }; 203 + 204 + static const struct { 205 + long offset; 206 + char string[ETH_GSTRING_LEN]; 207 + } bnge_port_stats_arr[] = { 208 + BNGE_RX_PORT_STATS_ENTRY(good_vlan_frames), 209 + BNGE_RX_PORT_STATS_ENTRY(mtu_err_frames), 210 + BNGE_RX_PORT_STATS_ENTRY(tagged_frames), 211 + BNGE_RX_PORT_STATS_ENTRY(double_tagged_frames), 212 + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri0), 213 + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri1), 214 + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri2), 215 + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri3), 216 + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri4), 217 + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri5), 218 + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri6), 219 + BNGE_RX_PORT_STATS_ENTRY(pfc_ena_frames_pri7), 220 + BNGE_RX_PORT_STATS_ENTRY(eee_lpi_events), 221 + BNGE_RX_PORT_STATS_ENTRY(eee_lpi_duration), 222 + BNGE_RX_PORT_STATS_ENTRY(runt_bytes), 223 + BNGE_RX_PORT_STATS_ENTRY(runt_frames), 224 + 225 + BNGE_TX_PORT_STATS_ENTRY(good_vlan_frames), 226 + BNGE_TX_PORT_STATS_ENTRY(jabber_frames), 227 + BNGE_TX_PORT_STATS_ENTRY(fcs_err_frames), 228 + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri0), 229 + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri1), 230 + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri2), 231 + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri3), 232 + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri4), 233 + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri5), 234 + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri6), 235 + BNGE_TX_PORT_STATS_ENTRY(pfc_ena_frames_pri7), 236 + BNGE_TX_PORT_STATS_ENTRY(eee_lpi_events), 237 + BNGE_TX_PORT_STATS_ENTRY(eee_lpi_duration), 238 + BNGE_TX_PORT_STATS_ENTRY(xthol_frames), 239 + }; 240 + 241 + static const struct { 242 + long offset; 243 + char string[ETH_GSTRING_LEN]; 244 + } bnge_port_stats_ext_arr[] = { 245 + BNGE_RX_STATS_EXT_ENTRY(continuous_pause_events), 246 + BNGE_RX_STATS_EXT_ENTRY(resume_pause_events), 247 + BNGE_RX_STATS_EXT_ENTRY(continuous_roce_pause_events), 248 + BNGE_RX_STATS_EXT_ENTRY(resume_roce_pause_events), 249 + BNGE_RX_STATS_EXT_COS_ENTRIES, 250 + BNGE_RX_STATS_EXT_PFC_ENTRIES, 251 + BNGE_RX_STATS_EXT_ENTRY(rx_bits), 252 + BNGE_RX_STATS_EXT_ENTRY(rx_buffer_passed_threshold), 253 + BNGE_RX_STATS_EXT_DISCARD_COS_ENTRIES, 254 + BNGE_RX_STATS_EXT_ENTRY(rx_filter_miss), 255 + }; 256 + 257 + static int bnge_get_num_tpa_ring_stats(struct bnge_dev *bd) 258 + { 259 + if (BNGE_SUPPORTS_TPA(bd)) 260 + return BNGE_NUM_TPA_RING_STATS; 261 + return 0; 262 + } 263 + 264 + #define BNGE_NUM_PORT_STATS ARRAY_SIZE(bnge_port_stats_arr) 265 + #define BNGE_NUM_STATS_PRI \ 266 + (ARRAY_SIZE(bnge_rx_bytes_pri_arr) + \ 267 + ARRAY_SIZE(bnge_rx_pkts_pri_arr) + \ 268 + ARRAY_SIZE(bnge_tx_bytes_pri_arr) + \ 269 + ARRAY_SIZE(bnge_tx_pkts_pri_arr)) 270 + 271 + static int bnge_get_num_ring_stats(struct bnge_dev *bd) 272 + { 273 + int rx, tx; 274 + 275 + rx = NUM_RING_Q_HW_STATS + bnge_get_num_tpa_ring_stats(bd); 276 + tx = NUM_RING_Q_HW_STATS; 277 + return rx * bd->rx_nr_rings + 278 + tx * bd->tx_nr_rings_per_tc; 279 + } 280 + 281 + static u32 bnge_get_num_stats(struct bnge_net *bn) 282 + { 283 + u32 num_stats = bnge_get_num_ring_stats(bn->bd); 284 + u32 len; 285 + 286 + if (bn->flags & BNGE_FLAG_PORT_STATS) 287 + num_stats += BNGE_NUM_PORT_STATS; 288 + 289 + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { 290 + len = min_t(u32, bn->fw_rx_stats_ext_size, 291 + ARRAY_SIZE(bnge_port_stats_ext_arr)); 292 + num_stats += len; 293 + len = min_t(u32, bn->fw_tx_stats_ext_size, 294 + ARRAY_SIZE(bnge_tx_port_stats_ext_arr)); 295 + num_stats += len; 296 + if (bn->pri2cos_valid) 297 + num_stats += BNGE_NUM_STATS_PRI; 298 + } 299 + 300 + return num_stats; 301 + } 14 302 15 303 static void bnge_get_drvinfo(struct net_device *dev, 16 304 struct ethtool_drvinfo *info) ··· 311 23 strscpy(info->bus_info, pci_name(bd->pdev), sizeof(info->bus_info)); 312 24 } 313 25 26 + static int bnge_get_sset_count(struct net_device *dev, int sset) 27 + { 28 + struct bnge_net *bn = netdev_priv(dev); 29 + 30 + switch (sset) { 31 + case ETH_SS_STATS: 32 + return bnge_get_num_stats(bn); 33 + default: 34 + return -EOPNOTSUPP; 35 + } 36 + } 37 + 38 + static bool is_rx_ring(struct bnge_dev *bd, u16 ring_num) 39 + { 40 + return ring_num < bd->rx_nr_rings; 41 + } 42 + 43 + static bool is_tx_ring(struct bnge_dev *bd, u16 ring_num) 44 + { 45 + u16 tx_base = 0; 46 + 47 + if (!(bd->flags & BNGE_EN_SHARED_CHNL)) 48 + tx_base = bd->rx_nr_rings; 49 + 50 + return ring_num >= tx_base && ring_num < (tx_base + bd->tx_nr_rings_per_tc); 51 + } 52 + 53 + static void bnge_get_ethtool_stats(struct net_device *dev, 54 + struct ethtool_stats *stats, u64 *buf) 55 + { 56 + struct bnge_net *bn = netdev_priv(dev); 57 + struct bnge_dev *bd = bn->bd; 58 + u32 tpa_stats; 59 + u32 i, j = 0; 60 + 61 + if (!bn->bnapi) { 62 + j += bnge_get_num_ring_stats(bd); 63 + goto skip_ring_stats; 64 + } 65 + 66 + tpa_stats = bnge_get_num_tpa_ring_stats(bd); 67 + for (i = 0; i < bd->nq_nr_rings; i++) { 68 + struct bnge_napi *bnapi = bn->bnapi[i]; 69 + struct bnge_nq_ring_info *nqr; 70 + u64 *sw_stats; 71 + int k; 72 + 73 + nqr = &bnapi->nq_ring; 74 + sw_stats = nqr->stats.sw_stats; 75 + 76 + if (is_rx_ring(bd, i)) { 77 + buf[j++] = BNGE_GET_RING_STATS64(sw_stats, rx_ucast_pkts); 78 + buf[j++] = BNGE_GET_RING_STATS64(sw_stats, rx_mcast_pkts); 79 + buf[j++] = BNGE_GET_RING_STATS64(sw_stats, rx_bcast_pkts); 80 + buf[j++] = BNGE_GET_RING_STATS64(sw_stats, rx_ucast_bytes); 81 + buf[j++] = BNGE_GET_RING_STATS64(sw_stats, rx_mcast_bytes); 82 + buf[j++] = BNGE_GET_RING_STATS64(sw_stats, rx_bcast_bytes); 83 + } 84 + if (is_tx_ring(bd, i)) { 85 + buf[j++] = BNGE_GET_RING_STATS64(sw_stats, tx_ucast_pkts); 86 + buf[j++] = BNGE_GET_RING_STATS64(sw_stats, tx_mcast_pkts); 87 + buf[j++] = BNGE_GET_RING_STATS64(sw_stats, tx_bcast_pkts); 88 + buf[j++] = BNGE_GET_RING_STATS64(sw_stats, tx_ucast_bytes); 89 + buf[j++] = BNGE_GET_RING_STATS64(sw_stats, tx_mcast_bytes); 90 + buf[j++] = BNGE_GET_RING_STATS64(sw_stats, tx_bcast_bytes); 91 + } 92 + if (!tpa_stats || !is_rx_ring(bd, i)) 93 + continue; 94 + 95 + k = BNGE_NUM_RX_RING_STATS + BNGE_NUM_TX_RING_STATS; 96 + for (; k < BNGE_NUM_RX_RING_STATS + BNGE_NUM_TX_RING_STATS + 97 + tpa_stats; j++, k++) 98 + buf[j] = sw_stats[k]; 99 + } 100 + 101 + skip_ring_stats: 102 + if (bn->flags & BNGE_FLAG_PORT_STATS) { 103 + u64 *port_stats = bn->port_stats.sw_stats; 104 + 105 + for (i = 0; i < BNGE_NUM_PORT_STATS; i++, j++) 106 + buf[j] = *(port_stats + bnge_port_stats_arr[i].offset); 107 + } 108 + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { 109 + u64 *rx_port_stats_ext = bn->rx_port_stats_ext.sw_stats; 110 + u64 *tx_port_stats_ext = bn->tx_port_stats_ext.sw_stats; 111 + u32 len; 112 + 113 + len = min_t(u32, bn->fw_rx_stats_ext_size, 114 + ARRAY_SIZE(bnge_port_stats_ext_arr)); 115 + for (i = 0; i < len; i++, j++) { 116 + buf[j] = *(rx_port_stats_ext + 117 + bnge_port_stats_ext_arr[i].offset); 118 + } 119 + len = min_t(u32, bn->fw_tx_stats_ext_size, 120 + ARRAY_SIZE(bnge_tx_port_stats_ext_arr)); 121 + for (i = 0; i < len; i++, j++) { 122 + buf[j] = *(tx_port_stats_ext + 123 + bnge_tx_port_stats_ext_arr[i].offset); 124 + } 125 + if (bn->pri2cos_valid) { 126 + for (i = 0; i < 8; i++, j++) { 127 + long n = bnge_rx_bytes_pri_arr[i].base_off + 128 + bn->pri2cos_idx[i]; 129 + 130 + buf[j] = *(rx_port_stats_ext + n); 131 + } 132 + for (i = 0; i < 8; i++, j++) { 133 + long n = bnge_rx_pkts_pri_arr[i].base_off + 134 + bn->pri2cos_idx[i]; 135 + 136 + buf[j] = *(rx_port_stats_ext + n); 137 + } 138 + for (i = 0; i < 8; i++, j++) { 139 + long n = bnge_tx_bytes_pri_arr[i].base_off + 140 + bn->pri2cos_idx[i]; 141 + 142 + buf[j] = *(tx_port_stats_ext + n); 143 + } 144 + for (i = 0; i < 8; i++, j++) { 145 + long n = bnge_tx_pkts_pri_arr[i].base_off + 146 + bn->pri2cos_idx[i]; 147 + 148 + buf[j] = *(tx_port_stats_ext + n); 149 + } 150 + } 151 + } 152 + } 153 + 154 + static void bnge_get_strings(struct net_device *dev, u32 stringset, u8 *buf) 155 + { 156 + struct bnge_net *bn = netdev_priv(dev); 157 + struct bnge_dev *bd = bn->bd; 158 + u32 i, j, num_str; 159 + const char *str; 160 + 161 + switch (stringset) { 162 + case ETH_SS_STATS: 163 + for (i = 0; i < bd->nq_nr_rings; i++) { 164 + if (is_rx_ring(bd, i)) 165 + for (j = 0; j < NUM_RING_Q_HW_STATS; j++) { 166 + str = bnge_ring_q_stats_str[j]; 167 + ethtool_sprintf(&buf, "rxq%d_%s", i, 168 + str); 169 + } 170 + if (is_tx_ring(bd, i)) 171 + for (j = 0; j < NUM_RING_Q_HW_STATS; j++) { 172 + str = bnge_ring_q_stats_str[j]; 173 + ethtool_sprintf(&buf, "txq%d_%s", i, 174 + str); 175 + } 176 + num_str = bnge_get_num_tpa_ring_stats(bd); 177 + if (!num_str || !is_rx_ring(bd, i)) 178 + continue; 179 + 180 + for (j = 0; j < num_str; j++) { 181 + str = bnge_ring_tpa2_stats_str[j]; 182 + ethtool_sprintf(&buf, "rxq%d_%s", i, str); 183 + } 184 + } 185 + 186 + if (bn->flags & BNGE_FLAG_PORT_STATS) 187 + for (i = 0; i < BNGE_NUM_PORT_STATS; i++) { 188 + str = bnge_port_stats_arr[i].string; 189 + ethtool_puts(&buf, str); 190 + } 191 + 192 + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { 193 + u32 len; 194 + 195 + len = min_t(u32, bn->fw_rx_stats_ext_size, 196 + ARRAY_SIZE(bnge_port_stats_ext_arr)); 197 + for (i = 0; i < len; i++) { 198 + str = bnge_port_stats_ext_arr[i].string; 199 + ethtool_puts(&buf, str); 200 + } 201 + 202 + len = min_t(u32, bn->fw_tx_stats_ext_size, 203 + ARRAY_SIZE(bnge_tx_port_stats_ext_arr)); 204 + for (i = 0; i < len; i++) { 205 + str = bnge_tx_port_stats_ext_arr[i].string; 206 + ethtool_puts(&buf, str); 207 + } 208 + 209 + if (bn->pri2cos_valid) { 210 + for (i = 0; i < 8; i++) { 211 + str = bnge_rx_bytes_pri_arr[i].string; 212 + ethtool_puts(&buf, str); 213 + } 214 + 215 + for (i = 0; i < 8; i++) { 216 + str = bnge_rx_pkts_pri_arr[i].string; 217 + ethtool_puts(&buf, str); 218 + } 219 + 220 + for (i = 0; i < 8; i++) { 221 + str = bnge_tx_bytes_pri_arr[i].string; 222 + ethtool_puts(&buf, str); 223 + } 224 + 225 + for (i = 0; i < 8; i++) { 226 + str = bnge_tx_pkts_pri_arr[i].string; 227 + ethtool_puts(&buf, str); 228 + } 229 + } 230 + } 231 + break; 232 + default: 233 + netdev_err(bd->netdev, "%s invalid request %x\n", 234 + __func__, stringset); 235 + break; 236 + } 237 + } 238 + 239 + static void bnge_get_eth_phy_stats(struct net_device *dev, 240 + struct ethtool_eth_phy_stats *phy_stats) 241 + { 242 + struct bnge_net *bn = netdev_priv(dev); 243 + u64 *rx; 244 + 245 + if (!(bn->flags & BNGE_FLAG_PORT_STATS_EXT)) 246 + return; 247 + 248 + rx = bn->rx_port_stats_ext.sw_stats; 249 + phy_stats->SymbolErrorDuringCarrier = 250 + *(rx + BNGE_RX_STATS_EXT_OFFSET(rx_pcs_symbol_err)); 251 + } 252 + 253 + static void bnge_get_eth_mac_stats(struct net_device *dev, 254 + struct ethtool_eth_mac_stats *mac_stats) 255 + { 256 + struct bnge_net *bn = netdev_priv(dev); 257 + u64 *rx, *tx; 258 + 259 + if (!(bn->flags & BNGE_FLAG_PORT_STATS)) 260 + return; 261 + 262 + rx = bn->port_stats.sw_stats; 263 + tx = bn->port_stats.sw_stats + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; 264 + 265 + mac_stats->FramesReceivedOK = 266 + BNGE_GET_RX_PORT_STATS64(rx, rx_good_frames); 267 + mac_stats->FramesTransmittedOK = 268 + BNGE_GET_TX_PORT_STATS64(tx, tx_good_frames); 269 + mac_stats->FrameCheckSequenceErrors = 270 + BNGE_GET_RX_PORT_STATS64(rx, rx_fcs_err_frames); 271 + mac_stats->AlignmentErrors = 272 + BNGE_GET_RX_PORT_STATS64(rx, rx_align_err_frames); 273 + mac_stats->OutOfRangeLengthField = 274 + BNGE_GET_RX_PORT_STATS64(rx, rx_oor_len_frames); 275 + mac_stats->OctetsReceivedOK = BNGE_GET_RX_PORT_STATS64(rx, rx_bytes); 276 + mac_stats->OctetsTransmittedOK = BNGE_GET_TX_PORT_STATS64(tx, tx_bytes); 277 + mac_stats->MulticastFramesReceivedOK = 278 + BNGE_GET_RX_PORT_STATS64(rx, rx_mcast_frames); 279 + mac_stats->BroadcastFramesReceivedOK = 280 + BNGE_GET_RX_PORT_STATS64(rx, rx_bcast_frames); 281 + mac_stats->MulticastFramesXmittedOK = 282 + BNGE_GET_TX_PORT_STATS64(tx, tx_mcast_frames); 283 + mac_stats->BroadcastFramesXmittedOK = 284 + BNGE_GET_TX_PORT_STATS64(tx, tx_bcast_frames); 285 + mac_stats->FrameTooLongErrors = 286 + BNGE_GET_RX_PORT_STATS64(rx, rx_ovrsz_frames); 287 + } 288 + 289 + static void bnge_get_eth_ctrl_stats(struct net_device *dev, 290 + struct ethtool_eth_ctrl_stats *ctrl_stats) 291 + { 292 + struct bnge_net *bn = netdev_priv(dev); 293 + u64 *rx; 294 + 295 + if (!(bn->flags & BNGE_FLAG_PORT_STATS)) 296 + return; 297 + 298 + rx = bn->port_stats.sw_stats; 299 + ctrl_stats->MACControlFramesReceived = 300 + BNGE_GET_RX_PORT_STATS64(rx, rx_ctrl_frames); 301 + } 302 + 303 + static void bnge_get_pause_stats(struct net_device *dev, 304 + struct ethtool_pause_stats *pause_stats) 305 + { 306 + struct bnge_net *bn = netdev_priv(dev); 307 + u64 *rx, *tx; 308 + 309 + if (!(bn->flags & BNGE_FLAG_PORT_STATS)) 310 + return; 311 + 312 + rx = bn->port_stats.sw_stats; 313 + tx = bn->port_stats.sw_stats + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; 314 + 315 + pause_stats->rx_pause_frames = 316 + BNGE_GET_RX_PORT_STATS64(rx, rx_pause_frames); 317 + pause_stats->tx_pause_frames = 318 + BNGE_GET_TX_PORT_STATS64(tx, tx_pause_frames); 319 + } 320 + 321 + static const struct ethtool_rmon_hist_range bnge_rmon_ranges[] = { 322 + { 0, 64 }, 323 + { 65, 127 }, 324 + { 128, 255 }, 325 + { 256, 511 }, 326 + { 512, 1023 }, 327 + { 1024, 1518 }, 328 + { 1519, 2047 }, 329 + { 2048, 4095 }, 330 + { 4096, 9216 }, 331 + { 9217, 16383 }, 332 + {} 333 + }; 334 + 335 + static void bnge_get_rmon_stats(struct net_device *dev, 336 + struct ethtool_rmon_stats *rmon_stats, 337 + const struct ethtool_rmon_hist_range **ranges) 338 + { 339 + struct bnge_net *bn = netdev_priv(dev); 340 + u64 *rx, *tx; 341 + 342 + if (!(bn->flags & BNGE_FLAG_PORT_STATS)) 343 + return; 344 + 345 + rx = bn->port_stats.sw_stats; 346 + tx = bn->port_stats.sw_stats + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; 347 + 348 + rmon_stats->jabbers = BNGE_GET_RX_PORT_STATS64(rx, rx_jbr_frames); 349 + rmon_stats->oversize_pkts = 350 + BNGE_GET_RX_PORT_STATS64(rx, rx_ovrsz_frames); 351 + rmon_stats->undersize_pkts = 352 + BNGE_GET_RX_PORT_STATS64(rx, rx_undrsz_frames); 353 + 354 + rmon_stats->hist[0] = BNGE_GET_RX_PORT_STATS64(rx, rx_64b_frames); 355 + rmon_stats->hist[1] = BNGE_GET_RX_PORT_STATS64(rx, rx_65b_127b_frames); 356 + rmon_stats->hist[2] = BNGE_GET_RX_PORT_STATS64(rx, rx_128b_255b_frames); 357 + rmon_stats->hist[3] = BNGE_GET_RX_PORT_STATS64(rx, rx_256b_511b_frames); 358 + rmon_stats->hist[4] = 359 + BNGE_GET_RX_PORT_STATS64(rx, rx_512b_1023b_frames); 360 + rmon_stats->hist[5] = 361 + BNGE_GET_RX_PORT_STATS64(rx, rx_1024b_1518b_frames); 362 + rmon_stats->hist[6] = 363 + BNGE_GET_RX_PORT_STATS64(rx, rx_1519b_2047b_frames); 364 + rmon_stats->hist[7] = 365 + BNGE_GET_RX_PORT_STATS64(rx, rx_2048b_4095b_frames); 366 + rmon_stats->hist[8] = 367 + BNGE_GET_RX_PORT_STATS64(rx, rx_4096b_9216b_frames); 368 + rmon_stats->hist[9] = 369 + BNGE_GET_RX_PORT_STATS64(rx, rx_9217b_16383b_frames); 370 + 371 + rmon_stats->hist_tx[0] = BNGE_GET_TX_PORT_STATS64(tx, tx_64b_frames); 372 + rmon_stats->hist_tx[1] = 373 + BNGE_GET_TX_PORT_STATS64(tx, tx_65b_127b_frames); 374 + rmon_stats->hist_tx[2] = 375 + BNGE_GET_TX_PORT_STATS64(tx, tx_128b_255b_frames); 376 + rmon_stats->hist_tx[3] = 377 + BNGE_GET_TX_PORT_STATS64(tx, tx_256b_511b_frames); 378 + rmon_stats->hist_tx[4] = 379 + BNGE_GET_TX_PORT_STATS64(tx, tx_512b_1023b_frames); 380 + rmon_stats->hist_tx[5] = 381 + BNGE_GET_TX_PORT_STATS64(tx, tx_1024b_1518b_frames); 382 + rmon_stats->hist_tx[6] = 383 + BNGE_GET_TX_PORT_STATS64(tx, tx_1519b_2047b_frames); 384 + rmon_stats->hist_tx[7] = 385 + BNGE_GET_TX_PORT_STATS64(tx, tx_2048b_4095b_frames); 386 + rmon_stats->hist_tx[8] = 387 + BNGE_GET_TX_PORT_STATS64(tx, tx_4096b_9216b_frames); 388 + rmon_stats->hist_tx[9] = 389 + BNGE_GET_TX_PORT_STATS64(tx, tx_9217b_16383b_frames); 390 + 391 + *ranges = bnge_rmon_ranges; 392 + } 393 + 394 + static void bnge_get_pauseparam(struct net_device *dev, 395 + struct ethtool_pauseparam *epause) 396 + { 397 + struct bnge_net *bn = netdev_priv(dev); 398 + struct bnge_dev *bd = bn->bd; 399 + 400 + if (bd->phy_flags & BNGE_PHY_FL_NO_PAUSE) { 401 + epause->autoneg = 0; 402 + epause->rx_pause = 0; 403 + epause->tx_pause = 0; 404 + return; 405 + } 406 + 407 + epause->autoneg = !!(bn->eth_link_info.autoneg & 408 + BNGE_AUTONEG_FLOW_CTRL); 409 + epause->rx_pause = !!(bn->eth_link_info.req_flow_ctrl & 410 + BNGE_LINK_PAUSE_RX); 411 + epause->tx_pause = !!(bn->eth_link_info.req_flow_ctrl & 412 + BNGE_LINK_PAUSE_TX); 413 + } 414 + 415 + static int bnge_set_pauseparam(struct net_device *dev, 416 + struct ethtool_pauseparam *epause) 417 + { 418 + struct bnge_ethtool_link_info old_elink_info, *elink_info; 419 + struct bnge_net *bn = netdev_priv(dev); 420 + struct bnge_dev *bd = bn->bd; 421 + int rc = 0; 422 + 423 + if (!BNGE_PHY_CFG_ABLE(bd) || (bd->phy_flags & BNGE_PHY_FL_NO_PAUSE)) 424 + return -EOPNOTSUPP; 425 + 426 + elink_info = &bn->eth_link_info; 427 + old_elink_info = *elink_info; 428 + 429 + if (epause->autoneg) { 430 + if (!(elink_info->autoneg & BNGE_AUTONEG_SPEED)) 431 + return -EINVAL; 432 + 433 + elink_info->autoneg |= BNGE_AUTONEG_FLOW_CTRL; 434 + } else { 435 + if (elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) 436 + elink_info->force_link_chng = true; 437 + elink_info->autoneg &= ~BNGE_AUTONEG_FLOW_CTRL; 438 + } 439 + 440 + elink_info->req_flow_ctrl = 0; 441 + if (epause->rx_pause) 442 + elink_info->req_flow_ctrl |= BNGE_LINK_PAUSE_RX; 443 + if (epause->tx_pause) 444 + elink_info->req_flow_ctrl |= BNGE_LINK_PAUSE_TX; 445 + 446 + if (netif_running(dev)) { 447 + rc = bnge_hwrm_set_pause(bn); 448 + if (rc) 449 + *elink_info = old_elink_info; 450 + } 451 + 452 + return rc; 453 + } 454 + 314 455 static const struct ethtool_ops bnge_ethtool_ops = { 456 + .cap_link_lanes_supported = 1, 457 + .get_link_ksettings = bnge_get_link_ksettings, 458 + .set_link_ksettings = bnge_set_link_ksettings, 315 459 .get_drvinfo = bnge_get_drvinfo, 460 + .get_link = bnge_get_link, 461 + .nway_reset = bnge_nway_reset, 462 + .get_pauseparam = bnge_get_pauseparam, 463 + .set_pauseparam = bnge_set_pauseparam, 464 + .get_sset_count = bnge_get_sset_count, 465 + .get_strings = bnge_get_strings, 466 + .get_ethtool_stats = bnge_get_ethtool_stats, 467 + .get_eth_phy_stats = bnge_get_eth_phy_stats, 468 + .get_eth_mac_stats = bnge_get_eth_mac_stats, 469 + .get_eth_ctrl_stats = bnge_get_eth_ctrl_stats, 470 + .get_pause_stats = bnge_get_pause_stats, 471 + .get_rmon_stats = bnge_get_rmon_stats, 316 472 }; 317 473 318 474 void bnge_set_ethtool_ops(struct net_device *dev)
+382 -2
drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c
··· 14 14 #include "bnge_hwrm_lib.h" 15 15 #include "bnge_rmem.h" 16 16 #include "bnge_resc.h" 17 + #include "bnge_netdev.h" 18 + 19 + static const u16 bnge_async_events_arr[] = { 20 + ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE, 21 + ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE, 22 + ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE, 23 + ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE, 24 + }; 17 25 18 26 int bnge_hwrm_ver_get(struct bnge_dev *bd) 19 27 { ··· 174 166 175 167 int bnge_hwrm_func_drv_rgtr(struct bnge_dev *bd) 176 168 { 169 + DECLARE_BITMAP(async_events_bmap, 256); 177 170 struct hwrm_func_drv_rgtr_output *resp; 178 171 struct hwrm_func_drv_rgtr_input *req; 172 + u32 events[8]; 179 173 u32 flags; 180 - int rc; 174 + int rc, i; 181 175 182 176 rc = bnge_hwrm_req_init(bd, req, HWRM_FUNC_DRV_RGTR); 183 177 if (rc) ··· 199 189 req->ver_maj = cpu_to_le16(DRV_VER_MAJ); 200 190 req->ver_min = cpu_to_le16(DRV_VER_MIN); 201 191 req->ver_upd = cpu_to_le16(DRV_VER_UPD); 192 + 193 + memset(async_events_bmap, 0, sizeof(async_events_bmap)); 194 + for (i = 0; i < ARRAY_SIZE(bnge_async_events_arr); i++) 195 + __set_bit(bnge_async_events_arr[i], async_events_bmap); 196 + 197 + bitmap_to_arr32(events, async_events_bmap, 256); 198 + for (i = 0; i < ARRAY_SIZE(req->async_event_fwd); i++) 199 + req->async_event_fwd[i] |= cpu_to_le32(events[i]); 202 200 203 201 resp = bnge_hwrm_req_hold(bd, req); 204 202 rc = bnge_hwrm_req_send(bd, req); ··· 595 577 struct hwrm_func_qcaps_output *resp; 596 578 struct hwrm_func_qcaps_input *req; 597 579 struct bnge_pf_info *pf = &bd->pf; 598 - u32 flags; 580 + u32 flags, flags_ext; 599 581 int rc; 600 582 601 583 rc = bnge_hwrm_req_init(bd, req, HWRM_FUNC_QCAPS); ··· 613 595 bd->flags |= BNGE_EN_ROCE_V1; 614 596 if (flags & FUNC_QCAPS_RESP_FLAGS_ROCE_V2_SUPPORTED) 615 597 bd->flags |= BNGE_EN_ROCE_V2; 598 + if (flags & FUNC_QCAPS_RESP_FLAGS_EXT_STATS_SUPPORTED) 599 + bd->fw_cap |= BNGE_FW_CAP_EXT_STATS_SUPPORTED; 600 + 601 + flags_ext = le32_to_cpu(resp->flags_ext); 602 + if (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_EXT_HW_STATS_SUPPORTED) 603 + bd->fw_cap |= BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED; 616 604 617 605 pf->fw_fid = le16_to_cpu(resp->fid); 618 606 pf->port_id = le16_to_cpu(resp->port_id); ··· 1005 981 vnic->fw_rss_cos_lb_ctx[ctx_idx] = INVALID_HW_RING_ID; 1006 982 } 1007 983 984 + static bool bnge_phy_qcaps_no_speed(struct hwrm_port_phy_qcaps_output *resp) 985 + { 986 + return !resp->supported_speeds2_auto_mode && 987 + !resp->supported_speeds2_force_mode; 988 + } 989 + 990 + int bnge_hwrm_phy_qcaps(struct bnge_dev *bd) 991 + { 992 + struct bnge_link_info *link_info = &bd->link_info; 993 + struct hwrm_port_phy_qcaps_output *resp; 994 + struct hwrm_port_phy_qcaps_input *req; 995 + int rc; 996 + 997 + rc = bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_QCAPS); 998 + if (rc) 999 + return rc; 1000 + 1001 + resp = bnge_hwrm_req_hold(bd, req); 1002 + rc = bnge_hwrm_req_send(bd, req); 1003 + if (rc) 1004 + goto hwrm_phy_qcaps_exit; 1005 + 1006 + bd->phy_flags = resp->flags | 1007 + (le16_to_cpu(resp->flags2) << BNGE_PHY_FLAGS2_SHIFT); 1008 + 1009 + if (bnge_phy_qcaps_no_speed(resp)) { 1010 + link_info->phy_enabled = false; 1011 + netdev_warn(bd->netdev, "Ethernet link disabled\n"); 1012 + } else if (!link_info->phy_enabled) { 1013 + link_info->phy_enabled = true; 1014 + netdev_info(bd->netdev, "Ethernet link enabled\n"); 1015 + /* Phy re-enabled, reprobe the speeds */ 1016 + link_info->support_auto_speeds2 = 0; 1017 + } 1018 + 1019 + /* Firmware may report 0 for autoneg supported speeds when no 1020 + * SFP module is present. Skip the update to preserve the 1021 + * current supported speeds -- storing 0 would cause autoneg 1022 + * default fallback to advertise nothing. 1023 + */ 1024 + if (resp->supported_speeds2_auto_mode) 1025 + link_info->support_auto_speeds2 = 1026 + le16_to_cpu(resp->supported_speeds2_auto_mode); 1027 + 1028 + bd->port_count = resp->port_cnt; 1029 + 1030 + hwrm_phy_qcaps_exit: 1031 + bnge_hwrm_req_drop(bd, req); 1032 + return rc; 1033 + } 1034 + 1035 + int bnge_hwrm_set_link_setting(struct bnge_net *bn, bool set_pause) 1036 + { 1037 + struct hwrm_port_phy_cfg_input *req; 1038 + struct bnge_dev *bd = bn->bd; 1039 + int rc; 1040 + 1041 + rc = bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_CFG); 1042 + if (rc) 1043 + return rc; 1044 + 1045 + if (set_pause) 1046 + bnge_hwrm_set_pause_common(bn, req); 1047 + 1048 + bnge_hwrm_set_link_common(bn, req); 1049 + 1050 + rc = bnge_hwrm_req_send(bd, req); 1051 + if (!rc) 1052 + bn->eth_link_info.force_link_chng = false; 1053 + 1054 + return rc; 1055 + } 1056 + 1057 + int bnge_update_link(struct bnge_net *bn, bool chng_link_state) 1058 + { 1059 + struct hwrm_port_phy_qcfg_output *resp; 1060 + struct hwrm_port_phy_qcfg_input *req; 1061 + struct bnge_link_info *link_info; 1062 + struct bnge_dev *bd = bn->bd; 1063 + bool support_changed; 1064 + u8 link_state; 1065 + int rc; 1066 + 1067 + link_info = &bd->link_info; 1068 + link_state = link_info->link_state; 1069 + 1070 + rc = bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_QCFG); 1071 + if (rc) 1072 + return rc; 1073 + 1074 + resp = bnge_hwrm_req_hold(bd, req); 1075 + rc = bnge_hwrm_req_send(bd, req); 1076 + if (rc) { 1077 + bnge_hwrm_req_drop(bd, req); 1078 + return rc; 1079 + } 1080 + 1081 + memcpy(&link_info->phy_qcfg_resp, resp, sizeof(*resp)); 1082 + link_info->phy_link_status = resp->link; 1083 + link_info->duplex = resp->duplex_state; 1084 + link_info->pause = resp->pause; 1085 + link_info->auto_mode = resp->auto_mode; 1086 + link_info->auto_pause_setting = resp->auto_pause; 1087 + link_info->lp_pause = resp->link_partner_adv_pause; 1088 + link_info->force_pause_setting = resp->force_pause; 1089 + link_info->duplex_setting = resp->duplex_cfg; 1090 + if (link_info->phy_link_status == BNGE_LINK_LINK) { 1091 + link_info->link_speed = le16_to_cpu(resp->link_speed); 1092 + link_info->active_lanes = resp->active_lanes; 1093 + } else { 1094 + link_info->link_speed = 0; 1095 + link_info->active_lanes = 0; 1096 + } 1097 + link_info->force_link_speed2 = le16_to_cpu(resp->force_link_speeds2); 1098 + link_info->support_speeds2 = le16_to_cpu(resp->support_speeds2); 1099 + link_info->auto_link_speeds2 = le16_to_cpu(resp->auto_link_speeds2); 1100 + link_info->lp_auto_link_speeds = 1101 + le16_to_cpu(resp->link_partner_adv_speeds); 1102 + link_info->media_type = resp->media_type; 1103 + link_info->phy_type = resp->phy_type; 1104 + link_info->phy_addr = resp->eee_config_phy_addr & 1105 + PORT_PHY_QCFG_RESP_PHY_ADDR_MASK; 1106 + link_info->module_status = resp->module_status; 1107 + 1108 + link_info->fec_cfg = le16_to_cpu(resp->fec_cfg); 1109 + link_info->active_fec_sig_mode = resp->active_fec_signal_mode; 1110 + 1111 + if (chng_link_state) { 1112 + if (link_info->phy_link_status == BNGE_LINK_LINK) 1113 + link_info->link_state = BNGE_LINK_STATE_UP; 1114 + else 1115 + link_info->link_state = BNGE_LINK_STATE_DOWN; 1116 + if (link_state != link_info->link_state) 1117 + bnge_report_link(bd); 1118 + } else { 1119 + /* always link down if not required to update link state */ 1120 + link_info->link_state = BNGE_LINK_STATE_DOWN; 1121 + } 1122 + bnge_hwrm_req_drop(bd, req); 1123 + 1124 + if (!BNGE_PHY_CFG_ABLE(bd)) 1125 + return 0; 1126 + 1127 + support_changed = bnge_support_speed_dropped(bn); 1128 + if (support_changed && (bn->eth_link_info.autoneg & BNGE_AUTONEG_SPEED)) 1129 + rc = bnge_hwrm_set_link_setting(bn, true); 1130 + return rc; 1131 + } 1132 + 1133 + int bnge_hwrm_set_pause(struct bnge_net *bn) 1134 + { 1135 + struct bnge_ethtool_link_info *elink_info = &bn->eth_link_info; 1136 + struct hwrm_port_phy_cfg_input *req; 1137 + struct bnge_dev *bd = bn->bd; 1138 + bool pause_autoneg; 1139 + int rc; 1140 + 1141 + rc = bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_CFG); 1142 + if (rc) 1143 + return rc; 1144 + 1145 + pause_autoneg = !!(elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL); 1146 + 1147 + /* Prepare PHY pause-advertisement or forced-pause settings. */ 1148 + bnge_hwrm_set_pause_common(bn, req); 1149 + 1150 + /* Prepare speed/autoneg settings */ 1151 + if (pause_autoneg || elink_info->force_link_chng) 1152 + bnge_hwrm_set_link_common(bn, req); 1153 + 1154 + rc = bnge_hwrm_req_send(bd, req); 1155 + if (!rc && !pause_autoneg) { 1156 + /* Since changing of pause setting, with pause autoneg off, 1157 + * doesn't trigger any link change event, the driver needs to 1158 + * update the current MAC pause upon successful return of the 1159 + * phy_cfg command. 1160 + */ 1161 + bd->link_info.force_pause_setting = 1162 + bd->link_info.pause = elink_info->req_flow_ctrl; 1163 + bd->link_info.auto_pause_setting = 0; 1164 + if (!elink_info->force_link_chng) 1165 + bnge_report_link(bd); 1166 + } 1167 + if (!rc) 1168 + elink_info->force_link_chng = false; 1169 + 1170 + return rc; 1171 + } 1172 + 1173 + int bnge_hwrm_shutdown_link(struct bnge_dev *bd) 1174 + { 1175 + struct hwrm_port_phy_cfg_input *req; 1176 + int rc; 1177 + 1178 + if (!BNGE_PHY_CFG_ABLE(bd)) 1179 + return 0; 1180 + 1181 + rc = bnge_hwrm_req_init(bd, req, HWRM_PORT_PHY_CFG); 1182 + if (rc) 1183 + return rc; 1184 + 1185 + req->flags = cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DWN); 1186 + rc = bnge_hwrm_req_send(bd, req); 1187 + if (!rc) { 1188 + /* Device is not obliged to link down in certain scenarios, 1189 + * even when forced. Setting the state unknown is consistent 1190 + * with driver startup and will force link state to be 1191 + * reported during subsequent open based on PORT_PHY_QCFG. 1192 + */ 1193 + bd->link_info.link_state = BNGE_LINK_STATE_UNKNOWN; 1194 + } 1195 + return rc; 1196 + } 1197 + 1008 1198 void bnge_hwrm_stat_ctx_free(struct bnge_net *bn) 1009 1199 { 1010 1200 struct hwrm_stat_ctx_free_input *req; ··· 1483 1245 bnge_hwrm_vnic_update_tunl_tpa(bd, req); 1484 1246 } 1485 1247 req->vnic_id = cpu_to_le16(vnic->fw_vnic_id); 1248 + 1249 + return bnge_hwrm_req_send(bd, req); 1250 + } 1251 + 1252 + int bnge_hwrm_func_qstat_ext(struct bnge_dev *bd, struct bnge_stats_mem *stats) 1253 + { 1254 + struct hwrm_func_qstats_ext_output *resp; 1255 + struct hwrm_func_qstats_ext_input *req; 1256 + __le64 *hw_masks; 1257 + int rc; 1258 + 1259 + if (!(bd->fw_cap & BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED)) 1260 + return -EOPNOTSUPP; 1261 + 1262 + rc = bnge_hwrm_req_init(bd, req, HWRM_FUNC_QSTATS_EXT); 1263 + if (rc) 1264 + return rc; 1265 + 1266 + req->fid = cpu_to_le16(0xffff); 1267 + req->flags = FUNC_QSTATS_EXT_REQ_FLAGS_COUNTER_MASK; 1268 + 1269 + resp = bnge_hwrm_req_hold(bd, req); 1270 + rc = bnge_hwrm_req_send(bd, req); 1271 + if (!rc) { 1272 + hw_masks = &resp->rx_ucast_pkts; 1273 + bnge_copy_hw_masks(stats->hw_masks, hw_masks, stats->len / 8); 1274 + } 1275 + bnge_hwrm_req_drop(bd, req); 1276 + return rc; 1277 + } 1278 + 1279 + int bnge_hwrm_port_qstats_ext(struct bnge_dev *bd, u8 flags) 1280 + { 1281 + struct hwrm_queue_pri2cos_qcfg_output *resp_qc; 1282 + struct bnge_net *bn = netdev_priv(bd->netdev); 1283 + struct hwrm_queue_pri2cos_qcfg_input *req_qc; 1284 + struct hwrm_port_qstats_ext_output *resp_qs; 1285 + struct hwrm_port_qstats_ext_input *req_qs; 1286 + struct bnge_pf_info *pf = &bd->pf; 1287 + u32 tx_stat_size; 1288 + int rc; 1289 + 1290 + if (!(bn->flags & BNGE_FLAG_PORT_STATS_EXT)) 1291 + return 0; 1292 + 1293 + if (flags && !(bd->fw_cap & BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED)) 1294 + return -EOPNOTSUPP; 1295 + 1296 + rc = bnge_hwrm_req_init(bd, req_qs, HWRM_PORT_QSTATS_EXT); 1297 + if (rc) 1298 + return rc; 1299 + 1300 + req_qs->flags = flags; 1301 + req_qs->port_id = cpu_to_le16(pf->port_id); 1302 + req_qs->rx_stat_size = cpu_to_le16(sizeof(struct rx_port_stats_ext)); 1303 + req_qs->rx_stat_host_addr = 1304 + cpu_to_le64(bn->rx_port_stats_ext.hw_stats_map); 1305 + tx_stat_size = bn->tx_port_stats_ext.hw_stats ? 1306 + sizeof(struct tx_port_stats_ext) : 0; 1307 + req_qs->tx_stat_size = cpu_to_le16(tx_stat_size); 1308 + req_qs->tx_stat_host_addr = 1309 + cpu_to_le64(bn->tx_port_stats_ext.hw_stats_map); 1310 + resp_qs = bnge_hwrm_req_hold(bd, req_qs); 1311 + rc = bnge_hwrm_req_send(bd, req_qs); 1312 + if (!rc) { 1313 + bn->fw_rx_stats_ext_size = 1314 + le16_to_cpu(resp_qs->rx_stat_size) / 8; 1315 + bn->fw_tx_stats_ext_size = tx_stat_size ? 1316 + le16_to_cpu(resp_qs->tx_stat_size) / 8 : 0; 1317 + } else { 1318 + bn->fw_rx_stats_ext_size = 0; 1319 + bn->fw_tx_stats_ext_size = 0; 1320 + } 1321 + bnge_hwrm_req_drop(bd, req_qs); 1322 + 1323 + if (flags) 1324 + return rc; 1325 + 1326 + if (bn->fw_tx_stats_ext_size <= 1327 + offsetof(struct tx_port_stats_ext, pfc_pri0_tx_duration_us) / 8) { 1328 + bn->pri2cos_valid = false; 1329 + return rc; 1330 + } 1331 + 1332 + rc = bnge_hwrm_req_init(bd, req_qc, HWRM_QUEUE_PRI2COS_QCFG); 1333 + if (rc) 1334 + return rc; 1335 + 1336 + req_qc->flags = cpu_to_le32(QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN); 1337 + 1338 + resp_qc = bnge_hwrm_req_hold(bd, req_qc); 1339 + rc = bnge_hwrm_req_send(bd, req_qc); 1340 + if (!rc) { 1341 + u8 *pri2cos; 1342 + int i, j; 1343 + 1344 + pri2cos = &resp_qc->pri0_cos_queue_id; 1345 + for (i = 0; i < 8; i++) { 1346 + u8 queue_id = pri2cos[i]; 1347 + u8 queue_idx; 1348 + 1349 + /* Per port queue IDs start from 0, 10, 20, etc */ 1350 + queue_idx = queue_id % 10; 1351 + if (queue_idx >= BNGE_MAX_QUEUE) { 1352 + bn->pri2cos_valid = false; 1353 + rc = -EINVAL; 1354 + goto drop_req; 1355 + } 1356 + for (j = 0; j < bd->max_q; j++) { 1357 + if (bd->q_ids[j] == queue_id) 1358 + bn->pri2cos_idx[i] = queue_idx; 1359 + } 1360 + } 1361 + bn->pri2cos_valid = true; 1362 + } 1363 + drop_req: 1364 + bnge_hwrm_req_drop(bd, req_qc); 1365 + return rc; 1366 + } 1367 + 1368 + int bnge_hwrm_port_qstats(struct bnge_dev *bd, u8 flags) 1369 + { 1370 + struct bnge_net *bn = netdev_priv(bd->netdev); 1371 + struct hwrm_port_qstats_input *req; 1372 + struct bnge_pf_info *pf = &bd->pf; 1373 + int rc; 1374 + 1375 + if (!(bn->flags & BNGE_FLAG_PORT_STATS)) 1376 + return 0; 1377 + 1378 + if (flags && !(bd->fw_cap & BNGE_FW_CAP_EXT_HW_STATS_SUPPORTED)) 1379 + return -EOPNOTSUPP; 1380 + 1381 + rc = bnge_hwrm_req_init(bd, req, HWRM_PORT_QSTATS); 1382 + if (rc) 1383 + return rc; 1384 + 1385 + req->flags = flags; 1386 + req->port_id = cpu_to_le16(pf->port_id); 1387 + req->tx_stat_host_addr = cpu_to_le64(bn->port_stats.hw_stats_map + 1388 + BNGE_TX_PORT_STATS_BYTE_OFFSET); 1389 + req->rx_stat_host_addr = cpu_to_le64(bn->port_stats.hw_stats_map); 1486 1390 1487 1391 return bnge_hwrm_req_send(bd, req); 1488 1392 }
+8
drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h
··· 57 57 int bnge_hwrm_set_async_event_cr(struct bnge_dev *bd, int idx); 58 58 int bnge_hwrm_vnic_set_tpa(struct bnge_dev *bd, struct bnge_vnic_info *vnic, 59 59 u32 tpa_flags); 60 + int bnge_update_link(struct bnge_net *bn, bool chng_link_state); 61 + int bnge_hwrm_phy_qcaps(struct bnge_dev *bd); 62 + int bnge_hwrm_set_link_setting(struct bnge_net *bn, bool set_pause); 63 + int bnge_hwrm_set_pause(struct bnge_net *bn); 64 + int bnge_hwrm_shutdown_link(struct bnge_dev *bd); 65 + int bnge_hwrm_port_qstats(struct bnge_dev *bd, u8 flags); 66 + int bnge_hwrm_port_qstats_ext(struct bnge_dev *bd, u8 flags); 67 + int bnge_hwrm_func_qstat_ext(struct bnge_dev *bd, struct bnge_stats_mem *stats); 60 68 #endif /* _BNGE_HWRM_LIB_H_ */
+1132
drivers/net/ethernet/broadcom/bnge/bnge_link.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2026 Broadcom. 3 + 4 + #include <linux/linkmode.h> 5 + 6 + #include "bnge.h" 7 + #include "bnge_link.h" 8 + #include "bnge_hwrm_lib.h" 9 + 10 + enum bnge_media_type { 11 + BNGE_MEDIA_UNKNOWN = 0, 12 + BNGE_MEDIA_CR, 13 + BNGE_MEDIA_SR, 14 + BNGE_MEDIA_LR_ER_FR, 15 + BNGE_MEDIA_KR, 16 + __BNGE_MEDIA_END, 17 + }; 18 + 19 + static const enum bnge_media_type bnge_phy_types[] = { 20 + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR4] = BNGE_MEDIA_CR, 21 + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR4] = BNGE_MEDIA_SR, 22 + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR4] = BNGE_MEDIA_LR_ER_FR, 23 + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER4] = BNGE_MEDIA_LR_ER_FR, 24 + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR10] = BNGE_MEDIA_SR, 25 + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASECR4] = BNGE_MEDIA_CR, 26 + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASESR4] = BNGE_MEDIA_SR, 27 + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASELR4] = BNGE_MEDIA_LR_ER_FR, 28 + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASEER4] = BNGE_MEDIA_LR_ER_FR, 29 + [PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASECR] = BNGE_MEDIA_CR, 30 + [PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASESR] = BNGE_MEDIA_SR, 31 + [PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASELR] = BNGE_MEDIA_LR_ER_FR, 32 + [PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASEER] = BNGE_MEDIA_LR_ER_FR, 33 + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR2] = BNGE_MEDIA_CR, 34 + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR2] = BNGE_MEDIA_SR, 35 + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR2] = BNGE_MEDIA_LR_ER_FR, 36 + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER2] = BNGE_MEDIA_LR_ER_FR, 37 + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR] = BNGE_MEDIA_CR, 38 + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR] = BNGE_MEDIA_SR, 39 + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR] = BNGE_MEDIA_LR_ER_FR, 40 + [PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER] = BNGE_MEDIA_LR_ER_FR, 41 + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASECR2] = BNGE_MEDIA_CR, 42 + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASESR2] = BNGE_MEDIA_SR, 43 + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASELR2] = BNGE_MEDIA_LR_ER_FR, 44 + [PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASEER2] = BNGE_MEDIA_LR_ER_FR, 45 + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASECR8] = BNGE_MEDIA_CR, 46 + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASESR8] = BNGE_MEDIA_SR, 47 + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASELR8] = BNGE_MEDIA_LR_ER_FR, 48 + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASEER8] = BNGE_MEDIA_LR_ER_FR, 49 + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASECR4] = BNGE_MEDIA_CR, 50 + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASESR4] = BNGE_MEDIA_SR, 51 + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASELR4] = BNGE_MEDIA_LR_ER_FR, 52 + [PORT_PHY_QCFG_RESP_PHY_TYPE_400G_BASEER4] = BNGE_MEDIA_LR_ER_FR, 53 + }; 54 + 55 + static u32 bnge_fw_to_ethtool_speed(u16 fw_link_speed) 56 + { 57 + switch (fw_link_speed) { 58 + case BNGE_LINK_SPEED_50GB: 59 + case BNGE_LINK_SPEED_50GB_PAM4: 60 + return SPEED_50000; 61 + case BNGE_LINK_SPEED_100GB: 62 + case BNGE_LINK_SPEED_100GB_PAM4: 63 + case BNGE_LINK_SPEED_100GB_PAM4_112: 64 + return SPEED_100000; 65 + case BNGE_LINK_SPEED_200GB: 66 + case BNGE_LINK_SPEED_200GB_PAM4: 67 + case BNGE_LINK_SPEED_200GB_PAM4_112: 68 + return SPEED_200000; 69 + case BNGE_LINK_SPEED_400GB: 70 + case BNGE_LINK_SPEED_400GB_PAM4: 71 + case BNGE_LINK_SPEED_400GB_PAM4_112: 72 + return SPEED_400000; 73 + case BNGE_LINK_SPEED_800GB: 74 + case BNGE_LINK_SPEED_800GB_PAM4_112: 75 + return SPEED_800000; 76 + default: 77 + return SPEED_UNKNOWN; 78 + } 79 + } 80 + 81 + static void bnge_set_auto_speed(struct bnge_net *bn) 82 + { 83 + struct bnge_ethtool_link_info *elink_info = &bn->eth_link_info; 84 + struct bnge_link_info *link_info; 85 + 86 + link_info = &bn->bd->link_info; 87 + elink_info->advertising = link_info->auto_link_speeds2; 88 + } 89 + 90 + static void bnge_set_force_speed(struct bnge_net *bn) 91 + { 92 + struct bnge_ethtool_link_info *elink_info = &bn->eth_link_info; 93 + struct bnge_link_info *link_info; 94 + 95 + link_info = &bn->bd->link_info; 96 + elink_info->req_link_speed = link_info->force_link_speed2; 97 + switch (elink_info->req_link_speed) { 98 + case BNGE_LINK_SPEED_50GB_PAM4: 99 + case BNGE_LINK_SPEED_100GB_PAM4: 100 + case BNGE_LINK_SPEED_200GB_PAM4: 101 + case BNGE_LINK_SPEED_400GB_PAM4: 102 + elink_info->req_signal_mode = BNGE_SIG_MODE_PAM4; 103 + break; 104 + case BNGE_LINK_SPEED_100GB_PAM4_112: 105 + case BNGE_LINK_SPEED_200GB_PAM4_112: 106 + case BNGE_LINK_SPEED_400GB_PAM4_112: 107 + case BNGE_LINK_SPEED_800GB_PAM4_112: 108 + elink_info->req_signal_mode = BNGE_SIG_MODE_PAM4_112; 109 + break; 110 + default: 111 + elink_info->req_signal_mode = BNGE_SIG_MODE_NRZ; 112 + break; 113 + } 114 + } 115 + 116 + void bnge_init_ethtool_link_settings(struct bnge_net *bn) 117 + { 118 + struct bnge_ethtool_link_info *elink_info = &bn->eth_link_info; 119 + struct bnge_link_info *link_info; 120 + struct bnge_dev *bd = bn->bd; 121 + 122 + link_info = &bd->link_info; 123 + 124 + if (BNGE_AUTO_MODE(link_info->auto_mode)) { 125 + elink_info->autoneg = BNGE_AUTONEG_SPEED; 126 + if (link_info->auto_pause_setting & 127 + PORT_PHY_QCFG_RESP_AUTO_PAUSE_AUTONEG_PAUSE) 128 + elink_info->autoneg |= BNGE_AUTONEG_FLOW_CTRL; 129 + bnge_set_auto_speed(bn); 130 + } else { 131 + elink_info->autoneg = 0; 132 + elink_info->advertising = 0; 133 + bnge_set_force_speed(bn); 134 + elink_info->req_duplex = link_info->duplex_setting; 135 + } 136 + if (elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) 137 + elink_info->req_flow_ctrl = 138 + link_info->auto_pause_setting & BNGE_LINK_PAUSE_BOTH; 139 + else 140 + elink_info->req_flow_ctrl = link_info->force_pause_setting; 141 + } 142 + 143 + int bnge_probe_phy(struct bnge_net *bn, bool fw_dflt) 144 + { 145 + struct bnge_dev *bd = bn->bd; 146 + int rc; 147 + 148 + bd->phy_flags = 0; 149 + rc = bnge_hwrm_phy_qcaps(bd); 150 + if (rc) { 151 + netdev_err(bn->netdev, 152 + "Probe PHY can't get PHY qcaps (rc: %d)\n", rc); 153 + return rc; 154 + } 155 + if (bd->phy_flags & BNGE_PHY_FL_NO_FCS) 156 + bn->netdev->priv_flags |= IFF_SUPP_NOFCS; 157 + else 158 + bn->netdev->priv_flags &= ~IFF_SUPP_NOFCS; 159 + if (!fw_dflt) 160 + return 0; 161 + 162 + rc = bnge_update_link(bn, false); 163 + if (rc) { 164 + netdev_err(bn->netdev, "Probe PHY can't update link (rc: %d)\n", 165 + rc); 166 + return rc; 167 + } 168 + bnge_init_ethtool_link_settings(bn); 169 + 170 + return 0; 171 + } 172 + 173 + void bnge_hwrm_set_link_common(struct bnge_net *bn, 174 + struct hwrm_port_phy_cfg_input *req) 175 + { 176 + struct bnge_ethtool_link_info *elink_info = &bn->eth_link_info; 177 + 178 + if (elink_info->autoneg & BNGE_AUTONEG_SPEED) { 179 + req->auto_mode |= PORT_PHY_CFG_REQ_AUTO_MODE_SPEED_MASK; 180 + req->enables |= cpu_to_le32(BNGE_PHY_AUTO_SPEEDS2_MASK); 181 + req->auto_link_speeds2_mask = 182 + cpu_to_le16(elink_info->advertising); 183 + req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_MODE); 184 + req->flags |= cpu_to_le32(BNGE_PHY_FLAGS_RESTART_AUTO); 185 + } else { 186 + req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE); 187 + req->force_link_speeds2 = 188 + cpu_to_le16(elink_info->req_link_speed); 189 + req->enables |= 190 + cpu_to_le32(BNGE_PHY_FLAGS_ENA_FORCE_SPEEDS2); 191 + netif_info(bn, link, bn->netdev, 192 + "Forcing FW speed2: %d\n", 193 + (u32)elink_info->req_link_speed); 194 + } 195 + 196 + /* tell FW that the setting takes effect immediately */ 197 + req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_RESET_PHY); 198 + } 199 + 200 + static bool bnge_auto_speed_updated(struct bnge_net *bn) 201 + { 202 + struct bnge_ethtool_link_info *elink_info = &bn->eth_link_info; 203 + struct bnge_link_info *link_info = &bn->bd->link_info; 204 + 205 + return elink_info->advertising != link_info->auto_link_speeds2; 206 + } 207 + 208 + void bnge_hwrm_set_pause_common(struct bnge_net *bn, 209 + struct hwrm_port_phy_cfg_input *req) 210 + { 211 + if (bn->eth_link_info.autoneg & BNGE_AUTONEG_FLOW_CTRL) { 212 + req->auto_pause = PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE; 213 + if (bn->eth_link_info.req_flow_ctrl & BNGE_LINK_PAUSE_RX) 214 + req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_RX; 215 + if (bn->eth_link_info.req_flow_ctrl & BNGE_LINK_PAUSE_TX) 216 + req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_TX; 217 + req->enables |= 218 + cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE); 219 + } else { 220 + if (bn->eth_link_info.req_flow_ctrl & BNGE_LINK_PAUSE_RX) 221 + req->force_pause |= PORT_PHY_CFG_REQ_FORCE_PAUSE_RX; 222 + if (bn->eth_link_info.req_flow_ctrl & BNGE_LINK_PAUSE_TX) 223 + req->force_pause |= PORT_PHY_CFG_REQ_FORCE_PAUSE_TX; 224 + req->enables |= 225 + cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_FORCE_PAUSE); 226 + req->auto_pause = req->force_pause; 227 + req->enables |= 228 + cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE); 229 + } 230 + } 231 + 232 + static bool bnge_force_speed_updated(struct bnge_net *bn) 233 + { 234 + struct bnge_ethtool_link_info *elink_info = &bn->eth_link_info; 235 + struct bnge_link_info *link_info = &bn->bd->link_info; 236 + 237 + return elink_info->req_link_speed != link_info->force_link_speed2; 238 + } 239 + 240 + int bnge_update_phy_setting(struct bnge_net *bn) 241 + { 242 + struct bnge_ethtool_link_info *elink_info; 243 + struct bnge_link_info *link_info; 244 + struct bnge_dev *bd = bn->bd; 245 + bool update_pause = false; 246 + bool update_link = false; 247 + bool hw_pause_autoneg; 248 + bool pause_autoneg; 249 + int rc; 250 + 251 + link_info = &bd->link_info; 252 + elink_info = &bn->eth_link_info; 253 + rc = bnge_update_link(bn, true); 254 + if (rc) { 255 + netdev_err(bn->netdev, "failed to update link (rc: %d)\n", 256 + rc); 257 + return rc; 258 + } 259 + 260 + pause_autoneg = !!(elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL); 261 + hw_pause_autoneg = !!(link_info->auto_pause_setting & 262 + PORT_PHY_QCFG_RESP_AUTO_PAUSE_AUTONEG_PAUSE); 263 + 264 + /* Check if pause autonegotiation state has changed */ 265 + if (pause_autoneg != hw_pause_autoneg) { 266 + update_pause = true; 267 + } else if (pause_autoneg) { 268 + /* If pause autoneg is enabled, check if the 269 + * requested RX/TX bits changed 270 + */ 271 + if ((link_info->auto_pause_setting & BNGE_LINK_PAUSE_BOTH) != 272 + elink_info->req_flow_ctrl) 273 + update_pause = true; 274 + } else { 275 + /* If pause autoneg is disabled, check if the 276 + * forced RX/TX bits changed 277 + */ 278 + if (link_info->force_pause_setting != elink_info->req_flow_ctrl) 279 + update_pause = true; 280 + } 281 + 282 + /* Force update if link change is requested */ 283 + if (elink_info->force_link_chng) 284 + update_pause = true; 285 + 286 + /* Check if link speed or duplex settings have changed */ 287 + if (!(elink_info->autoneg & BNGE_AUTONEG_SPEED)) { 288 + if (BNGE_AUTO_MODE(link_info->auto_mode) || 289 + bnge_force_speed_updated(bn) || 290 + elink_info->req_duplex != link_info->duplex_setting) 291 + update_link = true; 292 + } else { 293 + if (link_info->auto_mode == BNGE_LINK_AUTO_NONE || 294 + bnge_auto_speed_updated(bn)) 295 + update_link = true; 296 + } 297 + 298 + /* The last close may have shut down the link, so need to call 299 + * PHY_CFG to bring it back up. 300 + */ 301 + if (!BNGE_LINK_IS_UP(bd)) 302 + update_link = true; 303 + 304 + if (update_link) 305 + rc = bnge_hwrm_set_link_setting(bn, update_pause); 306 + else if (update_pause) 307 + rc = bnge_hwrm_set_pause(bn); 308 + 309 + if (rc) { 310 + netdev_err(bn->netdev, 311 + "failed to update PHY setting (rc: %d)\n", rc); 312 + return rc; 313 + } 314 + 315 + return 0; 316 + } 317 + 318 + void bnge_get_port_module_status(struct bnge_net *bn) 319 + { 320 + struct hwrm_port_phy_qcfg_output *resp; 321 + struct bnge_link_info *link_info; 322 + struct bnge_dev *bd = bn->bd; 323 + u8 module_status; 324 + 325 + link_info = &bd->link_info; 326 + resp = &link_info->phy_qcfg_resp; 327 + 328 + if (bnge_update_link(bn, true)) 329 + return; 330 + 331 + module_status = link_info->module_status; 332 + switch (module_status) { 333 + case PORT_PHY_QCFG_RESP_MODULE_STATUS_DISABLETX: 334 + case PORT_PHY_QCFG_RESP_MODULE_STATUS_PWRDOWN: 335 + case PORT_PHY_QCFG_RESP_MODULE_STATUS_WARNINGMSG: 336 + netdev_warn(bn->netdev, 337 + "Unqualified SFP+ module detected on port %d\n", 338 + bd->pf.port_id); 339 + netdev_warn(bn->netdev, "Module part number %.*s\n", 340 + (int)sizeof(resp->phy_vendor_partnumber), 341 + resp->phy_vendor_partnumber); 342 + if (module_status == PORT_PHY_QCFG_RESP_MODULE_STATUS_DISABLETX) 343 + netdev_warn(bn->netdev, "TX is disabled\n"); 344 + if (module_status == PORT_PHY_QCFG_RESP_MODULE_STATUS_PWRDOWN) 345 + netdev_warn(bn->netdev, "SFP+ module is shut down\n"); 346 + break; 347 + } 348 + } 349 + 350 + static void bnge_set_default_adv_speeds(struct bnge_net *bn) 351 + { 352 + struct bnge_ethtool_link_info *elink_info = &bn->eth_link_info; 353 + struct bnge_link_info *link_info = &bn->bd->link_info; 354 + 355 + elink_info->advertising = link_info->support_auto_speeds2; 356 + } 357 + 358 + static bool bnge_support_dropped(u16 advertising, u16 supported) 359 + { 360 + return (advertising & ~supported) != 0; 361 + } 362 + 363 + bool bnge_support_speed_dropped(struct bnge_net *bn) 364 + { 365 + struct bnge_ethtool_link_info *elink_info = &bn->eth_link_info; 366 + struct bnge_link_info *link_info = &bn->bd->link_info; 367 + 368 + /* Check if any advertised speeds are no longer supported. The caller 369 + * holds the netdev instance lock, so we can modify link_info settings. 370 + */ 371 + if (bnge_support_dropped(elink_info->advertising, 372 + link_info->support_auto_speeds2)) { 373 + elink_info->advertising = link_info->support_auto_speeds2; 374 + return true; 375 + } 376 + return false; 377 + } 378 + 379 + static char *bnge_report_fec(struct bnge_link_info *link_info) 380 + { 381 + u8 active_fec = link_info->active_fec_sig_mode & 382 + PORT_PHY_QCFG_RESP_ACTIVE_FEC_MASK; 383 + 384 + switch (active_fec) { 385 + default: 386 + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_NONE_ACTIVE: 387 + return "None"; 388 + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_CLAUSE74_ACTIVE: 389 + return "Clause 74 BaseR"; 390 + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_CLAUSE91_ACTIVE: 391 + return "Clause 91 RS(528,514)"; 392 + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS544_1XN_ACTIVE: 393 + return "Clause 91 RS544_1XN"; 394 + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS544_IEEE_ACTIVE: 395 + return "Clause 91 RS(544,514)"; 396 + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS272_1XN_ACTIVE: 397 + return "Clause 91 RS272_1XN"; 398 + case PORT_PHY_QCFG_RESP_ACTIVE_FEC_FEC_RS272_IEEE_ACTIVE: 399 + return "Clause 91 RS(272,257)"; 400 + } 401 + } 402 + 403 + void bnge_report_link(struct bnge_dev *bd) 404 + { 405 + if (BNGE_LINK_IS_UP(bd)) { 406 + const char *signal = ""; 407 + const char *flow_ctrl; 408 + const char *duplex; 409 + u32 speed; 410 + u16 fec; 411 + 412 + netif_carrier_on(bd->netdev); 413 + speed = bnge_fw_to_ethtool_speed(bd->link_info.link_speed); 414 + if (speed == SPEED_UNKNOWN) { 415 + netdev_info(bd->netdev, 416 + "NIC Link is Up, speed unknown\n"); 417 + return; 418 + } 419 + if (bd->link_info.duplex == BNGE_LINK_DUPLEX_FULL) 420 + duplex = "full"; 421 + else 422 + duplex = "half"; 423 + if (bd->link_info.pause == BNGE_LINK_PAUSE_BOTH) 424 + flow_ctrl = "ON - receive & transmit"; 425 + else if (bd->link_info.pause == BNGE_LINK_PAUSE_TX) 426 + flow_ctrl = "ON - transmit"; 427 + else if (bd->link_info.pause == BNGE_LINK_PAUSE_RX) 428 + flow_ctrl = "ON - receive"; 429 + else 430 + flow_ctrl = "none"; 431 + if (bd->link_info.phy_qcfg_resp.option_flags & 432 + PORT_PHY_QCFG_RESP_OPTION_FLAGS_SIGNAL_MODE_KNOWN) { 433 + u8 sig_mode = bd->link_info.active_fec_sig_mode & 434 + PORT_PHY_QCFG_RESP_SIGNAL_MODE_MASK; 435 + switch (sig_mode) { 436 + case PORT_PHY_QCFG_RESP_SIGNAL_MODE_NRZ: 437 + signal = "(NRZ) "; 438 + break; 439 + case PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4: 440 + signal = "(PAM4 56Gbps) "; 441 + break; 442 + case PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4_112: 443 + signal = "(PAM4 112Gbps) "; 444 + break; 445 + default: 446 + break; 447 + } 448 + } 449 + netdev_info(bd->netdev, "NIC Link is Up, %u Mbps %s%s duplex, Flow control: %s\n", 450 + speed, signal, duplex, flow_ctrl); 451 + fec = bd->link_info.fec_cfg; 452 + if (!(fec & PORT_PHY_QCFG_RESP_FEC_CFG_FEC_NONE_SUPPORTED)) 453 + netdev_info(bd->netdev, "FEC autoneg %s encoding: %s\n", 454 + (fec & BNGE_FEC_AUTONEG) ? "on" : "off", 455 + bnge_report_fec(&bd->link_info)); 456 + } else { 457 + netif_carrier_off(bd->netdev); 458 + netdev_info(bd->netdev, "NIC Link is Down\n"); 459 + } 460 + } 461 + 462 + static void bnge_get_ethtool_modes(struct bnge_net *bn, 463 + struct ethtool_link_ksettings *lk_ksettings) 464 + { 465 + struct bnge_ethtool_link_info *elink_info; 466 + struct bnge_link_info *link_info; 467 + struct bnge_dev *bd = bn->bd; 468 + 469 + elink_info = &bn->eth_link_info; 470 + link_info = &bd->link_info; 471 + 472 + if (!(bd->phy_flags & BNGE_PHY_FL_NO_PAUSE)) { 473 + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, 474 + lk_ksettings->link_modes.supported); 475 + linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, 476 + lk_ksettings->link_modes.supported); 477 + } 478 + 479 + if (link_info->support_auto_speeds2) 480 + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, 481 + lk_ksettings->link_modes.supported); 482 + 483 + if (~elink_info->autoneg & BNGE_AUTONEG_FLOW_CTRL) 484 + return; 485 + 486 + if (link_info->auto_pause_setting & BNGE_LINK_PAUSE_RX) 487 + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, 488 + lk_ksettings->link_modes.advertising); 489 + if (hweight8(link_info->auto_pause_setting & BNGE_LINK_PAUSE_BOTH) == 1) 490 + linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, 491 + lk_ksettings->link_modes.advertising); 492 + if (link_info->lp_pause & BNGE_LINK_PAUSE_RX) 493 + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, 494 + lk_ksettings->link_modes.lp_advertising); 495 + if (hweight8(link_info->lp_pause & BNGE_LINK_PAUSE_BOTH) == 1) 496 + linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, 497 + lk_ksettings->link_modes.lp_advertising); 498 + } 499 + 500 + u32 bnge_get_link(struct net_device *dev) 501 + { 502 + struct bnge_net *bn = netdev_priv(dev); 503 + 504 + return BNGE_LINK_IS_UP(bn->bd); 505 + } 506 + 507 + static enum bnge_media_type 508 + bnge_get_media(struct bnge_link_info *link_info) 509 + { 510 + switch (link_info->media_type) { 511 + case PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC: 512 + return BNGE_MEDIA_CR; 513 + default: 514 + if (link_info->phy_type < ARRAY_SIZE(bnge_phy_types)) 515 + return bnge_phy_types[link_info->phy_type]; 516 + return BNGE_MEDIA_UNKNOWN; 517 + } 518 + } 519 + 520 + enum bnge_link_speed_indices { 521 + BNGE_LINK_SPEED_UNKNOWN = 0, 522 + BNGE_LINK_SPEED_50GB_IDX, 523 + BNGE_LINK_SPEED_100GB_IDX, 524 + BNGE_LINK_SPEED_200GB_IDX, 525 + BNGE_LINK_SPEED_400GB_IDX, 526 + BNGE_LINK_SPEED_800GB_IDX, 527 + __BNGE_LINK_SPEED_END 528 + }; 529 + 530 + static enum bnge_link_speed_indices bnge_fw_speed_idx(u16 speed) 531 + { 532 + switch (speed) { 533 + case BNGE_LINK_SPEED_50GB: 534 + case BNGE_LINK_SPEED_50GB_PAM4: 535 + return BNGE_LINK_SPEED_50GB_IDX; 536 + case BNGE_LINK_SPEED_100GB: 537 + case BNGE_LINK_SPEED_100GB_PAM4: 538 + case BNGE_LINK_SPEED_100GB_PAM4_112: 539 + return BNGE_LINK_SPEED_100GB_IDX; 540 + case BNGE_LINK_SPEED_200GB: 541 + case BNGE_LINK_SPEED_200GB_PAM4: 542 + case BNGE_LINK_SPEED_200GB_PAM4_112: 543 + return BNGE_LINK_SPEED_200GB_IDX; 544 + case BNGE_LINK_SPEED_400GB: 545 + case BNGE_LINK_SPEED_400GB_PAM4: 546 + case BNGE_LINK_SPEED_400GB_PAM4_112: 547 + return BNGE_LINK_SPEED_400GB_IDX; 548 + case BNGE_LINK_SPEED_800GB: 549 + case BNGE_LINK_SPEED_800GB_PAM4_112: 550 + return BNGE_LINK_SPEED_800GB_IDX; 551 + default: 552 + return BNGE_LINK_SPEED_UNKNOWN; 553 + } 554 + } 555 + 556 + /* Compile-time link mode mapping table. 557 + * Indexed by [speed_idx][sig_mode][media]. 558 + */ 559 + #define BNGE_LINK_M(speed, sig, media, lm) \ 560 + [BNGE_LINK_SPEED_##speed##_IDX] \ 561 + [BNGE_SIG_MODE_##sig] \ 562 + [BNGE_MEDIA_##media] = ETHTOOL_LINK_MODE_##lm##_Full_BIT 563 + 564 + static const enum ethtool_link_mode_bit_indices 565 + bnge_link_modes[__BNGE_LINK_SPEED_END] 566 + [BNGE_SIG_MODE_MAX] 567 + [__BNGE_MEDIA_END] = { 568 + /* 50GB PAM4 */ 569 + BNGE_LINK_M(50GB, PAM4, CR, 50000baseCR), 570 + BNGE_LINK_M(50GB, PAM4, SR, 50000baseSR), 571 + BNGE_LINK_M(50GB, PAM4, LR_ER_FR, 50000baseLR_ER_FR), 572 + BNGE_LINK_M(50GB, PAM4, KR, 50000baseKR), 573 + 574 + /* 100GB NRZ */ 575 + BNGE_LINK_M(100GB, NRZ, CR, 100000baseCR4), 576 + BNGE_LINK_M(100GB, NRZ, SR, 100000baseSR4), 577 + BNGE_LINK_M(100GB, NRZ, LR_ER_FR, 100000baseLR4_ER4), 578 + BNGE_LINK_M(100GB, NRZ, KR, 100000baseKR4), 579 + 580 + /* 100GB PAM4 */ 581 + BNGE_LINK_M(100GB, PAM4, CR, 100000baseCR2), 582 + BNGE_LINK_M(100GB, PAM4, SR, 100000baseSR2), 583 + BNGE_LINK_M(100GB, PAM4, LR_ER_FR, 100000baseLR2_ER2_FR2), 584 + BNGE_LINK_M(100GB, PAM4, KR, 100000baseKR2), 585 + 586 + /* 100GB PAM4_112 */ 587 + BNGE_LINK_M(100GB, PAM4_112, CR, 100000baseCR), 588 + BNGE_LINK_M(100GB, PAM4_112, SR, 100000baseSR), 589 + BNGE_LINK_M(100GB, PAM4_112, LR_ER_FR, 100000baseLR_ER_FR), 590 + BNGE_LINK_M(100GB, PAM4_112, KR, 100000baseKR), 591 + 592 + /* 200GB PAM4 */ 593 + BNGE_LINK_M(200GB, PAM4, CR, 200000baseCR4), 594 + BNGE_LINK_M(200GB, PAM4, SR, 200000baseSR4), 595 + BNGE_LINK_M(200GB, PAM4, LR_ER_FR, 200000baseLR4_ER4_FR4), 596 + BNGE_LINK_M(200GB, PAM4, KR, 200000baseKR4), 597 + 598 + /* 200GB PAM4_112 */ 599 + BNGE_LINK_M(200GB, PAM4_112, CR, 200000baseCR2), 600 + BNGE_LINK_M(200GB, PAM4_112, SR, 200000baseSR2), 601 + BNGE_LINK_M(200GB, PAM4_112, LR_ER_FR, 200000baseLR2_ER2_FR2), 602 + BNGE_LINK_M(200GB, PAM4_112, KR, 200000baseKR2), 603 + 604 + /* 400GB PAM4 */ 605 + BNGE_LINK_M(400GB, PAM4, CR, 400000baseCR8), 606 + BNGE_LINK_M(400GB, PAM4, SR, 400000baseSR8), 607 + BNGE_LINK_M(400GB, PAM4, LR_ER_FR, 400000baseLR8_ER8_FR8), 608 + BNGE_LINK_M(400GB, PAM4, KR, 400000baseKR8), 609 + 610 + /* 400GB PAM4_112 */ 611 + BNGE_LINK_M(400GB, PAM4_112, CR, 400000baseCR4), 612 + BNGE_LINK_M(400GB, PAM4_112, SR, 400000baseSR4), 613 + BNGE_LINK_M(400GB, PAM4_112, LR_ER_FR, 400000baseLR4_ER4_FR4), 614 + BNGE_LINK_M(400GB, PAM4_112, KR, 400000baseKR4), 615 + 616 + /* 800GB PAM4_112 */ 617 + BNGE_LINK_M(800GB, PAM4_112, CR, 800000baseCR8), 618 + BNGE_LINK_M(800GB, PAM4_112, SR, 800000baseSR8), 619 + BNGE_LINK_M(800GB, PAM4_112, KR, 800000baseKR8), 620 + }; 621 + 622 + #define BNGE_LINK_MODE_UNKNOWN -1 623 + 624 + static enum ethtool_link_mode_bit_indices 625 + bnge_get_link_mode(struct bnge_net *bn) 626 + { 627 + enum ethtool_link_mode_bit_indices link_mode; 628 + struct bnge_ethtool_link_info *elink_info; 629 + enum bnge_link_speed_indices speed; 630 + struct bnge_link_info *link_info; 631 + struct bnge_dev *bd = bn->bd; 632 + enum bnge_media_type media; 633 + u8 sig_mode; 634 + 635 + elink_info = &bn->eth_link_info; 636 + link_info = &bd->link_info; 637 + 638 + if (link_info->phy_link_status != BNGE_LINK_LINK) 639 + return BNGE_LINK_MODE_UNKNOWN; 640 + 641 + media = bnge_get_media(link_info); 642 + if (BNGE_AUTO_MODE(link_info->auto_mode)) { 643 + speed = bnge_fw_speed_idx(link_info->link_speed); 644 + sig_mode = link_info->active_fec_sig_mode & 645 + PORT_PHY_QCFG_RESP_SIGNAL_MODE_MASK; 646 + } else { 647 + speed = bnge_fw_speed_idx(elink_info->req_link_speed); 648 + sig_mode = elink_info->req_signal_mode; 649 + } 650 + if (sig_mode >= BNGE_SIG_MODE_MAX) 651 + return BNGE_LINK_MODE_UNKNOWN; 652 + 653 + /* Since ETHTOOL_LINK_MODE_10baseT_Half_BIT is defined as 0 and 654 + * not actually supported, the zeroes in this map can be safely 655 + * used to represent unknown link modes. 656 + */ 657 + link_mode = bnge_link_modes[speed][sig_mode][media]; 658 + if (!link_mode) 659 + return BNGE_LINK_MODE_UNKNOWN; 660 + 661 + return link_mode; 662 + } 663 + 664 + static const u16 bnge_nrz_speeds2_masks[__BNGE_LINK_SPEED_END] = { 665 + [BNGE_LINK_SPEED_100GB_IDX] = BNGE_LINK_SPEEDS2_MSK_100GB, 666 + }; 667 + 668 + static const u16 bnge_pam4_speeds2_masks[__BNGE_LINK_SPEED_END] = { 669 + [BNGE_LINK_SPEED_50GB_IDX] = BNGE_LINK_SPEEDS2_MSK_50GB_PAM4, 670 + [BNGE_LINK_SPEED_100GB_IDX] = BNGE_LINK_SPEEDS2_MSK_100GB_PAM4, 671 + [BNGE_LINK_SPEED_200GB_IDX] = BNGE_LINK_SPEEDS2_MSK_200GB_PAM4, 672 + [BNGE_LINK_SPEED_400GB_IDX] = BNGE_LINK_SPEEDS2_MSK_400GB_PAM4, 673 + }; 674 + 675 + static const u16 bnge_pam4_112_speeds2_masks[__BNGE_LINK_SPEED_END] = { 676 + [BNGE_LINK_SPEED_100GB_IDX] = BNGE_LINK_SPEEDS2_MSK_100GB_PAM4_112, 677 + [BNGE_LINK_SPEED_200GB_IDX] = BNGE_LINK_SPEEDS2_MSK_200GB_PAM4_112, 678 + [BNGE_LINK_SPEED_400GB_IDX] = BNGE_LINK_SPEEDS2_MSK_400GB_PAM4_112, 679 + [BNGE_LINK_SPEED_800GB_IDX] = BNGE_LINK_SPEEDS2_MSK_800GB_PAM4_112, 680 + }; 681 + 682 + static enum bnge_link_speed_indices 683 + bnge_encoding_speed_idx(u8 sig_mode, u16 speed_msk) 684 + { 685 + const u16 *speeds; 686 + int idx, len; 687 + 688 + switch (sig_mode) { 689 + case BNGE_SIG_MODE_NRZ: 690 + speeds = bnge_nrz_speeds2_masks; 691 + len = ARRAY_SIZE(bnge_nrz_speeds2_masks); 692 + break; 693 + case BNGE_SIG_MODE_PAM4: 694 + speeds = bnge_pam4_speeds2_masks; 695 + len = ARRAY_SIZE(bnge_pam4_speeds2_masks); 696 + break; 697 + case BNGE_SIG_MODE_PAM4_112: 698 + speeds = bnge_pam4_112_speeds2_masks; 699 + len = ARRAY_SIZE(bnge_pam4_112_speeds2_masks); 700 + break; 701 + default: 702 + return BNGE_LINK_SPEED_UNKNOWN; 703 + } 704 + 705 + for (idx = 0; idx < len; idx++) { 706 + if (speeds[idx] == speed_msk) 707 + return idx; 708 + } 709 + 710 + return BNGE_LINK_SPEED_UNKNOWN; 711 + } 712 + 713 + #define BNGE_FW_SPEED_MSK_BITS 16 714 + 715 + static void 716 + __bnge_get_ethtool_speeds(unsigned long fw_mask, enum bnge_media_type media, 717 + u8 sig_mode, unsigned long *et_mask) 718 + { 719 + enum ethtool_link_mode_bit_indices link_mode; 720 + enum bnge_link_speed_indices speed; 721 + u8 bit; 722 + 723 + for_each_set_bit(bit, &fw_mask, BNGE_FW_SPEED_MSK_BITS) { 724 + speed = bnge_encoding_speed_idx(sig_mode, 1 << bit); 725 + if (!speed) 726 + continue; 727 + 728 + link_mode = bnge_link_modes[speed][sig_mode][media]; 729 + if (!link_mode) 730 + continue; 731 + 732 + linkmode_set_bit(link_mode, et_mask); 733 + } 734 + } 735 + 736 + static void 737 + bnge_get_ethtool_speeds(unsigned long fw_mask, enum bnge_media_type media, 738 + u8 sig_mode, unsigned long *et_mask) 739 + { 740 + if (media) { 741 + __bnge_get_ethtool_speeds(fw_mask, media, sig_mode, et_mask); 742 + return; 743 + } 744 + 745 + /* list speeds for all media if unknown */ 746 + for (media = 1; media < __BNGE_MEDIA_END; media++) 747 + __bnge_get_ethtool_speeds(fw_mask, media, sig_mode, et_mask); 748 + } 749 + 750 + static void 751 + bnge_get_all_ethtool_support_speeds(struct bnge_dev *bd, 752 + enum bnge_media_type media, 753 + struct ethtool_link_ksettings *lk_ksettings) 754 + { 755 + u16 sp = bd->link_info.support_speeds2; 756 + 757 + bnge_get_ethtool_speeds(sp, media, BNGE_SIG_MODE_NRZ, 758 + lk_ksettings->link_modes.supported); 759 + bnge_get_ethtool_speeds(sp, media, BNGE_SIG_MODE_PAM4, 760 + lk_ksettings->link_modes.supported); 761 + bnge_get_ethtool_speeds(sp, media, BNGE_SIG_MODE_PAM4_112, 762 + lk_ksettings->link_modes.supported); 763 + } 764 + 765 + static void 766 + bnge_get_all_ethtool_adv_speeds(struct bnge_net *bn, 767 + enum bnge_media_type media, 768 + struct ethtool_link_ksettings *lk_ksettings) 769 + { 770 + u16 sp = bn->eth_link_info.advertising; 771 + 772 + bnge_get_ethtool_speeds(sp, media, BNGE_SIG_MODE_NRZ, 773 + lk_ksettings->link_modes.advertising); 774 + bnge_get_ethtool_speeds(sp, media, BNGE_SIG_MODE_PAM4, 775 + lk_ksettings->link_modes.advertising); 776 + bnge_get_ethtool_speeds(sp, media, BNGE_SIG_MODE_PAM4_112, 777 + lk_ksettings->link_modes.advertising); 778 + } 779 + 780 + static void 781 + bnge_get_all_ethtool_lp_speeds(struct bnge_dev *bd, 782 + enum bnge_media_type media, 783 + struct ethtool_link_ksettings *lk_ksettings) 784 + { 785 + u16 sp = bd->link_info.lp_auto_link_speeds; 786 + 787 + bnge_get_ethtool_speeds(sp, media, BNGE_SIG_MODE_NRZ, 788 + lk_ksettings->link_modes.lp_advertising); 789 + bnge_get_ethtool_speeds(sp, media, BNGE_SIG_MODE_PAM4, 790 + lk_ksettings->link_modes.lp_advertising); 791 + bnge_get_ethtool_speeds(sp, media, BNGE_SIG_MODE_PAM4_112, 792 + lk_ksettings->link_modes.lp_advertising); 793 + } 794 + 795 + static void bnge_update_speed(u32 *delta, bool installed_media, u16 *speeds, 796 + u16 speed_msk, const unsigned long *et_mask, 797 + enum ethtool_link_mode_bit_indices mode) 798 + { 799 + bool mode_desired = linkmode_test_bit(mode, et_mask); 800 + 801 + if (!mode || !mode_desired) 802 + return; 803 + 804 + /* installed media takes priority; for non-installed media, only allow 805 + * one change per fw_speed bit (many to one mapping). 806 + */ 807 + if (installed_media || !(*delta & speed_msk)) { 808 + *speeds |= speed_msk; 809 + *delta |= speed_msk; 810 + } 811 + } 812 + 813 + static void bnge_set_ethtool_speeds(struct bnge_net *bn, 814 + const unsigned long *et_mask) 815 + { 816 + struct bnge_ethtool_link_info *elink_info = &bn->eth_link_info; 817 + enum bnge_media_type media; 818 + u32 delta_pam4_112 = 0; 819 + u32 delta_pam4 = 0; 820 + u32 delta_nrz = 0; 821 + int i, m; 822 + 823 + elink_info->advertising = 0; 824 + 825 + media = bnge_get_media(&bn->bd->link_info); 826 + for (i = 1; i < __BNGE_LINK_SPEED_END; i++) { 827 + /* accept any legal media from user */ 828 + for (m = 1; m < __BNGE_MEDIA_END; m++) { 829 + bnge_update_speed(&delta_nrz, m == media, 830 + &elink_info->advertising, 831 + bnge_nrz_speeds2_masks[i], et_mask, 832 + bnge_link_modes[i][BNGE_SIG_MODE_NRZ][m]); 833 + bnge_update_speed(&delta_pam4, m == media, 834 + &elink_info->advertising, 835 + bnge_pam4_speeds2_masks[i], et_mask, 836 + bnge_link_modes[i][BNGE_SIG_MODE_PAM4][m]); 837 + bnge_update_speed(&delta_pam4_112, m == media, 838 + &elink_info->advertising, 839 + bnge_pam4_112_speeds2_masks[i], 840 + et_mask, 841 + bnge_link_modes[i][BNGE_SIG_MODE_PAM4_112][m]); 842 + } 843 + } 844 + } 845 + 846 + static void 847 + bnge_fw_to_ethtool_advertised_fec(struct bnge_link_info *link_info, 848 + struct ethtool_link_ksettings *lk_ksettings) 849 + { 850 + u16 fec_cfg = link_info->fec_cfg; 851 + 852 + if ((fec_cfg & BNGE_FEC_NONE) || !(fec_cfg & BNGE_FEC_AUTONEG)) { 853 + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT, 854 + lk_ksettings->link_modes.advertising); 855 + return; 856 + } 857 + if (fec_cfg & BNGE_FEC_ENC_BASE_R) 858 + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT, 859 + lk_ksettings->link_modes.advertising); 860 + if (fec_cfg & BNGE_FEC_ENC_RS) 861 + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT, 862 + lk_ksettings->link_modes.advertising); 863 + if (fec_cfg & BNGE_FEC_ENC_LLRS) 864 + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_LLRS_BIT, 865 + lk_ksettings->link_modes.advertising); 866 + } 867 + 868 + static void 869 + bnge_fw_to_ethtool_support_fec(struct bnge_link_info *link_info, 870 + struct ethtool_link_ksettings *lk_ksettings) 871 + { 872 + u16 fec_cfg = link_info->fec_cfg; 873 + 874 + if (fec_cfg & BNGE_FEC_NONE) { 875 + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT, 876 + lk_ksettings->link_modes.supported); 877 + return; 878 + } 879 + if (fec_cfg & BNGE_FEC_ENC_BASE_R_CAP) 880 + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT, 881 + lk_ksettings->link_modes.supported); 882 + if (fec_cfg & BNGE_FEC_ENC_RS_CAP) 883 + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT, 884 + lk_ksettings->link_modes.supported); 885 + if (fec_cfg & BNGE_FEC_ENC_LLRS_CAP) 886 + linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_LLRS_BIT, 887 + lk_ksettings->link_modes.supported); 888 + } 889 + 890 + static void bnge_get_default_speeds(struct bnge_net *bn, 891 + struct ethtool_link_ksettings *lk_ksettings) 892 + { 893 + struct bnge_ethtool_link_info *elink_info = &bn->eth_link_info; 894 + struct ethtool_link_settings *base = &lk_ksettings->base; 895 + struct bnge_link_info *link_info; 896 + struct bnge_dev *bd = bn->bd; 897 + 898 + link_info = &bd->link_info; 899 + 900 + if (link_info->link_state == BNGE_LINK_STATE_UP) { 901 + base->speed = bnge_fw_to_ethtool_speed(link_info->link_speed); 902 + base->duplex = DUPLEX_HALF; 903 + if (link_info->duplex & BNGE_LINK_DUPLEX_FULL) 904 + base->duplex = DUPLEX_FULL; 905 + lk_ksettings->lanes = link_info->active_lanes; 906 + } else if (!elink_info->autoneg) { 907 + base->speed = 908 + bnge_fw_to_ethtool_speed(elink_info->req_link_speed); 909 + base->duplex = DUPLEX_HALF; 910 + if (elink_info->req_duplex == BNGE_LINK_DUPLEX_FULL) 911 + base->duplex = DUPLEX_FULL; 912 + } 913 + } 914 + 915 + int bnge_get_link_ksettings(struct net_device *dev, 916 + struct ethtool_link_ksettings *lk_ksettings) 917 + { 918 + struct ethtool_link_settings *base = &lk_ksettings->base; 919 + enum ethtool_link_mode_bit_indices link_mode; 920 + struct bnge_net *bn = netdev_priv(dev); 921 + struct bnge_link_info *link_info; 922 + struct bnge_dev *bd = bn->bd; 923 + enum bnge_media_type media; 924 + 925 + ethtool_link_ksettings_zero_link_mode(lk_ksettings, lp_advertising); 926 + ethtool_link_ksettings_zero_link_mode(lk_ksettings, advertising); 927 + ethtool_link_ksettings_zero_link_mode(lk_ksettings, supported); 928 + base->duplex = DUPLEX_UNKNOWN; 929 + base->speed = SPEED_UNKNOWN; 930 + link_info = &bd->link_info; 931 + 932 + bnge_get_ethtool_modes(bn, lk_ksettings); 933 + media = bnge_get_media(link_info); 934 + bnge_get_all_ethtool_support_speeds(bd, media, lk_ksettings); 935 + bnge_fw_to_ethtool_support_fec(link_info, lk_ksettings); 936 + link_mode = bnge_get_link_mode(bn); 937 + if (link_mode != BNGE_LINK_MODE_UNKNOWN) 938 + ethtool_params_from_link_mode(lk_ksettings, link_mode); 939 + else 940 + bnge_get_default_speeds(bn, lk_ksettings); 941 + 942 + if (bn->eth_link_info.autoneg) { 943 + bnge_fw_to_ethtool_advertised_fec(link_info, lk_ksettings); 944 + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, 945 + lk_ksettings->link_modes.advertising); 946 + base->autoneg = AUTONEG_ENABLE; 947 + bnge_get_all_ethtool_adv_speeds(bn, media, lk_ksettings); 948 + if (link_info->phy_link_status == BNGE_LINK_LINK) 949 + bnge_get_all_ethtool_lp_speeds(bd, media, lk_ksettings); 950 + } else { 951 + base->autoneg = AUTONEG_DISABLE; 952 + } 953 + 954 + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, 955 + lk_ksettings->link_modes.supported); 956 + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, 957 + lk_ksettings->link_modes.advertising); 958 + 959 + if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC) 960 + base->port = PORT_DA; 961 + else 962 + base->port = PORT_FIBRE; 963 + base->phy_address = link_info->phy_addr; 964 + 965 + return 0; 966 + } 967 + 968 + static bool bnge_lanes_match(u32 user_lanes, u32 supported_lanes) 969 + { 970 + /* 0 means lanes unspecified (auto) */ 971 + return !user_lanes || user_lanes == supported_lanes; 972 + } 973 + 974 + static int 975 + bnge_force_link_speed(struct net_device *dev, u32 ethtool_speed, u32 user_lanes) 976 + { 977 + struct bnge_ethtool_link_info *elink_info; 978 + struct bnge_net *bn = netdev_priv(dev); 979 + u8 sig_mode = BNGE_SIG_MODE_NRZ; 980 + u16 support_spds2; 981 + u16 fw_speed = 0; 982 + 983 + elink_info = &bn->eth_link_info; 984 + support_spds2 = bn->bd->link_info.support_speeds2; 985 + 986 + switch (ethtool_speed) { 987 + case SPEED_50000: 988 + if (bnge_lanes_match(user_lanes, 1) && 989 + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_50GB_PAM4)) { 990 + fw_speed = BNGE_LINK_SPEED_50GB_PAM4; 991 + sig_mode = BNGE_SIG_MODE_PAM4; 992 + } 993 + break; 994 + case SPEED_100000: 995 + if (bnge_lanes_match(user_lanes, 4) && 996 + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_100GB)) { 997 + fw_speed = PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_100GB; 998 + } else if (bnge_lanes_match(user_lanes, 2) && 999 + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_100GB_PAM4)) { 1000 + fw_speed = BNGE_LINK_SPEED_100GB_PAM4; 1001 + sig_mode = BNGE_SIG_MODE_PAM4; 1002 + } else if (bnge_lanes_match(user_lanes, 1) && 1003 + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_100GB_PAM4_112)) { 1004 + fw_speed = BNGE_LINK_SPEED_100GB_PAM4_112; 1005 + sig_mode = BNGE_SIG_MODE_PAM4_112; 1006 + } 1007 + break; 1008 + case SPEED_200000: 1009 + if (bnge_lanes_match(user_lanes, 4) && 1010 + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_200GB_PAM4)) { 1011 + fw_speed = BNGE_LINK_SPEED_200GB_PAM4; 1012 + sig_mode = BNGE_SIG_MODE_PAM4; 1013 + } else if (bnge_lanes_match(user_lanes, 2) && 1014 + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_200GB_PAM4_112)) { 1015 + fw_speed = BNGE_LINK_SPEED_200GB_PAM4_112; 1016 + sig_mode = BNGE_SIG_MODE_PAM4_112; 1017 + } 1018 + break; 1019 + case SPEED_400000: 1020 + if (bnge_lanes_match(user_lanes, 8) && 1021 + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_400GB_PAM4)) { 1022 + fw_speed = BNGE_LINK_SPEED_400GB_PAM4; 1023 + sig_mode = BNGE_SIG_MODE_PAM4; 1024 + } else if (bnge_lanes_match(user_lanes, 4) && 1025 + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_400GB_PAM4_112)) { 1026 + fw_speed = BNGE_LINK_SPEED_400GB_PAM4_112; 1027 + sig_mode = BNGE_SIG_MODE_PAM4_112; 1028 + } 1029 + break; 1030 + case SPEED_800000: 1031 + if (bnge_lanes_match(user_lanes, 8) && 1032 + (support_spds2 & BNGE_LINK_SPEEDS2_MSK_800GB_PAM4_112)) { 1033 + fw_speed = BNGE_LINK_SPEED_800GB_PAM4_112; 1034 + sig_mode = BNGE_SIG_MODE_PAM4_112; 1035 + } 1036 + break; 1037 + default: 1038 + break; 1039 + } 1040 + 1041 + if (!fw_speed) { 1042 + if (user_lanes) 1043 + netdev_err(dev, "unsupported speed or number of lanes!\n"); 1044 + else 1045 + netdev_err(dev, "unsupported speed!\n"); 1046 + return -EINVAL; 1047 + } 1048 + 1049 + if (elink_info->req_link_speed == fw_speed && 1050 + elink_info->req_signal_mode == sig_mode && 1051 + elink_info->autoneg == 0) 1052 + return -EALREADY; 1053 + 1054 + elink_info->req_link_speed = fw_speed; 1055 + elink_info->req_signal_mode = sig_mode; 1056 + elink_info->req_duplex = BNGE_LINK_DUPLEX_FULL; 1057 + elink_info->autoneg = 0; 1058 + elink_info->advertising = 0; 1059 + 1060 + return 0; 1061 + } 1062 + 1063 + int bnge_set_link_ksettings(struct net_device *dev, 1064 + const struct ethtool_link_ksettings *lk_ksettings) 1065 + { 1066 + const struct ethtool_link_settings *base = &lk_ksettings->base; 1067 + struct bnge_ethtool_link_info old_elink_info; 1068 + struct bnge_ethtool_link_info *elink_info; 1069 + struct bnge_net *bn = netdev_priv(dev); 1070 + struct bnge_dev *bd = bn->bd; 1071 + bool set_pause = false; 1072 + int rc = 0; 1073 + 1074 + if (!BNGE_PHY_CFG_ABLE(bd)) 1075 + return -EOPNOTSUPP; 1076 + 1077 + elink_info = &bn->eth_link_info; 1078 + old_elink_info = *elink_info; 1079 + 1080 + if (base->autoneg == AUTONEG_ENABLE) { 1081 + bnge_set_ethtool_speeds(bn, 1082 + lk_ksettings->link_modes.advertising); 1083 + elink_info->autoneg |= BNGE_AUTONEG_SPEED; 1084 + if (!elink_info->advertising) 1085 + bnge_set_default_adv_speeds(bn); 1086 + /* any change to autoneg will cause link change, therefore the 1087 + * driver should put back the original pause setting in autoneg 1088 + */ 1089 + if (!(bd->phy_flags & BNGE_PHY_FL_NO_PAUSE)) 1090 + set_pause = true; 1091 + } else { 1092 + if (base->duplex == DUPLEX_HALF) { 1093 + netdev_err(dev, "HALF DUPLEX is not supported!\n"); 1094 + rc = -EINVAL; 1095 + goto set_setting_exit; 1096 + } 1097 + rc = bnge_force_link_speed(dev, base->speed, 1098 + lk_ksettings->lanes); 1099 + if (rc) { 1100 + if (rc == -EALREADY) 1101 + rc = 0; 1102 + goto set_setting_exit; 1103 + } 1104 + } 1105 + 1106 + if (netif_running(dev)) { 1107 + rc = bnge_hwrm_set_link_setting(bn, set_pause); 1108 + if (rc) 1109 + *elink_info = old_elink_info; 1110 + } 1111 + 1112 + set_setting_exit: 1113 + return rc; 1114 + } 1115 + 1116 + void bnge_link_async_event_process(struct bnge_net *bn, u16 event_id) 1117 + { 1118 + switch (event_id) { 1119 + case ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE: 1120 + set_bit(BNGE_LINK_SPEED_CHNG_SP_EVENT, &bn->sp_event); 1121 + break; 1122 + case ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE: 1123 + case ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE: 1124 + set_bit(BNGE_LINK_CFG_CHANGE_SP_EVENT, &bn->sp_event); 1125 + break; 1126 + case ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE: 1127 + set_bit(BNGE_LINK_CHNG_SP_EVENT, &bn->sp_event); 1128 + break; 1129 + default: 1130 + break; 1131 + } 1132 + }
+173
drivers/net/ethernet/broadcom/bnge/bnge_link.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2026 Broadcom */ 3 + 4 + #ifndef _BNGE_LINK_H_ 5 + #define _BNGE_LINK_H_ 6 + 7 + #include <linux/ethtool.h> 8 + 9 + #define BNGE_PHY_CFG_ABLE(bd) \ 10 + ((bd)->link_info.phy_enabled) 11 + 12 + #define BNGE_PHY_AUTO_SPEEDS2_MASK \ 13 + PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEEDS2_MASK 14 + #define BNGE_PHY_FLAGS_RESTART_AUTO \ 15 + PORT_PHY_CFG_REQ_FLAGS_RESTART_AUTONEG 16 + #define BNGE_PHY_FLAGS_ENA_FORCE_SPEEDS2 \ 17 + PORT_PHY_CFG_REQ_ENABLES_FORCE_LINK_SPEEDS2 18 + 19 + #define BNGE_LINK_LINK PORT_PHY_QCFG_RESP_LINK_LINK 20 + 21 + enum bnge_link_state { 22 + BNGE_LINK_STATE_UNKNOWN, 23 + BNGE_LINK_STATE_DOWN, 24 + BNGE_LINK_STATE_UP, 25 + }; 26 + 27 + #define BNGE_LINK_IS_UP(bd) \ 28 + ((bd)->link_info.link_state == BNGE_LINK_STATE_UP) 29 + 30 + #define BNGE_LINK_DUPLEX_FULL PORT_PHY_QCFG_RESP_DUPLEX_STATE_FULL 31 + 32 + #define BNGE_LINK_PAUSE_TX PORT_PHY_QCFG_RESP_PAUSE_TX 33 + #define BNGE_LINK_PAUSE_RX PORT_PHY_QCFG_RESP_PAUSE_RX 34 + #define BNGE_LINK_PAUSE_BOTH (PORT_PHY_QCFG_RESP_PAUSE_RX | \ 35 + PORT_PHY_QCFG_RESP_PAUSE_TX) 36 + 37 + #define BNGE_LINK_AUTO_NONE PORT_PHY_QCFG_RESP_AUTO_MODE_NONE 38 + #define BNGE_LINK_AUTO_MSK PORT_PHY_QCFG_RESP_AUTO_MODE_SPEED_MASK 39 + #define BNGE_AUTO_MODE(mode) ((mode) > BNGE_LINK_AUTO_NONE && \ 40 + (mode) <= BNGE_LINK_AUTO_MSK) 41 + 42 + #define BNGE_LINK_SPEED_50GB PORT_PHY_QCFG_RESP_LINK_SPEED_50GB 43 + #define BNGE_LINK_SPEED_100GB PORT_PHY_QCFG_RESP_LINK_SPEED_100GB 44 + #define BNGE_LINK_SPEED_200GB PORT_PHY_QCFG_RESP_LINK_SPEED_200GB 45 + #define BNGE_LINK_SPEED_400GB PORT_PHY_QCFG_RESP_LINK_SPEED_400GB 46 + #define BNGE_LINK_SPEED_800GB PORT_PHY_QCFG_RESP_LINK_SPEED_800GB 47 + 48 + #define BNGE_LINK_SPEEDS2_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_50GB 49 + #define BNGE_LINK_SPEEDS2_MSK_100GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_100GB 50 + #define BNGE_LINK_SPEEDS2_MSK_50GB_PAM4 \ 51 + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_50GB_PAM4_56 52 + #define BNGE_LINK_SPEEDS2_MSK_100GB_PAM4 \ 53 + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_100GB_PAM4_56 54 + #define BNGE_LINK_SPEEDS2_MSK_200GB_PAM4 \ 55 + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_200GB_PAM4_56 56 + #define BNGE_LINK_SPEEDS2_MSK_400GB_PAM4 \ 57 + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_400GB_PAM4_56 58 + #define BNGE_LINK_SPEEDS2_MSK_100GB_PAM4_112 \ 59 + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_100GB_PAM4_112 60 + #define BNGE_LINK_SPEEDS2_MSK_200GB_PAM4_112 \ 61 + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_200GB_PAM4_112 62 + #define BNGE_LINK_SPEEDS2_MSK_400GB_PAM4_112 \ 63 + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_400GB_PAM4_112 64 + #define BNGE_LINK_SPEEDS2_MSK_800GB_PAM4_112 \ 65 + PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS2_800GB_PAM4_112 66 + 67 + #define BNGE_LINK_SPEED_50GB_PAM4 \ 68 + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_50GB_PAM4_56 69 + #define BNGE_LINK_SPEED_100GB_PAM4 \ 70 + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_100GB_PAM4_56 71 + #define BNGE_LINK_SPEED_200GB_PAM4 \ 72 + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_200GB_PAM4_56 73 + #define BNGE_LINK_SPEED_400GB_PAM4 \ 74 + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_400GB_PAM4_56 75 + #define BNGE_LINK_SPEED_100GB_PAM4_112 \ 76 + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_100GB_PAM4_112 77 + #define BNGE_LINK_SPEED_200GB_PAM4_112 \ 78 + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_200GB_PAM4_112 79 + #define BNGE_LINK_SPEED_400GB_PAM4_112 \ 80 + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_400GB_PAM4_112 81 + #define BNGE_LINK_SPEED_800GB_PAM4_112 \ 82 + PORT_PHY_CFG_REQ_FORCE_LINK_SPEEDS2_800GB_PAM4_112 83 + 84 + #define BNGE_FEC_NONE PORT_PHY_QCFG_RESP_FEC_CFG_FEC_NONE_SUPPORTED 85 + #define BNGE_FEC_AUTONEG PORT_PHY_QCFG_RESP_FEC_CFG_FEC_AUTONEG_ENABLED 86 + #define BNGE_FEC_ENC_BASE_R_CAP \ 87 + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_CLAUSE74_SUPPORTED 88 + #define BNGE_FEC_ENC_BASE_R PORT_PHY_QCFG_RESP_FEC_CFG_FEC_CLAUSE74_ENABLED 89 + #define BNGE_FEC_ENC_RS_CAP \ 90 + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_CLAUSE91_SUPPORTED 91 + #define BNGE_FEC_ENC_LLRS_CAP \ 92 + (PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS272_1XN_SUPPORTED | \ 93 + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS272_IEEE_SUPPORTED) 94 + #define BNGE_FEC_ENC_RS \ 95 + (PORT_PHY_QCFG_RESP_FEC_CFG_FEC_CLAUSE91_ENABLED | \ 96 + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS544_1XN_ENABLED | \ 97 + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS544_IEEE_ENABLED) 98 + #define BNGE_FEC_ENC_LLRS \ 99 + (PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS272_1XN_ENABLED | \ 100 + PORT_PHY_QCFG_RESP_FEC_CFG_FEC_RS272_IEEE_ENABLED) 101 + 102 + struct bnge_link_info { 103 + u8 phy_type; 104 + u8 media_type; 105 + u8 phy_addr; 106 + u8 phy_link_status; 107 + bool phy_enabled; 108 + 109 + u8 link_state; 110 + u8 active_lanes; 111 + u8 duplex; 112 + u8 pause; 113 + u8 lp_pause; 114 + u8 auto_pause_setting; 115 + u8 force_pause_setting; 116 + u8 duplex_setting; 117 + u8 auto_mode; 118 + u16 link_speed; 119 + u16 support_speeds2; 120 + u16 auto_link_speeds2; 121 + u16 support_auto_speeds2; 122 + u16 lp_auto_link_speeds; 123 + u16 force_link_speed2; 124 + 125 + u8 module_status; 126 + u8 active_fec_sig_mode; 127 + u16 fec_cfg; 128 + 129 + /* A copy of phy_qcfg output used to report link 130 + * info to VF 131 + */ 132 + struct hwrm_port_phy_qcfg_output phy_qcfg_resp; 133 + 134 + bool phy_retry; 135 + unsigned long phy_retry_expires; 136 + }; 137 + 138 + #define BNGE_AUTONEG_SPEED 1 139 + #define BNGE_AUTONEG_FLOW_CTRL 2 140 + 141 + #define BNGE_SIG_MODE_NRZ PORT_PHY_QCFG_RESP_SIGNAL_MODE_NRZ 142 + #define BNGE_SIG_MODE_PAM4 PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4 143 + #define BNGE_SIG_MODE_PAM4_112 PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4_112 144 + #define BNGE_SIG_MODE_MAX (PORT_PHY_QCFG_RESP_SIGNAL_MODE_LAST + 1) 145 + 146 + struct bnge_ethtool_link_info { 147 + /* copy of requested setting from ethtool cmd */ 148 + u8 autoneg; 149 + u8 req_signal_mode; 150 + u8 req_duplex; 151 + u8 req_flow_ctrl; 152 + u16 req_link_speed; 153 + u16 advertising; /* user adv setting */ 154 + bool force_link_chng; 155 + }; 156 + 157 + void bnge_hwrm_set_link_common(struct bnge_net *bn, 158 + struct hwrm_port_phy_cfg_input *req); 159 + void bnge_hwrm_set_pause_common(struct bnge_net *bn, 160 + struct hwrm_port_phy_cfg_input *req); 161 + int bnge_update_phy_setting(struct bnge_net *bn); 162 + void bnge_get_port_module_status(struct bnge_net *bn); 163 + void bnge_report_link(struct bnge_dev *bd); 164 + bool bnge_support_speed_dropped(struct bnge_net *bn); 165 + void bnge_init_ethtool_link_settings(struct bnge_net *bn); 166 + int bnge_probe_phy(struct bnge_net *bn, bool fw_dflt); 167 + int bnge_set_link_ksettings(struct net_device *dev, 168 + const struct ethtool_link_ksettings *lk_ksettings); 169 + int bnge_get_link_ksettings(struct net_device *dev, 170 + struct ethtool_link_ksettings *lk_ksettings); 171 + u32 bnge_get_link(struct net_device *dev); 172 + void bnge_link_async_event_process(struct bnge_net *bn, u16 event_id); 173 + #endif /* _BNGE_LINK_H_ */
+673 -3
drivers/net/ethernet/broadcom/bnge/bnge_netdev.c
··· 39 39 { 40 40 struct bnge_dev *bd = bn->bd; 41 41 42 + kfree(stats->hw_masks); 43 + stats->hw_masks = NULL; 44 + kfree(stats->sw_stats); 45 + stats->sw_stats = NULL; 42 46 if (stats->hw_stats) { 43 47 dma_free_coherent(bd->dev, stats->len, stats->hw_stats, 44 48 stats->hw_stats_map); ··· 51 47 } 52 48 53 49 static int bnge_alloc_stats_mem(struct bnge_net *bn, 54 - struct bnge_stats_mem *stats) 50 + struct bnge_stats_mem *stats, bool alloc_masks) 55 51 { 56 52 struct bnge_dev *bd = bn->bd; 57 53 ··· 60 56 if (!stats->hw_stats) 61 57 return -ENOMEM; 62 58 59 + stats->sw_stats = kzalloc(stats->len, GFP_KERNEL); 60 + if (!stats->sw_stats) 61 + goto stats_mem_err; 62 + 63 + if (alloc_masks) { 64 + stats->hw_masks = kzalloc(stats->len, GFP_KERNEL); 65 + if (!stats->hw_masks) 66 + goto stats_mem_err; 67 + } 68 + 69 + u64_stats_init(&stats->syncp); 70 + 63 71 return 0; 72 + 73 + stats_mem_err: 74 + bnge_free_stats_mem(bn, stats); 75 + return -ENOMEM; 64 76 } 65 77 66 78 static void bnge_free_ring_stats(struct bnge_net *bn) ··· 95 75 } 96 76 } 97 77 78 + static void bnge_fill_masks(u64 *mask_arr, u64 mask, int count) 79 + { 80 + int i; 81 + 82 + for (i = 0; i < count; i++) 83 + mask_arr[i] = mask; 84 + } 85 + 86 + void bnge_copy_hw_masks(u64 *mask_arr, __le64 *hw_mask_arr, int count) 87 + { 88 + int i; 89 + 90 + for (i = 0; i < count; i++) 91 + mask_arr[i] = le64_to_cpu(hw_mask_arr[i]); 92 + } 93 + 94 + static void bnge_init_stats(struct bnge_net *bn) 95 + { 96 + struct bnge_napi *bnapi = bn->bnapi[0]; 97 + struct bnge_nq_ring_info *nqr; 98 + struct bnge_stats_mem *stats; 99 + struct bnge_dev *bd = bn->bd; 100 + __le64 *rx_stats, *tx_stats; 101 + int rc, rx_count, tx_count; 102 + u64 *rx_masks, *tx_masks; 103 + u8 flags; 104 + 105 + nqr = &bnapi->nq_ring; 106 + stats = &nqr->stats; 107 + rc = bnge_hwrm_func_qstat_ext(bd, stats); 108 + if (rc) { 109 + u64 mask = (1ULL << 48) - 1; 110 + 111 + bnge_fill_masks(stats->hw_masks, mask, stats->len / 8); 112 + } 113 + 114 + if (bn->flags & BNGE_FLAG_PORT_STATS) { 115 + stats = &bn->port_stats; 116 + rx_stats = stats->hw_stats; 117 + rx_masks = stats->hw_masks; 118 + rx_count = sizeof(struct rx_port_stats) / 8; 119 + tx_stats = rx_stats + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; 120 + tx_masks = rx_masks + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; 121 + tx_count = sizeof(struct tx_port_stats) / 8; 122 + 123 + flags = PORT_QSTATS_REQ_FLAGS_COUNTER_MASK; 124 + rc = bnge_hwrm_port_qstats(bd, flags); 125 + if (rc) { 126 + u64 mask = (1ULL << 40) - 1; 127 + 128 + bnge_fill_masks(rx_masks, mask, rx_count); 129 + bnge_fill_masks(tx_masks, mask, tx_count); 130 + } else { 131 + bnge_copy_hw_masks(rx_masks, rx_stats, rx_count); 132 + bnge_copy_hw_masks(tx_masks, tx_stats, tx_count); 133 + } 134 + bnge_hwrm_port_qstats(bd, 0); 135 + } 136 + 137 + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { 138 + stats = &bn->rx_port_stats_ext; 139 + rx_stats = stats->hw_stats; 140 + rx_masks = stats->hw_masks; 141 + rx_count = sizeof(struct rx_port_stats_ext) / 8; 142 + stats = &bn->tx_port_stats_ext; 143 + tx_stats = stats->hw_stats; 144 + tx_masks = stats->hw_masks; 145 + tx_count = sizeof(struct tx_port_stats_ext) / 8; 146 + 147 + flags = PORT_QSTATS_EXT_REQ_FLAGS_COUNTER_MASK; 148 + rc = bnge_hwrm_port_qstats_ext(bd, flags); 149 + if (rc) { 150 + u64 mask = (1ULL << 40) - 1; 151 + 152 + bnge_fill_masks(rx_masks, mask, rx_count); 153 + if (tx_stats) 154 + bnge_fill_masks(tx_masks, mask, tx_count); 155 + } else { 156 + bnge_copy_hw_masks(rx_masks, rx_stats, rx_count); 157 + if (tx_stats) 158 + bnge_copy_hw_masks(tx_masks, tx_stats, 159 + tx_count); 160 + } 161 + bnge_hwrm_port_qstats_ext(bd, 0); 162 + } 163 + } 164 + 165 + static void bnge_free_port_ext_stats(struct bnge_net *bn) 166 + { 167 + bn->flags &= ~BNGE_FLAG_PORT_STATS_EXT; 168 + bnge_free_stats_mem(bn, &bn->rx_port_stats_ext); 169 + bnge_free_stats_mem(bn, &bn->tx_port_stats_ext); 170 + } 171 + 172 + static void bnge_free_port_stats(struct bnge_net *bn) 173 + { 174 + bn->flags &= ~BNGE_FLAG_PORT_STATS; 175 + bnge_free_stats_mem(bn, &bn->port_stats); 176 + bnge_free_port_ext_stats(bn); 177 + } 178 + 98 179 static int bnge_alloc_ring_stats(struct bnge_net *bn) 99 180 { 100 181 struct bnge_dev *bd = bn->bd; ··· 209 88 struct bnge_nq_ring_info *nqr = &bnapi->nq_ring; 210 89 211 90 nqr->stats.len = size; 212 - rc = bnge_alloc_stats_mem(bn, &nqr->stats); 91 + rc = bnge_alloc_stats_mem(bn, &nqr->stats, !i); 213 92 if (rc) 214 93 goto err_free_ring_stats; 215 94 216 95 nqr->hw_stats_ctx_id = INVALID_STATS_CTX_ID; 217 96 } 97 + 218 98 return 0; 219 99 220 100 err_free_ring_stats: 221 101 bnge_free_ring_stats(bn); 222 102 return rc; 103 + } 104 + 105 + static void bnge_alloc_port_ext_stats(struct bnge_net *bn) 106 + { 107 + struct bnge_dev *bd = bn->bd; 108 + int rc; 109 + 110 + if (!(bd->fw_cap & BNGE_FW_CAP_EXT_STATS_SUPPORTED)) 111 + return; 112 + 113 + if (!bn->rx_port_stats_ext.hw_stats) { 114 + bn->rx_port_stats_ext.len = sizeof(struct rx_port_stats_ext); 115 + rc = bnge_alloc_stats_mem(bn, &bn->rx_port_stats_ext, true); 116 + /* Extended stats are optional */ 117 + if (rc) 118 + return; 119 + } 120 + 121 + if (!bn->tx_port_stats_ext.hw_stats) { 122 + bn->tx_port_stats_ext.len = sizeof(struct tx_port_stats_ext); 123 + rc = bnge_alloc_stats_mem(bn, &bn->tx_port_stats_ext, true); 124 + /* Extended stats are optional */ 125 + if (rc) { 126 + bnge_free_port_ext_stats(bn); 127 + return; 128 + } 129 + } 130 + bn->flags |= BNGE_FLAG_PORT_STATS_EXT; 131 + } 132 + 133 + static int bnge_alloc_port_stats(struct bnge_net *bn) 134 + { 135 + int rc; 136 + 137 + if (!bn->port_stats.hw_stats) { 138 + bn->port_stats.len = BNGE_PORT_STATS_SIZE; 139 + rc = bnge_alloc_stats_mem(bn, &bn->port_stats, true); 140 + if (rc) 141 + return rc; 142 + 143 + bn->flags |= BNGE_FLAG_PORT_STATS; 144 + } 145 + 146 + bnge_alloc_port_ext_stats(bn); 147 + return 0; 148 + } 149 + 150 + void __bnge_queue_sp_work(struct bnge_net *bn) 151 + { 152 + queue_work(bn->bnge_pf_wq, &bn->sp_task); 153 + } 154 + 155 + static void bnge_queue_sp_work(struct bnge_net *bn, unsigned int event) 156 + { 157 + set_bit(event, &bn->sp_event); 158 + __bnge_queue_sp_work(bn); 159 + } 160 + 161 + static void bnge_timer(struct timer_list *t) 162 + { 163 + struct bnge_net *bn = timer_container_of(bn, t, timer); 164 + struct bnge_dev *bd = bn->bd; 165 + 166 + if (!netif_running(bn->netdev) || 167 + !test_bit(BNGE_STATE_OPEN, &bd->state)) 168 + return; 169 + 170 + if (READ_ONCE(bd->link_info.phy_retry)) { 171 + if (time_after(jiffies, READ_ONCE(bd->link_info.phy_retry_expires))) { 172 + WRITE_ONCE(bd->link_info.phy_retry, false); 173 + netdev_warn(bn->netdev, "failed to update PHY settings after maximum retries.\n"); 174 + } else { 175 + bnge_queue_sp_work(bn, BNGE_UPDATE_PHY_SP_EVENT); 176 + } 177 + } 178 + 179 + if (BNGE_LINK_IS_UP(bd) && bn->stats_coal_ticks) 180 + bnge_queue_sp_work(bn, BNGE_PERIODIC_STATS_SP_EVENT); 181 + 182 + mod_timer(&bn->timer, jiffies + bn->current_interval); 183 + } 184 + 185 + static void bnge_add_one_ctr(u64 hw, u64 *sw, u64 mask) 186 + { 187 + u64 sw_tmp, sw_val; 188 + 189 + hw &= mask; 190 + sw_val = READ_ONCE(*sw); 191 + sw_tmp = (sw_val & ~mask) | hw; 192 + if (hw < (sw_val & mask)) 193 + sw_tmp += mask + 1; 194 + WRITE_ONCE(*sw, sw_tmp); 195 + } 196 + 197 + static void __bnge_accumulate_stats(__le64 *hw_stats, u64 *sw_stats, u64 *masks, 198 + int count, struct u64_stats_sync *syncp) 199 + { 200 + unsigned long flags; 201 + int i; 202 + 203 + flags = u64_stats_update_begin_irqsave(syncp); 204 + for (i = 0; i < count; i++) { 205 + u64 hw = le64_to_cpu(READ_ONCE(hw_stats[i])); 206 + 207 + if (masks[i] == -1ULL) 208 + WRITE_ONCE(sw_stats[i], hw); 209 + else 210 + bnge_add_one_ctr(hw, &sw_stats[i], masks[i]); 211 + } 212 + u64_stats_update_end_irqrestore(syncp, flags); 213 + } 214 + 215 + static void bnge_accumulate_stats(struct bnge_stats_mem *stats) 216 + { 217 + if (!stats->hw_stats) 218 + return; 219 + 220 + __bnge_accumulate_stats(stats->hw_stats, stats->sw_stats, 221 + stats->hw_masks, stats->len / 8, &stats->syncp); 222 + } 223 + 224 + static void bnge_accumulate_all_stats(struct bnge_dev *bd) 225 + { 226 + struct bnge_net *bn = netdev_priv(bd->netdev); 227 + struct bnge_stats_mem *ring0_stats = NULL; 228 + int i; 229 + 230 + for (i = 0; i < bd->nq_nr_rings; i++) { 231 + struct bnge_napi *bnapi = bn->bnapi[i]; 232 + struct bnge_nq_ring_info *nqr; 233 + struct bnge_stats_mem *stats; 234 + 235 + nqr = &bnapi->nq_ring; 236 + stats = &nqr->stats; 237 + 238 + if (!ring0_stats) 239 + ring0_stats = &bn->bnapi[0]->nq_ring.stats; 240 + 241 + __bnge_accumulate_stats(stats->hw_stats, stats->sw_stats, 242 + ring0_stats->hw_masks, 243 + ring0_stats->len / 8, &stats->syncp); 244 + } 245 + 246 + if (bn->flags & BNGE_FLAG_PORT_STATS) { 247 + struct bnge_stats_mem *stats = &bn->port_stats; 248 + __le64 *hw_stats = stats->hw_stats; 249 + u64 *sw_stats = stats->sw_stats; 250 + u64 *masks = stats->hw_masks; 251 + u16 cnt; 252 + 253 + cnt = sizeof(struct rx_port_stats) / 8; 254 + __bnge_accumulate_stats(hw_stats, sw_stats, masks, cnt, 255 + &stats->syncp); 256 + 257 + hw_stats += BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; 258 + sw_stats += BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; 259 + masks += BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; 260 + cnt = sizeof(struct tx_port_stats) / 8; 261 + __bnge_accumulate_stats(hw_stats, sw_stats, masks, cnt, 262 + &stats->syncp); 263 + } 264 + 265 + if (bn->flags & BNGE_FLAG_PORT_STATS_EXT) { 266 + bnge_accumulate_stats(&bn->rx_port_stats_ext); 267 + bnge_accumulate_stats(&bn->tx_port_stats_ext); 268 + } 269 + } 270 + 271 + static void bnge_sp_task(struct work_struct *work) 272 + { 273 + struct bnge_net *bn = container_of(work, struct bnge_net, sp_task); 274 + bool speed_chng, cfg_chng, link_chng; 275 + struct bnge_dev *bd = bn->bd; 276 + 277 + netdev_lock(bn->netdev); 278 + if (!test_bit(BNGE_STATE_OPEN, &bd->state)) { 279 + netdev_unlock(bn->netdev); 280 + return; 281 + } 282 + 283 + if (test_and_clear_bit(BNGE_PERIODIC_STATS_SP_EVENT, &bn->sp_event)) { 284 + bnge_hwrm_port_qstats(bd, 0); 285 + bnge_hwrm_port_qstats_ext(bd, 0); 286 + bnge_accumulate_all_stats(bd); 287 + } 288 + 289 + if (test_and_clear_bit(BNGE_UPDATE_PHY_SP_EVENT, &bn->sp_event)) { 290 + int rc; 291 + 292 + rc = bnge_update_phy_setting(bn); 293 + if (rc) { 294 + netdev_warn(bn->netdev, "update PHY settings retry failed\n"); 295 + } else { 296 + WRITE_ONCE(bd->link_info.phy_retry, false); 297 + netdev_info(bn->netdev, "update PHY settings retry succeeded\n"); 298 + } 299 + } 300 + 301 + speed_chng = test_and_clear_bit(BNGE_LINK_SPEED_CHNG_SP_EVENT, 302 + &bn->sp_event); 303 + cfg_chng = test_and_clear_bit(BNGE_LINK_CFG_CHANGE_SP_EVENT, 304 + &bn->sp_event); 305 + link_chng = test_and_clear_bit(BNGE_LINK_CHNG_SP_EVENT, 306 + &bn->sp_event); 307 + 308 + if (speed_chng || cfg_chng || link_chng) { 309 + int rc; 310 + 311 + if (speed_chng) 312 + bnge_hwrm_phy_qcaps(bd); 313 + 314 + rc = bnge_update_link(bn, true); 315 + if (rc) 316 + netdev_err(bn->netdev, "SP task cannot update link (rc: %d)\n", 317 + rc); 318 + 319 + if (speed_chng || cfg_chng) 320 + bnge_init_ethtool_link_settings(bn); 321 + } 322 + 323 + netdev_unlock(bn->netdev); 223 324 } 224 325 225 326 static void bnge_free_nq_desc_arr(struct bnge_nq_ring_info *nqr) ··· 1289 946 rc = bnge_alloc_ring_stats(bn); 1290 947 if (rc) 1291 948 goto err_free_core; 949 + 950 + bnge_init_stats(bn); 1292 951 1293 952 rc = bnge_alloc_vnics(bn); 1294 953 if (rc) ··· 2811 2466 /* Make sure napi polls see @dev_state change */ 2812 2467 synchronize_net(); 2813 2468 netif_tx_wake_all_queues(bn->netdev); 2469 + if (BNGE_LINK_IS_UP(bn->bd)) 2470 + netif_carrier_on(bn->netdev); 2814 2471 } 2815 2472 2816 2473 static int bnge_open_core(struct bnge_net *bn) ··· 2849 2502 2850 2503 bnge_enable_napi(bn); 2851 2504 2505 + rc = bnge_update_phy_setting(bn); 2506 + if (rc) { 2507 + netdev_warn(bn->netdev, "failed to update PHY settings (rc: %d)\n", 2508 + rc); 2509 + WRITE_ONCE(bd->link_info.phy_retry_expires, jiffies + 5 * HZ); 2510 + WRITE_ONCE(bd->link_info.phy_retry, true); 2511 + } else { 2512 + WRITE_ONCE(bd->link_info.phy_retry, false); 2513 + } 2514 + 2852 2515 set_bit(BNGE_STATE_OPEN, &bd->state); 2516 + set_bit(BNGE_STATE_STATS_ENABLE, &bn->state); 2853 2517 2854 2518 bnge_enable_int(bn); 2855 2519 2856 2520 bnge_tx_enable(bn); 2521 + 2522 + mod_timer(&bn->timer, jiffies + bn->current_interval); 2523 + 2524 + /* Poll link status and check for SFP+ module status */ 2525 + bnge_get_port_module_status(bn); 2526 + 2857 2527 return 0; 2858 2528 2859 2529 err_free_irq: ··· 2899 2535 return 0; 2900 2536 } 2901 2537 2538 + static void bnge_add_prev_ring_stats64(struct bnge_net *bn, 2539 + struct rtnl_link_stats64 *stats) 2540 + { 2541 + struct netdev_queue_stats_rx *rx_save = &bn->rxq_prv_stats; 2542 + struct netdev_queue_stats_tx *tx_save = &bn->txq_prv_stats; 2543 + struct rtnl_link_stats64 *stats64_save = &bn->prv_stats64; 2544 + 2545 + stats->rx_packets += rx_save->packets; 2546 + stats->tx_packets += tx_save->packets; 2547 + stats->rx_bytes += rx_save->bytes; 2548 + stats->tx_bytes += tx_save->bytes; 2549 + stats->rx_missed_errors += rx_save->hw_drop_overruns; 2550 + stats->tx_dropped += tx_save->hw_drop_errors; 2551 + 2552 + stats->multicast += stats64_save->multicast; 2553 + } 2554 + 2555 + static void bnge_get_ring_stats64(struct bnge_dev *bd, 2556 + struct rtnl_link_stats64 *stats) 2557 + { 2558 + struct bnge_net *bn = netdev_priv(bd->netdev); 2559 + int i; 2560 + 2561 + for (i = 0; i < bd->nq_nr_rings; i++) { 2562 + struct bnge_napi *bnapi = bn->bnapi[i]; 2563 + u64 tx_bytes, tx_packets, tx_dropped; 2564 + u64 multicast, rx_missed_errors; 2565 + struct bnge_nq_ring_info *nqr; 2566 + u64 rx_bytes, rx_packets; 2567 + unsigned int start; 2568 + u64 *sw; 2569 + 2570 + nqr = &bnapi->nq_ring; 2571 + sw = nqr->stats.sw_stats; 2572 + 2573 + do { 2574 + start = u64_stats_fetch_begin(&nqr->stats.syncp); 2575 + 2576 + rx_packets = BNGE_GET_RING_STATS64(sw, rx_ucast_pkts); 2577 + rx_packets += BNGE_GET_RING_STATS64(sw, rx_mcast_pkts); 2578 + rx_packets += BNGE_GET_RING_STATS64(sw, rx_bcast_pkts); 2579 + 2580 + tx_packets = BNGE_GET_RING_STATS64(sw, tx_ucast_pkts); 2581 + tx_packets += BNGE_GET_RING_STATS64(sw, tx_mcast_pkts); 2582 + tx_packets += BNGE_GET_RING_STATS64(sw, tx_bcast_pkts); 2583 + 2584 + rx_bytes = BNGE_GET_RING_STATS64(sw, rx_ucast_bytes); 2585 + rx_bytes += BNGE_GET_RING_STATS64(sw, rx_mcast_bytes); 2586 + rx_bytes += BNGE_GET_RING_STATS64(sw, rx_bcast_bytes); 2587 + 2588 + tx_bytes = BNGE_GET_RING_STATS64(sw, tx_ucast_bytes); 2589 + tx_bytes += BNGE_GET_RING_STATS64(sw, tx_mcast_bytes); 2590 + tx_bytes += BNGE_GET_RING_STATS64(sw, tx_bcast_bytes); 2591 + 2592 + multicast = BNGE_GET_RING_STATS64(sw, rx_mcast_pkts); 2593 + rx_missed_errors = 2594 + BNGE_GET_RING_STATS64(sw, rx_discard_pkts); 2595 + tx_dropped = 2596 + BNGE_GET_RING_STATS64(sw, tx_error_pkts); 2597 + } while (u64_stats_fetch_retry(&nqr->stats.syncp, start)); 2598 + 2599 + stats->rx_packets += rx_packets; 2600 + stats->tx_packets += tx_packets; 2601 + stats->rx_bytes += rx_bytes; 2602 + stats->tx_bytes += tx_bytes; 2603 + stats->multicast += multicast; 2604 + stats->rx_missed_errors += rx_missed_errors; 2605 + stats->tx_dropped += tx_dropped; 2606 + } 2607 + } 2608 + 2609 + static void bnge_get_port_stats64(struct bnge_net *bn, 2610 + struct rtnl_link_stats64 *stats) 2611 + { 2612 + unsigned int start; 2613 + u64 *tx, *rx; 2614 + 2615 + rx = bn->port_stats.sw_stats; 2616 + tx = bn->port_stats.sw_stats + BNGE_TX_PORT_STATS_BYTE_OFFSET / 8; 2617 + 2618 + do { 2619 + start = u64_stats_fetch_begin(&bn->port_stats.syncp); 2620 + 2621 + stats->rx_crc_errors = 2622 + BNGE_GET_RX_PORT_STATS64(rx, rx_fcs_err_frames); 2623 + stats->rx_frame_errors = 2624 + BNGE_GET_RX_PORT_STATS64(rx, rx_align_err_frames); 2625 + stats->rx_length_errors = 2626 + BNGE_GET_RX_PORT_STATS64(rx, rx_undrsz_frames) + 2627 + BNGE_GET_RX_PORT_STATS64(rx, rx_ovrsz_frames) + 2628 + BNGE_GET_RX_PORT_STATS64(rx, rx_runt_frames); 2629 + stats->rx_errors = 2630 + BNGE_GET_RX_PORT_STATS64(rx, rx_false_carrier_frames) + 2631 + BNGE_GET_RX_PORT_STATS64(rx, rx_jbr_frames); 2632 + stats->collisions = 2633 + BNGE_GET_TX_PORT_STATS64(tx, tx_total_collisions); 2634 + stats->tx_fifo_errors = 2635 + BNGE_GET_TX_PORT_STATS64(tx, tx_fifo_underruns); 2636 + stats->tx_errors = BNGE_GET_TX_PORT_STATS64(tx, tx_err); 2637 + } while (u64_stats_fetch_retry(&bn->port_stats.syncp, start)); 2638 + } 2639 + 2640 + static void bnge_fill_prev_stats64(struct bnge_net *bn, 2641 + struct rtnl_link_stats64 *stats) 2642 + { 2643 + struct netdev_queue_stats_rx *rx_save = &bn->rxq_prv_stats; 2644 + struct netdev_queue_stats_tx *tx_save = &bn->txq_prv_stats; 2645 + struct rtnl_link_stats64 *stats64_save = &bn->prv_stats64; 2646 + 2647 + stats->rx_packets = rx_save->packets; 2648 + stats->tx_packets = tx_save->packets; 2649 + stats->rx_bytes = rx_save->bytes; 2650 + stats->tx_bytes = tx_save->bytes; 2651 + stats->rx_missed_errors = rx_save->hw_drop_overruns; 2652 + stats->tx_dropped = tx_save->hw_drop_errors; 2653 + stats->multicast = stats64_save->multicast; 2654 + } 2655 + 2656 + static void bnge_get_stats64(struct net_device *dev, 2657 + struct rtnl_link_stats64 *stats) 2658 + { 2659 + struct bnge_net *bn = netdev_priv(dev); 2660 + 2661 + if (bn->flags & BNGE_FLAG_PORT_STATS) 2662 + bnge_get_port_stats64(bn, stats); 2663 + 2664 + spin_lock_bh(&bn->stats_lock); 2665 + if (!test_bit(BNGE_STATE_STATS_ENABLE, &bn->state)) { 2666 + bnge_fill_prev_stats64(bn, stats); 2667 + spin_unlock_bh(&bn->stats_lock); 2668 + return; 2669 + } 2670 + 2671 + bnge_get_ring_stats64(bn->bd, stats); 2672 + bnge_add_prev_ring_stats64(bn, stats); 2673 + spin_unlock_bh(&bn->stats_lock); 2674 + } 2675 + 2676 + static void bnge_save_ring_stats(struct bnge_net *bn) 2677 + { 2678 + struct netdev_queue_stats_rx *rx_save = &bn->rxq_prv_stats; 2679 + struct netdev_queue_stats_tx *tx_save = &bn->txq_prv_stats; 2680 + struct rtnl_link_stats64 *stats64_save = &bn->prv_stats64; 2681 + int i; 2682 + 2683 + for (i = 0; i < bn->bd->nq_nr_rings; i++) { 2684 + struct bnge_napi *bnapi = bn->bnapi[i]; 2685 + struct bnge_nq_ring_info *nqr; 2686 + u64 *sw; 2687 + 2688 + nqr = &bnapi->nq_ring; 2689 + sw = nqr->stats.sw_stats; 2690 + 2691 + rx_save->packets += BNGE_GET_RING_STATS64(sw, rx_ucast_pkts); 2692 + rx_save->packets += BNGE_GET_RING_STATS64(sw, rx_mcast_pkts); 2693 + rx_save->packets += BNGE_GET_RING_STATS64(sw, rx_bcast_pkts); 2694 + rx_save->bytes += BNGE_GET_RING_STATS64(sw, rx_ucast_bytes); 2695 + rx_save->bytes += BNGE_GET_RING_STATS64(sw, rx_mcast_bytes); 2696 + rx_save->bytes += BNGE_GET_RING_STATS64(sw, rx_bcast_bytes); 2697 + rx_save->hw_drop_overruns += BNGE_GET_RING_STATS64(sw, rx_discard_pkts); 2698 + rx_save->hw_drops += BNGE_GET_RING_STATS64(sw, rx_error_pkts) + 2699 + BNGE_GET_RING_STATS64(sw, rx_discard_pkts); 2700 + 2701 + tx_save->packets += BNGE_GET_RING_STATS64(sw, tx_ucast_pkts); 2702 + tx_save->packets += BNGE_GET_RING_STATS64(sw, tx_mcast_pkts); 2703 + tx_save->packets += BNGE_GET_RING_STATS64(sw, tx_bcast_pkts); 2704 + tx_save->bytes += BNGE_GET_RING_STATS64(sw, tx_ucast_bytes); 2705 + tx_save->bytes += BNGE_GET_RING_STATS64(sw, tx_mcast_bytes); 2706 + tx_save->bytes += BNGE_GET_RING_STATS64(sw, tx_bcast_bytes); 2707 + tx_save->hw_drop_errors += BNGE_GET_RING_STATS64(sw, tx_error_pkts); 2708 + tx_save->hw_drops += BNGE_GET_RING_STATS64(sw, tx_discard_pkts) + 2709 + BNGE_GET_RING_STATS64(sw, tx_error_pkts); 2710 + 2711 + stats64_save->multicast += 2712 + BNGE_GET_RING_STATS64(sw, rx_mcast_pkts); 2713 + } 2714 + } 2715 + 2902 2716 static void bnge_close_core(struct bnge_net *bn) 2903 2717 { 2904 2718 struct bnge_dev *bd = bn->bd; ··· 3084 2542 bnge_tx_disable(bn); 3085 2543 3086 2544 clear_bit(BNGE_STATE_OPEN, &bd->state); 2545 + 2546 + timer_delete_sync(&bn->timer); 3087 2547 bnge_shutdown_nic(bn); 3088 2548 bnge_disable_napi(bn); 2549 + 2550 + /* Save ring stats before shutdown */ 2551 + spin_lock_bh(&bn->stats_lock); 2552 + bnge_save_ring_stats(bn); 2553 + clear_bit(BNGE_STATE_STATS_ENABLE, &bn->state); 2554 + spin_unlock_bh(&bn->stats_lock); 2555 + 3089 2556 bnge_free_all_rings_bufs(bn); 3090 2557 bnge_free_irq(bn); 3091 2558 bnge_del_napi(bn); ··· 3107 2556 struct bnge_net *bn = netdev_priv(dev); 3108 2557 3109 2558 bnge_close_core(bn); 2559 + bnge_hwrm_shutdown_link(bn->bd); 2560 + bn->sp_event = 0; 3110 2561 3111 2562 return 0; 3112 2563 } 2564 + 2565 + static void bnge_get_queue_stats_rx(struct net_device *dev, int i, 2566 + struct netdev_queue_stats_rx *stats) 2567 + { 2568 + struct bnge_net *bn = netdev_priv(dev); 2569 + struct bnge_nq_ring_info *nqr; 2570 + u64 *sw; 2571 + 2572 + if (!bn->bnapi) 2573 + return; 2574 + 2575 + nqr = &bn->bnapi[i]->nq_ring; 2576 + sw = nqr->stats.sw_stats; 2577 + 2578 + stats->packets = 0; 2579 + stats->packets += BNGE_GET_RING_STATS64(sw, rx_ucast_pkts); 2580 + stats->packets += BNGE_GET_RING_STATS64(sw, rx_mcast_pkts); 2581 + stats->packets += BNGE_GET_RING_STATS64(sw, rx_bcast_pkts); 2582 + 2583 + stats->bytes = 0; 2584 + stats->bytes += BNGE_GET_RING_STATS64(sw, rx_ucast_bytes); 2585 + stats->bytes += BNGE_GET_RING_STATS64(sw, rx_mcast_bytes); 2586 + stats->bytes += BNGE_GET_RING_STATS64(sw, rx_bcast_bytes); 2587 + 2588 + stats->hw_drop_overruns = BNGE_GET_RING_STATS64(sw, rx_discard_pkts); 2589 + stats->hw_drops = BNGE_GET_RING_STATS64(sw, rx_error_pkts) + 2590 + stats->hw_drop_overruns; 2591 + } 2592 + 2593 + static void bnge_get_queue_stats_tx(struct net_device *dev, int i, 2594 + struct netdev_queue_stats_tx *stats) 2595 + { 2596 + struct bnge_net *bn = netdev_priv(dev); 2597 + struct bnge_napi *bnapi; 2598 + u64 *sw; 2599 + 2600 + if (!bn->tx_ring) 2601 + return; 2602 + 2603 + bnapi = bn->tx_ring[bn->tx_ring_map[i]].bnapi; 2604 + sw = bnapi->nq_ring.stats.sw_stats; 2605 + 2606 + stats->packets = 0; 2607 + stats->packets += BNGE_GET_RING_STATS64(sw, tx_ucast_pkts); 2608 + stats->packets += BNGE_GET_RING_STATS64(sw, tx_mcast_pkts); 2609 + stats->packets += BNGE_GET_RING_STATS64(sw, tx_bcast_pkts); 2610 + 2611 + stats->bytes = 0; 2612 + stats->bytes += BNGE_GET_RING_STATS64(sw, tx_ucast_bytes); 2613 + stats->bytes += BNGE_GET_RING_STATS64(sw, tx_mcast_bytes); 2614 + stats->bytes += BNGE_GET_RING_STATS64(sw, tx_bcast_bytes); 2615 + 2616 + stats->hw_drop_errors = BNGE_GET_RING_STATS64(sw, tx_error_pkts); 2617 + stats->hw_drops = BNGE_GET_RING_STATS64(sw, tx_discard_pkts) + 2618 + stats->hw_drop_errors; 2619 + } 2620 + 2621 + static void bnge_get_base_stats(struct net_device *dev, 2622 + struct netdev_queue_stats_rx *rx, 2623 + struct netdev_queue_stats_tx *tx) 2624 + { 2625 + struct bnge_net *bn = netdev_priv(dev); 2626 + 2627 + rx->packets = bn->rxq_prv_stats.packets; 2628 + rx->bytes = bn->rxq_prv_stats.bytes; 2629 + rx->hw_drops = bn->rxq_prv_stats.hw_drops; 2630 + rx->hw_drop_overruns = bn->rxq_prv_stats.hw_drop_overruns; 2631 + 2632 + tx->packets = bn->txq_prv_stats.packets; 2633 + tx->bytes = bn->txq_prv_stats.bytes; 2634 + tx->hw_drops = bn->txq_prv_stats.hw_drops; 2635 + tx->hw_drop_errors = bn->txq_prv_stats.hw_drop_errors; 2636 + } 2637 + 2638 + static const struct netdev_stat_ops bnge_stat_ops = { 2639 + .get_queue_stats_rx = bnge_get_queue_stats_rx, 2640 + .get_queue_stats_tx = bnge_get_queue_stats_tx, 2641 + .get_base_stats = bnge_get_base_stats, 2642 + }; 3113 2643 3114 2644 static const struct net_device_ops bnge_netdev_ops = { 3115 2645 .ndo_open = bnge_open, 3116 2646 .ndo_stop = bnge_close, 3117 2647 .ndo_start_xmit = bnge_start_xmit, 2648 + .ndo_get_stats64 = bnge_get_stats64, 3118 2649 .ndo_features_check = bnge_features_check, 3119 2650 }; 3120 2651 ··· 3338 2705 bd->netdev = netdev; 3339 2706 3340 2707 netdev->netdev_ops = &bnge_netdev_ops; 2708 + netdev->stat_ops = &bnge_stat_ops; 3341 2709 3342 2710 bnge_set_ethtool_ops(netdev); 3343 2711 ··· 3408 2774 if (bd->tso_max_segs) 3409 2775 netif_set_tso_max_segs(netdev, bd->tso_max_segs); 3410 2776 2777 + INIT_WORK(&bn->sp_task, bnge_sp_task); 2778 + timer_setup(&bn->timer, bnge_timer, 0); 2779 + bn->current_interval = BNGE_TIMER_INTERVAL; 2780 + 2781 + bn->bnge_pf_wq = alloc_ordered_workqueue("bnge_pf_wq-%s", 0, 2782 + dev_name(bd->dev)); 2783 + if (!bn->bnge_pf_wq) { 2784 + netdev_err(netdev, "Unable to create workqueue.\n"); 2785 + rc = -ENOMEM; 2786 + goto err_netdev; 2787 + } 2788 + 3411 2789 bn->rx_ring_size = BNGE_DEFAULT_RX_RING_SIZE; 3412 2790 bn->tx_ring_size = BNGE_DEFAULT_TX_RING_SIZE; 3413 2791 bn->rx_dir = DMA_FROM_DEVICE; ··· 3431 2785 bnge_init_l2_fltr_tbl(bn); 3432 2786 bnge_init_mac_addr(bd); 3433 2787 2788 + rc = bnge_probe_phy(bn, true); 2789 + if (rc) 2790 + goto err_free_workq; 2791 + 2792 + rc = bnge_alloc_port_stats(bn); 2793 + if (rc) 2794 + goto err_free_workq; 2795 + spin_lock_init(&bn->stats_lock); 2796 + 3434 2797 netdev->request_ops_lock = true; 3435 2798 rc = register_netdev(netdev); 3436 2799 if (rc) { 3437 2800 dev_err(bd->dev, "Register netdev failed rc: %d\n", rc); 3438 - goto err_netdev; 2801 + goto err_free_port_stats; 3439 2802 } 3440 2803 3441 2804 return 0; 3442 2805 2806 + err_free_port_stats: 2807 + bnge_free_port_stats(bn); 2808 + err_free_workq: 2809 + destroy_workqueue(bn->bnge_pf_wq); 3443 2810 err_netdev: 3444 2811 free_netdev(netdev); 3445 2812 return rc; ··· 3461 2802 void bnge_netdev_free(struct bnge_dev *bd) 3462 2803 { 3463 2804 struct net_device *netdev = bd->netdev; 2805 + struct bnge_net *bn; 2806 + 2807 + bn = netdev_priv(netdev); 3464 2808 3465 2809 unregister_netdev(netdev); 2810 + 2811 + timer_shutdown_sync(&bn->timer); 2812 + cancel_work_sync(&bn->sp_task); 2813 + bn->sp_event = 0; 2814 + destroy_workqueue(bn->bnge_pf_wq); 2815 + 2816 + bnge_free_port_stats(bn); 2817 + 3466 2818 free_netdev(netdev); 3467 2819 bd->netdev = NULL; 3468 2820 }
+85 -9
drivers/net/ethernet/broadcom/bnge/bnge_netdev.h
··· 7 7 #include <linux/bnge/hsi.h> 8 8 #include <linux/io-64-nonatomic-lo-hi.h> 9 9 #include <linux/refcount.h> 10 + #include <linux/u64_stats_sync.h> 11 + #include <net/netdev_queues.h> 10 12 #include "bnge_db.h" 11 13 #include "bnge_hw_def.h" 14 + #include "bnge_link.h" 12 15 13 16 struct tx_bd { 14 17 __le32 tx_bd_len_flags_type; ··· 226 223 #define BNGE_NQ_HDL_IDX(hdl) ((hdl) & BNGE_NQ_HDL_IDX_MASK) 227 224 #define BNGE_NQ_HDL_TYPE(hdl) (((hdl) & BNGE_NQ_HDL_TYPE_MASK) >> \ 228 225 BNGE_NQ_HDL_TYPE_SHIFT) 226 + #define BNGE_GET_RING_STATS64(sw, counter) \ 227 + (*((sw) + offsetof(struct ctx_hw_stats, counter) / 8)) 228 + 229 + #define BNGE_GET_RX_PORT_STATS64(sw, counter) \ 230 + (*((sw) + offsetof(struct rx_port_stats, counter) / 8)) 231 + 232 + #define BNGE_GET_TX_PORT_STATS64(sw, counter) \ 233 + (*((sw) + offsetof(struct tx_port_stats, counter) / 8)) 234 + 235 + #define BNGE_PORT_STATS_SIZE \ 236 + (sizeof(struct rx_port_stats) + sizeof(struct tx_port_stats) + 1024) 237 + 238 + #define BNGE_TX_PORT_STATS_BYTE_OFFSET \ 239 + (sizeof(struct rx_port_stats) + 512) 240 + 241 + #define BNGE_RX_STATS_OFFSET(counter) \ 242 + (offsetof(struct rx_port_stats, counter) / 8) 243 + 244 + #define BNGE_TX_STATS_OFFSET(counter) \ 245 + ((offsetof(struct tx_port_stats, counter) + \ 246 + BNGE_TX_PORT_STATS_BYTE_OFFSET) / 8) 247 + 248 + #define BNGE_RX_STATS_EXT_OFFSET(counter) \ 249 + (offsetof(struct rx_port_stats_ext, counter) / 8) 250 + 251 + #define BNGE_TX_STATS_EXT_OFFSET(counter) \ 252 + (offsetof(struct tx_port_stats_ext, counter) / 8) 253 + 254 + struct bnge_stats_mem { 255 + u64 *sw_stats; 256 + u64 *hw_masks; 257 + void *hw_stats; 258 + dma_addr_t hw_stats_map; 259 + u32 len; 260 + struct u64_stats_sync syncp; 261 + }; 262 + 263 + enum bnge_net_state { 264 + BNGE_STATE_NAPI_DISABLED, 265 + BNGE_STATE_STATS_ENABLE, 266 + }; 267 + 268 + #define BNGE_TIMER_INTERVAL HZ 269 + 270 + enum bnge_net_flag { 271 + BNGE_FLAG_PORT_STATS = BIT(0), 272 + BNGE_FLAG_PORT_STATS_EXT = BIT(1), 273 + }; 274 + 275 + enum bnge_sp_event { 276 + BNGE_LINK_CHNG_SP_EVENT, 277 + BNGE_LINK_SPEED_CHNG_SP_EVENT, 278 + BNGE_LINK_CFG_CHANGE_SP_EVENT, 279 + BNGE_UPDATE_PHY_SP_EVENT, 280 + BNGE_PERIODIC_STATS_SP_EVENT, 281 + }; 229 282 230 283 struct bnge_net { 231 284 struct bnge_dev *bd; ··· 340 281 u32 stats_coal_ticks; 341 282 342 283 unsigned long state; 343 - #define BNGE_STATE_NAPI_DISABLED 0 344 284 345 285 u32 msg_enable; 346 286 u16 max_tpa; 347 287 __be16 vxlan_port; 348 288 __be16 nge_port; 349 289 __be16 vxlan_gpe_port; 290 + 291 + unsigned int current_interval; 292 + struct timer_list timer; 293 + struct workqueue_struct *bnge_pf_wq; 294 + struct work_struct sp_task; 295 + unsigned long sp_event; 296 + 297 + struct bnge_ethtool_link_info eth_link_info; 298 + 299 + u64 flags; 300 + 301 + struct bnge_stats_mem port_stats; 302 + struct bnge_stats_mem rx_port_stats_ext; 303 + struct bnge_stats_mem tx_port_stats_ext; 304 + u16 fw_rx_stats_ext_size; 305 + u16 fw_tx_stats_ext_size; 306 + 307 + struct netdev_queue_stats_rx rxq_prv_stats; 308 + struct netdev_queue_stats_tx txq_prv_stats; 309 + struct rtnl_link_stats64 prv_stats64; 310 + spinlock_t stats_lock; 311 + 312 + u8 pri2cos_idx[8]; 313 + bool pri2cos_valid; 350 314 }; 351 315 352 316 #define BNGE_DEFAULT_RX_RING_SIZE 511 ··· 434 352 #define BNGE_DB_NQ_ARM(bd, db, idx) \ 435 353 bnge_writeq(bd, (db)->db_key64 | DBR_TYPE_NQ_ARM | \ 436 354 DB_RING_IDX(db, idx), (db)->doorbell) 437 - 438 - struct bnge_stats_mem { 439 - u64 *sw_stats; 440 - u64 *hw_masks; 441 - void *hw_stats; 442 - dma_addr_t hw_stats_map; 443 - int len; 444 - }; 445 355 446 356 struct nqe_cn { 447 357 __le16 type; ··· 640 566 struct bnge_rx_ring_info *rxr, gfp_t gfp); 641 567 int bnge_alloc_rx_netmem(struct bnge_net *bn, struct bnge_rx_ring_info *rxr, 642 568 u16 prod, gfp_t gfp); 569 + void __bnge_queue_sp_work(struct bnge_net *bn); 570 + void bnge_copy_hw_masks(u64 *mask_arr, __le64 *hw_mask_arr, int count); 643 571 #endif /* _BNGE_NETDEV_H_ */
+31 -4
drivers/net/ethernet/broadcom/bnge/bnge_txrx.c
··· 1128 1128 } 1129 1129 } 1130 1130 1131 + static void bnge_async_event_process(struct bnge_net *bn, 1132 + struct hwrm_async_event_cmpl *cmpl) 1133 + { 1134 + u16 event_id = le16_to_cpu(cmpl->event_id); 1135 + u32 data1 = le32_to_cpu(cmpl->event_data1); 1136 + u32 data2 = le32_to_cpu(cmpl->event_data2); 1137 + 1138 + netdev_dbg(bn->netdev, "hwrm event 0x%x {0x%x, 0x%x}\n", 1139 + event_id, data1, data2); 1140 + 1141 + switch (event_id) { 1142 + case ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE: 1143 + case ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE: 1144 + case ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE: 1145 + case ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE: 1146 + bnge_link_async_event_process(bn, event_id); 1147 + break; 1148 + default: 1149 + return; 1150 + } 1151 + __bnge_queue_sp_work(bn); 1152 + } 1153 + 1131 1154 static void 1132 1155 bnge_hwrm_update_token(struct bnge_dev *bd, u16 seq_id, 1133 1156 enum bnge_hwrm_wait_state state) ··· 1169 1146 dev_err(bd->dev, "Invalid hwrm seq id %d\n", seq_id); 1170 1147 } 1171 1148 1172 - static int bnge_hwrm_handler(struct bnge_dev *bd, struct tx_cmp *txcmp) 1149 + static int bnge_hwrm_handler(struct bnge_net *bn, struct tx_cmp *txcmp) 1173 1150 { 1174 1151 struct hwrm_cmpl *h_cmpl = (struct hwrm_cmpl *)txcmp; 1175 1152 u16 cmpl_type = TX_CMP_TYPE(txcmp), seq_id; ··· 1177 1154 switch (cmpl_type) { 1178 1155 case CMPL_BASE_TYPE_HWRM_DONE: 1179 1156 seq_id = le16_to_cpu(h_cmpl->sequence_id); 1180 - bnge_hwrm_update_token(bd, seq_id, BNGE_HWRM_COMPLETE); 1157 + bnge_hwrm_update_token(bn->bd, seq_id, BNGE_HWRM_COMPLETE); 1181 1158 break; 1182 1159 1183 1160 case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT: 1161 + bnge_async_event_process(bn, 1162 + (struct hwrm_async_event_cmpl *)txcmp); 1163 + break; 1164 + 1184 1165 default: 1185 1166 break; 1186 1167 } ··· 1262 1235 } else if (unlikely(cmp_type == CMPL_BASE_TYPE_HWRM_DONE || 1263 1236 cmp_type == CMPL_BASE_TYPE_HWRM_FWD_REQ || 1264 1237 cmp_type == CMPL_BA_TY_HWRM_ASY_EVT)) { 1265 - bnge_hwrm_handler(bn->bd, txcmp); 1238 + bnge_hwrm_handler(bn, txcmp); 1266 1239 } 1267 1240 raw_cons = NEXT_RAW_CMP(raw_cons); 1268 1241 ··· 1382 1355 budget - work_done); 1383 1356 nqr->has_more_work |= cpr->has_more_work; 1384 1357 } else { 1385 - bnge_hwrm_handler(bn->bd, (struct tx_cmp *)nqcmp); 1358 + bnge_hwrm_handler(bn, (struct tx_cmp *)nqcmp); 1386 1359 } 1387 1360 raw_cons = NEXT_RAW_CMP(raw_cons); 1388 1361 }