xref: /openbmc/qemu/hw/net/igb_core.c (revision 173c427eb5705064da7dc8db22553c8df34f7f58)
13a977deeSAkihiko Odaki /*
23a977deeSAkihiko Odaki  * Core code for QEMU igb emulation
33a977deeSAkihiko Odaki  *
43a977deeSAkihiko Odaki  * Datasheet:
53a977deeSAkihiko Odaki  * https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82576eg-gbe-datasheet.pdf
63a977deeSAkihiko Odaki  *
73a977deeSAkihiko Odaki  * Copyright (c) 2020-2023 Red Hat, Inc.
83a977deeSAkihiko Odaki  * Copyright (c) 2015 Ravello Systems LTD (http://ravellosystems.com)
93a977deeSAkihiko Odaki  * Developed by Daynix Computing LTD (http://www.daynix.com)
103a977deeSAkihiko Odaki  *
113a977deeSAkihiko Odaki  * Authors:
123a977deeSAkihiko Odaki  * Akihiko Odaki <akihiko.odaki@daynix.com>
133a977deeSAkihiko Odaki  * Gal Hammmer <gal.hammer@sap.com>
143a977deeSAkihiko Odaki  * Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
153a977deeSAkihiko Odaki  * Dmitry Fleytman <dmitry@daynix.com>
163a977deeSAkihiko Odaki  * Leonid Bloch <leonid@daynix.com>
173a977deeSAkihiko Odaki  * Yan Vugenfirer <yan@daynix.com>
183a977deeSAkihiko Odaki  *
193a977deeSAkihiko Odaki  * Based on work done by:
203a977deeSAkihiko Odaki  * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc.
213a977deeSAkihiko Odaki  * Copyright (c) 2008 Qumranet
223a977deeSAkihiko Odaki  * Based on work done by:
233a977deeSAkihiko Odaki  * Copyright (c) 2007 Dan Aloni
243a977deeSAkihiko Odaki  * Copyright (c) 2004 Antony T Curtis
253a977deeSAkihiko Odaki  *
263a977deeSAkihiko Odaki  * This library is free software; you can redistribute it and/or
273a977deeSAkihiko Odaki  * modify it under the terms of the GNU Lesser General Public
283a977deeSAkihiko Odaki  * License as published by the Free Software Foundation; either
293a977deeSAkihiko Odaki  * version 2.1 of the License, or (at your option) any later version.
303a977deeSAkihiko Odaki  *
313a977deeSAkihiko Odaki  * This library is distributed in the hope that it will be useful,
323a977deeSAkihiko Odaki  * but WITHOUT ANY WARRANTY; without even the implied warranty of
333a977deeSAkihiko Odaki  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
343a977deeSAkihiko Odaki  * Lesser General Public License for more details.
353a977deeSAkihiko Odaki  *
363a977deeSAkihiko Odaki  * You should have received a copy of the GNU Lesser General Public
373a977deeSAkihiko Odaki  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
383a977deeSAkihiko Odaki  */
393a977deeSAkihiko Odaki 
403a977deeSAkihiko Odaki #include "qemu/osdep.h"
413a977deeSAkihiko Odaki #include "qemu/log.h"
423a977deeSAkihiko Odaki #include "net/net.h"
433a977deeSAkihiko Odaki #include "net/tap.h"
443a977deeSAkihiko Odaki #include "hw/net/mii.h"
453a977deeSAkihiko Odaki #include "hw/pci/msi.h"
463a977deeSAkihiko Odaki #include "hw/pci/msix.h"
473a977deeSAkihiko Odaki #include "sysemu/runstate.h"
483a977deeSAkihiko Odaki 
493a977deeSAkihiko Odaki #include "net_tx_pkt.h"
503a977deeSAkihiko Odaki #include "net_rx_pkt.h"
513a977deeSAkihiko Odaki 
523a977deeSAkihiko Odaki #include "igb_common.h"
533a977deeSAkihiko Odaki #include "e1000x_common.h"
543a977deeSAkihiko Odaki #include "igb_core.h"
553a977deeSAkihiko Odaki 
563a977deeSAkihiko Odaki #include "trace.h"
573a977deeSAkihiko Odaki 
583a977deeSAkihiko Odaki #define E1000E_MAX_TX_FRAGS (64)
593a977deeSAkihiko Odaki 
603a977deeSAkihiko Odaki union e1000_rx_desc_union {
613a977deeSAkihiko Odaki     struct e1000_rx_desc legacy;
623a977deeSAkihiko Odaki     union e1000_adv_rx_desc adv;
633a977deeSAkihiko Odaki };
643a977deeSAkihiko Odaki 
653a977deeSAkihiko Odaki typedef struct IGBTxPktVmdqCallbackContext {
663a977deeSAkihiko Odaki     IGBCore *core;
673a977deeSAkihiko Odaki     NetClientState *nc;
683a977deeSAkihiko Odaki } IGBTxPktVmdqCallbackContext;
693a977deeSAkihiko Odaki 
70dc9ef1bfSAkihiko Odaki typedef struct L2Header {
71dc9ef1bfSAkihiko Odaki     struct eth_header eth;
726aa262f8SAkihiko Odaki     struct vlan_header vlan[2];
73dc9ef1bfSAkihiko Odaki } L2Header;
74dc9ef1bfSAkihiko Odaki 
753a9926d9SAkihiko Odaki typedef struct PTP2 {
763a9926d9SAkihiko Odaki     uint8_t message_id_transport_specific;
773a9926d9SAkihiko Odaki     uint8_t version_ptp;
783a9926d9SAkihiko Odaki     uint16_t message_length;
793a9926d9SAkihiko Odaki     uint8_t subdomain_number;
803a9926d9SAkihiko Odaki     uint8_t reserved0;
813a9926d9SAkihiko Odaki     uint16_t flags;
823a9926d9SAkihiko Odaki     uint64_t correction;
833a9926d9SAkihiko Odaki     uint8_t reserved1[5];
843a9926d9SAkihiko Odaki     uint8_t source_communication_technology;
853a9926d9SAkihiko Odaki     uint32_t source_uuid_lo;
863a9926d9SAkihiko Odaki     uint16_t source_uuid_hi;
873a9926d9SAkihiko Odaki     uint16_t source_port_id;
883a9926d9SAkihiko Odaki     uint16_t sequence_id;
893a9926d9SAkihiko Odaki     uint8_t control;
903a9926d9SAkihiko Odaki     uint8_t log_message_period;
913a9926d9SAkihiko Odaki } PTP2;
923a9926d9SAkihiko Odaki 
933a977deeSAkihiko Odaki static ssize_t
943a977deeSAkihiko Odaki igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt,
953a977deeSAkihiko Odaki                      bool has_vnet, bool *external_tx);
963a977deeSAkihiko Odaki 
975844562bSAkihiko Odaki static void igb_raise_interrupts(IGBCore *core, size_t index, uint32_t causes);
983a977deeSAkihiko Odaki static void igb_reset(IGBCore *core, bool sw);
993a977deeSAkihiko Odaki 
1003a977deeSAkihiko Odaki static inline void
igb_raise_legacy_irq(IGBCore * core)1013a977deeSAkihiko Odaki igb_raise_legacy_irq(IGBCore *core)
1023a977deeSAkihiko Odaki {
1033a977deeSAkihiko Odaki     trace_e1000e_irq_legacy_notify(true);
1043a977deeSAkihiko Odaki     e1000x_inc_reg_if_not_full(core->mac, IAC);
1053a977deeSAkihiko Odaki     pci_set_irq(core->owner, 1);
1063a977deeSAkihiko Odaki }
1073a977deeSAkihiko Odaki 
1083a977deeSAkihiko Odaki static inline void
igb_lower_legacy_irq(IGBCore * core)1093a977deeSAkihiko Odaki igb_lower_legacy_irq(IGBCore *core)
1103a977deeSAkihiko Odaki {
1113a977deeSAkihiko Odaki     trace_e1000e_irq_legacy_notify(false);
1123a977deeSAkihiko Odaki     pci_set_irq(core->owner, 0);
1133a977deeSAkihiko Odaki }
1143a977deeSAkihiko Odaki 
igb_msix_notify(IGBCore * core,unsigned int cause)115fe619f20SAkihiko Odaki static void igb_msix_notify(IGBCore *core, unsigned int cause)
1163a977deeSAkihiko Odaki {
1173a977deeSAkihiko Odaki     PCIDevice *dev = core->owner;
1183a977deeSAkihiko Odaki     uint16_t vfn;
119fe619f20SAkihiko Odaki     uint32_t effective_eiac;
120fe619f20SAkihiko Odaki     unsigned int vector;
1213a977deeSAkihiko Odaki 
122fe619f20SAkihiko Odaki     vfn = 8 - (cause + 2) / IGBVF_MSIX_VEC_NUM;
1233a977deeSAkihiko Odaki     if (vfn < pcie_sriov_num_vfs(core->owner)) {
1243a977deeSAkihiko Odaki         dev = pcie_sriov_get_vf_at_index(core->owner, vfn);
1253a977deeSAkihiko Odaki         assert(dev);
126fe619f20SAkihiko Odaki         vector = (cause + 2) % IGBVF_MSIX_VEC_NUM;
127fe619f20SAkihiko Odaki     } else if (cause >= IGB_MSIX_VEC_NUM) {
1283a977deeSAkihiko Odaki         qemu_log_mask(LOG_GUEST_ERROR,
1293a977deeSAkihiko Odaki                       "igb: Tried to use vector unavailable for PF");
1303a977deeSAkihiko Odaki         return;
131fe619f20SAkihiko Odaki     } else {
132fe619f20SAkihiko Odaki         vector = cause;
1333a977deeSAkihiko Odaki     }
1343a977deeSAkihiko Odaki 
1353a977deeSAkihiko Odaki     msix_notify(dev, vector);
136fe619f20SAkihiko Odaki 
137fe619f20SAkihiko Odaki     trace_e1000e_irq_icr_clear_eiac(core->mac[EICR], core->mac[EIAC]);
138fe619f20SAkihiko Odaki     effective_eiac = core->mac[EIAC] & BIT(cause);
139fe619f20SAkihiko Odaki     core->mac[EICR] &= ~effective_eiac;
1403a977deeSAkihiko Odaki }
1413a977deeSAkihiko Odaki 
1423a977deeSAkihiko Odaki static inline void
igb_intrmgr_rearm_timer(IGBIntrDelayTimer * timer)1433a977deeSAkihiko Odaki igb_intrmgr_rearm_timer(IGBIntrDelayTimer *timer)
1443a977deeSAkihiko Odaki {
1453a977deeSAkihiko Odaki     int64_t delay_ns = (int64_t) timer->core->mac[timer->delay_reg] *
1463a977deeSAkihiko Odaki                                  timer->delay_resolution_ns;
1473a977deeSAkihiko Odaki 
1483a977deeSAkihiko Odaki     trace_e1000e_irq_rearm_timer(timer->delay_reg << 2, delay_ns);
1493a977deeSAkihiko Odaki 
1503a977deeSAkihiko Odaki     timer_mod(timer->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + delay_ns);
1513a977deeSAkihiko Odaki 
1523a977deeSAkihiko Odaki     timer->running = true;
1533a977deeSAkihiko Odaki }
1543a977deeSAkihiko Odaki 
1553a977deeSAkihiko Odaki static void
igb_intmgr_timer_resume(IGBIntrDelayTimer * timer)1563a977deeSAkihiko Odaki igb_intmgr_timer_resume(IGBIntrDelayTimer *timer)
1573a977deeSAkihiko Odaki {
1583a977deeSAkihiko Odaki     if (timer->running) {
1593a977deeSAkihiko Odaki         igb_intrmgr_rearm_timer(timer);
1603a977deeSAkihiko Odaki     }
1613a977deeSAkihiko Odaki }
1623a977deeSAkihiko Odaki 
1633a977deeSAkihiko Odaki static void
igb_intrmgr_on_msix_throttling_timer(void * opaque)1643a977deeSAkihiko Odaki igb_intrmgr_on_msix_throttling_timer(void *opaque)
1653a977deeSAkihiko Odaki {
1663a977deeSAkihiko Odaki     IGBIntrDelayTimer *timer = opaque;
1673a977deeSAkihiko Odaki     int idx = timer - &timer->core->eitr[0];
1683a977deeSAkihiko Odaki 
1693a977deeSAkihiko Odaki     timer->running = false;
1703a977deeSAkihiko Odaki 
1713a977deeSAkihiko Odaki     trace_e1000e_irq_msix_notify_postponed_vec(idx);
1723a977deeSAkihiko Odaki     igb_msix_notify(timer->core, idx);
1733a977deeSAkihiko Odaki }
1743a977deeSAkihiko Odaki 
1753a977deeSAkihiko Odaki static void
igb_intrmgr_initialize_all_timers(IGBCore * core,bool create)1763a977deeSAkihiko Odaki igb_intrmgr_initialize_all_timers(IGBCore *core, bool create)
1773a977deeSAkihiko Odaki {
1783a977deeSAkihiko Odaki     int i;
1793a977deeSAkihiko Odaki 
1803a977deeSAkihiko Odaki     for (i = 0; i < IGB_INTR_NUM; i++) {
1813a977deeSAkihiko Odaki         core->eitr[i].core = core;
1823a977deeSAkihiko Odaki         core->eitr[i].delay_reg = EITR0 + i;
1833a977deeSAkihiko Odaki         core->eitr[i].delay_resolution_ns = E1000_INTR_DELAY_NS_RES;
1843a977deeSAkihiko Odaki     }
1853a977deeSAkihiko Odaki 
1863a977deeSAkihiko Odaki     if (!create) {
1873a977deeSAkihiko Odaki         return;
1883a977deeSAkihiko Odaki     }
1893a977deeSAkihiko Odaki 
1903a977deeSAkihiko Odaki     for (i = 0; i < IGB_INTR_NUM; i++) {
1913a977deeSAkihiko Odaki         core->eitr[i].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
1923a977deeSAkihiko Odaki                                            igb_intrmgr_on_msix_throttling_timer,
1933a977deeSAkihiko Odaki                                            &core->eitr[i]);
1943a977deeSAkihiko Odaki     }
1953a977deeSAkihiko Odaki }
1963a977deeSAkihiko Odaki 
1973a977deeSAkihiko Odaki static void
igb_intrmgr_resume(IGBCore * core)1983a977deeSAkihiko Odaki igb_intrmgr_resume(IGBCore *core)
1993a977deeSAkihiko Odaki {
2003a977deeSAkihiko Odaki     int i;
2013a977deeSAkihiko Odaki 
2023a977deeSAkihiko Odaki     for (i = 0; i < IGB_INTR_NUM; i++) {
2033a977deeSAkihiko Odaki         igb_intmgr_timer_resume(&core->eitr[i]);
2043a977deeSAkihiko Odaki     }
2053a977deeSAkihiko Odaki }
2063a977deeSAkihiko Odaki 
2073a977deeSAkihiko Odaki static void
igb_intrmgr_reset(IGBCore * core)2083a977deeSAkihiko Odaki igb_intrmgr_reset(IGBCore *core)
2093a977deeSAkihiko Odaki {
2103a977deeSAkihiko Odaki     int i;
2113a977deeSAkihiko Odaki 
2123a977deeSAkihiko Odaki     for (i = 0; i < IGB_INTR_NUM; i++) {
2133a977deeSAkihiko Odaki         if (core->eitr[i].running) {
2143a977deeSAkihiko Odaki             timer_del(core->eitr[i].timer);
2153a977deeSAkihiko Odaki             igb_intrmgr_on_msix_throttling_timer(&core->eitr[i]);
2163a977deeSAkihiko Odaki         }
2173a977deeSAkihiko Odaki     }
2183a977deeSAkihiko Odaki }
2193a977deeSAkihiko Odaki 
2203a977deeSAkihiko Odaki static void
igb_intrmgr_pci_unint(IGBCore * core)2213a977deeSAkihiko Odaki igb_intrmgr_pci_unint(IGBCore *core)
2223a977deeSAkihiko Odaki {
2233a977deeSAkihiko Odaki     int i;
2243a977deeSAkihiko Odaki 
2253a977deeSAkihiko Odaki     for (i = 0; i < IGB_INTR_NUM; i++) {
2263a977deeSAkihiko Odaki         timer_free(core->eitr[i].timer);
2273a977deeSAkihiko Odaki     }
2283a977deeSAkihiko Odaki }
2293a977deeSAkihiko Odaki 
2303a977deeSAkihiko Odaki static void
igb_intrmgr_pci_realize(IGBCore * core)2313a977deeSAkihiko Odaki igb_intrmgr_pci_realize(IGBCore *core)
2323a977deeSAkihiko Odaki {
2333a977deeSAkihiko Odaki     igb_intrmgr_initialize_all_timers(core, true);
2343a977deeSAkihiko Odaki }
2353a977deeSAkihiko Odaki 
2363a977deeSAkihiko Odaki static inline bool
igb_rx_csum_enabled(IGBCore * core)2373a977deeSAkihiko Odaki igb_rx_csum_enabled(IGBCore *core)
2383a977deeSAkihiko Odaki {
2393a977deeSAkihiko Odaki     return (core->mac[RXCSUM] & E1000_RXCSUM_PCSD) ? false : true;
2403a977deeSAkihiko Odaki }
2413a977deeSAkihiko Odaki 
2423a977deeSAkihiko Odaki static inline bool
igb_rx_use_legacy_descriptor(IGBCore * core)2433a977deeSAkihiko Odaki igb_rx_use_legacy_descriptor(IGBCore *core)
2443a977deeSAkihiko Odaki {
2453a977deeSAkihiko Odaki     /*
2463a977deeSAkihiko Odaki      * TODO: If SRRCTL[n],DESCTYPE = 000b, the 82576 uses the legacy Rx
2473a977deeSAkihiko Odaki      * descriptor.
2483a977deeSAkihiko Odaki      */
2493a977deeSAkihiko Odaki     return false;
2503a977deeSAkihiko Odaki }
2513a977deeSAkihiko Odaki 
252560cf339STomasz Dzieciol typedef struct E1000ERingInfo {
253560cf339STomasz Dzieciol     int dbah;
254560cf339STomasz Dzieciol     int dbal;
255560cf339STomasz Dzieciol     int dlen;
256560cf339STomasz Dzieciol     int dh;
257560cf339STomasz Dzieciol     int dt;
258560cf339STomasz Dzieciol     int idx;
259560cf339STomasz Dzieciol } E1000ERingInfo;
260560cf339STomasz Dzieciol 
261560cf339STomasz Dzieciol static uint32_t
igb_rx_queue_desctyp_get(IGBCore * core,const E1000ERingInfo * r)262560cf339STomasz Dzieciol igb_rx_queue_desctyp_get(IGBCore *core, const E1000ERingInfo *r)
263560cf339STomasz Dzieciol {
264560cf339STomasz Dzieciol     return core->mac[E1000_SRRCTL(r->idx) >> 2] & E1000_SRRCTL_DESCTYPE_MASK;
265560cf339STomasz Dzieciol }
266560cf339STomasz Dzieciol 
267560cf339STomasz Dzieciol static bool
igb_rx_use_ps_descriptor(IGBCore * core,const E1000ERingInfo * r)268560cf339STomasz Dzieciol igb_rx_use_ps_descriptor(IGBCore *core, const E1000ERingInfo *r)
269560cf339STomasz Dzieciol {
270560cf339STomasz Dzieciol     uint32_t desctyp = igb_rx_queue_desctyp_get(core, r);
271560cf339STomasz Dzieciol     return desctyp == E1000_SRRCTL_DESCTYPE_HDR_SPLIT ||
272560cf339STomasz Dzieciol            desctyp == E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
273560cf339STomasz Dzieciol }
274560cf339STomasz Dzieciol 
2753a977deeSAkihiko Odaki static inline bool
igb_rss_enabled(IGBCore * core)2763a977deeSAkihiko Odaki igb_rss_enabled(IGBCore *core)
2773a977deeSAkihiko Odaki {
2783a977deeSAkihiko Odaki     return (core->mac[MRQC] & 3) == E1000_MRQC_ENABLE_RSS_MQ &&
2793a977deeSAkihiko Odaki            !igb_rx_csum_enabled(core) &&
2803a977deeSAkihiko Odaki            !igb_rx_use_legacy_descriptor(core);
2813a977deeSAkihiko Odaki }
2823a977deeSAkihiko Odaki 
2833a977deeSAkihiko Odaki typedef struct E1000E_RSSInfo_st {
2843a977deeSAkihiko Odaki     bool enabled;
2853a977deeSAkihiko Odaki     uint32_t hash;
2863a977deeSAkihiko Odaki     uint32_t queue;
2873a977deeSAkihiko Odaki     uint32_t type;
2883a977deeSAkihiko Odaki } E1000E_RSSInfo;
2893a977deeSAkihiko Odaki 
2903a977deeSAkihiko Odaki static uint32_t
igb_rss_get_hash_type(IGBCore * core,struct NetRxPkt * pkt)2913a977deeSAkihiko Odaki igb_rss_get_hash_type(IGBCore *core, struct NetRxPkt *pkt)
2923a977deeSAkihiko Odaki {
2933a977deeSAkihiko Odaki     bool hasip4, hasip6;
2943a977deeSAkihiko Odaki     EthL4HdrProto l4hdr_proto;
2953a977deeSAkihiko Odaki 
2963a977deeSAkihiko Odaki     assert(igb_rss_enabled(core));
2973a977deeSAkihiko Odaki 
2983a977deeSAkihiko Odaki     net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
2993a977deeSAkihiko Odaki 
3003a977deeSAkihiko Odaki     if (hasip4) {
3013a977deeSAkihiko Odaki         trace_e1000e_rx_rss_ip4(l4hdr_proto, core->mac[MRQC],
3023a977deeSAkihiko Odaki                                 E1000_MRQC_EN_TCPIPV4(core->mac[MRQC]),
3033a977deeSAkihiko Odaki                                 E1000_MRQC_EN_IPV4(core->mac[MRQC]));
3043a977deeSAkihiko Odaki 
3053a977deeSAkihiko Odaki         if (l4hdr_proto == ETH_L4_HDR_PROTO_TCP &&
3063a977deeSAkihiko Odaki             E1000_MRQC_EN_TCPIPV4(core->mac[MRQC])) {
3073a977deeSAkihiko Odaki             return E1000_MRQ_RSS_TYPE_IPV4TCP;
3083a977deeSAkihiko Odaki         }
3093a977deeSAkihiko Odaki 
310abc9a29dSAkihiko Odaki         if (l4hdr_proto == ETH_L4_HDR_PROTO_UDP &&
311abc9a29dSAkihiko Odaki             (core->mac[MRQC] & E1000_MRQC_RSS_FIELD_IPV4_UDP)) {
312abc9a29dSAkihiko Odaki             return E1000_MRQ_RSS_TYPE_IPV4UDP;
313abc9a29dSAkihiko Odaki         }
314abc9a29dSAkihiko Odaki 
3153a977deeSAkihiko Odaki         if (E1000_MRQC_EN_IPV4(core->mac[MRQC])) {
3163a977deeSAkihiko Odaki             return E1000_MRQ_RSS_TYPE_IPV4;
3173a977deeSAkihiko Odaki         }
3183a977deeSAkihiko Odaki     } else if (hasip6) {
3193a977deeSAkihiko Odaki         eth_ip6_hdr_info *ip6info = net_rx_pkt_get_ip6_info(pkt);
3203a977deeSAkihiko Odaki 
3213a977deeSAkihiko Odaki         bool ex_dis = core->mac[RFCTL] & E1000_RFCTL_IPV6_EX_DIS;
3223a977deeSAkihiko Odaki         bool new_ex_dis = core->mac[RFCTL] & E1000_RFCTL_NEW_IPV6_EXT_DIS;
3233a977deeSAkihiko Odaki 
3243a977deeSAkihiko Odaki         /*
3253a977deeSAkihiko Odaki          * Following two traces must not be combined because resulting
3263a977deeSAkihiko Odaki          * event will have 11 arguments totally and some trace backends
3273a977deeSAkihiko Odaki          * (at least "ust") have limitation of maximum 10 arguments per
3283a977deeSAkihiko Odaki          * event. Events with more arguments fail to compile for
3293a977deeSAkihiko Odaki          * backends like these.
3303a977deeSAkihiko Odaki          */
3313a977deeSAkihiko Odaki         trace_e1000e_rx_rss_ip6_rfctl(core->mac[RFCTL]);
3323a977deeSAkihiko Odaki         trace_e1000e_rx_rss_ip6(ex_dis, new_ex_dis, l4hdr_proto,
3333a977deeSAkihiko Odaki                                 ip6info->has_ext_hdrs,
3343a977deeSAkihiko Odaki                                 ip6info->rss_ex_dst_valid,
3353a977deeSAkihiko Odaki                                 ip6info->rss_ex_src_valid,
3363a977deeSAkihiko Odaki                                 core->mac[MRQC],
3375052fc9eSAkihiko Odaki                                 E1000_MRQC_EN_TCPIPV6EX(core->mac[MRQC]),
3383a977deeSAkihiko Odaki                                 E1000_MRQC_EN_IPV6EX(core->mac[MRQC]),
3393a977deeSAkihiko Odaki                                 E1000_MRQC_EN_IPV6(core->mac[MRQC]));
3403a977deeSAkihiko Odaki 
3413a977deeSAkihiko Odaki         if ((!ex_dis || !ip6info->has_ext_hdrs) &&
3423a977deeSAkihiko Odaki             (!new_ex_dis || !(ip6info->rss_ex_dst_valid ||
3433a977deeSAkihiko Odaki                               ip6info->rss_ex_src_valid))) {
3443a977deeSAkihiko Odaki 
3453a977deeSAkihiko Odaki             if (l4hdr_proto == ETH_L4_HDR_PROTO_TCP &&
3465052fc9eSAkihiko Odaki                 E1000_MRQC_EN_TCPIPV6EX(core->mac[MRQC])) {
3475052fc9eSAkihiko Odaki                 return E1000_MRQ_RSS_TYPE_IPV6TCPEX;
3483a977deeSAkihiko Odaki             }
3493a977deeSAkihiko Odaki 
350abc9a29dSAkihiko Odaki             if (l4hdr_proto == ETH_L4_HDR_PROTO_UDP &&
351abc9a29dSAkihiko Odaki                 (core->mac[MRQC] & E1000_MRQC_RSS_FIELD_IPV6_UDP)) {
352abc9a29dSAkihiko Odaki                 return E1000_MRQ_RSS_TYPE_IPV6UDP;
353abc9a29dSAkihiko Odaki             }
354abc9a29dSAkihiko Odaki 
3553a977deeSAkihiko Odaki             if (E1000_MRQC_EN_IPV6EX(core->mac[MRQC])) {
3563a977deeSAkihiko Odaki                 return E1000_MRQ_RSS_TYPE_IPV6EX;
3573a977deeSAkihiko Odaki             }
3583a977deeSAkihiko Odaki 
3593a977deeSAkihiko Odaki         }
3603a977deeSAkihiko Odaki 
3613a977deeSAkihiko Odaki         if (E1000_MRQC_EN_IPV6(core->mac[MRQC])) {
3623a977deeSAkihiko Odaki             return E1000_MRQ_RSS_TYPE_IPV6;
3633a977deeSAkihiko Odaki         }
3643a977deeSAkihiko Odaki 
3653a977deeSAkihiko Odaki     }
3663a977deeSAkihiko Odaki 
3673a977deeSAkihiko Odaki     return E1000_MRQ_RSS_TYPE_NONE;
3683a977deeSAkihiko Odaki }
3693a977deeSAkihiko Odaki 
3703a977deeSAkihiko Odaki static uint32_t
igb_rss_calc_hash(IGBCore * core,struct NetRxPkt * pkt,E1000E_RSSInfo * info)3713a977deeSAkihiko Odaki igb_rss_calc_hash(IGBCore *core, struct NetRxPkt *pkt, E1000E_RSSInfo *info)
3723a977deeSAkihiko Odaki {
3733a977deeSAkihiko Odaki     NetRxPktRssType type;
3743a977deeSAkihiko Odaki 
3753a977deeSAkihiko Odaki     assert(igb_rss_enabled(core));
3763a977deeSAkihiko Odaki 
3773a977deeSAkihiko Odaki     switch (info->type) {
3783a977deeSAkihiko Odaki     case E1000_MRQ_RSS_TYPE_IPV4:
3793a977deeSAkihiko Odaki         type = NetPktRssIpV4;
3803a977deeSAkihiko Odaki         break;
3813a977deeSAkihiko Odaki     case E1000_MRQ_RSS_TYPE_IPV4TCP:
3823a977deeSAkihiko Odaki         type = NetPktRssIpV4Tcp;
3833a977deeSAkihiko Odaki         break;
3845052fc9eSAkihiko Odaki     case E1000_MRQ_RSS_TYPE_IPV6TCPEX:
3853a977deeSAkihiko Odaki         type = NetPktRssIpV6TcpEx;
3863a977deeSAkihiko Odaki         break;
3873a977deeSAkihiko Odaki     case E1000_MRQ_RSS_TYPE_IPV6:
3883a977deeSAkihiko Odaki         type = NetPktRssIpV6;
3893a977deeSAkihiko Odaki         break;
3903a977deeSAkihiko Odaki     case E1000_MRQ_RSS_TYPE_IPV6EX:
3913a977deeSAkihiko Odaki         type = NetPktRssIpV6Ex;
3923a977deeSAkihiko Odaki         break;
393abc9a29dSAkihiko Odaki     case E1000_MRQ_RSS_TYPE_IPV4UDP:
394abc9a29dSAkihiko Odaki         type = NetPktRssIpV4Udp;
395abc9a29dSAkihiko Odaki         break;
396abc9a29dSAkihiko Odaki     case E1000_MRQ_RSS_TYPE_IPV6UDP:
397abc9a29dSAkihiko Odaki         type = NetPktRssIpV6Udp;
398abc9a29dSAkihiko Odaki         break;
3993a977deeSAkihiko Odaki     default:
400*d81e87e9SPierrick Bouvier         g_assert_not_reached();
4013a977deeSAkihiko Odaki     }
4023a977deeSAkihiko Odaki 
4033a977deeSAkihiko Odaki     return net_rx_pkt_calc_rss_hash(pkt, type, (uint8_t *) &core->mac[RSSRK]);
4043a977deeSAkihiko Odaki }
4053a977deeSAkihiko Odaki 
4063a977deeSAkihiko Odaki static void
igb_rss_parse_packet(IGBCore * core,struct NetRxPkt * pkt,bool tx,E1000E_RSSInfo * info)4073a977deeSAkihiko Odaki igb_rss_parse_packet(IGBCore *core, struct NetRxPkt *pkt, bool tx,
4083a977deeSAkihiko Odaki                      E1000E_RSSInfo *info)
4093a977deeSAkihiko Odaki {
4103a977deeSAkihiko Odaki     trace_e1000e_rx_rss_started();
4113a977deeSAkihiko Odaki 
4123a977deeSAkihiko Odaki     if (tx || !igb_rss_enabled(core)) {
4133a977deeSAkihiko Odaki         info->enabled = false;
4143a977deeSAkihiko Odaki         info->hash = 0;
4153a977deeSAkihiko Odaki         info->queue = 0;
4163a977deeSAkihiko Odaki         info->type = 0;
4173a977deeSAkihiko Odaki         trace_e1000e_rx_rss_disabled();
4183a977deeSAkihiko Odaki         return;
4193a977deeSAkihiko Odaki     }
4203a977deeSAkihiko Odaki 
4213a977deeSAkihiko Odaki     info->enabled = true;
4223a977deeSAkihiko Odaki 
4233a977deeSAkihiko Odaki     info->type = igb_rss_get_hash_type(core, pkt);
4243a977deeSAkihiko Odaki 
4253a977deeSAkihiko Odaki     trace_e1000e_rx_rss_type(info->type);
4263a977deeSAkihiko Odaki 
4273a977deeSAkihiko Odaki     if (info->type == E1000_MRQ_RSS_TYPE_NONE) {
4283a977deeSAkihiko Odaki         info->hash = 0;
4293a977deeSAkihiko Odaki         info->queue = 0;
4303a977deeSAkihiko Odaki         return;
4313a977deeSAkihiko Odaki     }
4323a977deeSAkihiko Odaki 
4333a977deeSAkihiko Odaki     info->hash = igb_rss_calc_hash(core, pkt, info);
4343a977deeSAkihiko Odaki     info->queue = E1000_RSS_QUEUE(&core->mac[RETA], info->hash);
4353a977deeSAkihiko Odaki }
4363a977deeSAkihiko Odaki 
437fba7c3b7SSriram Yagnaraman static void
igb_tx_insert_vlan(IGBCore * core,uint16_t qn,struct igb_tx * tx,uint16_t vlan,bool insert_vlan)438fba7c3b7SSriram Yagnaraman igb_tx_insert_vlan(IGBCore *core, uint16_t qn, struct igb_tx *tx,
439fba7c3b7SSriram Yagnaraman     uint16_t vlan, bool insert_vlan)
440fba7c3b7SSriram Yagnaraman {
441fba7c3b7SSriram Yagnaraman     if (core->mac[MRQC] & 1) {
442fba7c3b7SSriram Yagnaraman         uint16_t pool = qn % IGB_NUM_VM_POOLS;
443fba7c3b7SSriram Yagnaraman 
444fba7c3b7SSriram Yagnaraman         if (core->mac[VMVIR0 + pool] & E1000_VMVIR_VLANA_DEFAULT) {
445fba7c3b7SSriram Yagnaraman             /* always insert default VLAN */
446fba7c3b7SSriram Yagnaraman             insert_vlan = true;
447fba7c3b7SSriram Yagnaraman             vlan = core->mac[VMVIR0 + pool] & 0xffff;
448fba7c3b7SSriram Yagnaraman         } else if (core->mac[VMVIR0 + pool] & E1000_VMVIR_VLANA_NEVER) {
449fba7c3b7SSriram Yagnaraman             insert_vlan = false;
450fba7c3b7SSriram Yagnaraman         }
451fba7c3b7SSriram Yagnaraman     }
452fba7c3b7SSriram Yagnaraman 
453e2097167SAkihiko Odaki     if (insert_vlan) {
454fba7c3b7SSriram Yagnaraman         net_tx_pkt_setup_vlan_header_ex(tx->tx_pkt, vlan,
455fba7c3b7SSriram Yagnaraman             core->mac[VET] & 0xffff);
456fba7c3b7SSriram Yagnaraman     }
457fba7c3b7SSriram Yagnaraman }
458fba7c3b7SSriram Yagnaraman 
4593a977deeSAkihiko Odaki static bool
igb_setup_tx_offloads(IGBCore * core,struct igb_tx * tx)4603a977deeSAkihiko Odaki igb_setup_tx_offloads(IGBCore *core, struct igb_tx *tx)
4613a977deeSAkihiko Odaki {
462212f7b1dSAkihiko Odaki     uint32_t idx = (tx->first_olinfo_status >> 4) & 1;
463f199b13bSAkihiko Odaki 
464f199b13bSAkihiko Odaki     if (tx->first_cmd_type_len & E1000_ADVTXD_DCMD_TSE) {
4654847dabfSAkihiko Odaki         uint32_t mss = tx->ctx[idx].mss_l4len_idx >> E1000_ADVTXD_MSS_SHIFT;
466212f7b1dSAkihiko Odaki         if (!net_tx_pkt_build_vheader(tx->tx_pkt, true, true, mss)) {
4673a977deeSAkihiko Odaki             return false;
4683a977deeSAkihiko Odaki         }
4693a977deeSAkihiko Odaki 
4703a977deeSAkihiko Odaki         net_tx_pkt_update_ip_checksums(tx->tx_pkt);
4713a977deeSAkihiko Odaki         e1000x_inc_reg_if_not_full(core->mac, TSCTC);
4723a977deeSAkihiko Odaki         return true;
4733a977deeSAkihiko Odaki     }
4743a977deeSAkihiko Odaki 
475f199b13bSAkihiko Odaki     if ((tx->first_olinfo_status & E1000_ADVTXD_POTS_TXSM) &&
476f199b13bSAkihiko Odaki         !((tx->ctx[idx].type_tucmd_mlhl & E1000_ADVTXD_TUCMD_L4T_SCTP) ?
477f199b13bSAkihiko Odaki           net_tx_pkt_update_sctp_checksum(tx->tx_pkt) :
478f199b13bSAkihiko Odaki           net_tx_pkt_build_vheader(tx->tx_pkt, false, true, 0))) {
4793a977deeSAkihiko Odaki         return false;
4803a977deeSAkihiko Odaki     }
4813a977deeSAkihiko Odaki 
482212f7b1dSAkihiko Odaki     if (tx->first_olinfo_status & E1000_ADVTXD_POTS_IXSM) {
4833a977deeSAkihiko Odaki         net_tx_pkt_update_ip_hdr_checksum(tx->tx_pkt);
4843a977deeSAkihiko Odaki     }
4853a977deeSAkihiko Odaki 
4863a977deeSAkihiko Odaki     return true;
4873a977deeSAkihiko Odaki }
4883a977deeSAkihiko Odaki 
igb_tx_pkt_mac_callback(void * core,const struct iovec * iov,int iovcnt,const struct iovec * virt_iov,int virt_iovcnt)4893a977deeSAkihiko Odaki static void igb_tx_pkt_mac_callback(void *core,
4903a977deeSAkihiko Odaki                                     const struct iovec *iov,
4913a977deeSAkihiko Odaki                                     int iovcnt,
4923a977deeSAkihiko Odaki                                     const struct iovec *virt_iov,
4933a977deeSAkihiko Odaki                                     int virt_iovcnt)
4943a977deeSAkihiko Odaki {
4953a977deeSAkihiko Odaki     igb_receive_internal(core, virt_iov, virt_iovcnt, true, NULL);
4963a977deeSAkihiko Odaki }
4973a977deeSAkihiko Odaki 
igb_tx_pkt_vmdq_callback(void * opaque,const struct iovec * iov,int iovcnt,const struct iovec * virt_iov,int virt_iovcnt)4983a977deeSAkihiko Odaki static void igb_tx_pkt_vmdq_callback(void *opaque,
4993a977deeSAkihiko Odaki                                      const struct iovec *iov,
5003a977deeSAkihiko Odaki                                      int iovcnt,
5013a977deeSAkihiko Odaki                                      const struct iovec *virt_iov,
5023a977deeSAkihiko Odaki                                      int virt_iovcnt)
5033a977deeSAkihiko Odaki {
5043a977deeSAkihiko Odaki     IGBTxPktVmdqCallbackContext *context = opaque;
5053a977deeSAkihiko Odaki     bool external_tx;
5063a977deeSAkihiko Odaki 
5073a977deeSAkihiko Odaki     igb_receive_internal(context->core, virt_iov, virt_iovcnt, true,
5083a977deeSAkihiko Odaki                          &external_tx);
5093a977deeSAkihiko Odaki 
5103a977deeSAkihiko Odaki     if (external_tx) {
5113a977deeSAkihiko Odaki         if (context->core->has_vnet) {
5123a977deeSAkihiko Odaki             qemu_sendv_packet(context->nc, virt_iov, virt_iovcnt);
5133a977deeSAkihiko Odaki         } else {
5143a977deeSAkihiko Odaki             qemu_sendv_packet(context->nc, iov, iovcnt);
5153a977deeSAkihiko Odaki         }
5163a977deeSAkihiko Odaki     }
5173a977deeSAkihiko Odaki }
5183a977deeSAkihiko Odaki 
5193a977deeSAkihiko Odaki /* TX Packets Switching (7.10.3.6) */
igb_tx_pkt_switch(IGBCore * core,struct igb_tx * tx,NetClientState * nc)5203a977deeSAkihiko Odaki static bool igb_tx_pkt_switch(IGBCore *core, struct igb_tx *tx,
5213a977deeSAkihiko Odaki                               NetClientState *nc)
5223a977deeSAkihiko Odaki {
5233a977deeSAkihiko Odaki     IGBTxPktVmdqCallbackContext context;
5243a977deeSAkihiko Odaki 
5253a977deeSAkihiko Odaki     /* TX switching is only used to serve VM to VM traffic. */
5263a977deeSAkihiko Odaki     if (!(core->mac[MRQC] & 1)) {
5273a977deeSAkihiko Odaki         goto send_out;
5283a977deeSAkihiko Odaki     }
5293a977deeSAkihiko Odaki 
5303a977deeSAkihiko Odaki     /* TX switching requires DTXSWC.Loopback_en bit enabled. */
5313a977deeSAkihiko Odaki     if (!(core->mac[DTXSWC] & E1000_DTXSWC_VMDQ_LOOPBACK_EN)) {
5323a977deeSAkihiko Odaki         goto send_out;
5333a977deeSAkihiko Odaki     }
5343a977deeSAkihiko Odaki 
5353a977deeSAkihiko Odaki     context.core = core;
5363a977deeSAkihiko Odaki     context.nc = nc;
5373a977deeSAkihiko Odaki 
5383a977deeSAkihiko Odaki     return net_tx_pkt_send_custom(tx->tx_pkt, false,
5393a977deeSAkihiko Odaki                                   igb_tx_pkt_vmdq_callback, &context);
5403a977deeSAkihiko Odaki 
5413a977deeSAkihiko Odaki send_out:
5423a977deeSAkihiko Odaki     return net_tx_pkt_send(tx->tx_pkt, nc);
5433a977deeSAkihiko Odaki }
5443a977deeSAkihiko Odaki 
5453a977deeSAkihiko Odaki static bool
igb_tx_pkt_send(IGBCore * core,struct igb_tx * tx,int queue_index)5463a977deeSAkihiko Odaki igb_tx_pkt_send(IGBCore *core, struct igb_tx *tx, int queue_index)
5473a977deeSAkihiko Odaki {
5483a977deeSAkihiko Odaki     int target_queue = MIN(core->max_queue_num, queue_index);
5493a977deeSAkihiko Odaki     NetClientState *queue = qemu_get_subqueue(core->owner_nic, target_queue);
5503a977deeSAkihiko Odaki 
5513a977deeSAkihiko Odaki     if (!igb_setup_tx_offloads(core, tx)) {
5523a977deeSAkihiko Odaki         return false;
5533a977deeSAkihiko Odaki     }
5543a977deeSAkihiko Odaki 
5553a977deeSAkihiko Odaki     net_tx_pkt_dump(tx->tx_pkt);
5563a977deeSAkihiko Odaki 
5573a977deeSAkihiko Odaki     if ((core->phy[MII_BMCR] & MII_BMCR_LOOPBACK) ||
5583a977deeSAkihiko Odaki         ((core->mac[RCTL] & E1000_RCTL_LBM_MAC) == E1000_RCTL_LBM_MAC)) {
5593a977deeSAkihiko Odaki         return net_tx_pkt_send_custom(tx->tx_pkt, false,
5603a977deeSAkihiko Odaki                                       igb_tx_pkt_mac_callback, core);
5613a977deeSAkihiko Odaki     } else {
5623a977deeSAkihiko Odaki         return igb_tx_pkt_switch(core, tx, queue);
5633a977deeSAkihiko Odaki     }
5643a977deeSAkihiko Odaki }
5653a977deeSAkihiko Odaki 
5663a977deeSAkihiko Odaki static void
igb_on_tx_done_update_stats(IGBCore * core,struct NetTxPkt * tx_pkt,int qn)5677581baedSSriram Yagnaraman igb_on_tx_done_update_stats(IGBCore *core, struct NetTxPkt *tx_pkt, int qn)
5683a977deeSAkihiko Odaki {
5693a977deeSAkihiko Odaki     static const int PTCregs[6] = { PTC64, PTC127, PTC255, PTC511,
5703a977deeSAkihiko Odaki                                     PTC1023, PTC1522 };
5713a977deeSAkihiko Odaki 
5723a977deeSAkihiko Odaki     size_t tot_len = net_tx_pkt_get_total_len(tx_pkt) + 4;
5733a977deeSAkihiko Odaki 
5743a977deeSAkihiko Odaki     e1000x_increase_size_stats(core->mac, PTCregs, tot_len);
5753a977deeSAkihiko Odaki     e1000x_inc_reg_if_not_full(core->mac, TPT);
5763a977deeSAkihiko Odaki     e1000x_grow_8reg_if_not_full(core->mac, TOTL, tot_len);
5773a977deeSAkihiko Odaki 
5783a977deeSAkihiko Odaki     switch (net_tx_pkt_get_packet_type(tx_pkt)) {
5793a977deeSAkihiko Odaki     case ETH_PKT_BCAST:
5803a977deeSAkihiko Odaki         e1000x_inc_reg_if_not_full(core->mac, BPTC);
5813a977deeSAkihiko Odaki         break;
5823a977deeSAkihiko Odaki     case ETH_PKT_MCAST:
5833a977deeSAkihiko Odaki         e1000x_inc_reg_if_not_full(core->mac, MPTC);
5843a977deeSAkihiko Odaki         break;
5853a977deeSAkihiko Odaki     case ETH_PKT_UCAST:
5863a977deeSAkihiko Odaki         break;
5873a977deeSAkihiko Odaki     default:
5883a977deeSAkihiko Odaki         g_assert_not_reached();
5893a977deeSAkihiko Odaki     }
5903a977deeSAkihiko Odaki 
5918d689f6aStimothee.cocault@gmail.com     e1000x_inc_reg_if_not_full(core->mac, GPTC);
5928d689f6aStimothee.cocault@gmail.com     e1000x_grow_8reg_if_not_full(core->mac, GOTCL, tot_len);
5937581baedSSriram Yagnaraman 
5947581baedSSriram Yagnaraman     if (core->mac[MRQC] & 1) {
5957581baedSSriram Yagnaraman         uint16_t pool = qn % IGB_NUM_VM_POOLS;
5967581baedSSriram Yagnaraman 
5977581baedSSriram Yagnaraman         core->mac[PVFGOTC0 + (pool * 64)] += tot_len;
5987581baedSSriram Yagnaraman         core->mac[PVFGPTC0 + (pool * 64)]++;
5997581baedSSriram Yagnaraman     }
6003a977deeSAkihiko Odaki }
6013a977deeSAkihiko Odaki 
6023a977deeSAkihiko Odaki static void
igb_process_tx_desc(IGBCore * core,PCIDevice * dev,struct igb_tx * tx,union e1000_adv_tx_desc * tx_desc,int queue_index)6033a977deeSAkihiko Odaki igb_process_tx_desc(IGBCore *core,
604f4fdaf00SAkihiko Odaki                     PCIDevice *dev,
6053a977deeSAkihiko Odaki                     struct igb_tx *tx,
6063a977deeSAkihiko Odaki                     union e1000_adv_tx_desc *tx_desc,
6073a977deeSAkihiko Odaki                     int queue_index)
6083a977deeSAkihiko Odaki {
6093a977deeSAkihiko Odaki     struct e1000_adv_tx_context_desc *tx_ctx_desc;
6103a977deeSAkihiko Odaki     uint32_t cmd_type_len;
611212f7b1dSAkihiko Odaki     uint32_t idx;
6123a977deeSAkihiko Odaki     uint64_t buffer_addr;
6133a977deeSAkihiko Odaki     uint16_t length;
6143a977deeSAkihiko Odaki 
6153a977deeSAkihiko Odaki     cmd_type_len = le32_to_cpu(tx_desc->read.cmd_type_len);
6163a977deeSAkihiko Odaki 
6173a977deeSAkihiko Odaki     if (cmd_type_len & E1000_ADVTXD_DCMD_DEXT) {
6183a977deeSAkihiko Odaki         if ((cmd_type_len & E1000_ADVTXD_DTYP_DATA) ==
6193a977deeSAkihiko Odaki             E1000_ADVTXD_DTYP_DATA) {
6203a977deeSAkihiko Odaki             /* advanced transmit data descriptor */
6213a977deeSAkihiko Odaki             if (tx->first) {
622212f7b1dSAkihiko Odaki                 tx->first_cmd_type_len = cmd_type_len;
623212f7b1dSAkihiko Odaki                 tx->first_olinfo_status = le32_to_cpu(tx_desc->read.olinfo_status);
6243a977deeSAkihiko Odaki                 tx->first = false;
6253a977deeSAkihiko Odaki             }
6263a977deeSAkihiko Odaki         } else if ((cmd_type_len & E1000_ADVTXD_DTYP_CTXT) ==
6273a977deeSAkihiko Odaki                    E1000_ADVTXD_DTYP_CTXT) {
6283a977deeSAkihiko Odaki             /* advanced transmit context descriptor */
6293a977deeSAkihiko Odaki             tx_ctx_desc = (struct e1000_adv_tx_context_desc *)tx_desc;
630212f7b1dSAkihiko Odaki             idx = (le32_to_cpu(tx_ctx_desc->mss_l4len_idx) >> 4) & 1;
631212f7b1dSAkihiko Odaki             tx->ctx[idx].vlan_macip_lens = le32_to_cpu(tx_ctx_desc->vlan_macip_lens);
632212f7b1dSAkihiko Odaki             tx->ctx[idx].seqnum_seed = le32_to_cpu(tx_ctx_desc->seqnum_seed);
633212f7b1dSAkihiko Odaki             tx->ctx[idx].type_tucmd_mlhl = le32_to_cpu(tx_ctx_desc->type_tucmd_mlhl);
634212f7b1dSAkihiko Odaki             tx->ctx[idx].mss_l4len_idx = le32_to_cpu(tx_ctx_desc->mss_l4len_idx);
6353a977deeSAkihiko Odaki             return;
6363a977deeSAkihiko Odaki         } else {
6373a977deeSAkihiko Odaki             /* unknown descriptor type */
6383a977deeSAkihiko Odaki             return;
6393a977deeSAkihiko Odaki         }
6403a977deeSAkihiko Odaki     } else {
6413a977deeSAkihiko Odaki         /* legacy descriptor */
6423a977deeSAkihiko Odaki 
6433a977deeSAkihiko Odaki         /* TODO: Implement a support for legacy descriptors (7.2.2.1). */
6443a977deeSAkihiko Odaki     }
6453a977deeSAkihiko Odaki 
6463a977deeSAkihiko Odaki     buffer_addr = le64_to_cpu(tx_desc->read.buffer_addr);
6473a977deeSAkihiko Odaki     length = cmd_type_len & 0xFFFF;
6483a977deeSAkihiko Odaki 
6493a977deeSAkihiko Odaki     if (!tx->skip_cp) {
650a51db580SAkihiko Odaki         if (!net_tx_pkt_add_raw_fragment_pci(tx->tx_pkt, dev,
651a51db580SAkihiko Odaki                                              buffer_addr, length)) {
6523a977deeSAkihiko Odaki             tx->skip_cp = true;
6533a977deeSAkihiko Odaki         }
6543a977deeSAkihiko Odaki     }
6553a977deeSAkihiko Odaki 
6563a977deeSAkihiko Odaki     if (cmd_type_len & E1000_TXD_CMD_EOP) {
6573a977deeSAkihiko Odaki         if (!tx->skip_cp && net_tx_pkt_parse(tx->tx_pkt)) {
658212f7b1dSAkihiko Odaki             idx = (tx->first_olinfo_status >> 4) & 1;
659fba7c3b7SSriram Yagnaraman             igb_tx_insert_vlan(core, queue_index, tx,
6604847dabfSAkihiko Odaki                 tx->ctx[idx].vlan_macip_lens >> IGB_TX_FLAGS_VLAN_SHIFT,
6615d92e88aSAkihiko Odaki                 !!(tx->first_cmd_type_len & E1000_TXD_CMD_VLE));
662fba7c3b7SSriram Yagnaraman 
6633dfc616eSAkihiko Odaki             if ((tx->first_cmd_type_len & E1000_ADVTXD_MAC_TSTAMP) &&
6643dfc616eSAkihiko Odaki                 (core->mac[TSYNCTXCTL] & E1000_TSYNCTXCTL_ENABLED) &&
6653dfc616eSAkihiko Odaki                 !(core->mac[TSYNCTXCTL] & E1000_TSYNCTXCTL_VALID)) {
6663dfc616eSAkihiko Odaki                 core->mac[TSYNCTXCTL] |= E1000_TSYNCTXCTL_VALID;
6673dfc616eSAkihiko Odaki                 e1000x_timestamp(core->mac, core->timadj, TXSTMPL, TXSTMPH);
6683dfc616eSAkihiko Odaki             }
6693dfc616eSAkihiko Odaki 
6703a977deeSAkihiko Odaki             if (igb_tx_pkt_send(core, tx, queue_index)) {
6717581baedSSriram Yagnaraman                 igb_on_tx_done_update_stats(core, tx->tx_pkt, queue_index);
6723a977deeSAkihiko Odaki             }
6733a977deeSAkihiko Odaki         }
6743a977deeSAkihiko Odaki 
6753a977deeSAkihiko Odaki         tx->first = true;
6763a977deeSAkihiko Odaki         tx->skip_cp = false;
677a51db580SAkihiko Odaki         net_tx_pkt_reset(tx->tx_pkt, net_tx_pkt_unmap_frag_pci, dev);
6783a977deeSAkihiko Odaki     }
6793a977deeSAkihiko Odaki }
6803a977deeSAkihiko Odaki 
igb_tx_wb_eic(IGBCore * core,int queue_idx)6813a977deeSAkihiko Odaki static uint32_t igb_tx_wb_eic(IGBCore *core, int queue_idx)
6823a977deeSAkihiko Odaki {
6833a977deeSAkihiko Odaki     uint32_t n, ent = 0;
6843a977deeSAkihiko Odaki 
6853a977deeSAkihiko Odaki     n = igb_ivar_entry_tx(queue_idx);
6863a977deeSAkihiko Odaki     ent = (core->mac[IVAR0 + n / 4] >> (8 * (n % 4))) & 0xff;
6873a977deeSAkihiko Odaki 
6883a977deeSAkihiko Odaki     return (ent & E1000_IVAR_VALID) ? BIT(ent & 0x1f) : 0;
6893a977deeSAkihiko Odaki }
6903a977deeSAkihiko Odaki 
igb_rx_wb_eic(IGBCore * core,int queue_idx)6913a977deeSAkihiko Odaki static uint32_t igb_rx_wb_eic(IGBCore *core, int queue_idx)
6923a977deeSAkihiko Odaki {
6933a977deeSAkihiko Odaki     uint32_t n, ent = 0;
6943a977deeSAkihiko Odaki 
6953a977deeSAkihiko Odaki     n = igb_ivar_entry_rx(queue_idx);
6963a977deeSAkihiko Odaki     ent = (core->mac[IVAR0 + n / 4] >> (8 * (n % 4))) & 0xff;
6973a977deeSAkihiko Odaki 
6983a977deeSAkihiko Odaki     return (ent & E1000_IVAR_VALID) ? BIT(ent & 0x1f) : 0;
6993a977deeSAkihiko Odaki }
7003a977deeSAkihiko Odaki 
7013a977deeSAkihiko Odaki static inline bool
igb_ring_empty(IGBCore * core,const E1000ERingInfo * r)702a86aee7eSTomasz Dzieciol igb_ring_empty(IGBCore *core, const E1000ERingInfo *r)
7033a977deeSAkihiko Odaki {
7043a977deeSAkihiko Odaki     return core->mac[r->dh] == core->mac[r->dt] ||
7053a977deeSAkihiko Odaki                 core->mac[r->dt] >= core->mac[r->dlen] / E1000_RING_DESC_LEN;
7063a977deeSAkihiko Odaki }
7073a977deeSAkihiko Odaki 
7083a977deeSAkihiko Odaki static inline uint64_t
igb_ring_base(IGBCore * core,const E1000ERingInfo * r)709a86aee7eSTomasz Dzieciol igb_ring_base(IGBCore *core, const E1000ERingInfo *r)
7103a977deeSAkihiko Odaki {
7113a977deeSAkihiko Odaki     uint64_t bah = core->mac[r->dbah];
7123a977deeSAkihiko Odaki     uint64_t bal = core->mac[r->dbal];
7133a977deeSAkihiko Odaki 
7143a977deeSAkihiko Odaki     return (bah << 32) + bal;
7153a977deeSAkihiko Odaki }
7163a977deeSAkihiko Odaki 
7173a977deeSAkihiko Odaki static inline uint64_t
igb_ring_head_descr(IGBCore * core,const E1000ERingInfo * r)718a86aee7eSTomasz Dzieciol igb_ring_head_descr(IGBCore *core, const E1000ERingInfo *r)
7193a977deeSAkihiko Odaki {
7203a977deeSAkihiko Odaki     return igb_ring_base(core, r) + E1000_RING_DESC_LEN * core->mac[r->dh];
7213a977deeSAkihiko Odaki }
7223a977deeSAkihiko Odaki 
7233a977deeSAkihiko Odaki static inline void
igb_ring_advance(IGBCore * core,const E1000ERingInfo * r,uint32_t count)724a86aee7eSTomasz Dzieciol igb_ring_advance(IGBCore *core, const E1000ERingInfo *r, uint32_t count)
7253a977deeSAkihiko Odaki {
7263a977deeSAkihiko Odaki     core->mac[r->dh] += count;
7273a977deeSAkihiko Odaki 
7283a977deeSAkihiko Odaki     if (core->mac[r->dh] * E1000_RING_DESC_LEN >= core->mac[r->dlen]) {
7293a977deeSAkihiko Odaki         core->mac[r->dh] = 0;
7303a977deeSAkihiko Odaki     }
7313a977deeSAkihiko Odaki }
7323a977deeSAkihiko Odaki 
7333a977deeSAkihiko Odaki static inline uint32_t
igb_ring_free_descr_num(IGBCore * core,const E1000ERingInfo * r)734a86aee7eSTomasz Dzieciol igb_ring_free_descr_num(IGBCore *core, const E1000ERingInfo *r)
7353a977deeSAkihiko Odaki {
7363a977deeSAkihiko Odaki     trace_e1000e_ring_free_space(r->idx, core->mac[r->dlen],
7373a977deeSAkihiko Odaki                                  core->mac[r->dh],  core->mac[r->dt]);
7383a977deeSAkihiko Odaki 
7393a977deeSAkihiko Odaki     if (core->mac[r->dh] <= core->mac[r->dt]) {
7403a977deeSAkihiko Odaki         return core->mac[r->dt] - core->mac[r->dh];
7413a977deeSAkihiko Odaki     }
7423a977deeSAkihiko Odaki 
7433a977deeSAkihiko Odaki     if (core->mac[r->dh] > core->mac[r->dt]) {
7443a977deeSAkihiko Odaki         return core->mac[r->dlen] / E1000_RING_DESC_LEN +
7453a977deeSAkihiko Odaki                core->mac[r->dt] - core->mac[r->dh];
7463a977deeSAkihiko Odaki     }
7473a977deeSAkihiko Odaki 
7483a977deeSAkihiko Odaki     g_assert_not_reached();
7493a977deeSAkihiko Odaki }
7503a977deeSAkihiko Odaki 
7513a977deeSAkihiko Odaki static inline bool
igb_ring_enabled(IGBCore * core,const E1000ERingInfo * r)752a86aee7eSTomasz Dzieciol igb_ring_enabled(IGBCore *core, const E1000ERingInfo *r)
7533a977deeSAkihiko Odaki {
7543a977deeSAkihiko Odaki     return core->mac[r->dlen] > 0;
7553a977deeSAkihiko Odaki }
7563a977deeSAkihiko Odaki 
7573a977deeSAkihiko Odaki typedef struct IGB_TxRing_st {
758a86aee7eSTomasz Dzieciol     const E1000ERingInfo *i;
7593a977deeSAkihiko Odaki     struct igb_tx *tx;
7603a977deeSAkihiko Odaki } IGB_TxRing;
7613a977deeSAkihiko Odaki 
7623a977deeSAkihiko Odaki static inline int
igb_mq_queue_idx(int base_reg_idx,int reg_idx)7633a977deeSAkihiko Odaki igb_mq_queue_idx(int base_reg_idx, int reg_idx)
7643a977deeSAkihiko Odaki {
7653a977deeSAkihiko Odaki     return (reg_idx - base_reg_idx) / 16;
7663a977deeSAkihiko Odaki }
7673a977deeSAkihiko Odaki 
7683a977deeSAkihiko Odaki static inline void
igb_tx_ring_init(IGBCore * core,IGB_TxRing * txr,int idx)7693a977deeSAkihiko Odaki igb_tx_ring_init(IGBCore *core, IGB_TxRing *txr, int idx)
7703a977deeSAkihiko Odaki {
771a86aee7eSTomasz Dzieciol     static const E1000ERingInfo i[IGB_NUM_QUEUES] = {
7723a977deeSAkihiko Odaki         { TDBAH0, TDBAL0, TDLEN0, TDH0, TDT0, 0 },
7733a977deeSAkihiko Odaki         { TDBAH1, TDBAL1, TDLEN1, TDH1, TDT1, 1 },
7743a977deeSAkihiko Odaki         { TDBAH2, TDBAL2, TDLEN2, TDH2, TDT2, 2 },
7753a977deeSAkihiko Odaki         { TDBAH3, TDBAL3, TDLEN3, TDH3, TDT3, 3 },
7763a977deeSAkihiko Odaki         { TDBAH4, TDBAL4, TDLEN4, TDH4, TDT4, 4 },
7773a977deeSAkihiko Odaki         { TDBAH5, TDBAL5, TDLEN5, TDH5, TDT5, 5 },
7783a977deeSAkihiko Odaki         { TDBAH6, TDBAL6, TDLEN6, TDH6, TDT6, 6 },
7793a977deeSAkihiko Odaki         { TDBAH7, TDBAL7, TDLEN7, TDH7, TDT7, 7 },
7803a977deeSAkihiko Odaki         { TDBAH8, TDBAL8, TDLEN8, TDH8, TDT8, 8 },
7813a977deeSAkihiko Odaki         { TDBAH9, TDBAL9, TDLEN9, TDH9, TDT9, 9 },
7823a977deeSAkihiko Odaki         { TDBAH10, TDBAL10, TDLEN10, TDH10, TDT10, 10 },
7833a977deeSAkihiko Odaki         { TDBAH11, TDBAL11, TDLEN11, TDH11, TDT11, 11 },
7843a977deeSAkihiko Odaki         { TDBAH12, TDBAL12, TDLEN12, TDH12, TDT12, 12 },
7853a977deeSAkihiko Odaki         { TDBAH13, TDBAL13, TDLEN13, TDH13, TDT13, 13 },
7863a977deeSAkihiko Odaki         { TDBAH14, TDBAL14, TDLEN14, TDH14, TDT14, 14 },
7873a977deeSAkihiko Odaki         { TDBAH15, TDBAL15, TDLEN15, TDH15, TDT15, 15 }
7883a977deeSAkihiko Odaki     };
7893a977deeSAkihiko Odaki 
7903a977deeSAkihiko Odaki     assert(idx < ARRAY_SIZE(i));
7913a977deeSAkihiko Odaki 
7923a977deeSAkihiko Odaki     txr->i     = &i[idx];
7933a977deeSAkihiko Odaki     txr->tx    = &core->tx[idx];
7943a977deeSAkihiko Odaki }
7953a977deeSAkihiko Odaki 
7963a977deeSAkihiko Odaki typedef struct E1000E_RxRing_st {
797a86aee7eSTomasz Dzieciol     const E1000ERingInfo *i;
7983a977deeSAkihiko Odaki } E1000E_RxRing;
7993a977deeSAkihiko Odaki 
8003a977deeSAkihiko Odaki static inline void
igb_rx_ring_init(IGBCore * core,E1000E_RxRing * rxr,int idx)8013a977deeSAkihiko Odaki igb_rx_ring_init(IGBCore *core, E1000E_RxRing *rxr, int idx)
8023a977deeSAkihiko Odaki {
803a86aee7eSTomasz Dzieciol     static const E1000ERingInfo i[IGB_NUM_QUEUES] = {
8043a977deeSAkihiko Odaki         { RDBAH0, RDBAL0, RDLEN0, RDH0, RDT0, 0 },
8053a977deeSAkihiko Odaki         { RDBAH1, RDBAL1, RDLEN1, RDH1, RDT1, 1 },
8063a977deeSAkihiko Odaki         { RDBAH2, RDBAL2, RDLEN2, RDH2, RDT2, 2 },
8073a977deeSAkihiko Odaki         { RDBAH3, RDBAL3, RDLEN3, RDH3, RDT3, 3 },
8083a977deeSAkihiko Odaki         { RDBAH4, RDBAL4, RDLEN4, RDH4, RDT4, 4 },
8093a977deeSAkihiko Odaki         { RDBAH5, RDBAL5, RDLEN5, RDH5, RDT5, 5 },
8103a977deeSAkihiko Odaki         { RDBAH6, RDBAL6, RDLEN6, RDH6, RDT6, 6 },
8113a977deeSAkihiko Odaki         { RDBAH7, RDBAL7, RDLEN7, RDH7, RDT7, 7 },
8123a977deeSAkihiko Odaki         { RDBAH8, RDBAL8, RDLEN8, RDH8, RDT8, 8 },
8133a977deeSAkihiko Odaki         { RDBAH9, RDBAL9, RDLEN9, RDH9, RDT9, 9 },
8143a977deeSAkihiko Odaki         { RDBAH10, RDBAL10, RDLEN10, RDH10, RDT10, 10 },
8153a977deeSAkihiko Odaki         { RDBAH11, RDBAL11, RDLEN11, RDH11, RDT11, 11 },
8163a977deeSAkihiko Odaki         { RDBAH12, RDBAL12, RDLEN12, RDH12, RDT12, 12 },
8173a977deeSAkihiko Odaki         { RDBAH13, RDBAL13, RDLEN13, RDH13, RDT13, 13 },
8183a977deeSAkihiko Odaki         { RDBAH14, RDBAL14, RDLEN14, RDH14, RDT14, 14 },
8193a977deeSAkihiko Odaki         { RDBAH15, RDBAL15, RDLEN15, RDH15, RDT15, 15 }
8203a977deeSAkihiko Odaki     };
8213a977deeSAkihiko Odaki 
8223a977deeSAkihiko Odaki     assert(idx < ARRAY_SIZE(i));
8233a977deeSAkihiko Odaki 
8243a977deeSAkihiko Odaki     rxr->i      = &i[idx];
8253a977deeSAkihiko Odaki }
8263a977deeSAkihiko Odaki 
8273a977deeSAkihiko Odaki static uint32_t
igb_txdesc_writeback(IGBCore * core,dma_addr_t base,union e1000_adv_tx_desc * tx_desc,const E1000ERingInfo * txi)8283a977deeSAkihiko Odaki igb_txdesc_writeback(IGBCore *core, dma_addr_t base,
8293a977deeSAkihiko Odaki                      union e1000_adv_tx_desc *tx_desc,
830a86aee7eSTomasz Dzieciol                      const E1000ERingInfo *txi)
8313a977deeSAkihiko Odaki {
8323a977deeSAkihiko Odaki     PCIDevice *d;
8333a977deeSAkihiko Odaki     uint32_t cmd_type_len = le32_to_cpu(tx_desc->read.cmd_type_len);
8343a977deeSAkihiko Odaki     uint64_t tdwba;
8353a977deeSAkihiko Odaki 
8363a977deeSAkihiko Odaki     tdwba = core->mac[E1000_TDWBAL(txi->idx) >> 2];
8373a977deeSAkihiko Odaki     tdwba |= (uint64_t)core->mac[E1000_TDWBAH(txi->idx) >> 2] << 32;
8383a977deeSAkihiko Odaki 
8393a977deeSAkihiko Odaki     if (!(cmd_type_len & E1000_TXD_CMD_RS)) {
8403a977deeSAkihiko Odaki         return 0;
8413a977deeSAkihiko Odaki     }
8423a977deeSAkihiko Odaki 
8433a977deeSAkihiko Odaki     d = pcie_sriov_get_vf_at_index(core->owner, txi->idx % 8);
8443a977deeSAkihiko Odaki     if (!d) {
8453a977deeSAkihiko Odaki         d = core->owner;
8463a977deeSAkihiko Odaki     }
8473a977deeSAkihiko Odaki 
8483a977deeSAkihiko Odaki     if (tdwba & 1) {
8493a977deeSAkihiko Odaki         uint32_t buffer = cpu_to_le32(core->mac[txi->dh]);
8503a977deeSAkihiko Odaki         pci_dma_write(d, tdwba & ~3, &buffer, sizeof(buffer));
8513a977deeSAkihiko Odaki     } else {
8523a977deeSAkihiko Odaki         uint32_t status = le32_to_cpu(tx_desc->wb.status) | E1000_TXD_STAT_DD;
8533a977deeSAkihiko Odaki 
8543a977deeSAkihiko Odaki         tx_desc->wb.status = cpu_to_le32(status);
8553a977deeSAkihiko Odaki         pci_dma_write(d, base + offsetof(union e1000_adv_tx_desc, wb),
8563a977deeSAkihiko Odaki             &tx_desc->wb, sizeof(tx_desc->wb));
8573a977deeSAkihiko Odaki     }
8583a977deeSAkihiko Odaki 
8593a977deeSAkihiko Odaki     return igb_tx_wb_eic(core, txi->idx);
8603a977deeSAkihiko Odaki }
8613a977deeSAkihiko Odaki 
8623269ebb3SSriram Yagnaraman static inline bool
igb_tx_enabled(IGBCore * core,const E1000ERingInfo * txi)863a86aee7eSTomasz Dzieciol igb_tx_enabled(IGBCore *core, const E1000ERingInfo *txi)
8643269ebb3SSriram Yagnaraman {
8653269ebb3SSriram Yagnaraman     bool vmdq = core->mac[MRQC] & 1;
8663269ebb3SSriram Yagnaraman     uint16_t qn = txi->idx;
8673269ebb3SSriram Yagnaraman     uint16_t pool = qn % IGB_NUM_VM_POOLS;
8683269ebb3SSriram Yagnaraman 
8693269ebb3SSriram Yagnaraman     return (core->mac[TCTL] & E1000_TCTL_EN) &&
8703269ebb3SSriram Yagnaraman         (!vmdq || core->mac[VFTE] & BIT(pool)) &&
8713269ebb3SSriram Yagnaraman         (core->mac[TXDCTL0 + (qn * 16)] & E1000_TXDCTL_QUEUE_ENABLE);
8723269ebb3SSriram Yagnaraman }
8733269ebb3SSriram Yagnaraman 
8743a977deeSAkihiko Odaki static void
igb_start_xmit(IGBCore * core,const IGB_TxRing * txr)8753a977deeSAkihiko Odaki igb_start_xmit(IGBCore *core, const IGB_TxRing *txr)
8763a977deeSAkihiko Odaki {
8773a977deeSAkihiko Odaki     PCIDevice *d;
8783a977deeSAkihiko Odaki     dma_addr_t base;
8793a977deeSAkihiko Odaki     union e1000_adv_tx_desc desc;
880a86aee7eSTomasz Dzieciol     const E1000ERingInfo *txi = txr->i;
8813a977deeSAkihiko Odaki     uint32_t eic = 0;
8823a977deeSAkihiko Odaki 
8833269ebb3SSriram Yagnaraman     if (!igb_tx_enabled(core, txi)) {
8843a977deeSAkihiko Odaki         trace_e1000e_tx_disabled();
8853a977deeSAkihiko Odaki         return;
8863a977deeSAkihiko Odaki     }
8873a977deeSAkihiko Odaki 
8883a977deeSAkihiko Odaki     d = pcie_sriov_get_vf_at_index(core->owner, txi->idx % 8);
8893a977deeSAkihiko Odaki     if (!d) {
8903a977deeSAkihiko Odaki         d = core->owner;
8913a977deeSAkihiko Odaki     }
8923a977deeSAkihiko Odaki 
8933a977deeSAkihiko Odaki     while (!igb_ring_empty(core, txi)) {
8943a977deeSAkihiko Odaki         base = igb_ring_head_descr(core, txi);
8953a977deeSAkihiko Odaki 
8963a977deeSAkihiko Odaki         pci_dma_read(d, base, &desc, sizeof(desc));
8973a977deeSAkihiko Odaki 
8983a977deeSAkihiko Odaki         trace_e1000e_tx_descr((void *)(intptr_t)desc.read.buffer_addr,
8993a977deeSAkihiko Odaki                               desc.read.cmd_type_len, desc.wb.status);
9003a977deeSAkihiko Odaki 
901f4fdaf00SAkihiko Odaki         igb_process_tx_desc(core, d, txr->tx, &desc, txi->idx);
9023a977deeSAkihiko Odaki         igb_ring_advance(core, txi, 1);
9033a977deeSAkihiko Odaki         eic |= igb_txdesc_writeback(core, base, &desc, txi);
9043a977deeSAkihiko Odaki     }
9053a977deeSAkihiko Odaki 
9063a977deeSAkihiko Odaki     if (eic) {
9075844562bSAkihiko Odaki         igb_raise_interrupts(core, EICR, eic);
9085844562bSAkihiko Odaki         igb_raise_interrupts(core, ICR, E1000_ICR_TXDW);
9093a977deeSAkihiko Odaki     }
910a51db580SAkihiko Odaki 
911a51db580SAkihiko Odaki     net_tx_pkt_reset(txr->tx->tx_pkt, net_tx_pkt_unmap_frag_pci, d);
9123a977deeSAkihiko Odaki }
9133a977deeSAkihiko Odaki 
9143a977deeSAkihiko Odaki static uint32_t
igb_rxbufsize(IGBCore * core,const E1000ERingInfo * r)915a86aee7eSTomasz Dzieciol igb_rxbufsize(IGBCore *core, const E1000ERingInfo *r)
9163a977deeSAkihiko Odaki {
9173a977deeSAkihiko Odaki     uint32_t srrctl = core->mac[E1000_SRRCTL(r->idx) >> 2];
9183a977deeSAkihiko Odaki     uint32_t bsizepkt = srrctl & E1000_SRRCTL_BSIZEPKT_MASK;
9193a977deeSAkihiko Odaki     if (bsizepkt) {
9203a977deeSAkihiko Odaki         return bsizepkt << E1000_SRRCTL_BSIZEPKT_SHIFT;
9213a977deeSAkihiko Odaki     }
9223a977deeSAkihiko Odaki 
9233a977deeSAkihiko Odaki     return e1000x_rxbufsize(core->mac[RCTL]);
9243a977deeSAkihiko Odaki }
9253a977deeSAkihiko Odaki 
9263a977deeSAkihiko Odaki static bool
igb_has_rxbufs(IGBCore * core,const E1000ERingInfo * r,size_t total_size)927a86aee7eSTomasz Dzieciol igb_has_rxbufs(IGBCore *core, const E1000ERingInfo *r, size_t total_size)
9283a977deeSAkihiko Odaki {
9293a977deeSAkihiko Odaki     uint32_t bufs = igb_ring_free_descr_num(core, r);
9303a977deeSAkihiko Odaki     uint32_t bufsize = igb_rxbufsize(core, r);
9313a977deeSAkihiko Odaki 
9323a977deeSAkihiko Odaki     trace_e1000e_rx_has_buffers(r->idx, bufs, total_size, bufsize);
9333a977deeSAkihiko Odaki 
9343a977deeSAkihiko Odaki     return total_size <= bufs / (core->rx_desc_len / E1000_MIN_RX_DESC_LEN) *
9353a977deeSAkihiko Odaki                          bufsize;
9363a977deeSAkihiko Odaki }
9373a977deeSAkihiko Odaki 
93817ccd016STomasz Dzieciol static uint32_t
igb_rxhdrbufsize(IGBCore * core,const E1000ERingInfo * r)93917ccd016STomasz Dzieciol igb_rxhdrbufsize(IGBCore *core, const E1000ERingInfo *r)
94017ccd016STomasz Dzieciol {
94117ccd016STomasz Dzieciol     uint32_t srrctl = core->mac[E1000_SRRCTL(r->idx) >> 2];
94217ccd016STomasz Dzieciol     return (srrctl & E1000_SRRCTL_BSIZEHDRSIZE_MASK) >>
94317ccd016STomasz Dzieciol            E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
94417ccd016STomasz Dzieciol }
94517ccd016STomasz Dzieciol 
9463a977deeSAkihiko Odaki void
igb_start_recv(IGBCore * core)9473a977deeSAkihiko Odaki igb_start_recv(IGBCore *core)
9483a977deeSAkihiko Odaki {
9493a977deeSAkihiko Odaki     int i;
9503a977deeSAkihiko Odaki 
9513a977deeSAkihiko Odaki     trace_e1000e_rx_start_recv();
9523a977deeSAkihiko Odaki 
9533a977deeSAkihiko Odaki     for (i = 0; i <= core->max_queue_num; i++) {
9543a977deeSAkihiko Odaki         qemu_flush_queued_packets(qemu_get_subqueue(core->owner_nic, i));
9553a977deeSAkihiko Odaki     }
9563a977deeSAkihiko Odaki }
9573a977deeSAkihiko Odaki 
9583a977deeSAkihiko Odaki bool
igb_can_receive(IGBCore * core)9593a977deeSAkihiko Odaki igb_can_receive(IGBCore *core)
9603a977deeSAkihiko Odaki {
9613a977deeSAkihiko Odaki     int i;
9623a977deeSAkihiko Odaki 
9633a977deeSAkihiko Odaki     if (!e1000x_rx_ready(core->owner, core->mac)) {
9643a977deeSAkihiko Odaki         return false;
9653a977deeSAkihiko Odaki     }
9663a977deeSAkihiko Odaki 
9673a977deeSAkihiko Odaki     for (i = 0; i < IGB_NUM_QUEUES; i++) {
9683a977deeSAkihiko Odaki         E1000E_RxRing rxr;
9693269ebb3SSriram Yagnaraman         if (!(core->mac[RXDCTL0 + (i * 16)] & E1000_RXDCTL_QUEUE_ENABLE)) {
9703269ebb3SSriram Yagnaraman             continue;
9713269ebb3SSriram Yagnaraman         }
9723a977deeSAkihiko Odaki 
9733a977deeSAkihiko Odaki         igb_rx_ring_init(core, &rxr, i);
9743a977deeSAkihiko Odaki         if (igb_ring_enabled(core, rxr.i) && igb_has_rxbufs(core, rxr.i, 1)) {
9753a977deeSAkihiko Odaki             trace_e1000e_rx_can_recv();
9763a977deeSAkihiko Odaki             return true;
9773a977deeSAkihiko Odaki         }
9783a977deeSAkihiko Odaki     }
9793a977deeSAkihiko Odaki 
9803a977deeSAkihiko Odaki     trace_e1000e_rx_can_recv_rings_full();
9813a977deeSAkihiko Odaki     return false;
9823a977deeSAkihiko Odaki }
9833a977deeSAkihiko Odaki 
9843a977deeSAkihiko Odaki ssize_t
igb_receive(IGBCore * core,const uint8_t * buf,size_t size)9853a977deeSAkihiko Odaki igb_receive(IGBCore *core, const uint8_t *buf, size_t size)
9863a977deeSAkihiko Odaki {
9873a977deeSAkihiko Odaki     const struct iovec iov = {
9883a977deeSAkihiko Odaki         .iov_base = (uint8_t *)buf,
9893a977deeSAkihiko Odaki         .iov_len = size
9903a977deeSAkihiko Odaki     };
9913a977deeSAkihiko Odaki 
9923a977deeSAkihiko Odaki     return igb_receive_iov(core, &iov, 1);
9933a977deeSAkihiko Odaki }
9943a977deeSAkihiko Odaki 
9953a977deeSAkihiko Odaki static inline bool
igb_rx_l3_cso_enabled(IGBCore * core)9963a977deeSAkihiko Odaki igb_rx_l3_cso_enabled(IGBCore *core)
9973a977deeSAkihiko Odaki {
9983a977deeSAkihiko Odaki     return !!(core->mac[RXCSUM] & E1000_RXCSUM_IPOFLD);
9993a977deeSAkihiko Odaki }
10003a977deeSAkihiko Odaki 
10013a977deeSAkihiko Odaki static inline bool
igb_rx_l4_cso_enabled(IGBCore * core)10023a977deeSAkihiko Odaki igb_rx_l4_cso_enabled(IGBCore *core)
10033a977deeSAkihiko Odaki {
10043a977deeSAkihiko Odaki     return !!(core->mac[RXCSUM] & E1000_RXCSUM_TUOFLD);
10053a977deeSAkihiko Odaki }
10063a977deeSAkihiko Odaki 
igb_rx_is_oversized(IGBCore * core,const struct eth_header * ehdr,size_t size,size_t vlan_num,bool lpe,uint16_t rlpml)1007bb97003eSAkihiko Odaki static bool igb_rx_is_oversized(IGBCore *core, const struct eth_header *ehdr,
1008bb97003eSAkihiko Odaki                                 size_t size, size_t vlan_num,
1009bb97003eSAkihiko Odaki                                 bool lpe, uint16_t rlpml)
10105f12d703SSriram Yagnaraman {
1011bb97003eSAkihiko Odaki     size_t vlan_header_size = sizeof(struct vlan_header) * vlan_num;
1012bb97003eSAkihiko Odaki     size_t header_size = sizeof(struct eth_header) + vlan_header_size;
1013bb97003eSAkihiko Odaki     return lpe ? size + ETH_FCS_LEN > rlpml : size > header_size + ETH_MTU;
10145f12d703SSriram Yagnaraman }
10155f12d703SSriram Yagnaraman 
igb_receive_assign(IGBCore * core,const struct iovec * iov,size_t iovcnt,size_t iov_ofs,const L2Header * l2_header,size_t size,E1000E_RSSInfo * rss_info,uint16_t * etqf,bool * ts,bool * external_tx)10163a9926d9SAkihiko Odaki static uint16_t igb_receive_assign(IGBCore *core, const struct iovec *iov,
10173a9926d9SAkihiko Odaki                                    size_t iovcnt, size_t iov_ofs,
10183a9926d9SAkihiko Odaki                                    const L2Header *l2_header, size_t size,
10193a9926d9SAkihiko Odaki                                    E1000E_RSSInfo *rss_info,
10203a9926d9SAkihiko Odaki                                    uint16_t *etqf, bool *ts, bool *external_tx)
10213a977deeSAkihiko Odaki {
10223a977deeSAkihiko Odaki     static const int ta_shift[] = { 4, 3, 2, 0 };
1023dc9ef1bfSAkihiko Odaki     const struct eth_header *ehdr = &l2_header->eth;
10243a977deeSAkihiko Odaki     uint32_t f, ra[2], *macp, rctl = core->mac[RCTL];
10253a977deeSAkihiko Odaki     uint16_t queues = 0;
10265f12d703SSriram Yagnaraman     uint16_t oversized = 0;
10276aa262f8SAkihiko Odaki     size_t vlan_num = 0;
10283a9926d9SAkihiko Odaki     PTP2 ptp2;
1029bb97003eSAkihiko Odaki     bool lpe;
1030bb97003eSAkihiko Odaki     uint16_t rlpml;
10313a977deeSAkihiko Odaki     int i;
10323a977deeSAkihiko Odaki 
10333a977deeSAkihiko Odaki     memset(rss_info, 0, sizeof(E1000E_RSSInfo));
10343a9926d9SAkihiko Odaki     *ts = false;
10353a977deeSAkihiko Odaki 
10363a977deeSAkihiko Odaki     if (external_tx) {
10373a977deeSAkihiko Odaki         *external_tx = true;
10383a977deeSAkihiko Odaki     }
10393a977deeSAkihiko Odaki 
10406aa262f8SAkihiko Odaki     if (core->mac[CTRL_EXT] & BIT(26)) {
10416aa262f8SAkihiko Odaki         if (be16_to_cpu(ehdr->h_proto) == core->mac[VET] >> 16 &&
10426aa262f8SAkihiko Odaki             be16_to_cpu(l2_header->vlan[0].h_proto) == (core->mac[VET] & 0xffff)) {
10436aa262f8SAkihiko Odaki             vlan_num = 2;
10446aa262f8SAkihiko Odaki         }
10456aa262f8SAkihiko Odaki     } else {
10466aa262f8SAkihiko Odaki         if (be16_to_cpu(ehdr->h_proto) == (core->mac[VET] & 0xffff)) {
10476aa262f8SAkihiko Odaki             vlan_num = 1;
10486aa262f8SAkihiko Odaki         }
10496aa262f8SAkihiko Odaki     }
10506aa262f8SAkihiko Odaki 
1051bb97003eSAkihiko Odaki     lpe = !!(core->mac[RCTL] & E1000_RCTL_LPE);
1052bb97003eSAkihiko Odaki     rlpml = core->mac[RLPML];
1053bb97003eSAkihiko Odaki     if (!(core->mac[RCTL] & E1000_RCTL_SBP) &&
1054bb97003eSAkihiko Odaki         igb_rx_is_oversized(core, ehdr, size, vlan_num, lpe, rlpml)) {
1055bb97003eSAkihiko Odaki         trace_e1000x_rx_oversized(size);
1056bb97003eSAkihiko Odaki         return queues;
1057bb97003eSAkihiko Odaki     }
1058bb97003eSAkihiko Odaki 
10593a9926d9SAkihiko Odaki     for (*etqf = 0; *etqf < 8; (*etqf)++) {
10603a9926d9SAkihiko Odaki         if ((core->mac[ETQF0 + *etqf] & E1000_ETQF_FILTER_ENABLE) &&
10613a9926d9SAkihiko Odaki             be16_to_cpu(ehdr->h_proto) == (core->mac[ETQF0 + *etqf] & E1000_ETQF_ETYPE_MASK)) {
10623a9926d9SAkihiko Odaki             if ((core->mac[ETQF0 + *etqf] & E1000_ETQF_1588) &&
10633a9926d9SAkihiko Odaki                 (core->mac[TSYNCRXCTL] & E1000_TSYNCRXCTL_ENABLED) &&
10643a9926d9SAkihiko Odaki                 !(core->mac[TSYNCRXCTL] & E1000_TSYNCRXCTL_VALID) &&
10653a9926d9SAkihiko Odaki                 iov_to_buf(iov, iovcnt, iov_ofs + ETH_HLEN, &ptp2, sizeof(ptp2)) >= sizeof(ptp2) &&
10663a9926d9SAkihiko Odaki                 (ptp2.version_ptp & 15) == 2 &&
10673a9926d9SAkihiko Odaki                 ptp2.message_id_transport_specific == ((core->mac[TSYNCRXCFG] >> 8) & 255)) {
10683a9926d9SAkihiko Odaki                 e1000x_timestamp(core->mac, core->timadj, RXSTMPL, RXSTMPH);
10693a9926d9SAkihiko Odaki                 *ts = true;
10703a9926d9SAkihiko Odaki                 core->mac[TSYNCRXCTL] |= E1000_TSYNCRXCTL_VALID;
10713a9926d9SAkihiko Odaki                 core->mac[RXSATRL] = le32_to_cpu(ptp2.source_uuid_lo);
10723a9926d9SAkihiko Odaki                 core->mac[RXSATRH] = le16_to_cpu(ptp2.source_uuid_hi) |
10733a9926d9SAkihiko Odaki                                      (le16_to_cpu(ptp2.sequence_id) << 16);
10743a9926d9SAkihiko Odaki             }
10753a9926d9SAkihiko Odaki             break;
10763a9926d9SAkihiko Odaki         }
10773a9926d9SAkihiko Odaki     }
10783a9926d9SAkihiko Odaki 
10796aa262f8SAkihiko Odaki     if (vlan_num &&
10806aa262f8SAkihiko Odaki         !e1000x_rx_vlan_filter(core->mac, l2_header->vlan + vlan_num - 1)) {
10813a977deeSAkihiko Odaki         return queues;
10823a977deeSAkihiko Odaki     }
10833a977deeSAkihiko Odaki 
10843a977deeSAkihiko Odaki     if (core->mac[MRQC] & 1) {
10853a977deeSAkihiko Odaki         if (is_broadcast_ether_addr(ehdr->h_dest)) {
10863269ebb3SSriram Yagnaraman             for (i = 0; i < IGB_NUM_VM_POOLS; i++) {
10873a977deeSAkihiko Odaki                 if (core->mac[VMOLR0 + i] & E1000_VMOLR_BAM) {
10883a977deeSAkihiko Odaki                     queues |= BIT(i);
10893a977deeSAkihiko Odaki                 }
10903a977deeSAkihiko Odaki             }
10913a977deeSAkihiko Odaki         } else {
10923a977deeSAkihiko Odaki             for (macp = core->mac + RA; macp < core->mac + RA + 32; macp += 2) {
10933a977deeSAkihiko Odaki                 if (!(macp[1] & E1000_RAH_AV)) {
10943a977deeSAkihiko Odaki                     continue;
10953a977deeSAkihiko Odaki                 }
10963a977deeSAkihiko Odaki                 ra[0] = cpu_to_le32(macp[0]);
10973a977deeSAkihiko Odaki                 ra[1] = cpu_to_le32(macp[1]);
10983a977deeSAkihiko Odaki                 if (!memcmp(ehdr->h_dest, (uint8_t *)ra, ETH_ALEN)) {
10993a977deeSAkihiko Odaki                     queues |= (macp[1] & E1000_RAH_POOL_MASK) / E1000_RAH_POOL_1;
11003a977deeSAkihiko Odaki                 }
11013a977deeSAkihiko Odaki             }
11023a977deeSAkihiko Odaki 
11033a977deeSAkihiko Odaki             for (macp = core->mac + RA2; macp < core->mac + RA2 + 16; macp += 2) {
11043a977deeSAkihiko Odaki                 if (!(macp[1] & E1000_RAH_AV)) {
11053a977deeSAkihiko Odaki                     continue;
11063a977deeSAkihiko Odaki                 }
11073a977deeSAkihiko Odaki                 ra[0] = cpu_to_le32(macp[0]);
11083a977deeSAkihiko Odaki                 ra[1] = cpu_to_le32(macp[1]);
11093a977deeSAkihiko Odaki                 if (!memcmp(ehdr->h_dest, (uint8_t *)ra, ETH_ALEN)) {
11103a977deeSAkihiko Odaki                     queues |= (macp[1] & E1000_RAH_POOL_MASK) / E1000_RAH_POOL_1;
11113a977deeSAkihiko Odaki                 }
11123a977deeSAkihiko Odaki             }
11133a977deeSAkihiko Odaki 
11143a977deeSAkihiko Odaki             if (!queues) {
11153a977deeSAkihiko Odaki                 macp = core->mac + (is_multicast_ether_addr(ehdr->h_dest) ? MTA : UTA);
11163a977deeSAkihiko Odaki 
11173a977deeSAkihiko Odaki                 f = ta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3];
11183a977deeSAkihiko Odaki                 f = (((ehdr->h_dest[5] << 8) | ehdr->h_dest[4]) >> f) & 0xfff;
11193a977deeSAkihiko Odaki                 if (macp[f >> 5] & (1 << (f & 0x1f))) {
11203269ebb3SSriram Yagnaraman                     for (i = 0; i < IGB_NUM_VM_POOLS; i++) {
11213a977deeSAkihiko Odaki                         if (core->mac[VMOLR0 + i] & E1000_VMOLR_ROMPE) {
11223a977deeSAkihiko Odaki                             queues |= BIT(i);
11233a977deeSAkihiko Odaki                         }
11243a977deeSAkihiko Odaki                     }
11253a977deeSAkihiko Odaki                 }
11263a977deeSAkihiko Odaki             } else if (is_unicast_ether_addr(ehdr->h_dest) && external_tx) {
11273a977deeSAkihiko Odaki                 *external_tx = false;
11283a977deeSAkihiko Odaki             }
11293a977deeSAkihiko Odaki         }
11303a977deeSAkihiko Odaki 
11313a977deeSAkihiko Odaki         if (e1000x_vlan_rx_filter_enabled(core->mac)) {
11323a977deeSAkihiko Odaki             uint16_t mask = 0;
11333a977deeSAkihiko Odaki 
11346aa262f8SAkihiko Odaki             if (vlan_num) {
11356aa262f8SAkihiko Odaki                 uint16_t vid = be16_to_cpu(l2_header->vlan[vlan_num - 1].h_tci) & VLAN_VID_MASK;
11366aa262f8SAkihiko Odaki 
11373a977deeSAkihiko Odaki                 for (i = 0; i < E1000_VLVF_ARRAY_SIZE; i++) {
11383a977deeSAkihiko Odaki                     if ((core->mac[VLVF0 + i] & E1000_VLVF_VLANID_MASK) == vid &&
11393a977deeSAkihiko Odaki                         (core->mac[VLVF0 + i] & E1000_VLVF_VLANID_ENABLE)) {
11403a977deeSAkihiko Odaki                         uint32_t poolsel = core->mac[VLVF0 + i] & E1000_VLVF_POOLSEL_MASK;
11413a977deeSAkihiko Odaki                         mask |= poolsel >> E1000_VLVF_POOLSEL_SHIFT;
11423a977deeSAkihiko Odaki                     }
11433a977deeSAkihiko Odaki                 }
11443a977deeSAkihiko Odaki             } else {
11453269ebb3SSriram Yagnaraman                 for (i = 0; i < IGB_NUM_VM_POOLS; i++) {
11463a977deeSAkihiko Odaki                     if (core->mac[VMOLR0 + i] & E1000_VMOLR_AUPE) {
11473a977deeSAkihiko Odaki                         mask |= BIT(i);
11483a977deeSAkihiko Odaki                     }
11493a977deeSAkihiko Odaki                 }
11503a977deeSAkihiko Odaki             }
11513a977deeSAkihiko Odaki 
11523a977deeSAkihiko Odaki             queues &= mask;
11533a977deeSAkihiko Odaki         }
11543a977deeSAkihiko Odaki 
11553a977deeSAkihiko Odaki         if (is_unicast_ether_addr(ehdr->h_dest) && !queues && !external_tx &&
11563a977deeSAkihiko Odaki             !(core->mac[VT_CTL] & E1000_VT_CTL_DISABLE_DEF_POOL)) {
11573a977deeSAkihiko Odaki             uint32_t def_pl = core->mac[VT_CTL] & E1000_VT_CTL_DEFAULT_POOL_MASK;
11583a977deeSAkihiko Odaki             queues = BIT(def_pl >> E1000_VT_CTL_DEFAULT_POOL_SHIFT);
11593a977deeSAkihiko Odaki         }
11603a977deeSAkihiko Odaki 
11613269ebb3SSriram Yagnaraman         queues &= core->mac[VFRE];
11625f12d703SSriram Yagnaraman         if (queues) {
11635f12d703SSriram Yagnaraman             for (i = 0; i < IGB_NUM_VM_POOLS; i++) {
1164bb97003eSAkihiko Odaki                 lpe = !!(core->mac[VMOLR0 + i] & E1000_VMOLR_LPE);
1165bb97003eSAkihiko Odaki                 rlpml = core->mac[VMOLR0 + i] & E1000_VMOLR_RLPML_MASK;
1166bb97003eSAkihiko Odaki                 if ((queues & BIT(i)) &&
1167bb97003eSAkihiko Odaki                     igb_rx_is_oversized(core, ehdr, size, vlan_num,
1168bb97003eSAkihiko Odaki                                         lpe, rlpml)) {
11695f12d703SSriram Yagnaraman                     oversized |= BIT(i);
11705f12d703SSriram Yagnaraman                 }
11715f12d703SSriram Yagnaraman             }
11725f12d703SSriram Yagnaraman             /* 8.19.37 increment ROC if packet is oversized for all queues */
11735f12d703SSriram Yagnaraman             if (oversized == queues) {
11745f12d703SSriram Yagnaraman                 trace_e1000x_rx_oversized(size);
11755f12d703SSriram Yagnaraman                 e1000x_inc_reg_if_not_full(core->mac, ROC);
11765f12d703SSriram Yagnaraman             }
11775f12d703SSriram Yagnaraman             queues &= ~oversized;
11785f12d703SSriram Yagnaraman         }
11795f12d703SSriram Yagnaraman 
11805f12d703SSriram Yagnaraman         if (queues) {
11815f12d703SSriram Yagnaraman             igb_rss_parse_packet(core, core->rx_pkt,
11825f12d703SSriram Yagnaraman                                  external_tx != NULL, rss_info);
11833c2e0a68SSriram Yagnaraman             /* Sec 8.26.1: PQn = VFn + VQn*8 */
11843a977deeSAkihiko Odaki             if (rss_info->queue & 1) {
11853c2e0a68SSriram Yagnaraman                 for (i = 0; i < IGB_NUM_VM_POOLS; i++) {
11863c2e0a68SSriram Yagnaraman                     if ((queues & BIT(i)) &&
11873c2e0a68SSriram Yagnaraman                         (core->mac[VMOLR0 + i] & E1000_VMOLR_RSSE)) {
11883c2e0a68SSriram Yagnaraman                         queues |= BIT(i + IGB_NUM_VM_POOLS);
11893c2e0a68SSriram Yagnaraman                         queues &= ~BIT(i);
11903c2e0a68SSriram Yagnaraman                     }
11913c2e0a68SSriram Yagnaraman                 }
11923a977deeSAkihiko Odaki             }
11935f12d703SSriram Yagnaraman         }
11943a977deeSAkihiko Odaki     } else {
1195e9e5b930SAkihiko Odaki         bool accepted = e1000x_rx_group_filter(core->mac, ehdr);
11963a977deeSAkihiko Odaki         if (!accepted) {
11973a977deeSAkihiko Odaki             for (macp = core->mac + RA2; macp < core->mac + RA2 + 16; macp += 2) {
11983a977deeSAkihiko Odaki                 if (!(macp[1] & E1000_RAH_AV)) {
11993a977deeSAkihiko Odaki                     continue;
12003a977deeSAkihiko Odaki                 }
12013a977deeSAkihiko Odaki                 ra[0] = cpu_to_le32(macp[0]);
12023a977deeSAkihiko Odaki                 ra[1] = cpu_to_le32(macp[1]);
12033a977deeSAkihiko Odaki                 if (!memcmp(ehdr->h_dest, (uint8_t *)ra, ETH_ALEN)) {
12043a977deeSAkihiko Odaki                     trace_e1000x_rx_flt_ucast_match((int)(macp - core->mac - RA2) / 2,
12053a977deeSAkihiko Odaki                                                     MAC_ARG(ehdr->h_dest));
12063a977deeSAkihiko Odaki 
12073a977deeSAkihiko Odaki                     accepted = true;
12083a977deeSAkihiko Odaki                     break;
12093a977deeSAkihiko Odaki                 }
12103a977deeSAkihiko Odaki             }
12113a977deeSAkihiko Odaki         }
12123a977deeSAkihiko Odaki 
12133a977deeSAkihiko Odaki         if (accepted) {
12143a977deeSAkihiko Odaki             igb_rss_parse_packet(core, core->rx_pkt, false, rss_info);
12153a977deeSAkihiko Odaki             queues = BIT(rss_info->queue);
12163a977deeSAkihiko Odaki         }
12173a977deeSAkihiko Odaki     }
12183a977deeSAkihiko Odaki 
12193a977deeSAkihiko Odaki     return queues;
12203a977deeSAkihiko Odaki }
12213a977deeSAkihiko Odaki 
12223a977deeSAkihiko Odaki static inline void
igb_read_lgcy_rx_descr(IGBCore * core,struct e1000_rx_desc * desc,hwaddr * buff_addr)12233a977deeSAkihiko Odaki igb_read_lgcy_rx_descr(IGBCore *core, struct e1000_rx_desc *desc,
12243a977deeSAkihiko Odaki                        hwaddr *buff_addr)
12253a977deeSAkihiko Odaki {
12263a977deeSAkihiko Odaki     *buff_addr = le64_to_cpu(desc->buffer_addr);
12273a977deeSAkihiko Odaki }
12283a977deeSAkihiko Odaki 
12293a977deeSAkihiko Odaki static inline void
igb_read_adv_rx_single_buf_descr(IGBCore * core,union e1000_adv_rx_desc * desc,hwaddr * buff_addr)1230560cf339STomasz Dzieciol igb_read_adv_rx_single_buf_descr(IGBCore *core, union e1000_adv_rx_desc *desc,
12313a977deeSAkihiko Odaki                                  hwaddr *buff_addr)
12323a977deeSAkihiko Odaki {
12333a977deeSAkihiko Odaki     *buff_addr = le64_to_cpu(desc->read.pkt_addr);
12343a977deeSAkihiko Odaki }
12353a977deeSAkihiko Odaki 
1236560cf339STomasz Dzieciol static inline void
igb_read_adv_rx_split_buf_descr(IGBCore * core,union e1000_adv_rx_desc * desc,hwaddr * buff_addr)1237560cf339STomasz Dzieciol igb_read_adv_rx_split_buf_descr(IGBCore *core, union e1000_adv_rx_desc *desc,
1238560cf339STomasz Dzieciol                                 hwaddr *buff_addr)
1239560cf339STomasz Dzieciol {
1240560cf339STomasz Dzieciol     buff_addr[0] = le64_to_cpu(desc->read.hdr_addr);
1241560cf339STomasz Dzieciol     buff_addr[1] = le64_to_cpu(desc->read.pkt_addr);
1242560cf339STomasz Dzieciol }
1243560cf339STomasz Dzieciol 
1244560cf339STomasz Dzieciol typedef struct IGBBAState {
1245560cf339STomasz Dzieciol     uint16_t written[IGB_MAX_PS_BUFFERS];
1246560cf339STomasz Dzieciol     uint8_t cur_idx;
1247560cf339STomasz Dzieciol } IGBBAState;
1248560cf339STomasz Dzieciol 
1249560cf339STomasz Dzieciol typedef struct IGBSplitDescriptorData {
1250560cf339STomasz Dzieciol     bool sph;
1251560cf339STomasz Dzieciol     bool hbo;
1252560cf339STomasz Dzieciol     size_t hdr_len;
1253560cf339STomasz Dzieciol } IGBSplitDescriptorData;
1254560cf339STomasz Dzieciol 
125517ccd016STomasz Dzieciol typedef struct IGBPacketRxDMAState {
125617ccd016STomasz Dzieciol     size_t size;
125717ccd016STomasz Dzieciol     size_t total_size;
125817ccd016STomasz Dzieciol     size_t ps_hdr_len;
125917ccd016STomasz Dzieciol     size_t desc_size;
126017ccd016STomasz Dzieciol     size_t desc_offset;
126117ccd016STomasz Dzieciol     uint32_t rx_desc_packet_buf_size;
126217ccd016STomasz Dzieciol     uint32_t rx_desc_header_buf_size;
126317ccd016STomasz Dzieciol     struct iovec *iov;
126417ccd016STomasz Dzieciol     size_t iov_ofs;
1265560cf339STomasz Dzieciol     bool do_ps;
126617ccd016STomasz Dzieciol     bool is_first;
1267560cf339STomasz Dzieciol     IGBBAState bastate;
1268560cf339STomasz Dzieciol     hwaddr ba[IGB_MAX_PS_BUFFERS];
1269560cf339STomasz Dzieciol     IGBSplitDescriptorData ps_desc_data;
127017ccd016STomasz Dzieciol } IGBPacketRxDMAState;
127117ccd016STomasz Dzieciol 
12723a977deeSAkihiko Odaki static inline void
igb_read_rx_descr(IGBCore * core,union e1000_rx_desc_union * desc,IGBPacketRxDMAState * pdma_st,const E1000ERingInfo * r)1273560cf339STomasz Dzieciol igb_read_rx_descr(IGBCore *core,
1274560cf339STomasz Dzieciol                   union e1000_rx_desc_union *desc,
1275560cf339STomasz Dzieciol                   IGBPacketRxDMAState *pdma_st,
1276560cf339STomasz Dzieciol                   const E1000ERingInfo *r)
12773a977deeSAkihiko Odaki {
1278560cf339STomasz Dzieciol     uint32_t desc_type;
1279560cf339STomasz Dzieciol 
12803a977deeSAkihiko Odaki     if (igb_rx_use_legacy_descriptor(core)) {
1281560cf339STomasz Dzieciol         igb_read_lgcy_rx_descr(core, &desc->legacy, &pdma_st->ba[1]);
1282560cf339STomasz Dzieciol         pdma_st->ba[0] = 0;
1283560cf339STomasz Dzieciol         return;
12843a977deeSAkihiko Odaki     }
1285560cf339STomasz Dzieciol 
1286560cf339STomasz Dzieciol     /* advanced header split descriptor */
1287560cf339STomasz Dzieciol     if (igb_rx_use_ps_descriptor(core, r)) {
1288560cf339STomasz Dzieciol         igb_read_adv_rx_split_buf_descr(core, &desc->adv, &pdma_st->ba[0]);
1289560cf339STomasz Dzieciol         return;
1290560cf339STomasz Dzieciol     }
1291560cf339STomasz Dzieciol 
1292560cf339STomasz Dzieciol     /* descriptor replication modes not supported */
1293560cf339STomasz Dzieciol     desc_type = igb_rx_queue_desctyp_get(core, r);
1294560cf339STomasz Dzieciol     if (desc_type != E1000_SRRCTL_DESCTYPE_ADV_ONEBUF) {
1295560cf339STomasz Dzieciol         trace_igb_wrn_rx_desc_modes_not_supp(desc_type);
1296560cf339STomasz Dzieciol     }
1297560cf339STomasz Dzieciol 
1298560cf339STomasz Dzieciol     /* advanced single buffer descriptor */
1299560cf339STomasz Dzieciol     igb_read_adv_rx_single_buf_descr(core, &desc->adv, &pdma_st->ba[1]);
1300560cf339STomasz Dzieciol     pdma_st->ba[0] = 0;
13013a977deeSAkihiko Odaki }
13023a977deeSAkihiko Odaki 
13033a977deeSAkihiko Odaki static void
igb_verify_csum_in_sw(IGBCore * core,struct NetRxPkt * pkt,uint32_t * status_flags,EthL4HdrProto l4hdr_proto)13043a977deeSAkihiko Odaki igb_verify_csum_in_sw(IGBCore *core,
13053a977deeSAkihiko Odaki                       struct NetRxPkt *pkt,
13063a977deeSAkihiko Odaki                       uint32_t *status_flags,
13073a977deeSAkihiko Odaki                       EthL4HdrProto l4hdr_proto)
13083a977deeSAkihiko Odaki {
13093a977deeSAkihiko Odaki     bool csum_valid;
13103a977deeSAkihiko Odaki     uint32_t csum_error;
13113a977deeSAkihiko Odaki 
13123a977deeSAkihiko Odaki     if (igb_rx_l3_cso_enabled(core)) {
13133a977deeSAkihiko Odaki         if (!net_rx_pkt_validate_l3_csum(pkt, &csum_valid)) {
13143a977deeSAkihiko Odaki             trace_e1000e_rx_metadata_l3_csum_validation_failed();
13153a977deeSAkihiko Odaki         } else {
13163a977deeSAkihiko Odaki             csum_error = csum_valid ? 0 : E1000_RXDEXT_STATERR_IPE;
13173a977deeSAkihiko Odaki             *status_flags |= E1000_RXD_STAT_IPCS | csum_error;
13183a977deeSAkihiko Odaki         }
13193a977deeSAkihiko Odaki     } else {
13203a977deeSAkihiko Odaki         trace_e1000e_rx_metadata_l3_cso_disabled();
13213a977deeSAkihiko Odaki     }
13223a977deeSAkihiko Odaki 
13233a977deeSAkihiko Odaki     if (!igb_rx_l4_cso_enabled(core)) {
13243a977deeSAkihiko Odaki         trace_e1000e_rx_metadata_l4_cso_disabled();
13253a977deeSAkihiko Odaki         return;
13263a977deeSAkihiko Odaki     }
13273a977deeSAkihiko Odaki 
13283a977deeSAkihiko Odaki     if (!net_rx_pkt_validate_l4_csum(pkt, &csum_valid)) {
13293a977deeSAkihiko Odaki         trace_e1000e_rx_metadata_l4_csum_validation_failed();
13303a977deeSAkihiko Odaki         return;
13313a977deeSAkihiko Odaki     }
13323a977deeSAkihiko Odaki 
13333a977deeSAkihiko Odaki     csum_error = csum_valid ? 0 : E1000_RXDEXT_STATERR_TCPE;
13343a977deeSAkihiko Odaki     *status_flags |= E1000_RXD_STAT_TCPCS | csum_error;
13353a977deeSAkihiko Odaki 
13363a977deeSAkihiko Odaki     if (l4hdr_proto == ETH_L4_HDR_PROTO_UDP) {
13373a977deeSAkihiko Odaki         *status_flags |= E1000_RXD_STAT_UDPCS;
13383a977deeSAkihiko Odaki     }
13393a977deeSAkihiko Odaki }
13403a977deeSAkihiko Odaki 
13413a977deeSAkihiko Odaki static void
igb_build_rx_metadata_common(IGBCore * core,struct NetRxPkt * pkt,bool is_eop,uint32_t * status_flags,uint16_t * vlan_tag)1342ec82ad7cSTomasz Dzieciol igb_build_rx_metadata_common(IGBCore *core,
13433a977deeSAkihiko Odaki                              struct NetRxPkt *pkt,
13443a977deeSAkihiko Odaki                              bool is_eop,
13453a977deeSAkihiko Odaki                              uint32_t *status_flags,
13463a977deeSAkihiko Odaki                              uint16_t *vlan_tag)
13473a977deeSAkihiko Odaki {
13483a977deeSAkihiko Odaki     struct virtio_net_hdr *vhdr;
1349907209e3SAkihiko Odaki     bool hasip4, hasip6, csum_valid;
13503a977deeSAkihiko Odaki     EthL4HdrProto l4hdr_proto;
13513a977deeSAkihiko Odaki 
13523a977deeSAkihiko Odaki     *status_flags = E1000_RXD_STAT_DD;
13533a977deeSAkihiko Odaki 
13543a977deeSAkihiko Odaki     /* No additional metadata needed for non-EOP descriptors */
13553a977deeSAkihiko Odaki     if (!is_eop) {
13563a977deeSAkihiko Odaki         goto func_exit;
13573a977deeSAkihiko Odaki     }
13583a977deeSAkihiko Odaki 
13593a977deeSAkihiko Odaki     *status_flags |= E1000_RXD_STAT_EOP;
13603a977deeSAkihiko Odaki 
13613a977deeSAkihiko Odaki     net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
13623a977deeSAkihiko Odaki     trace_e1000e_rx_metadata_protocols(hasip4, hasip6, l4hdr_proto);
13633a977deeSAkihiko Odaki 
13643a977deeSAkihiko Odaki     /* VLAN state */
13653a977deeSAkihiko Odaki     if (net_rx_pkt_is_vlan_stripped(pkt)) {
13663a977deeSAkihiko Odaki         *status_flags |= E1000_RXD_STAT_VP;
13673a977deeSAkihiko Odaki         *vlan_tag = cpu_to_le16(net_rx_pkt_get_vlan_tag(pkt));
13683a977deeSAkihiko Odaki         trace_e1000e_rx_metadata_vlan(*vlan_tag);
13693a977deeSAkihiko Odaki     }
13703a977deeSAkihiko Odaki 
13713a977deeSAkihiko Odaki     /* RX CSO information */
13723a977deeSAkihiko Odaki     if (hasip6 && (core->mac[RFCTL] & E1000_RFCTL_IPV6_XSUM_DIS)) {
13733a977deeSAkihiko Odaki         trace_e1000e_rx_metadata_ipv6_sum_disabled();
13743a977deeSAkihiko Odaki         goto func_exit;
13753a977deeSAkihiko Odaki     }
13763a977deeSAkihiko Odaki 
13773a977deeSAkihiko Odaki     vhdr = net_rx_pkt_get_vhdr(pkt);
13783a977deeSAkihiko Odaki 
13793a977deeSAkihiko Odaki     if (!(vhdr->flags & VIRTIO_NET_HDR_F_DATA_VALID) &&
13803a977deeSAkihiko Odaki         !(vhdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM)) {
13813a977deeSAkihiko Odaki         trace_e1000e_rx_metadata_virthdr_no_csum_info();
13823a977deeSAkihiko Odaki         igb_verify_csum_in_sw(core, pkt, status_flags, l4hdr_proto);
13833a977deeSAkihiko Odaki         goto func_exit;
13843a977deeSAkihiko Odaki     }
13853a977deeSAkihiko Odaki 
13863a977deeSAkihiko Odaki     if (igb_rx_l3_cso_enabled(core)) {
13873a977deeSAkihiko Odaki         *status_flags |= hasip4 ? E1000_RXD_STAT_IPCS : 0;
13883a977deeSAkihiko Odaki     } else {
13893a977deeSAkihiko Odaki         trace_e1000e_rx_metadata_l3_cso_disabled();
13903a977deeSAkihiko Odaki     }
13913a977deeSAkihiko Odaki 
13923a977deeSAkihiko Odaki     if (igb_rx_l4_cso_enabled(core)) {
13933a977deeSAkihiko Odaki         switch (l4hdr_proto) {
1394907209e3SAkihiko Odaki         case ETH_L4_HDR_PROTO_SCTP:
1395907209e3SAkihiko Odaki             if (!net_rx_pkt_validate_l4_csum(pkt, &csum_valid)) {
1396907209e3SAkihiko Odaki                 trace_e1000e_rx_metadata_l4_csum_validation_failed();
1397907209e3SAkihiko Odaki                 goto func_exit;
1398907209e3SAkihiko Odaki             }
1399907209e3SAkihiko Odaki             if (!csum_valid) {
1400907209e3SAkihiko Odaki                 *status_flags |= E1000_RXDEXT_STATERR_TCPE;
1401907209e3SAkihiko Odaki             }
1402907209e3SAkihiko Odaki             /* fall through */
14033a977deeSAkihiko Odaki         case ETH_L4_HDR_PROTO_TCP:
14043a977deeSAkihiko Odaki             *status_flags |= E1000_RXD_STAT_TCPCS;
14053a977deeSAkihiko Odaki             break;
14063a977deeSAkihiko Odaki 
14073a977deeSAkihiko Odaki         case ETH_L4_HDR_PROTO_UDP:
14083a977deeSAkihiko Odaki             *status_flags |= E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS;
14093a977deeSAkihiko Odaki             break;
14103a977deeSAkihiko Odaki 
14113a977deeSAkihiko Odaki         default:
1412a09cc21eSAkihiko Odaki             break;
14133a977deeSAkihiko Odaki         }
14143a977deeSAkihiko Odaki     } else {
14153a977deeSAkihiko Odaki         trace_e1000e_rx_metadata_l4_cso_disabled();
14163a977deeSAkihiko Odaki     }
14173a977deeSAkihiko Odaki 
14183a977deeSAkihiko Odaki func_exit:
1419d5241351SAkihiko Odaki     trace_e1000e_rx_metadata_status_flags(*status_flags);
14203a977deeSAkihiko Odaki     *status_flags = cpu_to_le32(*status_flags);
14213a977deeSAkihiko Odaki }
14223a977deeSAkihiko Odaki 
14233a977deeSAkihiko Odaki static inline void
igb_write_lgcy_rx_descr(IGBCore * core,struct e1000_rx_desc * desc,struct NetRxPkt * pkt,const E1000E_RSSInfo * rss_info,uint16_t length)14243a977deeSAkihiko Odaki igb_write_lgcy_rx_descr(IGBCore *core, struct e1000_rx_desc *desc,
14253a977deeSAkihiko Odaki                         struct NetRxPkt *pkt,
1426ec82ad7cSTomasz Dzieciol                         const E1000E_RSSInfo *rss_info,
14273a977deeSAkihiko Odaki                         uint16_t length)
14283a977deeSAkihiko Odaki {
1429ec82ad7cSTomasz Dzieciol     uint32_t status_flags;
14303a977deeSAkihiko Odaki 
14313a977deeSAkihiko Odaki     assert(!rss_info->enabled);
14323a977deeSAkihiko Odaki 
1433ec82ad7cSTomasz Dzieciol     memset(desc, 0, sizeof(*desc));
1434ec82ad7cSTomasz Dzieciol     desc->length = cpu_to_le16(length);
1435ec82ad7cSTomasz Dzieciol     igb_build_rx_metadata_common(core, pkt, pkt != NULL,
1436ec82ad7cSTomasz Dzieciol                                  &status_flags,
14373a977deeSAkihiko Odaki                                  &desc->special);
1438ec82ad7cSTomasz Dzieciol 
14393a977deeSAkihiko Odaki     desc->errors = (uint8_t) (le32_to_cpu(status_flags) >> 24);
14403a977deeSAkihiko Odaki     desc->status = (uint8_t) le32_to_cpu(status_flags);
14413a977deeSAkihiko Odaki }
14423a977deeSAkihiko Odaki 
1443560cf339STomasz Dzieciol static bool
igb_rx_ps_descriptor_split_always(IGBCore * core,const E1000ERingInfo * r)1444560cf339STomasz Dzieciol igb_rx_ps_descriptor_split_always(IGBCore *core, const E1000ERingInfo *r)
1445560cf339STomasz Dzieciol {
1446560cf339STomasz Dzieciol     uint32_t desctyp = igb_rx_queue_desctyp_get(core, r);
1447560cf339STomasz Dzieciol     return desctyp == E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
1448560cf339STomasz Dzieciol }
1449560cf339STomasz Dzieciol 
1450ec82ad7cSTomasz Dzieciol static uint16_t
igb_rx_desc_get_packet_type(IGBCore * core,struct NetRxPkt * pkt,uint16_t etqf)1451ec82ad7cSTomasz Dzieciol igb_rx_desc_get_packet_type(IGBCore *core, struct NetRxPkt *pkt, uint16_t etqf)
1452ec82ad7cSTomasz Dzieciol {
1453ec82ad7cSTomasz Dzieciol     uint16_t pkt_type;
1454ec82ad7cSTomasz Dzieciol     bool hasip4, hasip6;
1455ec82ad7cSTomasz Dzieciol     EthL4HdrProto l4hdr_proto;
1456ec82ad7cSTomasz Dzieciol 
1457ec82ad7cSTomasz Dzieciol     if (etqf < 8) {
1458ec82ad7cSTomasz Dzieciol         pkt_type = BIT(11) | etqf;
1459ec82ad7cSTomasz Dzieciol         return pkt_type;
1460ec82ad7cSTomasz Dzieciol     }
1461ec82ad7cSTomasz Dzieciol 
1462ec82ad7cSTomasz Dzieciol     net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
1463ec82ad7cSTomasz Dzieciol 
1464ec82ad7cSTomasz Dzieciol     if (hasip6 && !(core->mac[RFCTL] & E1000_RFCTL_IPV6_DIS)) {
14651c4e67a5STomasz Dzieciol         eth_ip6_hdr_info *ip6hdr_info = net_rx_pkt_get_ip6_info(pkt);
14661c4e67a5STomasz Dzieciol         pkt_type = ip6hdr_info->has_ext_hdrs ? E1000_ADVRXD_PKT_IP6E :
14671c4e67a5STomasz Dzieciol                                                E1000_ADVRXD_PKT_IP6;
1468ec82ad7cSTomasz Dzieciol     } else if (hasip4) {
1469ec82ad7cSTomasz Dzieciol         pkt_type = E1000_ADVRXD_PKT_IP4;
1470ec82ad7cSTomasz Dzieciol     } else {
1471ec82ad7cSTomasz Dzieciol         pkt_type = 0;
1472ec82ad7cSTomasz Dzieciol     }
1473ec82ad7cSTomasz Dzieciol 
1474ec82ad7cSTomasz Dzieciol     switch (l4hdr_proto) {
1475ec82ad7cSTomasz Dzieciol     case ETH_L4_HDR_PROTO_TCP:
1476ec82ad7cSTomasz Dzieciol         pkt_type |= E1000_ADVRXD_PKT_TCP;
1477ec82ad7cSTomasz Dzieciol         break;
1478ec82ad7cSTomasz Dzieciol     case ETH_L4_HDR_PROTO_UDP:
1479ec82ad7cSTomasz Dzieciol         pkt_type |= E1000_ADVRXD_PKT_UDP;
1480ec82ad7cSTomasz Dzieciol         break;
1481ec82ad7cSTomasz Dzieciol     case ETH_L4_HDR_PROTO_SCTP:
1482ec82ad7cSTomasz Dzieciol         pkt_type |= E1000_ADVRXD_PKT_SCTP;
1483ec82ad7cSTomasz Dzieciol         break;
1484ec82ad7cSTomasz Dzieciol     default:
1485ec82ad7cSTomasz Dzieciol         break;
1486ec82ad7cSTomasz Dzieciol     }
1487ec82ad7cSTomasz Dzieciol 
1488ec82ad7cSTomasz Dzieciol     return pkt_type;
1489ec82ad7cSTomasz Dzieciol }
1490ec82ad7cSTomasz Dzieciol 
14913a977deeSAkihiko Odaki static inline void
igb_write_adv_rx_descr(IGBCore * core,union e1000_adv_rx_desc * desc,struct NetRxPkt * pkt,const E1000E_RSSInfo * rss_info,uint16_t etqf,bool ts,uint16_t length)14923a977deeSAkihiko Odaki igb_write_adv_rx_descr(IGBCore *core, union e1000_adv_rx_desc *desc,
14933a977deeSAkihiko Odaki                        struct NetRxPkt *pkt,
14943a9926d9SAkihiko Odaki                        const E1000E_RSSInfo *rss_info, uint16_t etqf, bool ts,
14953a977deeSAkihiko Odaki                        uint16_t length)
14963a977deeSAkihiko Odaki {
1497ec82ad7cSTomasz Dzieciol     bool hasip4, hasip6;
1498ec82ad7cSTomasz Dzieciol     EthL4HdrProto l4hdr_proto;
1499ec82ad7cSTomasz Dzieciol     uint16_t rss_type = 0, pkt_type;
1500ec82ad7cSTomasz Dzieciol     bool eop = (pkt != NULL);
1501ec82ad7cSTomasz Dzieciol     uint32_t adv_desc_status_error = 0;
15023a977deeSAkihiko Odaki     memset(&desc->wb, 0, sizeof(desc->wb));
15033a977deeSAkihiko Odaki 
15043a977deeSAkihiko Odaki     desc->wb.upper.length = cpu_to_le16(length);
1505ec82ad7cSTomasz Dzieciol     igb_build_rx_metadata_common(core, pkt, eop,
15063a977deeSAkihiko Odaki                                  &desc->wb.upper.status_error,
15073a977deeSAkihiko Odaki                                  &desc->wb.upper.vlan);
1508ec82ad7cSTomasz Dzieciol 
1509ec82ad7cSTomasz Dzieciol     if (!eop) {
1510ec82ad7cSTomasz Dzieciol         return;
1511ec82ad7cSTomasz Dzieciol     }
1512ec82ad7cSTomasz Dzieciol 
1513ec82ad7cSTomasz Dzieciol     net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
1514ec82ad7cSTomasz Dzieciol 
1515ec82ad7cSTomasz Dzieciol     if ((core->mac[RXCSUM] & E1000_RXCSUM_PCSD) != 0) {
1516ec82ad7cSTomasz Dzieciol         if (rss_info->enabled) {
1517ec82ad7cSTomasz Dzieciol             desc->wb.lower.hi_dword.rss = cpu_to_le32(rss_info->hash);
1518ec82ad7cSTomasz Dzieciol             rss_type = rss_info->type;
1519ec82ad7cSTomasz Dzieciol             trace_igb_rx_metadata_rss(desc->wb.lower.hi_dword.rss, rss_type);
1520ec82ad7cSTomasz Dzieciol         }
1521ec82ad7cSTomasz Dzieciol     } else if (hasip4) {
1522ec82ad7cSTomasz Dzieciol             adv_desc_status_error |= E1000_RXD_STAT_IPIDV;
1523ec82ad7cSTomasz Dzieciol             desc->wb.lower.hi_dword.csum_ip.ip_id =
1524ec82ad7cSTomasz Dzieciol                 cpu_to_le16(net_rx_pkt_get_ip_id(pkt));
1525ec82ad7cSTomasz Dzieciol             trace_e1000e_rx_metadata_ip_id(
1526ec82ad7cSTomasz Dzieciol                 desc->wb.lower.hi_dword.csum_ip.ip_id);
1527ec82ad7cSTomasz Dzieciol     }
1528ec82ad7cSTomasz Dzieciol 
1529ec82ad7cSTomasz Dzieciol     if (ts) {
1530ec82ad7cSTomasz Dzieciol         adv_desc_status_error |= BIT(16);
1531ec82ad7cSTomasz Dzieciol     }
1532ec82ad7cSTomasz Dzieciol 
1533ec82ad7cSTomasz Dzieciol     pkt_type = igb_rx_desc_get_packet_type(core, pkt, etqf);
1534ec82ad7cSTomasz Dzieciol     trace_e1000e_rx_metadata_pkt_type(pkt_type);
1535ec82ad7cSTomasz Dzieciol     desc->wb.lower.lo_dword.pkt_info = cpu_to_le16(rss_type | (pkt_type << 4));
1536ec82ad7cSTomasz Dzieciol     desc->wb.upper.status_error |= cpu_to_le32(adv_desc_status_error);
15373a977deeSAkihiko Odaki }
15383a977deeSAkihiko Odaki 
15393a977deeSAkihiko Odaki static inline void
igb_write_adv_ps_rx_descr(IGBCore * core,union e1000_adv_rx_desc * desc,struct NetRxPkt * pkt,const E1000E_RSSInfo * rss_info,const E1000ERingInfo * r,uint16_t etqf,bool ts,IGBPacketRxDMAState * pdma_st)1540560cf339STomasz Dzieciol igb_write_adv_ps_rx_descr(IGBCore *core,
1541560cf339STomasz Dzieciol                           union e1000_adv_rx_desc *desc,
1542560cf339STomasz Dzieciol                           struct NetRxPkt *pkt,
1543560cf339STomasz Dzieciol                           const E1000E_RSSInfo *rss_info,
1544560cf339STomasz Dzieciol                           const E1000ERingInfo *r,
1545560cf339STomasz Dzieciol                           uint16_t etqf,
1546560cf339STomasz Dzieciol                           bool ts,
1547560cf339STomasz Dzieciol                           IGBPacketRxDMAState *pdma_st)
1548560cf339STomasz Dzieciol {
1549560cf339STomasz Dzieciol     size_t pkt_len;
1550560cf339STomasz Dzieciol     uint16_t hdr_info = 0;
1551560cf339STomasz Dzieciol 
1552560cf339STomasz Dzieciol     if (pdma_st->do_ps) {
1553560cf339STomasz Dzieciol         pkt_len = pdma_st->bastate.written[1];
1554560cf339STomasz Dzieciol     } else {
1555560cf339STomasz Dzieciol         pkt_len = pdma_st->bastate.written[0] + pdma_st->bastate.written[1];
1556560cf339STomasz Dzieciol     }
1557560cf339STomasz Dzieciol 
1558560cf339STomasz Dzieciol     igb_write_adv_rx_descr(core, desc, pkt, rss_info, etqf, ts, pkt_len);
1559560cf339STomasz Dzieciol 
1560560cf339STomasz Dzieciol     hdr_info = (pdma_st->ps_desc_data.hdr_len << E1000_ADVRXD_HDR_LEN_OFFSET) &
1561560cf339STomasz Dzieciol                E1000_ADVRXD_ADV_HDR_LEN_MASK;
1562560cf339STomasz Dzieciol     hdr_info |= pdma_st->ps_desc_data.sph ? E1000_ADVRXD_HDR_SPH : 0;
1563560cf339STomasz Dzieciol     desc->wb.lower.lo_dword.hdr_info = cpu_to_le16(hdr_info);
1564560cf339STomasz Dzieciol 
1565560cf339STomasz Dzieciol     desc->wb.upper.status_error |= cpu_to_le32(
1566560cf339STomasz Dzieciol         pdma_st->ps_desc_data.hbo ? E1000_ADVRXD_ST_ERR_HBO_OFFSET : 0);
1567560cf339STomasz Dzieciol }
1568560cf339STomasz Dzieciol 
1569560cf339STomasz Dzieciol static inline void
igb_write_rx_descr(IGBCore * core,union e1000_rx_desc_union * desc,struct NetRxPkt * pkt,const E1000E_RSSInfo * rss_info,uint16_t etqf,bool ts,IGBPacketRxDMAState * pdma_st,const E1000ERingInfo * r)1570560cf339STomasz Dzieciol igb_write_rx_descr(IGBCore *core,
1571560cf339STomasz Dzieciol                    union e1000_rx_desc_union *desc,
1572560cf339STomasz Dzieciol                    struct NetRxPkt *pkt,
1573560cf339STomasz Dzieciol                    const E1000E_RSSInfo *rss_info,
1574560cf339STomasz Dzieciol                    uint16_t etqf,
1575560cf339STomasz Dzieciol                    bool ts,
1576560cf339STomasz Dzieciol                    IGBPacketRxDMAState *pdma_st,
1577560cf339STomasz Dzieciol                    const E1000ERingInfo *r)
15783a977deeSAkihiko Odaki {
15793a977deeSAkihiko Odaki     if (igb_rx_use_legacy_descriptor(core)) {
1580560cf339STomasz Dzieciol         igb_write_lgcy_rx_descr(core, &desc->legacy, pkt, rss_info,
1581560cf339STomasz Dzieciol                                 pdma_st->bastate.written[1]);
1582560cf339STomasz Dzieciol     } else if (igb_rx_use_ps_descriptor(core, r)) {
1583560cf339STomasz Dzieciol         igb_write_adv_ps_rx_descr(core, &desc->adv, pkt, rss_info, r, etqf, ts,
1584560cf339STomasz Dzieciol                                   pdma_st);
15853a977deeSAkihiko Odaki     } else {
15863a9926d9SAkihiko Odaki         igb_write_adv_rx_descr(core, &desc->adv, pkt, rss_info,
1587560cf339STomasz Dzieciol                                etqf, ts, pdma_st->bastate.written[1]);
15883a977deeSAkihiko Odaki     }
15893a977deeSAkihiko Odaki }
15903a977deeSAkihiko Odaki 
15913a977deeSAkihiko Odaki static inline void
igb_pci_dma_write_rx_desc(IGBCore * core,PCIDevice * dev,dma_addr_t addr,union e1000_rx_desc_union * desc,dma_addr_t len)15923a977deeSAkihiko Odaki igb_pci_dma_write_rx_desc(IGBCore *core, PCIDevice *dev, dma_addr_t addr,
15933a977deeSAkihiko Odaki                           union e1000_rx_desc_union *desc, dma_addr_t len)
15943a977deeSAkihiko Odaki {
15953a977deeSAkihiko Odaki     if (igb_rx_use_legacy_descriptor(core)) {
15963a977deeSAkihiko Odaki         struct e1000_rx_desc *d = &desc->legacy;
15973a977deeSAkihiko Odaki         size_t offset = offsetof(struct e1000_rx_desc, status);
15983a977deeSAkihiko Odaki         uint8_t status = d->status;
15993a977deeSAkihiko Odaki 
16003a977deeSAkihiko Odaki         d->status &= ~E1000_RXD_STAT_DD;
16013a977deeSAkihiko Odaki         pci_dma_write(dev, addr, desc, len);
16023a977deeSAkihiko Odaki 
16033a977deeSAkihiko Odaki         if (status & E1000_RXD_STAT_DD) {
16043a977deeSAkihiko Odaki             d->status = status;
16053a977deeSAkihiko Odaki             pci_dma_write(dev, addr + offset, &status, sizeof(status));
16063a977deeSAkihiko Odaki         }
16073a977deeSAkihiko Odaki     } else {
16083a977deeSAkihiko Odaki         union e1000_adv_rx_desc *d = &desc->adv;
16093a977deeSAkihiko Odaki         size_t offset =
16103a977deeSAkihiko Odaki             offsetof(union e1000_adv_rx_desc, wb.upper.status_error);
16113a977deeSAkihiko Odaki         uint32_t status = d->wb.upper.status_error;
16123a977deeSAkihiko Odaki 
16133a977deeSAkihiko Odaki         d->wb.upper.status_error &= ~E1000_RXD_STAT_DD;
16143a977deeSAkihiko Odaki         pci_dma_write(dev, addr, desc, len);
16153a977deeSAkihiko Odaki 
16163a977deeSAkihiko Odaki         if (status & E1000_RXD_STAT_DD) {
16173a977deeSAkihiko Odaki             d->wb.upper.status_error = status;
16183a977deeSAkihiko Odaki             pci_dma_write(dev, addr + offset, &status, sizeof(status));
16193a977deeSAkihiko Odaki         }
16203a977deeSAkihiko Odaki     }
16213a977deeSAkihiko Odaki }
16223a977deeSAkihiko Odaki 
16233a977deeSAkihiko Odaki static void
igb_update_rx_stats(IGBCore * core,const E1000ERingInfo * rxi,size_t pkt_size,size_t pkt_fcs_size)1624a86aee7eSTomasz Dzieciol igb_update_rx_stats(IGBCore *core, const E1000ERingInfo *rxi,
1625f3f9b726SAkihiko Odaki                     size_t pkt_size, size_t pkt_fcs_size)
16263a977deeSAkihiko Odaki {
1627f3f9b726SAkihiko Odaki     eth_pkt_types_e pkt_type = net_rx_pkt_get_packet_type(core->rx_pkt);
1628f3f9b726SAkihiko Odaki     e1000x_update_rx_total_stats(core->mac, pkt_type, pkt_size, pkt_fcs_size);
16297581baedSSriram Yagnaraman 
16307581baedSSriram Yagnaraman     if (core->mac[MRQC] & 1) {
16317581baedSSriram Yagnaraman         uint16_t pool = rxi->idx % IGB_NUM_VM_POOLS;
16327581baedSSriram Yagnaraman 
1633f3f9b726SAkihiko Odaki         core->mac[PVFGORC0 + (pool * 64)] += pkt_size + 4;
16347581baedSSriram Yagnaraman         core->mac[PVFGPRC0 + (pool * 64)]++;
1635f3f9b726SAkihiko Odaki         if (pkt_type == ETH_PKT_MCAST) {
16367581baedSSriram Yagnaraman             core->mac[PVFMPRC0 + (pool * 64)]++;
16377581baedSSriram Yagnaraman         }
16387581baedSSriram Yagnaraman     }
16393a977deeSAkihiko Odaki }
16403a977deeSAkihiko Odaki 
16413a977deeSAkihiko Odaki static inline bool
igb_rx_descr_threshold_hit(IGBCore * core,const E1000ERingInfo * rxi)1642a86aee7eSTomasz Dzieciol igb_rx_descr_threshold_hit(IGBCore *core, const E1000ERingInfo *rxi)
16433a977deeSAkihiko Odaki {
16443a977deeSAkihiko Odaki     return igb_ring_free_descr_num(core, rxi) ==
16453a977deeSAkihiko Odaki            ((core->mac[E1000_SRRCTL(rxi->idx) >> 2] >> 20) & 31) * 16;
16463a977deeSAkihiko Odaki }
16473a977deeSAkihiko Odaki 
1648560cf339STomasz Dzieciol static bool
igb_do_ps(IGBCore * core,const E1000ERingInfo * r,struct NetRxPkt * pkt,IGBPacketRxDMAState * pdma_st)1649560cf339STomasz Dzieciol igb_do_ps(IGBCore *core,
1650560cf339STomasz Dzieciol           const E1000ERingInfo *r,
1651560cf339STomasz Dzieciol           struct NetRxPkt *pkt,
1652560cf339STomasz Dzieciol           IGBPacketRxDMAState *pdma_st)
1653560cf339STomasz Dzieciol {
1654560cf339STomasz Dzieciol     bool hasip4, hasip6;
1655560cf339STomasz Dzieciol     EthL4HdrProto l4hdr_proto;
1656560cf339STomasz Dzieciol     bool fragment;
1657560cf339STomasz Dzieciol     bool split_always;
1658560cf339STomasz Dzieciol     size_t bheader_size;
1659560cf339STomasz Dzieciol     size_t total_pkt_len;
1660560cf339STomasz Dzieciol 
1661560cf339STomasz Dzieciol     if (!igb_rx_use_ps_descriptor(core, r)) {
1662560cf339STomasz Dzieciol         return false;
1663560cf339STomasz Dzieciol     }
1664560cf339STomasz Dzieciol 
1665560cf339STomasz Dzieciol     total_pkt_len = net_rx_pkt_get_total_len(pkt);
1666560cf339STomasz Dzieciol     bheader_size = igb_rxhdrbufsize(core, r);
1667560cf339STomasz Dzieciol     split_always = igb_rx_ps_descriptor_split_always(core, r);
1668560cf339STomasz Dzieciol     if (split_always && total_pkt_len <= bheader_size) {
1669560cf339STomasz Dzieciol         pdma_st->ps_hdr_len = total_pkt_len;
1670560cf339STomasz Dzieciol         pdma_st->ps_desc_data.hdr_len = total_pkt_len;
1671560cf339STomasz Dzieciol         return true;
1672560cf339STomasz Dzieciol     }
1673560cf339STomasz Dzieciol 
1674560cf339STomasz Dzieciol     net_rx_pkt_get_protocols(pkt, &hasip4, &hasip6, &l4hdr_proto);
1675560cf339STomasz Dzieciol 
1676560cf339STomasz Dzieciol     if (hasip4) {
1677560cf339STomasz Dzieciol         fragment = net_rx_pkt_get_ip4_info(pkt)->fragment;
1678560cf339STomasz Dzieciol     } else if (hasip6) {
1679560cf339STomasz Dzieciol         fragment = net_rx_pkt_get_ip6_info(pkt)->fragment;
1680560cf339STomasz Dzieciol     } else {
1681560cf339STomasz Dzieciol         pdma_st->ps_desc_data.hdr_len = bheader_size;
1682560cf339STomasz Dzieciol         goto header_not_handled;
1683560cf339STomasz Dzieciol     }
1684560cf339STomasz Dzieciol 
1685560cf339STomasz Dzieciol     if (fragment && (core->mac[RFCTL] & E1000_RFCTL_IPFRSP_DIS)) {
1686560cf339STomasz Dzieciol         pdma_st->ps_desc_data.hdr_len = bheader_size;
1687560cf339STomasz Dzieciol         goto header_not_handled;
1688560cf339STomasz Dzieciol     }
1689560cf339STomasz Dzieciol 
1690560cf339STomasz Dzieciol     /* no header splitting for SCTP */
1691560cf339STomasz Dzieciol     if (!fragment && (l4hdr_proto == ETH_L4_HDR_PROTO_UDP ||
1692560cf339STomasz Dzieciol                       l4hdr_proto == ETH_L4_HDR_PROTO_TCP)) {
1693560cf339STomasz Dzieciol         pdma_st->ps_hdr_len = net_rx_pkt_get_l5_hdr_offset(pkt);
1694560cf339STomasz Dzieciol     } else {
1695560cf339STomasz Dzieciol         pdma_st->ps_hdr_len = net_rx_pkt_get_l4_hdr_offset(pkt);
1696560cf339STomasz Dzieciol     }
1697560cf339STomasz Dzieciol 
1698560cf339STomasz Dzieciol     pdma_st->ps_desc_data.sph = true;
1699560cf339STomasz Dzieciol     pdma_st->ps_desc_data.hdr_len = pdma_st->ps_hdr_len;
1700560cf339STomasz Dzieciol 
1701560cf339STomasz Dzieciol     if (pdma_st->ps_hdr_len > bheader_size) {
1702560cf339STomasz Dzieciol         pdma_st->ps_desc_data.hbo = true;
1703560cf339STomasz Dzieciol         goto header_not_handled;
1704560cf339STomasz Dzieciol     }
1705560cf339STomasz Dzieciol 
1706560cf339STomasz Dzieciol     return true;
1707560cf339STomasz Dzieciol 
1708560cf339STomasz Dzieciol header_not_handled:
1709560cf339STomasz Dzieciol     if (split_always) {
1710560cf339STomasz Dzieciol         pdma_st->ps_hdr_len = bheader_size;
1711560cf339STomasz Dzieciol         return true;
1712560cf339STomasz Dzieciol     }
1713560cf339STomasz Dzieciol 
1714560cf339STomasz Dzieciol     return false;
1715560cf339STomasz Dzieciol }
1716560cf339STomasz Dzieciol 
17173a977deeSAkihiko Odaki static void
igb_truncate_to_descriptor_size(IGBPacketRxDMAState * pdma_st,size_t * size)171817ccd016STomasz Dzieciol igb_truncate_to_descriptor_size(IGBPacketRxDMAState *pdma_st, size_t *size)
171917ccd016STomasz Dzieciol {
1720560cf339STomasz Dzieciol     if (pdma_st->do_ps && pdma_st->is_first) {
1721560cf339STomasz Dzieciol         if (*size > pdma_st->rx_desc_packet_buf_size + pdma_st->ps_hdr_len) {
1722560cf339STomasz Dzieciol             *size = pdma_st->rx_desc_packet_buf_size + pdma_st->ps_hdr_len;
1723560cf339STomasz Dzieciol         }
1724560cf339STomasz Dzieciol     } else {
172517ccd016STomasz Dzieciol         if (*size > pdma_st->rx_desc_packet_buf_size) {
172617ccd016STomasz Dzieciol             *size = pdma_st->rx_desc_packet_buf_size;
172717ccd016STomasz Dzieciol         }
172817ccd016STomasz Dzieciol     }
1729560cf339STomasz Dzieciol }
1730560cf339STomasz Dzieciol 
1731560cf339STomasz Dzieciol static inline void
igb_write_hdr_frag_to_rx_buffers(IGBCore * core,PCIDevice * d,IGBPacketRxDMAState * pdma_st,const char * data,dma_addr_t data_len)1732560cf339STomasz Dzieciol igb_write_hdr_frag_to_rx_buffers(IGBCore *core,
1733560cf339STomasz Dzieciol                                  PCIDevice *d,
1734560cf339STomasz Dzieciol                                  IGBPacketRxDMAState *pdma_st,
1735560cf339STomasz Dzieciol                                  const char *data,
1736560cf339STomasz Dzieciol                                  dma_addr_t data_len)
1737560cf339STomasz Dzieciol {
1738560cf339STomasz Dzieciol     assert(data_len <= pdma_st->rx_desc_header_buf_size -
1739560cf339STomasz Dzieciol                        pdma_st->bastate.written[0]);
1740560cf339STomasz Dzieciol     pci_dma_write(d,
1741560cf339STomasz Dzieciol                   pdma_st->ba[0] + pdma_st->bastate.written[0],
1742560cf339STomasz Dzieciol                   data, data_len);
1743560cf339STomasz Dzieciol     pdma_st->bastate.written[0] += data_len;
1744560cf339STomasz Dzieciol     pdma_st->bastate.cur_idx = 1;
1745560cf339STomasz Dzieciol }
1746560cf339STomasz Dzieciol 
1747560cf339STomasz Dzieciol static void
igb_write_header_to_rx_buffers(IGBCore * core,struct NetRxPkt * pkt,PCIDevice * d,IGBPacketRxDMAState * pdma_st,size_t * copy_size)1748560cf339STomasz Dzieciol igb_write_header_to_rx_buffers(IGBCore *core,
1749560cf339STomasz Dzieciol                                struct NetRxPkt *pkt,
1750560cf339STomasz Dzieciol                                PCIDevice *d,
1751560cf339STomasz Dzieciol                                IGBPacketRxDMAState *pdma_st,
1752560cf339STomasz Dzieciol                                size_t *copy_size)
1753560cf339STomasz Dzieciol {
1754560cf339STomasz Dzieciol     size_t iov_copy;
1755560cf339STomasz Dzieciol     size_t ps_hdr_copied = 0;
1756560cf339STomasz Dzieciol 
1757560cf339STomasz Dzieciol     if (!pdma_st->is_first) {
1758560cf339STomasz Dzieciol         /* Leave buffer 0 of each descriptor except first */
1759560cf339STomasz Dzieciol         /* empty                                          */
1760560cf339STomasz Dzieciol         pdma_st->bastate.cur_idx = 1;
1761560cf339STomasz Dzieciol         return;
1762560cf339STomasz Dzieciol     }
1763560cf339STomasz Dzieciol 
1764560cf339STomasz Dzieciol     do {
1765560cf339STomasz Dzieciol         iov_copy = MIN(pdma_st->ps_hdr_len - ps_hdr_copied,
1766560cf339STomasz Dzieciol                        pdma_st->iov->iov_len - pdma_st->iov_ofs);
1767560cf339STomasz Dzieciol 
1768560cf339STomasz Dzieciol         igb_write_hdr_frag_to_rx_buffers(core, d, pdma_st,
1769560cf339STomasz Dzieciol                                          pdma_st->iov->iov_base,
1770560cf339STomasz Dzieciol                                          iov_copy);
1771560cf339STomasz Dzieciol 
1772560cf339STomasz Dzieciol         *copy_size -= iov_copy;
1773560cf339STomasz Dzieciol         ps_hdr_copied += iov_copy;
1774560cf339STomasz Dzieciol 
1775560cf339STomasz Dzieciol         pdma_st->iov_ofs += iov_copy;
1776560cf339STomasz Dzieciol         if (pdma_st->iov_ofs == pdma_st->iov->iov_len) {
1777560cf339STomasz Dzieciol             pdma_st->iov++;
1778560cf339STomasz Dzieciol             pdma_st->iov_ofs = 0;
1779560cf339STomasz Dzieciol         }
1780560cf339STomasz Dzieciol     } while (ps_hdr_copied < pdma_st->ps_hdr_len);
1781560cf339STomasz Dzieciol 
1782560cf339STomasz Dzieciol     pdma_st->is_first = false;
1783560cf339STomasz Dzieciol }
178417ccd016STomasz Dzieciol 
178517ccd016STomasz Dzieciol static void
igb_write_payload_frag_to_rx_buffers(IGBCore * core,PCIDevice * d,IGBPacketRxDMAState * pdma_st,const char * data,dma_addr_t data_len)178617ccd016STomasz Dzieciol igb_write_payload_frag_to_rx_buffers(IGBCore *core,
178717ccd016STomasz Dzieciol                                      PCIDevice *d,
1788560cf339STomasz Dzieciol                                      IGBPacketRxDMAState *pdma_st,
178917ccd016STomasz Dzieciol                                      const char *data,
179017ccd016STomasz Dzieciol                                      dma_addr_t data_len)
179117ccd016STomasz Dzieciol {
1792560cf339STomasz Dzieciol     while (data_len > 0) {
1793560cf339STomasz Dzieciol         assert(pdma_st->bastate.cur_idx < IGB_MAX_PS_BUFFERS);
1794560cf339STomasz Dzieciol 
1795560cf339STomasz Dzieciol         uint32_t cur_buf_bytes_left =
1796560cf339STomasz Dzieciol             pdma_st->rx_desc_packet_buf_size -
1797560cf339STomasz Dzieciol             pdma_st->bastate.written[pdma_st->bastate.cur_idx];
1798560cf339STomasz Dzieciol         uint32_t bytes_to_write = MIN(data_len, cur_buf_bytes_left);
1799560cf339STomasz Dzieciol 
1800560cf339STomasz Dzieciol         trace_igb_rx_desc_buff_write(
1801560cf339STomasz Dzieciol             pdma_st->bastate.cur_idx,
1802560cf339STomasz Dzieciol             pdma_st->ba[pdma_st->bastate.cur_idx],
1803560cf339STomasz Dzieciol             pdma_st->bastate.written[pdma_st->bastate.cur_idx],
1804560cf339STomasz Dzieciol             data,
1805560cf339STomasz Dzieciol             bytes_to_write);
1806560cf339STomasz Dzieciol 
1807560cf339STomasz Dzieciol         pci_dma_write(d,
1808560cf339STomasz Dzieciol                       pdma_st->ba[pdma_st->bastate.cur_idx] +
1809560cf339STomasz Dzieciol                       pdma_st->bastate.written[pdma_st->bastate.cur_idx],
1810560cf339STomasz Dzieciol                       data, bytes_to_write);
1811560cf339STomasz Dzieciol 
1812560cf339STomasz Dzieciol         pdma_st->bastate.written[pdma_st->bastate.cur_idx] += bytes_to_write;
1813560cf339STomasz Dzieciol         data += bytes_to_write;
1814560cf339STomasz Dzieciol         data_len -= bytes_to_write;
1815560cf339STomasz Dzieciol 
1816560cf339STomasz Dzieciol         if (pdma_st->bastate.written[pdma_st->bastate.cur_idx] ==
1817560cf339STomasz Dzieciol             pdma_st->rx_desc_packet_buf_size) {
1818560cf339STomasz Dzieciol             pdma_st->bastate.cur_idx++;
1819560cf339STomasz Dzieciol         }
1820560cf339STomasz Dzieciol     }
182117ccd016STomasz Dzieciol }
182217ccd016STomasz Dzieciol 
182317ccd016STomasz Dzieciol static void
igb_write_payload_to_rx_buffers(IGBCore * core,struct NetRxPkt * pkt,PCIDevice * d,IGBPacketRxDMAState * pdma_st,size_t * copy_size)182417ccd016STomasz Dzieciol igb_write_payload_to_rx_buffers(IGBCore *core,
182517ccd016STomasz Dzieciol                                 struct NetRxPkt *pkt,
182617ccd016STomasz Dzieciol                                 PCIDevice *d,
182717ccd016STomasz Dzieciol                                 IGBPacketRxDMAState *pdma_st,
182817ccd016STomasz Dzieciol                                 size_t *copy_size)
182917ccd016STomasz Dzieciol {
183017ccd016STomasz Dzieciol     static const uint32_t fcs_pad;
183117ccd016STomasz Dzieciol     size_t iov_copy;
183217ccd016STomasz Dzieciol 
183317ccd016STomasz Dzieciol     /* Copy packet payload */
183417ccd016STomasz Dzieciol     while (*copy_size) {
183517ccd016STomasz Dzieciol         iov_copy = MIN(*copy_size, pdma_st->iov->iov_len - pdma_st->iov_ofs);
183617ccd016STomasz Dzieciol         igb_write_payload_frag_to_rx_buffers(core, d,
1837560cf339STomasz Dzieciol                                              pdma_st,
183817ccd016STomasz Dzieciol                                              pdma_st->iov->iov_base +
183917ccd016STomasz Dzieciol                                              pdma_st->iov_ofs,
184017ccd016STomasz Dzieciol                                              iov_copy);
184117ccd016STomasz Dzieciol 
184217ccd016STomasz Dzieciol         *copy_size -= iov_copy;
184317ccd016STomasz Dzieciol         pdma_st->iov_ofs += iov_copy;
184417ccd016STomasz Dzieciol         if (pdma_st->iov_ofs == pdma_st->iov->iov_len) {
184517ccd016STomasz Dzieciol             pdma_st->iov++;
184617ccd016STomasz Dzieciol             pdma_st->iov_ofs = 0;
184717ccd016STomasz Dzieciol         }
184817ccd016STomasz Dzieciol     }
184917ccd016STomasz Dzieciol 
185017ccd016STomasz Dzieciol     if (pdma_st->desc_offset + pdma_st->desc_size >= pdma_st->total_size) {
185117ccd016STomasz Dzieciol         /* Simulate FCS checksum presence in the last descriptor */
185217ccd016STomasz Dzieciol         igb_write_payload_frag_to_rx_buffers(core, d,
1853560cf339STomasz Dzieciol                                              pdma_st,
185417ccd016STomasz Dzieciol                                              (const char *) &fcs_pad,
185517ccd016STomasz Dzieciol                                              e1000x_fcs_len(core->mac));
185617ccd016STomasz Dzieciol     }
185717ccd016STomasz Dzieciol }
185817ccd016STomasz Dzieciol 
185917ccd016STomasz Dzieciol static void
igb_write_to_rx_buffers(IGBCore * core,struct NetRxPkt * pkt,PCIDevice * d,IGBPacketRxDMAState * pdma_st)186017ccd016STomasz Dzieciol igb_write_to_rx_buffers(IGBCore *core,
186117ccd016STomasz Dzieciol                         struct NetRxPkt *pkt,
186217ccd016STomasz Dzieciol                         PCIDevice *d,
186317ccd016STomasz Dzieciol                         IGBPacketRxDMAState *pdma_st)
186417ccd016STomasz Dzieciol {
186517ccd016STomasz Dzieciol     size_t copy_size;
186617ccd016STomasz Dzieciol 
1867560cf339STomasz Dzieciol     if (!(pdma_st->ba)[1] || (pdma_st->do_ps && !(pdma_st->ba[0]))) {
186817ccd016STomasz Dzieciol         /* as per intel docs; skip descriptors with null buf addr */
186917ccd016STomasz Dzieciol         trace_e1000e_rx_null_descriptor();
187017ccd016STomasz Dzieciol         return;
187117ccd016STomasz Dzieciol     }
187217ccd016STomasz Dzieciol 
187317ccd016STomasz Dzieciol     if (pdma_st->desc_offset >= pdma_st->size) {
187417ccd016STomasz Dzieciol         return;
187517ccd016STomasz Dzieciol     }
187617ccd016STomasz Dzieciol 
187717ccd016STomasz Dzieciol     pdma_st->desc_size = pdma_st->total_size - pdma_st->desc_offset;
187817ccd016STomasz Dzieciol     igb_truncate_to_descriptor_size(pdma_st, &pdma_st->desc_size);
187917ccd016STomasz Dzieciol     copy_size = pdma_st->size - pdma_st->desc_offset;
188017ccd016STomasz Dzieciol     igb_truncate_to_descriptor_size(pdma_st, &copy_size);
1881560cf339STomasz Dzieciol 
1882560cf339STomasz Dzieciol     /* For PS mode copy the packet header first */
1883560cf339STomasz Dzieciol     if (pdma_st->do_ps) {
1884560cf339STomasz Dzieciol         igb_write_header_to_rx_buffers(core, pkt, d, pdma_st, &copy_size);
1885560cf339STomasz Dzieciol     } else {
1886560cf339STomasz Dzieciol         pdma_st->bastate.cur_idx = 1;
1887560cf339STomasz Dzieciol     }
1888560cf339STomasz Dzieciol 
188917ccd016STomasz Dzieciol     igb_write_payload_to_rx_buffers(core, pkt, d, pdma_st, &copy_size);
189017ccd016STomasz Dzieciol }
189117ccd016STomasz Dzieciol 
189217ccd016STomasz Dzieciol static void
igb_write_packet_to_guest(IGBCore * core,struct NetRxPkt * pkt,const E1000E_RxRing * rxr,const E1000E_RSSInfo * rss_info,uint16_t etqf,bool ts)18933a977deeSAkihiko Odaki igb_write_packet_to_guest(IGBCore *core, struct NetRxPkt *pkt,
18943a977deeSAkihiko Odaki                           const E1000E_RxRing *rxr,
18953a9926d9SAkihiko Odaki                           const E1000E_RSSInfo *rss_info,
18963a9926d9SAkihiko Odaki                           uint16_t etqf, bool ts)
18973a977deeSAkihiko Odaki {
18983a977deeSAkihiko Odaki     PCIDevice *d;
18993a977deeSAkihiko Odaki     dma_addr_t base;
19003a977deeSAkihiko Odaki     union e1000_rx_desc_union desc;
190117ccd016STomasz Dzieciol     const E1000ERingInfo *rxi;
190217ccd016STomasz Dzieciol     size_t rx_desc_len;
19033a977deeSAkihiko Odaki 
190417ccd016STomasz Dzieciol     IGBPacketRxDMAState pdma_st = {0};
190517ccd016STomasz Dzieciol     pdma_st.is_first = true;
190617ccd016STomasz Dzieciol     pdma_st.size = net_rx_pkt_get_total_len(pkt);
190717ccd016STomasz Dzieciol     pdma_st.total_size = pdma_st.size + e1000x_fcs_len(core->mac);
19083a977deeSAkihiko Odaki 
190917ccd016STomasz Dzieciol     rxi = rxr->i;
191017ccd016STomasz Dzieciol     rx_desc_len = core->rx_desc_len;
191117ccd016STomasz Dzieciol     pdma_st.rx_desc_packet_buf_size = igb_rxbufsize(core, rxi);
191217ccd016STomasz Dzieciol     pdma_st.rx_desc_header_buf_size = igb_rxhdrbufsize(core, rxi);
191317ccd016STomasz Dzieciol     pdma_st.iov = net_rx_pkt_get_iovec(pkt);
19143a977deeSAkihiko Odaki     d = pcie_sriov_get_vf_at_index(core->owner, rxi->idx % 8);
19153a977deeSAkihiko Odaki     if (!d) {
19163a977deeSAkihiko Odaki         d = core->owner;
19173a977deeSAkihiko Odaki     }
19183a977deeSAkihiko Odaki 
1919560cf339STomasz Dzieciol     pdma_st.do_ps = igb_do_ps(core, rxi, pkt, &pdma_st);
1920560cf339STomasz Dzieciol 
19213a977deeSAkihiko Odaki     do {
1922560cf339STomasz Dzieciol         memset(&pdma_st.bastate, 0, sizeof(IGBBAState));
19233a977deeSAkihiko Odaki         bool is_last = false;
19243a977deeSAkihiko Odaki 
19253a977deeSAkihiko Odaki         if (igb_ring_empty(core, rxi)) {
19263a977deeSAkihiko Odaki             return;
19273a977deeSAkihiko Odaki         }
19283a977deeSAkihiko Odaki 
19293a977deeSAkihiko Odaki         base = igb_ring_head_descr(core, rxi);
193017ccd016STomasz Dzieciol         pci_dma_read(d, base, &desc, rx_desc_len);
193117ccd016STomasz Dzieciol         trace_e1000e_rx_descr(rxi->idx, base, rx_desc_len);
19323a977deeSAkihiko Odaki 
1933560cf339STomasz Dzieciol         igb_read_rx_descr(core, &desc, &pdma_st, rxi);
19343a977deeSAkihiko Odaki 
193517ccd016STomasz Dzieciol         igb_write_to_rx_buffers(core, pkt, d, &pdma_st);
193617ccd016STomasz Dzieciol         pdma_st.desc_offset += pdma_st.desc_size;
193717ccd016STomasz Dzieciol         if (pdma_st.desc_offset >= pdma_st.total_size) {
19383a977deeSAkihiko Odaki             is_last = true;
19393a977deeSAkihiko Odaki         }
19403a977deeSAkihiko Odaki 
1941560cf339STomasz Dzieciol         igb_write_rx_descr(core, &desc,
1942560cf339STomasz Dzieciol                            is_last ? pkt : NULL,
1943560cf339STomasz Dzieciol                            rss_info,
1944560cf339STomasz Dzieciol                            etqf, ts,
1945560cf339STomasz Dzieciol                            &pdma_st,
1946560cf339STomasz Dzieciol                            rxi);
194717ccd016STomasz Dzieciol         igb_pci_dma_write_rx_desc(core, d, base, &desc, rx_desc_len);
194817ccd016STomasz Dzieciol         igb_ring_advance(core, rxi, rx_desc_len / E1000_MIN_RX_DESC_LEN);
194917ccd016STomasz Dzieciol     } while (pdma_st.desc_offset < pdma_st.total_size);
19503a977deeSAkihiko Odaki 
195117ccd016STomasz Dzieciol     igb_update_rx_stats(core, rxi, pdma_st.size, pdma_st.total_size);
19523a977deeSAkihiko Odaki }
19533a977deeSAkihiko Odaki 
1954fba7c3b7SSriram Yagnaraman static bool
igb_rx_strip_vlan(IGBCore * core,const E1000ERingInfo * rxi)1955a86aee7eSTomasz Dzieciol igb_rx_strip_vlan(IGBCore *core, const E1000ERingInfo *rxi)
1956fba7c3b7SSriram Yagnaraman {
1957fba7c3b7SSriram Yagnaraman     if (core->mac[MRQC] & 1) {
1958fba7c3b7SSriram Yagnaraman         uint16_t pool = rxi->idx % IGB_NUM_VM_POOLS;
1959fba7c3b7SSriram Yagnaraman         /* Sec 7.10.3.8: CTRL.VME is ignored, only VMOLR/RPLOLR is used */
1960fba7c3b7SSriram Yagnaraman         return (net_rx_pkt_get_packet_type(core->rx_pkt) == ETH_PKT_MCAST) ?
1961fba7c3b7SSriram Yagnaraman                 core->mac[RPLOLR] & E1000_RPLOLR_STRVLAN :
1962fba7c3b7SSriram Yagnaraman                 core->mac[VMOLR0 + pool] & E1000_VMOLR_STRVLAN;
1963fba7c3b7SSriram Yagnaraman     }
1964fba7c3b7SSriram Yagnaraman 
1965fba7c3b7SSriram Yagnaraman     return e1000x_vlan_enabled(core->mac);
1966fba7c3b7SSriram Yagnaraman }
1967fba7c3b7SSriram Yagnaraman 
19683a977deeSAkihiko Odaki static inline void
igb_rx_fix_l4_csum(IGBCore * core,struct NetRxPkt * pkt)19693a977deeSAkihiko Odaki igb_rx_fix_l4_csum(IGBCore *core, struct NetRxPkt *pkt)
19703a977deeSAkihiko Odaki {
19713a977deeSAkihiko Odaki     struct virtio_net_hdr *vhdr = net_rx_pkt_get_vhdr(pkt);
19723a977deeSAkihiko Odaki 
19733a977deeSAkihiko Odaki     if (vhdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
19743a977deeSAkihiko Odaki         net_rx_pkt_fix_l4_csum(pkt);
19753a977deeSAkihiko Odaki     }
19763a977deeSAkihiko Odaki }
19773a977deeSAkihiko Odaki 
19783a977deeSAkihiko Odaki ssize_t
igb_receive_iov(IGBCore * core,const struct iovec * iov,int iovcnt)19793a977deeSAkihiko Odaki igb_receive_iov(IGBCore *core, const struct iovec *iov, int iovcnt)
19803a977deeSAkihiko Odaki {
19813a977deeSAkihiko Odaki     return igb_receive_internal(core, iov, iovcnt, core->has_vnet, NULL);
19823a977deeSAkihiko Odaki }
19833a977deeSAkihiko Odaki 
19843a977deeSAkihiko Odaki static ssize_t
igb_receive_internal(IGBCore * core,const struct iovec * iov,int iovcnt,bool has_vnet,bool * external_tx)19853a977deeSAkihiko Odaki igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt,
19863a977deeSAkihiko Odaki                      bool has_vnet, bool *external_tx)
19873a977deeSAkihiko Odaki {
19883a977deeSAkihiko Odaki     uint16_t queues = 0;
19895c30aea4SAkihiko Odaki     uint32_t causes = 0;
19905844562bSAkihiko Odaki     uint32_t ecauses = 0;
1991dc9ef1bfSAkihiko Odaki     union {
1992dc9ef1bfSAkihiko Odaki         L2Header l2_header;
1993dc9ef1bfSAkihiko Odaki         uint8_t octets[ETH_ZLEN];
1994dc9ef1bfSAkihiko Odaki     } buf;
19953a977deeSAkihiko Odaki     struct iovec min_iov;
19963a977deeSAkihiko Odaki     size_t size, orig_size;
19973a977deeSAkihiko Odaki     size_t iov_ofs = 0;
19983a977deeSAkihiko Odaki     E1000E_RxRing rxr;
19993a977deeSAkihiko Odaki     E1000E_RSSInfo rss_info;
20003a9926d9SAkihiko Odaki     uint16_t etqf;
20013a9926d9SAkihiko Odaki     bool ts;
20023a977deeSAkihiko Odaki     size_t total_size;
20037e64a9caSAkihiko Odaki     int strip_vlan_index;
20043a977deeSAkihiko Odaki     int i;
20053a977deeSAkihiko Odaki 
20063a977deeSAkihiko Odaki     trace_e1000e_rx_receive_iov(iovcnt);
20073a977deeSAkihiko Odaki 
20083a977deeSAkihiko Odaki     if (external_tx) {
20093a977deeSAkihiko Odaki         *external_tx = true;
20103a977deeSAkihiko Odaki     }
20113a977deeSAkihiko Odaki 
20123a977deeSAkihiko Odaki     if (!e1000x_hw_rx_enabled(core->mac)) {
20133a977deeSAkihiko Odaki         return -1;
20143a977deeSAkihiko Odaki     }
20153a977deeSAkihiko Odaki 
20163a977deeSAkihiko Odaki     /* Pull virtio header in */
20173a977deeSAkihiko Odaki     if (has_vnet) {
20183a977deeSAkihiko Odaki         net_rx_pkt_set_vhdr_iovec(core->rx_pkt, iov, iovcnt);
20193a977deeSAkihiko Odaki         iov_ofs = sizeof(struct virtio_net_hdr);
20203a977deeSAkihiko Odaki     } else {
20213a977deeSAkihiko Odaki         net_rx_pkt_unset_vhdr(core->rx_pkt);
20223a977deeSAkihiko Odaki     }
20233a977deeSAkihiko Odaki 
20243a977deeSAkihiko Odaki     orig_size = iov_size(iov, iovcnt);
20253a977deeSAkihiko Odaki     size = orig_size - iov_ofs;
20263a977deeSAkihiko Odaki 
20273a977deeSAkihiko Odaki     /* Pad to minimum Ethernet frame length */
2028dc9ef1bfSAkihiko Odaki     if (size < sizeof(buf)) {
2029dc9ef1bfSAkihiko Odaki         iov_to_buf(iov, iovcnt, iov_ofs, &buf, size);
2030dc9ef1bfSAkihiko Odaki         memset(&buf.octets[size], 0, sizeof(buf) - size);
20313a977deeSAkihiko Odaki         e1000x_inc_reg_if_not_full(core->mac, RUC);
2032dc9ef1bfSAkihiko Odaki         min_iov.iov_base = &buf;
2033dc9ef1bfSAkihiko Odaki         min_iov.iov_len = size = sizeof(buf);
20343a977deeSAkihiko Odaki         iovcnt = 1;
20353a977deeSAkihiko Odaki         iov = &min_iov;
20363a977deeSAkihiko Odaki         iov_ofs = 0;
2037dc9ef1bfSAkihiko Odaki     } else {
2038dc9ef1bfSAkihiko Odaki         iov_to_buf(iov, iovcnt, iov_ofs, &buf, sizeof(buf.l2_header));
20393a977deeSAkihiko Odaki     }
20403a977deeSAkihiko Odaki 
2041dc9ef1bfSAkihiko Odaki     net_rx_pkt_set_packet_type(core->rx_pkt,
2042dc9ef1bfSAkihiko Odaki                                get_eth_packet_type(&buf.l2_header.eth));
20432f0fa232SAkihiko Odaki     net_rx_pkt_set_protocols(core->rx_pkt, iov, iovcnt, iov_ofs);
20443a977deeSAkihiko Odaki 
20453a9926d9SAkihiko Odaki     queues = igb_receive_assign(core, iov, iovcnt, iov_ofs,
20463a9926d9SAkihiko Odaki                                 &buf.l2_header, size,
20473a9926d9SAkihiko Odaki                                 &rss_info, &etqf, &ts, external_tx);
20483a977deeSAkihiko Odaki     if (!queues) {
20493a977deeSAkihiko Odaki         trace_e1000e_rx_flt_dropped();
20503a977deeSAkihiko Odaki         return orig_size;
20513a977deeSAkihiko Odaki     }
20523a977deeSAkihiko Odaki 
20533a977deeSAkihiko Odaki     for (i = 0; i < IGB_NUM_QUEUES; i++) {
20543269ebb3SSriram Yagnaraman         if (!(queues & BIT(i)) ||
20553269ebb3SSriram Yagnaraman             !(core->mac[RXDCTL0 + (i * 16)] & E1000_RXDCTL_QUEUE_ENABLE)) {
20563a977deeSAkihiko Odaki             continue;
20573a977deeSAkihiko Odaki         }
20583a977deeSAkihiko Odaki 
20593a977deeSAkihiko Odaki         igb_rx_ring_init(core, &rxr, i);
20603a977deeSAkihiko Odaki 
20617e64a9caSAkihiko Odaki         if (!igb_rx_strip_vlan(core, rxr.i)) {
20627e64a9caSAkihiko Odaki             strip_vlan_index = -1;
20637e64a9caSAkihiko Odaki         } else if (core->mac[CTRL_EXT] & BIT(26)) {
20647e64a9caSAkihiko Odaki             strip_vlan_index = 1;
20657e64a9caSAkihiko Odaki         } else {
20667e64a9caSAkihiko Odaki             strip_vlan_index = 0;
20677e64a9caSAkihiko Odaki         }
20687e64a9caSAkihiko Odaki 
2069fba7c3b7SSriram Yagnaraman         net_rx_pkt_attach_iovec_ex(core->rx_pkt, iov, iovcnt, iov_ofs,
20707e64a9caSAkihiko Odaki                                    strip_vlan_index,
20717e64a9caSAkihiko Odaki                                    core->mac[VET] & 0xffff,
20727e64a9caSAkihiko Odaki                                    core->mac[VET] >> 16);
2073fba7c3b7SSriram Yagnaraman 
2074fba7c3b7SSriram Yagnaraman         total_size = net_rx_pkt_get_total_len(core->rx_pkt) +
2075fba7c3b7SSriram Yagnaraman             e1000x_fcs_len(core->mac);
2076fba7c3b7SSriram Yagnaraman 
20773a977deeSAkihiko Odaki         if (!igb_has_rxbufs(core, rxr.i, total_size)) {
20785c30aea4SAkihiko Odaki             causes |= E1000_ICS_RXO;
20793a977deeSAkihiko Odaki             trace_e1000e_rx_not_written_to_guest(rxr.i->idx);
20803a977deeSAkihiko Odaki             continue;
20813a977deeSAkihiko Odaki         }
20823a977deeSAkihiko Odaki 
20835c30aea4SAkihiko Odaki         causes |= E1000_ICR_RXDW;
20843a977deeSAkihiko Odaki 
20853a977deeSAkihiko Odaki         igb_rx_fix_l4_csum(core, core->rx_pkt);
20863a9926d9SAkihiko Odaki         igb_write_packet_to_guest(core, core->rx_pkt, &rxr, &rss_info, etqf, ts);
20873a977deeSAkihiko Odaki 
20883a977deeSAkihiko Odaki         /* Check if receive descriptor minimum threshold hit */
20893a977deeSAkihiko Odaki         if (igb_rx_descr_threshold_hit(core, rxr.i)) {
20905c30aea4SAkihiko Odaki             causes |= E1000_ICS_RXDMT0;
20913a977deeSAkihiko Odaki         }
20923a977deeSAkihiko Odaki 
20935844562bSAkihiko Odaki         ecauses |= igb_rx_wb_eic(core, rxr.i->idx);
20943a977deeSAkihiko Odaki 
20953a977deeSAkihiko Odaki         trace_e1000e_rx_written_to_guest(rxr.i->idx);
20963a977deeSAkihiko Odaki     }
20973a977deeSAkihiko Odaki 
20985c30aea4SAkihiko Odaki     trace_e1000e_rx_interrupt_set(causes);
20995844562bSAkihiko Odaki     igb_raise_interrupts(core, EICR, ecauses);
21005844562bSAkihiko Odaki     igb_raise_interrupts(core, ICR, causes);
21013a977deeSAkihiko Odaki 
21023a977deeSAkihiko Odaki     return orig_size;
21033a977deeSAkihiko Odaki }
21043a977deeSAkihiko Odaki 
21053a977deeSAkihiko Odaki static inline bool
igb_have_autoneg(IGBCore * core)21063a977deeSAkihiko Odaki igb_have_autoneg(IGBCore *core)
21073a977deeSAkihiko Odaki {
21083a977deeSAkihiko Odaki     return core->phy[MII_BMCR] & MII_BMCR_AUTOEN;
21093a977deeSAkihiko Odaki }
21103a977deeSAkihiko Odaki 
igb_update_flowctl_status(IGBCore * core)21113a977deeSAkihiko Odaki static void igb_update_flowctl_status(IGBCore *core)
21123a977deeSAkihiko Odaki {
21133a977deeSAkihiko Odaki     if (igb_have_autoneg(core) && core->phy[MII_BMSR] & MII_BMSR_AN_COMP) {
21143a977deeSAkihiko Odaki         trace_e1000e_link_autoneg_flowctl(true);
21153a977deeSAkihiko Odaki         core->mac[CTRL] |= E1000_CTRL_TFCE | E1000_CTRL_RFCE;
21163a977deeSAkihiko Odaki     } else {
21173a977deeSAkihiko Odaki         trace_e1000e_link_autoneg_flowctl(false);
21183a977deeSAkihiko Odaki     }
21193a977deeSAkihiko Odaki }
21203a977deeSAkihiko Odaki 
21213a977deeSAkihiko Odaki static inline void
igb_link_down(IGBCore * core)21223a977deeSAkihiko Odaki igb_link_down(IGBCore *core)
21233a977deeSAkihiko Odaki {
21243a977deeSAkihiko Odaki     e1000x_update_regs_on_link_down(core->mac, core->phy);
21253a977deeSAkihiko Odaki     igb_update_flowctl_status(core);
21263a977deeSAkihiko Odaki }
21273a977deeSAkihiko Odaki 
21283a977deeSAkihiko Odaki static inline void
igb_set_phy_ctrl(IGBCore * core,uint16_t val)21293a977deeSAkihiko Odaki igb_set_phy_ctrl(IGBCore *core, uint16_t val)
21303a977deeSAkihiko Odaki {
21313a977deeSAkihiko Odaki     /* bits 0-5 reserved; MII_BMCR_[ANRESTART,RESET] are self clearing */
21323a977deeSAkihiko Odaki     core->phy[MII_BMCR] = val & ~(0x3f | MII_BMCR_RESET | MII_BMCR_ANRESTART);
21333a977deeSAkihiko Odaki 
21343a977deeSAkihiko Odaki     if ((val & MII_BMCR_ANRESTART) && igb_have_autoneg(core)) {
21353a977deeSAkihiko Odaki         e1000x_restart_autoneg(core->mac, core->phy, core->autoneg_timer);
21363a977deeSAkihiko Odaki     }
21373a977deeSAkihiko Odaki }
21383a977deeSAkihiko Odaki 
igb_core_set_link_status(IGBCore * core)21393a977deeSAkihiko Odaki void igb_core_set_link_status(IGBCore *core)
21403a977deeSAkihiko Odaki {
21413a977deeSAkihiko Odaki     NetClientState *nc = qemu_get_queue(core->owner_nic);
21423a977deeSAkihiko Odaki     uint32_t old_status = core->mac[STATUS];
21433a977deeSAkihiko Odaki 
21443a977deeSAkihiko Odaki     trace_e1000e_link_status_changed(nc->link_down ? false : true);
21453a977deeSAkihiko Odaki 
21463a977deeSAkihiko Odaki     if (nc->link_down) {
21473a977deeSAkihiko Odaki         e1000x_update_regs_on_link_down(core->mac, core->phy);
21483a977deeSAkihiko Odaki     } else {
21493a977deeSAkihiko Odaki         if (igb_have_autoneg(core) &&
21503a977deeSAkihiko Odaki             !(core->phy[MII_BMSR] & MII_BMSR_AN_COMP)) {
21513a977deeSAkihiko Odaki             e1000x_restart_autoneg(core->mac, core->phy,
21523a977deeSAkihiko Odaki                                    core->autoneg_timer);
21533a977deeSAkihiko Odaki         } else {
21543a977deeSAkihiko Odaki             e1000x_update_regs_on_link_up(core->mac, core->phy);
21553a977deeSAkihiko Odaki             igb_start_recv(core);
21563a977deeSAkihiko Odaki         }
21573a977deeSAkihiko Odaki     }
21583a977deeSAkihiko Odaki 
21593a977deeSAkihiko Odaki     if (core->mac[STATUS] != old_status) {
21605844562bSAkihiko Odaki         igb_raise_interrupts(core, ICR, E1000_ICR_LSC);
21613a977deeSAkihiko Odaki     }
21623a977deeSAkihiko Odaki }
21633a977deeSAkihiko Odaki 
21643a977deeSAkihiko Odaki static void
igb_set_ctrl(IGBCore * core,int index,uint32_t val)21653a977deeSAkihiko Odaki igb_set_ctrl(IGBCore *core, int index, uint32_t val)
21663a977deeSAkihiko Odaki {
21673a977deeSAkihiko Odaki     trace_e1000e_core_ctrl_write(index, val);
21683a977deeSAkihiko Odaki 
21693a977deeSAkihiko Odaki     /* RST is self clearing */
21703a977deeSAkihiko Odaki     core->mac[CTRL] = val & ~E1000_CTRL_RST;
21713a977deeSAkihiko Odaki     core->mac[CTRL_DUP] = core->mac[CTRL];
21723a977deeSAkihiko Odaki 
21733a977deeSAkihiko Odaki     trace_e1000e_link_set_params(
21743a977deeSAkihiko Odaki         !!(val & E1000_CTRL_ASDE),
21753a977deeSAkihiko Odaki         (val & E1000_CTRL_SPD_SEL) >> E1000_CTRL_SPD_SHIFT,
21763a977deeSAkihiko Odaki         !!(val & E1000_CTRL_FRCSPD),
21773a977deeSAkihiko Odaki         !!(val & E1000_CTRL_FRCDPX),
21783a977deeSAkihiko Odaki         !!(val & E1000_CTRL_RFCE),
21793a977deeSAkihiko Odaki         !!(val & E1000_CTRL_TFCE));
21803a977deeSAkihiko Odaki 
21813a977deeSAkihiko Odaki     if (val & E1000_CTRL_RST) {
21823a977deeSAkihiko Odaki         trace_e1000e_core_ctrl_sw_reset();
21833a977deeSAkihiko Odaki         igb_reset(core, true);
21843a977deeSAkihiko Odaki     }
21853a977deeSAkihiko Odaki 
21863a977deeSAkihiko Odaki     if (val & E1000_CTRL_PHY_RST) {
21873a977deeSAkihiko Odaki         trace_e1000e_core_ctrl_phy_reset();
21883a977deeSAkihiko Odaki         core->mac[STATUS] |= E1000_STATUS_PHYRA;
21893a977deeSAkihiko Odaki     }
21903a977deeSAkihiko Odaki }
21913a977deeSAkihiko Odaki 
21923a977deeSAkihiko Odaki static void
igb_set_rfctl(IGBCore * core,int index,uint32_t val)21933a977deeSAkihiko Odaki igb_set_rfctl(IGBCore *core, int index, uint32_t val)
21943a977deeSAkihiko Odaki {
21953a977deeSAkihiko Odaki     trace_e1000e_rx_set_rfctl(val);
21963a977deeSAkihiko Odaki 
21973a977deeSAkihiko Odaki     if (!(val & E1000_RFCTL_ISCSI_DIS)) {
21983a977deeSAkihiko Odaki         trace_e1000e_wrn_iscsi_filtering_not_supported();
21993a977deeSAkihiko Odaki     }
22003a977deeSAkihiko Odaki 
22013a977deeSAkihiko Odaki     if (!(val & E1000_RFCTL_NFSW_DIS)) {
22023a977deeSAkihiko Odaki         trace_e1000e_wrn_nfsw_filtering_not_supported();
22033a977deeSAkihiko Odaki     }
22043a977deeSAkihiko Odaki 
22053a977deeSAkihiko Odaki     if (!(val & E1000_RFCTL_NFSR_DIS)) {
22063a977deeSAkihiko Odaki         trace_e1000e_wrn_nfsr_filtering_not_supported();
22073a977deeSAkihiko Odaki     }
22083a977deeSAkihiko Odaki 
22093a977deeSAkihiko Odaki     core->mac[RFCTL] = val;
22103a977deeSAkihiko Odaki }
22113a977deeSAkihiko Odaki 
22123a977deeSAkihiko Odaki static void
igb_calc_rxdesclen(IGBCore * core)22133a977deeSAkihiko Odaki igb_calc_rxdesclen(IGBCore *core)
22143a977deeSAkihiko Odaki {
22153a977deeSAkihiko Odaki     if (igb_rx_use_legacy_descriptor(core)) {
22163a977deeSAkihiko Odaki         core->rx_desc_len = sizeof(struct e1000_rx_desc);
22173a977deeSAkihiko Odaki     } else {
22183a977deeSAkihiko Odaki         core->rx_desc_len = sizeof(union e1000_adv_rx_desc);
22193a977deeSAkihiko Odaki     }
22203a977deeSAkihiko Odaki     trace_e1000e_rx_desc_len(core->rx_desc_len);
22213a977deeSAkihiko Odaki }
22223a977deeSAkihiko Odaki 
22233a977deeSAkihiko Odaki static void
igb_set_rx_control(IGBCore * core,int index,uint32_t val)22243a977deeSAkihiko Odaki igb_set_rx_control(IGBCore *core, int index, uint32_t val)
22253a977deeSAkihiko Odaki {
22263a977deeSAkihiko Odaki     core->mac[RCTL] = val;
22273a977deeSAkihiko Odaki     trace_e1000e_rx_set_rctl(core->mac[RCTL]);
22283a977deeSAkihiko Odaki 
22293a977deeSAkihiko Odaki     if (val & E1000_RCTL_DTYP_MASK) {
22303a977deeSAkihiko Odaki         qemu_log_mask(LOG_GUEST_ERROR,
22313a977deeSAkihiko Odaki                       "igb: RCTL.DTYP must be zero for compatibility");
22323a977deeSAkihiko Odaki     }
22333a977deeSAkihiko Odaki 
22343a977deeSAkihiko Odaki     if (val & E1000_RCTL_EN) {
22353a977deeSAkihiko Odaki         igb_calc_rxdesclen(core);
22363a977deeSAkihiko Odaki         igb_start_recv(core);
22373a977deeSAkihiko Odaki     }
22383a977deeSAkihiko Odaki }
22393a977deeSAkihiko Odaki 
22403a977deeSAkihiko Odaki static inline bool
igb_postpone_interrupt(IGBIntrDelayTimer * timer)22413a977deeSAkihiko Odaki igb_postpone_interrupt(IGBIntrDelayTimer *timer)
22423a977deeSAkihiko Odaki {
22433a977deeSAkihiko Odaki     if (timer->running) {
22443a977deeSAkihiko Odaki         trace_e1000e_irq_postponed_by_xitr(timer->delay_reg << 2);
22453a977deeSAkihiko Odaki 
22463a977deeSAkihiko Odaki         return true;
22473a977deeSAkihiko Odaki     }
22483a977deeSAkihiko Odaki 
22493a977deeSAkihiko Odaki     if (timer->core->mac[timer->delay_reg] != 0) {
22503a977deeSAkihiko Odaki         igb_intrmgr_rearm_timer(timer);
22513a977deeSAkihiko Odaki     }
22523a977deeSAkihiko Odaki 
22533a977deeSAkihiko Odaki     return false;
22543a977deeSAkihiko Odaki }
22553a977deeSAkihiko Odaki 
22563a977deeSAkihiko Odaki static inline bool
igb_eitr_should_postpone(IGBCore * core,int idx)22573a977deeSAkihiko Odaki igb_eitr_should_postpone(IGBCore *core, int idx)
22583a977deeSAkihiko Odaki {
22593a977deeSAkihiko Odaki     return igb_postpone_interrupt(&core->eitr[idx]);
22603a977deeSAkihiko Odaki }
22613a977deeSAkihiko Odaki 
igb_send_msix(IGBCore * core,uint32_t causes)22625844562bSAkihiko Odaki static void igb_send_msix(IGBCore *core, uint32_t causes)
22633a977deeSAkihiko Odaki {
22643a977deeSAkihiko Odaki     int vector;
22653a977deeSAkihiko Odaki 
22663a977deeSAkihiko Odaki     for (vector = 0; vector < IGB_INTR_NUM; ++vector) {
22673a977deeSAkihiko Odaki         if ((causes & BIT(vector)) && !igb_eitr_should_postpone(core, vector)) {
22683a977deeSAkihiko Odaki 
22693a977deeSAkihiko Odaki             trace_e1000e_irq_msix_notify_vec(vector);
22703a977deeSAkihiko Odaki             igb_msix_notify(core, vector);
22713a977deeSAkihiko Odaki         }
22723a977deeSAkihiko Odaki     }
22733a977deeSAkihiko Odaki }
22743a977deeSAkihiko Odaki 
22753a977deeSAkihiko Odaki static inline void
igb_fix_icr_asserted(IGBCore * core)22763a977deeSAkihiko Odaki igb_fix_icr_asserted(IGBCore *core)
22773a977deeSAkihiko Odaki {
22783a977deeSAkihiko Odaki     core->mac[ICR] &= ~E1000_ICR_ASSERTED;
22793a977deeSAkihiko Odaki     if (core->mac[ICR]) {
22803a977deeSAkihiko Odaki         core->mac[ICR] |= E1000_ICR_ASSERTED;
22813a977deeSAkihiko Odaki     }
22823a977deeSAkihiko Odaki 
22833a977deeSAkihiko Odaki     trace_e1000e_irq_fix_icr_asserted(core->mac[ICR]);
22843a977deeSAkihiko Odaki }
22853a977deeSAkihiko Odaki 
igb_raise_interrupts(IGBCore * core,size_t index,uint32_t causes)22865844562bSAkihiko Odaki static void igb_raise_interrupts(IGBCore *core, size_t index, uint32_t causes)
22873a977deeSAkihiko Odaki {
22885844562bSAkihiko Odaki     uint32_t old_causes = core->mac[ICR] & core->mac[IMS];
22895844562bSAkihiko Odaki     uint32_t old_ecauses = core->mac[EICR] & core->mac[EIMS];
22905844562bSAkihiko Odaki     uint32_t raised_causes;
22915844562bSAkihiko Odaki     uint32_t raised_ecauses;
22923a977deeSAkihiko Odaki     uint32_t int_alloc;
22933a977deeSAkihiko Odaki 
22945844562bSAkihiko Odaki     trace_e1000e_irq_set(index << 2,
22955844562bSAkihiko Odaki                          core->mac[index], core->mac[index] | causes);
22965844562bSAkihiko Odaki 
22975844562bSAkihiko Odaki     core->mac[index] |= causes;
22983a977deeSAkihiko Odaki 
2299191e8bdeSAkihiko Odaki     if (core->mac[GPIE] & E1000_GPIE_MSIX_MODE) {
23005844562bSAkihiko Odaki         raised_causes = core->mac[ICR] & core->mac[IMS] & ~old_causes;
23015844562bSAkihiko Odaki 
23025844562bSAkihiko Odaki         if (raised_causes & E1000_ICR_DRSTA) {
23033a977deeSAkihiko Odaki             int_alloc = core->mac[IVAR_MISC] & 0xff;
23043a977deeSAkihiko Odaki             if (int_alloc & E1000_IVAR_VALID) {
23055844562bSAkihiko Odaki                 core->mac[EICR] |= BIT(int_alloc & 0x1f);
23063a977deeSAkihiko Odaki             }
23073a977deeSAkihiko Odaki         }
23083a977deeSAkihiko Odaki         /* Check if other bits (excluding the TCP Timer) are enabled. */
23095844562bSAkihiko Odaki         if (raised_causes & ~E1000_ICR_DRSTA) {
23103a977deeSAkihiko Odaki             int_alloc = (core->mac[IVAR_MISC] >> 8) & 0xff;
23113a977deeSAkihiko Odaki             if (int_alloc & E1000_IVAR_VALID) {
23125844562bSAkihiko Odaki                 core->mac[EICR] |= BIT(int_alloc & 0x1f);
23133a977deeSAkihiko Odaki             }
23143a977deeSAkihiko Odaki         }
23153a977deeSAkihiko Odaki 
23165844562bSAkihiko Odaki         raised_ecauses = core->mac[EICR] & core->mac[EIMS] & ~old_ecauses;
23175844562bSAkihiko Odaki         if (!raised_ecauses) {
23185844562bSAkihiko Odaki             return;
23193a977deeSAkihiko Odaki         }
23205844562bSAkihiko Odaki 
23215844562bSAkihiko Odaki         igb_send_msix(core, raised_ecauses);
23223a977deeSAkihiko Odaki     } else {
23233a977deeSAkihiko Odaki         igb_fix_icr_asserted(core);
23243a977deeSAkihiko Odaki 
23255844562bSAkihiko Odaki         raised_causes = core->mac[ICR] & core->mac[IMS] & ~old_causes;
23265844562bSAkihiko Odaki         if (!raised_causes) {
23275844562bSAkihiko Odaki             return;
23283a977deeSAkihiko Odaki         }
23293a977deeSAkihiko Odaki 
23305844562bSAkihiko Odaki         core->mac[EICR] |= (raised_causes & E1000_ICR_DRSTA) | E1000_EICR_OTHER;
23315844562bSAkihiko Odaki 
23325844562bSAkihiko Odaki         if (msix_enabled(core->owner)) {
23335844562bSAkihiko Odaki             trace_e1000e_irq_msix_notify_vec(0);
23345844562bSAkihiko Odaki             msix_notify(core->owner, 0);
23355844562bSAkihiko Odaki         } else if (msi_enabled(core->owner)) {
23365844562bSAkihiko Odaki             trace_e1000e_irq_msi_notify(raised_causes);
23375844562bSAkihiko Odaki             msi_notify(core->owner, 0);
23385844562bSAkihiko Odaki         } else {
23395844562bSAkihiko Odaki             igb_raise_legacy_irq(core);
23405844562bSAkihiko Odaki         }
23415844562bSAkihiko Odaki     }
23425844562bSAkihiko Odaki }
23435844562bSAkihiko Odaki 
igb_lower_interrupts(IGBCore * core,size_t index,uint32_t causes)23445844562bSAkihiko Odaki static void igb_lower_interrupts(IGBCore *core, size_t index, uint32_t causes)
23455844562bSAkihiko Odaki {
23465844562bSAkihiko Odaki     trace_e1000e_irq_clear(index << 2,
23475844562bSAkihiko Odaki                            core->mac[index], core->mac[index] & ~causes);
23485844562bSAkihiko Odaki 
23495844562bSAkihiko Odaki     core->mac[index] &= ~causes;
23505844562bSAkihiko Odaki 
23513a977deeSAkihiko Odaki     trace_e1000e_irq_pending_interrupts(core->mac[ICR] & core->mac[IMS],
23523a977deeSAkihiko Odaki                                         core->mac[ICR], core->mac[IMS]);
23533a977deeSAkihiko Odaki 
23545844562bSAkihiko Odaki     if (!(core->mac[ICR] & core->mac[IMS]) &&
23555844562bSAkihiko Odaki         !(core->mac[GPIE] & E1000_GPIE_MSIX_MODE)) {
23565844562bSAkihiko Odaki         core->mac[EICR] &= ~E1000_EICR_OTHER;
23575844562bSAkihiko Odaki 
23585844562bSAkihiko Odaki         if (!msix_enabled(core->owner) && !msi_enabled(core->owner)) {
23593a977deeSAkihiko Odaki             igb_lower_legacy_irq(core);
23603a977deeSAkihiko Odaki         }
23613a977deeSAkihiko Odaki     }
23623a977deeSAkihiko Odaki }
23633a977deeSAkihiko Odaki 
igb_set_eics(IGBCore * core,int index,uint32_t val)23643a977deeSAkihiko Odaki static void igb_set_eics(IGBCore *core, int index, uint32_t val)
23653a977deeSAkihiko Odaki {
23663a977deeSAkihiko Odaki     bool msix = !!(core->mac[GPIE] & E1000_GPIE_MSIX_MODE);
23675844562bSAkihiko Odaki     uint32_t mask = msix ? E1000_EICR_MSIX_MASK : E1000_EICR_LEGACY_MASK;
23683a977deeSAkihiko Odaki 
23693a977deeSAkihiko Odaki     trace_igb_irq_write_eics(val, msix);
23705844562bSAkihiko Odaki     igb_raise_interrupts(core, EICR, val & mask);
23713a977deeSAkihiko Odaki }
23723a977deeSAkihiko Odaki 
igb_set_eims(IGBCore * core,int index,uint32_t val)23733a977deeSAkihiko Odaki static void igb_set_eims(IGBCore *core, int index, uint32_t val)
23743a977deeSAkihiko Odaki {
23753a977deeSAkihiko Odaki     bool msix = !!(core->mac[GPIE] & E1000_GPIE_MSIX_MODE);
23765844562bSAkihiko Odaki     uint32_t mask = msix ? E1000_EICR_MSIX_MASK : E1000_EICR_LEGACY_MASK;
23773a977deeSAkihiko Odaki 
23783a977deeSAkihiko Odaki     trace_igb_irq_write_eims(val, msix);
23795844562bSAkihiko Odaki     igb_raise_interrupts(core, EIMS, val & mask);
23803a977deeSAkihiko Odaki }
23813a977deeSAkihiko Odaki 
mailbox_interrupt_to_vf(IGBCore * core,uint16_t vfn)23823a977deeSAkihiko Odaki static void mailbox_interrupt_to_vf(IGBCore *core, uint16_t vfn)
23833a977deeSAkihiko Odaki {
23843a977deeSAkihiko Odaki     uint32_t ent = core->mac[VTIVAR_MISC + vfn];
23855844562bSAkihiko Odaki     uint32_t causes;
23863a977deeSAkihiko Odaki 
23873a977deeSAkihiko Odaki     if ((ent & E1000_IVAR_VALID)) {
23885844562bSAkihiko Odaki         causes = (ent & 0x3) << (22 - vfn * IGBVF_MSIX_VEC_NUM);
23895844562bSAkihiko Odaki         igb_raise_interrupts(core, EICR, causes);
23903a977deeSAkihiko Odaki     }
23913a977deeSAkihiko Odaki }
23923a977deeSAkihiko Odaki 
mailbox_interrupt_to_pf(IGBCore * core)23933a977deeSAkihiko Odaki static void mailbox_interrupt_to_pf(IGBCore *core)
23943a977deeSAkihiko Odaki {
23955844562bSAkihiko Odaki     igb_raise_interrupts(core, ICR, E1000_ICR_VMMB);
23963a977deeSAkihiko Odaki }
23973a977deeSAkihiko Odaki 
igb_set_pfmailbox(IGBCore * core,int index,uint32_t val)23983a977deeSAkihiko Odaki static void igb_set_pfmailbox(IGBCore *core, int index, uint32_t val)
23993a977deeSAkihiko Odaki {
24003a977deeSAkihiko Odaki     uint16_t vfn = index - P2VMAILBOX0;
24013a977deeSAkihiko Odaki 
24023a977deeSAkihiko Odaki     trace_igb_set_pfmailbox(vfn, val);
24033a977deeSAkihiko Odaki 
24043a977deeSAkihiko Odaki     if (val & E1000_P2VMAILBOX_STS) {
24053a977deeSAkihiko Odaki         core->mac[V2PMAILBOX0 + vfn] |= E1000_V2PMAILBOX_PFSTS;
24063a977deeSAkihiko Odaki         mailbox_interrupt_to_vf(core, vfn);
24073a977deeSAkihiko Odaki     }
24083a977deeSAkihiko Odaki 
24093a977deeSAkihiko Odaki     if (val & E1000_P2VMAILBOX_ACK) {
24103a977deeSAkihiko Odaki         core->mac[V2PMAILBOX0 + vfn] |= E1000_V2PMAILBOX_PFACK;
24113a977deeSAkihiko Odaki         mailbox_interrupt_to_vf(core, vfn);
24123a977deeSAkihiko Odaki     }
24133a977deeSAkihiko Odaki 
24143a977deeSAkihiko Odaki     /* Buffer Taken by PF (can be set only if the VFU is cleared). */
24153a977deeSAkihiko Odaki     if (val & E1000_P2VMAILBOX_PFU) {
24163a977deeSAkihiko Odaki         if (!(core->mac[index] & E1000_P2VMAILBOX_VFU)) {
24173a977deeSAkihiko Odaki             core->mac[index] |= E1000_P2VMAILBOX_PFU;
24183a977deeSAkihiko Odaki             core->mac[V2PMAILBOX0 + vfn] |= E1000_V2PMAILBOX_PFU;
24193a977deeSAkihiko Odaki         }
24203a977deeSAkihiko Odaki     } else {
24213a977deeSAkihiko Odaki         core->mac[index] &= ~E1000_P2VMAILBOX_PFU;
24223a977deeSAkihiko Odaki         core->mac[V2PMAILBOX0 + vfn] &= ~E1000_V2PMAILBOX_PFU;
24233a977deeSAkihiko Odaki     }
24243a977deeSAkihiko Odaki 
24253a977deeSAkihiko Odaki     if (val & E1000_P2VMAILBOX_RVFU) {
24263a977deeSAkihiko Odaki         core->mac[V2PMAILBOX0 + vfn] &= ~E1000_V2PMAILBOX_VFU;
24273a977deeSAkihiko Odaki         core->mac[MBVFICR] &= ~((E1000_MBVFICR_VFACK_VF1 << vfn) |
24283a977deeSAkihiko Odaki                                 (E1000_MBVFICR_VFREQ_VF1 << vfn));
24293a977deeSAkihiko Odaki     }
24303a977deeSAkihiko Odaki }
24313a977deeSAkihiko Odaki 
igb_set_vfmailbox(IGBCore * core,int index,uint32_t val)24323a977deeSAkihiko Odaki static void igb_set_vfmailbox(IGBCore *core, int index, uint32_t val)
24333a977deeSAkihiko Odaki {
24343a977deeSAkihiko Odaki     uint16_t vfn = index - V2PMAILBOX0;
24353a977deeSAkihiko Odaki 
24363a977deeSAkihiko Odaki     trace_igb_set_vfmailbox(vfn, val);
24373a977deeSAkihiko Odaki 
24383a977deeSAkihiko Odaki     if (val & E1000_V2PMAILBOX_REQ) {
24393a977deeSAkihiko Odaki         core->mac[MBVFICR] |= E1000_MBVFICR_VFREQ_VF1 << vfn;
24403a977deeSAkihiko Odaki         mailbox_interrupt_to_pf(core);
24413a977deeSAkihiko Odaki     }
24423a977deeSAkihiko Odaki 
24433a977deeSAkihiko Odaki     if (val & E1000_V2PMAILBOX_ACK) {
24443a977deeSAkihiko Odaki         core->mac[MBVFICR] |= E1000_MBVFICR_VFACK_VF1 << vfn;
24453a977deeSAkihiko Odaki         mailbox_interrupt_to_pf(core);
24463a977deeSAkihiko Odaki     }
24473a977deeSAkihiko Odaki 
24483a977deeSAkihiko Odaki     /* Buffer Taken by VF (can be set only if the PFU is cleared). */
24493a977deeSAkihiko Odaki     if (val & E1000_V2PMAILBOX_VFU) {
24503a977deeSAkihiko Odaki         if (!(core->mac[index] & E1000_V2PMAILBOX_PFU)) {
24513a977deeSAkihiko Odaki             core->mac[index] |= E1000_V2PMAILBOX_VFU;
24523a977deeSAkihiko Odaki             core->mac[P2VMAILBOX0 + vfn] |= E1000_P2VMAILBOX_VFU;
24533a977deeSAkihiko Odaki         }
24543a977deeSAkihiko Odaki     } else {
24553a977deeSAkihiko Odaki         core->mac[index] &= ~E1000_V2PMAILBOX_VFU;
24563a977deeSAkihiko Odaki         core->mac[P2VMAILBOX0 + vfn] &= ~E1000_P2VMAILBOX_VFU;
24573a977deeSAkihiko Odaki     }
24583a977deeSAkihiko Odaki }
24593a977deeSAkihiko Odaki 
igb_core_vf_reset(IGBCore * core,uint16_t vfn)2460fe73674aSCédric Le Goater void igb_core_vf_reset(IGBCore *core, uint16_t vfn)
24612e68546aSSriram Yagnaraman {
24623269ebb3SSriram Yagnaraman     uint16_t qn0 = vfn;
24633269ebb3SSriram Yagnaraman     uint16_t qn1 = vfn + IGB_NUM_VM_POOLS;
24643269ebb3SSriram Yagnaraman 
2465fe73674aSCédric Le Goater     trace_igb_core_vf_reset(vfn);
2466fe73674aSCédric Le Goater 
24672e68546aSSriram Yagnaraman     /* disable Rx and Tx for the VF*/
24683269ebb3SSriram Yagnaraman     core->mac[RXDCTL0 + (qn0 * 16)] &= ~E1000_RXDCTL_QUEUE_ENABLE;
24693269ebb3SSriram Yagnaraman     core->mac[RXDCTL0 + (qn1 * 16)] &= ~E1000_RXDCTL_QUEUE_ENABLE;
24703269ebb3SSriram Yagnaraman     core->mac[TXDCTL0 + (qn0 * 16)] &= ~E1000_TXDCTL_QUEUE_ENABLE;
24713269ebb3SSriram Yagnaraman     core->mac[TXDCTL0 + (qn1 * 16)] &= ~E1000_TXDCTL_QUEUE_ENABLE;
24722e68546aSSriram Yagnaraman     core->mac[VFRE] &= ~BIT(vfn);
24733269ebb3SSriram Yagnaraman     core->mac[VFTE] &= ~BIT(vfn);
24742e68546aSSriram Yagnaraman     /* indicate VF reset to PF */
24752e68546aSSriram Yagnaraman     core->mac[VFLRE] |= BIT(vfn);
24762e68546aSSriram Yagnaraman     /* VFLRE and mailbox use the same interrupt cause */
24772e68546aSSriram Yagnaraman     mailbox_interrupt_to_pf(core);
24782e68546aSSriram Yagnaraman }
24792e68546aSSriram Yagnaraman 
igb_w1c(IGBCore * core,int index,uint32_t val)24803a977deeSAkihiko Odaki static void igb_w1c(IGBCore *core, int index, uint32_t val)
24813a977deeSAkihiko Odaki {
24823a977deeSAkihiko Odaki     core->mac[index] &= ~val;
24833a977deeSAkihiko Odaki }
24843a977deeSAkihiko Odaki 
igb_set_eimc(IGBCore * core,int index,uint32_t val)24853a977deeSAkihiko Odaki static void igb_set_eimc(IGBCore *core, int index, uint32_t val)
24863a977deeSAkihiko Odaki {
24873a977deeSAkihiko Odaki     bool msix = !!(core->mac[GPIE] & E1000_GPIE_MSIX_MODE);
24885844562bSAkihiko Odaki     uint32_t mask = msix ? E1000_EICR_MSIX_MASK : E1000_EICR_LEGACY_MASK;
24895844562bSAkihiko Odaki 
24905844562bSAkihiko Odaki     trace_igb_irq_write_eimc(val, msix);
24913a977deeSAkihiko Odaki 
24923a977deeSAkihiko Odaki     /* Interrupts are disabled via a write to EIMC and reflected in EIMS. */
24935844562bSAkihiko Odaki     igb_lower_interrupts(core, EIMS, val & mask);
24943a977deeSAkihiko Odaki }
24953a977deeSAkihiko Odaki 
igb_set_eiac(IGBCore * core,int index,uint32_t val)24963a977deeSAkihiko Odaki static void igb_set_eiac(IGBCore *core, int index, uint32_t val)
24973a977deeSAkihiko Odaki {
24983a977deeSAkihiko Odaki     bool msix = !!(core->mac[GPIE] & E1000_GPIE_MSIX_MODE);
24993a977deeSAkihiko Odaki 
25003a977deeSAkihiko Odaki     if (msix) {
25013a977deeSAkihiko Odaki         trace_igb_irq_write_eiac(val);
25023a977deeSAkihiko Odaki 
25033a977deeSAkihiko Odaki         /*
25043a977deeSAkihiko Odaki          * TODO: When using IOV, the bits that correspond to MSI-X vectors
25053a977deeSAkihiko Odaki          * that are assigned to a VF are read-only.
25063a977deeSAkihiko Odaki          */
25073a977deeSAkihiko Odaki         core->mac[EIAC] |= (val & E1000_EICR_MSIX_MASK);
25083a977deeSAkihiko Odaki     }
25093a977deeSAkihiko Odaki }
25103a977deeSAkihiko Odaki 
igb_set_eiam(IGBCore * core,int index,uint32_t val)25113a977deeSAkihiko Odaki static void igb_set_eiam(IGBCore *core, int index, uint32_t val)
25123a977deeSAkihiko Odaki {
25133a977deeSAkihiko Odaki     bool msix = !!(core->mac[GPIE] & E1000_GPIE_MSIX_MODE);
25143a977deeSAkihiko Odaki 
25153a977deeSAkihiko Odaki     /*
25163a977deeSAkihiko Odaki      * TODO: When using IOV, the bits that correspond to MSI-X vectors that
25173a977deeSAkihiko Odaki      * are assigned to a VF are read-only.
25183a977deeSAkihiko Odaki      */
25193a977deeSAkihiko Odaki     core->mac[EIAM] |=
25203a977deeSAkihiko Odaki         ~(val & (msix ? E1000_EICR_MSIX_MASK : E1000_EICR_LEGACY_MASK));
25213a977deeSAkihiko Odaki 
25223a977deeSAkihiko Odaki     trace_igb_irq_write_eiam(val, msix);
25233a977deeSAkihiko Odaki }
25243a977deeSAkihiko Odaki 
igb_set_eicr(IGBCore * core,int index,uint32_t val)25253a977deeSAkihiko Odaki static void igb_set_eicr(IGBCore *core, int index, uint32_t val)
25263a977deeSAkihiko Odaki {
25273a977deeSAkihiko Odaki     bool msix = !!(core->mac[GPIE] & E1000_GPIE_MSIX_MODE);
25283a977deeSAkihiko Odaki 
25293a977deeSAkihiko Odaki     /*
25303a977deeSAkihiko Odaki      * TODO: In IOV mode, only bit zero of this vector is available for the PF
25313a977deeSAkihiko Odaki      * function.
25323a977deeSAkihiko Odaki      */
25335844562bSAkihiko Odaki     uint32_t mask = msix ? E1000_EICR_MSIX_MASK : E1000_EICR_LEGACY_MASK;
25343a977deeSAkihiko Odaki 
25353a977deeSAkihiko Odaki     trace_igb_irq_write_eicr(val, msix);
25365844562bSAkihiko Odaki     igb_lower_interrupts(core, EICR, val & mask);
25373a977deeSAkihiko Odaki }
25383a977deeSAkihiko Odaki 
igb_set_vtctrl(IGBCore * core,int index,uint32_t val)25393a977deeSAkihiko Odaki static void igb_set_vtctrl(IGBCore *core, int index, uint32_t val)
25403a977deeSAkihiko Odaki {
25413a977deeSAkihiko Odaki     uint16_t vfn;
25423a977deeSAkihiko Odaki 
25433a977deeSAkihiko Odaki     if (val & E1000_CTRL_RST) {
25443a977deeSAkihiko Odaki         vfn = (index - PVTCTRL0) / 0x40;
2545fe73674aSCédric Le Goater         igb_core_vf_reset(core, vfn);
25463a977deeSAkihiko Odaki     }
25473a977deeSAkihiko Odaki }
25483a977deeSAkihiko Odaki 
igb_set_vteics(IGBCore * core,int index,uint32_t val)25493a977deeSAkihiko Odaki static void igb_set_vteics(IGBCore *core, int index, uint32_t val)
25503a977deeSAkihiko Odaki {
25513a977deeSAkihiko Odaki     uint16_t vfn = (index - PVTEICS0) / 0x40;
25523a977deeSAkihiko Odaki 
25533a977deeSAkihiko Odaki     core->mac[index] = val;
25543a977deeSAkihiko Odaki     igb_set_eics(core, EICS, (val & 0x7) << (22 - vfn * IGBVF_MSIX_VEC_NUM));
25553a977deeSAkihiko Odaki }
25563a977deeSAkihiko Odaki 
igb_set_vteims(IGBCore * core,int index,uint32_t val)25573a977deeSAkihiko Odaki static void igb_set_vteims(IGBCore *core, int index, uint32_t val)
25583a977deeSAkihiko Odaki {
25593a977deeSAkihiko Odaki     uint16_t vfn = (index - PVTEIMS0) / 0x40;
25603a977deeSAkihiko Odaki 
25613a977deeSAkihiko Odaki     core->mac[index] = val;
25623a977deeSAkihiko Odaki     igb_set_eims(core, EIMS, (val & 0x7) << (22 - vfn * IGBVF_MSIX_VEC_NUM));
25633a977deeSAkihiko Odaki }
25643a977deeSAkihiko Odaki 
igb_set_vteimc(IGBCore * core,int index,uint32_t val)25653a977deeSAkihiko Odaki static void igb_set_vteimc(IGBCore *core, int index, uint32_t val)
25663a977deeSAkihiko Odaki {
25673a977deeSAkihiko Odaki     uint16_t vfn = (index - PVTEIMC0) / 0x40;
25683a977deeSAkihiko Odaki 
25693a977deeSAkihiko Odaki     core->mac[index] = val;
25703a977deeSAkihiko Odaki     igb_set_eimc(core, EIMC, (val & 0x7) << (22 - vfn * IGBVF_MSIX_VEC_NUM));
25713a977deeSAkihiko Odaki }
25723a977deeSAkihiko Odaki 
igb_set_vteiac(IGBCore * core,int index,uint32_t val)25733a977deeSAkihiko Odaki static void igb_set_vteiac(IGBCore *core, int index, uint32_t val)
25743a977deeSAkihiko Odaki {
25753a977deeSAkihiko Odaki     uint16_t vfn = (index - PVTEIAC0) / 0x40;
25763a977deeSAkihiko Odaki 
25773a977deeSAkihiko Odaki     core->mac[index] = val;
25783a977deeSAkihiko Odaki     igb_set_eiac(core, EIAC, (val & 0x7) << (22 - vfn * IGBVF_MSIX_VEC_NUM));
25793a977deeSAkihiko Odaki }
25803a977deeSAkihiko Odaki 
igb_set_vteiam(IGBCore * core,int index,uint32_t val)25813a977deeSAkihiko Odaki static void igb_set_vteiam(IGBCore *core, int index, uint32_t val)
25823a977deeSAkihiko Odaki {
25833a977deeSAkihiko Odaki     uint16_t vfn = (index - PVTEIAM0) / 0x40;
25843a977deeSAkihiko Odaki 
25853a977deeSAkihiko Odaki     core->mac[index] = val;
25863a977deeSAkihiko Odaki     igb_set_eiam(core, EIAM, (val & 0x7) << (22 - vfn * IGBVF_MSIX_VEC_NUM));
25873a977deeSAkihiko Odaki }
25883a977deeSAkihiko Odaki 
igb_set_vteicr(IGBCore * core,int index,uint32_t val)25893a977deeSAkihiko Odaki static void igb_set_vteicr(IGBCore *core, int index, uint32_t val)
25903a977deeSAkihiko Odaki {
25913a977deeSAkihiko Odaki     uint16_t vfn = (index - PVTEICR0) / 0x40;
25923a977deeSAkihiko Odaki 
25933a977deeSAkihiko Odaki     core->mac[index] = val;
25943a977deeSAkihiko Odaki     igb_set_eicr(core, EICR, (val & 0x7) << (22 - vfn * IGBVF_MSIX_VEC_NUM));
25953a977deeSAkihiko Odaki }
25963a977deeSAkihiko Odaki 
igb_set_vtivar(IGBCore * core,int index,uint32_t val)25973a977deeSAkihiko Odaki static void igb_set_vtivar(IGBCore *core, int index, uint32_t val)
25983a977deeSAkihiko Odaki {
25993a977deeSAkihiko Odaki     uint16_t vfn = (index - VTIVAR);
26003a977deeSAkihiko Odaki     uint16_t qn = vfn;
26013a977deeSAkihiko Odaki     uint8_t ent;
26023a977deeSAkihiko Odaki     int n;
26033a977deeSAkihiko Odaki 
26043a977deeSAkihiko Odaki     core->mac[index] = val;
26053a977deeSAkihiko Odaki 
26063a977deeSAkihiko Odaki     /* Get assigned vector associated with queue Rx#0. */
26073a977deeSAkihiko Odaki     if ((val & E1000_IVAR_VALID)) {
26083a977deeSAkihiko Odaki         n = igb_ivar_entry_rx(qn);
26093a977deeSAkihiko Odaki         ent = E1000_IVAR_VALID | (24 - vfn * IGBVF_MSIX_VEC_NUM - (2 - (val & 0x7)));
26103a977deeSAkihiko Odaki         core->mac[IVAR0 + n / 4] |= ent << 8 * (n % 4);
26113a977deeSAkihiko Odaki     }
26123a977deeSAkihiko Odaki 
26133a977deeSAkihiko Odaki     /* Get assigned vector associated with queue Tx#0 */
26143a977deeSAkihiko Odaki     ent = val >> 8;
26153a977deeSAkihiko Odaki     if ((ent & E1000_IVAR_VALID)) {
26163a977deeSAkihiko Odaki         n = igb_ivar_entry_tx(qn);
26173a977deeSAkihiko Odaki         ent = E1000_IVAR_VALID | (24 - vfn * IGBVF_MSIX_VEC_NUM - (2 - (ent & 0x7)));
26183a977deeSAkihiko Odaki         core->mac[IVAR0 + n / 4] |= ent << 8 * (n % 4);
26193a977deeSAkihiko Odaki     }
26203a977deeSAkihiko Odaki 
26213a977deeSAkihiko Odaki     /*
26223a977deeSAkihiko Odaki      * Ignoring assigned vectors associated with queues Rx#1 and Tx#1 for now.
26233a977deeSAkihiko Odaki      */
26243a977deeSAkihiko Odaki }
26253a977deeSAkihiko Odaki 
26263a977deeSAkihiko Odaki static inline void
igb_autoneg_timer(void * opaque)26273a977deeSAkihiko Odaki igb_autoneg_timer(void *opaque)
26283a977deeSAkihiko Odaki {
26293a977deeSAkihiko Odaki     IGBCore *core = opaque;
26303a977deeSAkihiko Odaki     if (!qemu_get_queue(core->owner_nic)->link_down) {
26313a977deeSAkihiko Odaki         e1000x_update_regs_on_autoneg_done(core->mac, core->phy);
26323a977deeSAkihiko Odaki         igb_start_recv(core);
26333a977deeSAkihiko Odaki 
26343a977deeSAkihiko Odaki         igb_update_flowctl_status(core);
26353a977deeSAkihiko Odaki         /* signal link status change to the guest */
26365844562bSAkihiko Odaki         igb_raise_interrupts(core, ICR, E1000_ICR_LSC);
26373a977deeSAkihiko Odaki     }
26383a977deeSAkihiko Odaki }
26393a977deeSAkihiko Odaki 
26403a977deeSAkihiko Odaki static inline uint16_t
igb_get_reg_index_with_offset(const uint16_t * mac_reg_access,hwaddr addr)26413a977deeSAkihiko Odaki igb_get_reg_index_with_offset(const uint16_t *mac_reg_access, hwaddr addr)
26423a977deeSAkihiko Odaki {
26433a977deeSAkihiko Odaki     uint16_t index = (addr & 0x1ffff) >> 2;
26443a977deeSAkihiko Odaki     return index + (mac_reg_access[index] & 0xfffe);
26453a977deeSAkihiko Odaki }
26463a977deeSAkihiko Odaki 
26473a977deeSAkihiko Odaki static const char igb_phy_regcap[MAX_PHY_REG_ADDRESS + 1] = {
26483a977deeSAkihiko Odaki     [MII_BMCR]                   = PHY_RW,
26493a977deeSAkihiko Odaki     [MII_BMSR]                   = PHY_R,
26503a977deeSAkihiko Odaki     [MII_PHYID1]                 = PHY_R,
26513a977deeSAkihiko Odaki     [MII_PHYID2]                 = PHY_R,
26523a977deeSAkihiko Odaki     [MII_ANAR]                   = PHY_RW,
26533a977deeSAkihiko Odaki     [MII_ANLPAR]                 = PHY_R,
26543a977deeSAkihiko Odaki     [MII_ANER]                   = PHY_R,
26553a977deeSAkihiko Odaki     [MII_ANNP]                   = PHY_RW,
26563a977deeSAkihiko Odaki     [MII_ANLPRNP]                = PHY_R,
26573a977deeSAkihiko Odaki     [MII_CTRL1000]               = PHY_RW,
26583a977deeSAkihiko Odaki     [MII_STAT1000]               = PHY_R,
26593a977deeSAkihiko Odaki     [MII_EXTSTAT]                = PHY_R,
26603a977deeSAkihiko Odaki 
26613a977deeSAkihiko Odaki     [IGP01E1000_PHY_PORT_CONFIG] = PHY_RW,
26623a977deeSAkihiko Odaki     [IGP01E1000_PHY_PORT_STATUS] = PHY_R,
26633a977deeSAkihiko Odaki     [IGP01E1000_PHY_PORT_CTRL]   = PHY_RW,
26643a977deeSAkihiko Odaki     [IGP01E1000_PHY_LINK_HEALTH] = PHY_R,
26653a977deeSAkihiko Odaki     [IGP02E1000_PHY_POWER_MGMT]  = PHY_RW,
26663a977deeSAkihiko Odaki     [IGP01E1000_PHY_PAGE_SELECT] = PHY_W
26673a977deeSAkihiko Odaki };
26683a977deeSAkihiko Odaki 
26693a977deeSAkihiko Odaki static void
igb_phy_reg_write(IGBCore * core,uint32_t addr,uint16_t data)26703a977deeSAkihiko Odaki igb_phy_reg_write(IGBCore *core, uint32_t addr, uint16_t data)
26713a977deeSAkihiko Odaki {
26723a977deeSAkihiko Odaki     assert(addr <= MAX_PHY_REG_ADDRESS);
26733a977deeSAkihiko Odaki 
26743a977deeSAkihiko Odaki     if (addr == MII_BMCR) {
26753a977deeSAkihiko Odaki         igb_set_phy_ctrl(core, data);
26763a977deeSAkihiko Odaki     } else {
26773a977deeSAkihiko Odaki         core->phy[addr] = data;
26783a977deeSAkihiko Odaki     }
26793a977deeSAkihiko Odaki }
26803a977deeSAkihiko Odaki 
26813a977deeSAkihiko Odaki static void
igb_set_mdic(IGBCore * core,int index,uint32_t val)26823a977deeSAkihiko Odaki igb_set_mdic(IGBCore *core, int index, uint32_t val)
26833a977deeSAkihiko Odaki {
26843a977deeSAkihiko Odaki     uint32_t data = val & E1000_MDIC_DATA_MASK;
26853a977deeSAkihiko Odaki     uint32_t addr = ((val & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
26863a977deeSAkihiko Odaki 
26873a977deeSAkihiko Odaki     if ((val & E1000_MDIC_PHY_MASK) >> E1000_MDIC_PHY_SHIFT != 1) { /* phy # */
26883a977deeSAkihiko Odaki         val = core->mac[MDIC] | E1000_MDIC_ERROR;
26893a977deeSAkihiko Odaki     } else if (val & E1000_MDIC_OP_READ) {
26903a977deeSAkihiko Odaki         if (!(igb_phy_regcap[addr] & PHY_R)) {
26913a977deeSAkihiko Odaki             trace_igb_core_mdic_read_unhandled(addr);
26923a977deeSAkihiko Odaki             val |= E1000_MDIC_ERROR;
26933a977deeSAkihiko Odaki         } else {
26943a977deeSAkihiko Odaki             val = (val ^ data) | core->phy[addr];
26953a977deeSAkihiko Odaki             trace_igb_core_mdic_read(addr, val);
26963a977deeSAkihiko Odaki         }
26973a977deeSAkihiko Odaki     } else if (val & E1000_MDIC_OP_WRITE) {
26983a977deeSAkihiko Odaki         if (!(igb_phy_regcap[addr] & PHY_W)) {
26993a977deeSAkihiko Odaki             trace_igb_core_mdic_write_unhandled(addr);
27003a977deeSAkihiko Odaki             val |= E1000_MDIC_ERROR;
27013a977deeSAkihiko Odaki         } else {
27023a977deeSAkihiko Odaki             trace_igb_core_mdic_write(addr, data);
27033a977deeSAkihiko Odaki             igb_phy_reg_write(core, addr, data);
27043a977deeSAkihiko Odaki         }
27053a977deeSAkihiko Odaki     }
27063a977deeSAkihiko Odaki     core->mac[MDIC] = val | E1000_MDIC_READY;
27073a977deeSAkihiko Odaki 
27083a977deeSAkihiko Odaki     if (val & E1000_MDIC_INT_EN) {
27095844562bSAkihiko Odaki         igb_raise_interrupts(core, ICR, E1000_ICR_MDAC);
27103a977deeSAkihiko Odaki     }
27113a977deeSAkihiko Odaki }
27123a977deeSAkihiko Odaki 
27133a977deeSAkihiko Odaki static void
igb_set_rdt(IGBCore * core,int index,uint32_t val)27143a977deeSAkihiko Odaki igb_set_rdt(IGBCore *core, int index, uint32_t val)
27153a977deeSAkihiko Odaki {
27163a977deeSAkihiko Odaki     core->mac[index] = val & 0xffff;
27173a977deeSAkihiko Odaki     trace_e1000e_rx_set_rdt(igb_mq_queue_idx(RDT0, index), val);
27183a977deeSAkihiko Odaki     igb_start_recv(core);
27193a977deeSAkihiko Odaki }
27203a977deeSAkihiko Odaki 
27213a977deeSAkihiko Odaki static void
igb_set_status(IGBCore * core,int index,uint32_t val)27223a977deeSAkihiko Odaki igb_set_status(IGBCore *core, int index, uint32_t val)
27233a977deeSAkihiko Odaki {
27243a977deeSAkihiko Odaki     if ((val & E1000_STATUS_PHYRA) == 0) {
27253a977deeSAkihiko Odaki         core->mac[index] &= ~E1000_STATUS_PHYRA;
27263a977deeSAkihiko Odaki     }
27273a977deeSAkihiko Odaki }
27283a977deeSAkihiko Odaki 
27293a977deeSAkihiko Odaki static void
igb_set_ctrlext(IGBCore * core,int index,uint32_t val)27303a977deeSAkihiko Odaki igb_set_ctrlext(IGBCore *core, int index, uint32_t val)
27313a977deeSAkihiko Odaki {
27322e68546aSSriram Yagnaraman     trace_igb_link_set_ext_params(!!(val & E1000_CTRL_EXT_ASDCHK),
27332e68546aSSriram Yagnaraman                                   !!(val & E1000_CTRL_EXT_SPD_BYPS),
27342e68546aSSriram Yagnaraman                                   !!(val & E1000_CTRL_EXT_PFRSTD));
27353a977deeSAkihiko Odaki 
27363a977deeSAkihiko Odaki     /* Zero self-clearing bits */
27373a977deeSAkihiko Odaki     val &= ~(E1000_CTRL_EXT_ASDCHK | E1000_CTRL_EXT_EE_RST);
27383a977deeSAkihiko Odaki     core->mac[CTRL_EXT] = val;
27392e68546aSSriram Yagnaraman 
27402e68546aSSriram Yagnaraman     if (core->mac[CTRL_EXT] & E1000_CTRL_EXT_PFRSTD) {
27412e68546aSSriram Yagnaraman         for (int vfn = 0; vfn < IGB_MAX_VF_FUNCTIONS; vfn++) {
27422e68546aSSriram Yagnaraman             core->mac[V2PMAILBOX0 + vfn] &= ~E1000_V2PMAILBOX_RSTI;
27432e68546aSSriram Yagnaraman             core->mac[V2PMAILBOX0 + vfn] |= E1000_V2PMAILBOX_RSTD;
27442e68546aSSriram Yagnaraman         }
27452e68546aSSriram Yagnaraman     }
27463a977deeSAkihiko Odaki }
27473a977deeSAkihiko Odaki 
27483a977deeSAkihiko Odaki static void
igb_set_pbaclr(IGBCore * core,int index,uint32_t val)27493a977deeSAkihiko Odaki igb_set_pbaclr(IGBCore *core, int index, uint32_t val)
27503a977deeSAkihiko Odaki {
27513a977deeSAkihiko Odaki     int i;
27523a977deeSAkihiko Odaki 
27533a977deeSAkihiko Odaki     core->mac[PBACLR] = val & E1000_PBACLR_VALID_MASK;
27543a977deeSAkihiko Odaki 
27553a977deeSAkihiko Odaki     if (!msix_enabled(core->owner)) {
27563a977deeSAkihiko Odaki         return;
27573a977deeSAkihiko Odaki     }
27583a977deeSAkihiko Odaki 
27593a977deeSAkihiko Odaki     for (i = 0; i < IGB_INTR_NUM; i++) {
27603a977deeSAkihiko Odaki         if (core->mac[PBACLR] & BIT(i)) {
27613a977deeSAkihiko Odaki             msix_clr_pending(core->owner, i);
27623a977deeSAkihiko Odaki         }
27633a977deeSAkihiko Odaki     }
27643a977deeSAkihiko Odaki }
27653a977deeSAkihiko Odaki 
27663a977deeSAkihiko Odaki static void
igb_set_fcrth(IGBCore * core,int index,uint32_t val)27673a977deeSAkihiko Odaki igb_set_fcrth(IGBCore *core, int index, uint32_t val)
27683a977deeSAkihiko Odaki {
27693a977deeSAkihiko Odaki     core->mac[FCRTH] = val & 0xFFF8;
27703a977deeSAkihiko Odaki }
27713a977deeSAkihiko Odaki 
27723a977deeSAkihiko Odaki static void
igb_set_fcrtl(IGBCore * core,int index,uint32_t val)27733a977deeSAkihiko Odaki igb_set_fcrtl(IGBCore *core, int index, uint32_t val)
27743a977deeSAkihiko Odaki {
27753a977deeSAkihiko Odaki     core->mac[FCRTL] = val & 0x8000FFF8;
27763a977deeSAkihiko Odaki }
27773a977deeSAkihiko Odaki 
27783a977deeSAkihiko Odaki #define IGB_LOW_BITS_SET_FUNC(num)                             \
27793a977deeSAkihiko Odaki     static void                                                \
27803a977deeSAkihiko Odaki     igb_set_##num##bit(IGBCore *core, int index, uint32_t val) \
27813a977deeSAkihiko Odaki     {                                                          \
27823a977deeSAkihiko Odaki         core->mac[index] = val & (BIT(num) - 1);               \
27833a977deeSAkihiko Odaki     }
27843a977deeSAkihiko Odaki 
27853a977deeSAkihiko Odaki IGB_LOW_BITS_SET_FUNC(4)
27863a977deeSAkihiko Odaki IGB_LOW_BITS_SET_FUNC(13)
27873a977deeSAkihiko Odaki IGB_LOW_BITS_SET_FUNC(16)
27883a977deeSAkihiko Odaki 
27893a977deeSAkihiko Odaki static void
igb_set_dlen(IGBCore * core,int index,uint32_t val)27903a977deeSAkihiko Odaki igb_set_dlen(IGBCore *core, int index, uint32_t val)
27913a977deeSAkihiko Odaki {
27923a977deeSAkihiko Odaki     core->mac[index] = val & 0xffff0;
27933a977deeSAkihiko Odaki }
27943a977deeSAkihiko Odaki 
27953a977deeSAkihiko Odaki static void
igb_set_dbal(IGBCore * core,int index,uint32_t val)27963a977deeSAkihiko Odaki igb_set_dbal(IGBCore *core, int index, uint32_t val)
27973a977deeSAkihiko Odaki {
27983a977deeSAkihiko Odaki     core->mac[index] = val & E1000_XDBAL_MASK;
27993a977deeSAkihiko Odaki }
28003a977deeSAkihiko Odaki 
28013a977deeSAkihiko Odaki static void
igb_set_tdt(IGBCore * core,int index,uint32_t val)28023a977deeSAkihiko Odaki igb_set_tdt(IGBCore *core, int index, uint32_t val)
28033a977deeSAkihiko Odaki {
28043a977deeSAkihiko Odaki     IGB_TxRing txr;
28053a977deeSAkihiko Odaki     int qn = igb_mq_queue_idx(TDT0, index);
28063a977deeSAkihiko Odaki 
28073a977deeSAkihiko Odaki     core->mac[index] = val & 0xffff;
28083a977deeSAkihiko Odaki 
28093a977deeSAkihiko Odaki     igb_tx_ring_init(core, &txr, qn);
28103a977deeSAkihiko Odaki     igb_start_xmit(core, &txr);
28113a977deeSAkihiko Odaki }
28123a977deeSAkihiko Odaki 
28133a977deeSAkihiko Odaki static void
igb_set_ics(IGBCore * core,int index,uint32_t val)28143a977deeSAkihiko Odaki igb_set_ics(IGBCore *core, int index, uint32_t val)
28153a977deeSAkihiko Odaki {
28163a977deeSAkihiko Odaki     trace_e1000e_irq_write_ics(val);
28175844562bSAkihiko Odaki     igb_raise_interrupts(core, ICR, val);
28183a977deeSAkihiko Odaki }
28193a977deeSAkihiko Odaki 
28203a977deeSAkihiko Odaki static void
igb_set_imc(IGBCore * core,int index,uint32_t val)28213a977deeSAkihiko Odaki igb_set_imc(IGBCore *core, int index, uint32_t val)
28223a977deeSAkihiko Odaki {
28233a977deeSAkihiko Odaki     trace_e1000e_irq_ims_clear_set_imc(val);
28245844562bSAkihiko Odaki     igb_lower_interrupts(core, IMS, val);
28253a977deeSAkihiko Odaki }
28263a977deeSAkihiko Odaki 
28273a977deeSAkihiko Odaki static void
igb_set_ims(IGBCore * core,int index,uint32_t val)28283a977deeSAkihiko Odaki igb_set_ims(IGBCore *core, int index, uint32_t val)
28293a977deeSAkihiko Odaki {
28305844562bSAkihiko Odaki     igb_raise_interrupts(core, IMS, val & 0x77D4FBFD);
28313a977deeSAkihiko Odaki }
28323a977deeSAkihiko Odaki 
igb_nsicr(IGBCore * core)28335844562bSAkihiko Odaki static void igb_nsicr(IGBCore *core)
28343a977deeSAkihiko Odaki {
28353a977deeSAkihiko Odaki     /*
2836f0b1df5cSAkihiko Odaki      * If GPIE.NSICR = 0, then the clear of IMS will occur only if at
28373a977deeSAkihiko Odaki      * least one bit is set in the IMS and there is a true interrupt as
28383a977deeSAkihiko Odaki      * reflected in ICR.INTA.
28393a977deeSAkihiko Odaki      */
28403a977deeSAkihiko Odaki     if ((core->mac[GPIE] & E1000_GPIE_NSICR) ||
28413a977deeSAkihiko Odaki         (core->mac[IMS] && (core->mac[ICR] & E1000_ICR_INT_ASSERTED))) {
28425844562bSAkihiko Odaki         igb_lower_interrupts(core, IMS, core->mac[IAM]);
28433a977deeSAkihiko Odaki     }
28443a977deeSAkihiko Odaki }
28453a977deeSAkihiko Odaki 
igb_set_icr(IGBCore * core,int index,uint32_t val)28463a977deeSAkihiko Odaki static void igb_set_icr(IGBCore *core, int index, uint32_t val)
28473a977deeSAkihiko Odaki {
28485844562bSAkihiko Odaki     igb_nsicr(core);
28495844562bSAkihiko Odaki     igb_lower_interrupts(core, ICR, val);
28503a977deeSAkihiko Odaki }
28513a977deeSAkihiko Odaki 
28523a977deeSAkihiko Odaki static uint32_t
igb_mac_readreg(IGBCore * core,int index)28533a977deeSAkihiko Odaki igb_mac_readreg(IGBCore *core, int index)
28543a977deeSAkihiko Odaki {
28553a977deeSAkihiko Odaki     return core->mac[index];
28563a977deeSAkihiko Odaki }
28573a977deeSAkihiko Odaki 
28583a977deeSAkihiko Odaki static uint32_t
igb_mac_ics_read(IGBCore * core,int index)28593a977deeSAkihiko Odaki igb_mac_ics_read(IGBCore *core, int index)
28603a977deeSAkihiko Odaki {
28613a977deeSAkihiko Odaki     trace_e1000e_irq_read_ics(core->mac[ICS]);
28623a977deeSAkihiko Odaki     return core->mac[ICS];
28633a977deeSAkihiko Odaki }
28643a977deeSAkihiko Odaki 
28653a977deeSAkihiko Odaki static uint32_t
igb_mac_ims_read(IGBCore * core,int index)28663a977deeSAkihiko Odaki igb_mac_ims_read(IGBCore *core, int index)
28673a977deeSAkihiko Odaki {
28683a977deeSAkihiko Odaki     trace_e1000e_irq_read_ims(core->mac[IMS]);
28693a977deeSAkihiko Odaki     return core->mac[IMS];
28703a977deeSAkihiko Odaki }
28713a977deeSAkihiko Odaki 
28723a977deeSAkihiko Odaki static uint32_t
igb_mac_swsm_read(IGBCore * core,int index)28733a977deeSAkihiko Odaki igb_mac_swsm_read(IGBCore *core, int index)
28743a977deeSAkihiko Odaki {
28753a977deeSAkihiko Odaki     uint32_t val = core->mac[SWSM];
28763a977deeSAkihiko Odaki     core->mac[SWSM] = val | E1000_SWSM_SMBI;
28773a977deeSAkihiko Odaki     return val;
28783a977deeSAkihiko Odaki }
28793a977deeSAkihiko Odaki 
28803a977deeSAkihiko Odaki static uint32_t
igb_mac_eitr_read(IGBCore * core,int index)28813a977deeSAkihiko Odaki igb_mac_eitr_read(IGBCore *core, int index)
28823a977deeSAkihiko Odaki {
28833a977deeSAkihiko Odaki     return core->eitr_guest_value[index - EITR0];
28843a977deeSAkihiko Odaki }
28853a977deeSAkihiko Odaki 
igb_mac_vfmailbox_read(IGBCore * core,int index)28863a977deeSAkihiko Odaki static uint32_t igb_mac_vfmailbox_read(IGBCore *core, int index)
28873a977deeSAkihiko Odaki {
28883a977deeSAkihiko Odaki     uint32_t val = core->mac[index];
28893a977deeSAkihiko Odaki 
28903a977deeSAkihiko Odaki     core->mac[index] &= ~(E1000_V2PMAILBOX_PFSTS | E1000_V2PMAILBOX_PFACK |
28913a977deeSAkihiko Odaki                           E1000_V2PMAILBOX_RSTD);
28923a977deeSAkihiko Odaki 
28933a977deeSAkihiko Odaki     return val;
28943a977deeSAkihiko Odaki }
28953a977deeSAkihiko Odaki 
28963a977deeSAkihiko Odaki static uint32_t
igb_mac_icr_read(IGBCore * core,int index)28973a977deeSAkihiko Odaki igb_mac_icr_read(IGBCore *core, int index)
28983a977deeSAkihiko Odaki {
28993a977deeSAkihiko Odaki     uint32_t ret = core->mac[ICR];
29003a977deeSAkihiko Odaki 
29013a977deeSAkihiko Odaki     if (core->mac[GPIE] & E1000_GPIE_NSICR) {
29023a977deeSAkihiko Odaki         trace_igb_irq_icr_clear_gpie_nsicr();
29035844562bSAkihiko Odaki         igb_lower_interrupts(core, ICR, 0xffffffff);
29043a977deeSAkihiko Odaki     } else if (core->mac[IMS] == 0) {
29053a977deeSAkihiko Odaki         trace_e1000e_irq_icr_clear_zero_ims();
29065844562bSAkihiko Odaki         igb_lower_interrupts(core, ICR, 0xffffffff);
2907efb1fd7aSAkihiko Odaki     } else if (core->mac[ICR] & E1000_ICR_INT_ASSERTED) {
2908efb1fd7aSAkihiko Odaki         igb_lower_interrupts(core, ICR, 0xffffffff);
29093a977deeSAkihiko Odaki     } else if (!msix_enabled(core->owner)) {
29103a977deeSAkihiko Odaki         trace_e1000e_irq_icr_clear_nonmsix_icr_read();
29115844562bSAkihiko Odaki         igb_lower_interrupts(core, ICR, 0xffffffff);
29123a977deeSAkihiko Odaki     }
29133a977deeSAkihiko Odaki 
29145844562bSAkihiko Odaki     igb_nsicr(core);
29153a977deeSAkihiko Odaki     return ret;
29163a977deeSAkihiko Odaki }
29173a977deeSAkihiko Odaki 
29183a977deeSAkihiko Odaki static uint32_t
igb_mac_read_clr4(IGBCore * core,int index)29193a977deeSAkihiko Odaki igb_mac_read_clr4(IGBCore *core, int index)
29203a977deeSAkihiko Odaki {
29213a977deeSAkihiko Odaki     uint32_t ret = core->mac[index];
29223a977deeSAkihiko Odaki 
29233a977deeSAkihiko Odaki     core->mac[index] = 0;
29243a977deeSAkihiko Odaki     return ret;
29253a977deeSAkihiko Odaki }
29263a977deeSAkihiko Odaki 
29273a977deeSAkihiko Odaki static uint32_t
igb_mac_read_clr8(IGBCore * core,int index)29283a977deeSAkihiko Odaki igb_mac_read_clr8(IGBCore *core, int index)
29293a977deeSAkihiko Odaki {
29303a977deeSAkihiko Odaki     uint32_t ret = core->mac[index];
29313a977deeSAkihiko Odaki 
29323a977deeSAkihiko Odaki     core->mac[index] = 0;
29333a977deeSAkihiko Odaki     core->mac[index - 1] = 0;
29343a977deeSAkihiko Odaki     return ret;
29353a977deeSAkihiko Odaki }
29363a977deeSAkihiko Odaki 
29373a977deeSAkihiko Odaki static uint32_t
igb_get_ctrl(IGBCore * core,int index)29383a977deeSAkihiko Odaki igb_get_ctrl(IGBCore *core, int index)
29393a977deeSAkihiko Odaki {
29403a977deeSAkihiko Odaki     uint32_t val = core->mac[CTRL];
29413a977deeSAkihiko Odaki 
29423a977deeSAkihiko Odaki     trace_e1000e_link_read_params(
29433a977deeSAkihiko Odaki         !!(val & E1000_CTRL_ASDE),
29443a977deeSAkihiko Odaki         (val & E1000_CTRL_SPD_SEL) >> E1000_CTRL_SPD_SHIFT,
29453a977deeSAkihiko Odaki         !!(val & E1000_CTRL_FRCSPD),
29463a977deeSAkihiko Odaki         !!(val & E1000_CTRL_FRCDPX),
29473a977deeSAkihiko Odaki         !!(val & E1000_CTRL_RFCE),
29483a977deeSAkihiko Odaki         !!(val & E1000_CTRL_TFCE));
29493a977deeSAkihiko Odaki 
29503a977deeSAkihiko Odaki     return val;
29513a977deeSAkihiko Odaki }
29523a977deeSAkihiko Odaki 
igb_get_status(IGBCore * core,int index)29533a977deeSAkihiko Odaki static uint32_t igb_get_status(IGBCore *core, int index)
29543a977deeSAkihiko Odaki {
29553a977deeSAkihiko Odaki     uint32_t res = core->mac[STATUS];
29563a977deeSAkihiko Odaki     uint16_t num_vfs = pcie_sriov_num_vfs(core->owner);
29573a977deeSAkihiko Odaki 
29583a977deeSAkihiko Odaki     if (core->mac[CTRL] & E1000_CTRL_FRCDPX) {
29593a977deeSAkihiko Odaki         res |= (core->mac[CTRL] & E1000_CTRL_FD) ? E1000_STATUS_FD : 0;
29603a977deeSAkihiko Odaki     } else {
29613a977deeSAkihiko Odaki         res |= E1000_STATUS_FD;
29623a977deeSAkihiko Odaki     }
29633a977deeSAkihiko Odaki 
29643a977deeSAkihiko Odaki     if ((core->mac[CTRL] & E1000_CTRL_FRCSPD) ||
29653a977deeSAkihiko Odaki         (core->mac[CTRL_EXT] & E1000_CTRL_EXT_SPD_BYPS)) {
29663a977deeSAkihiko Odaki         switch (core->mac[CTRL] & E1000_CTRL_SPD_SEL) {
29673a977deeSAkihiko Odaki         case E1000_CTRL_SPD_10:
29683a977deeSAkihiko Odaki             res |= E1000_STATUS_SPEED_10;
29693a977deeSAkihiko Odaki             break;
29703a977deeSAkihiko Odaki         case E1000_CTRL_SPD_100:
29713a977deeSAkihiko Odaki             res |= E1000_STATUS_SPEED_100;
29723a977deeSAkihiko Odaki             break;
29733a977deeSAkihiko Odaki         case E1000_CTRL_SPD_1000:
29743a977deeSAkihiko Odaki         default:
29753a977deeSAkihiko Odaki             res |= E1000_STATUS_SPEED_1000;
29763a977deeSAkihiko Odaki             break;
29773a977deeSAkihiko Odaki         }
29783a977deeSAkihiko Odaki     } else {
29793a977deeSAkihiko Odaki         res |= E1000_STATUS_SPEED_1000;
29803a977deeSAkihiko Odaki     }
29813a977deeSAkihiko Odaki 
29823a977deeSAkihiko Odaki     if (num_vfs) {
29833a977deeSAkihiko Odaki         res |= num_vfs << E1000_STATUS_NUM_VFS_SHIFT;
29843a977deeSAkihiko Odaki         res |= E1000_STATUS_IOV_MODE;
29853a977deeSAkihiko Odaki     }
29863a977deeSAkihiko Odaki 
2987da9f7f77SAkihiko Odaki     if (!(core->mac[CTRL] & E1000_CTRL_GIO_MASTER_DISABLE)) {
29883a977deeSAkihiko Odaki         res |= E1000_STATUS_GIO_MASTER_ENABLE;
29893a977deeSAkihiko Odaki     }
29903a977deeSAkihiko Odaki 
29913a977deeSAkihiko Odaki     return res;
29923a977deeSAkihiko Odaki }
29933a977deeSAkihiko Odaki 
29943a977deeSAkihiko Odaki static void
igb_mac_writereg(IGBCore * core,int index,uint32_t val)29953a977deeSAkihiko Odaki igb_mac_writereg(IGBCore *core, int index, uint32_t val)
29963a977deeSAkihiko Odaki {
29973a977deeSAkihiko Odaki     core->mac[index] = val;
29983a977deeSAkihiko Odaki }
29993a977deeSAkihiko Odaki 
30003a977deeSAkihiko Odaki static void
igb_mac_setmacaddr(IGBCore * core,int index,uint32_t val)30013a977deeSAkihiko Odaki igb_mac_setmacaddr(IGBCore *core, int index, uint32_t val)
30023a977deeSAkihiko Odaki {
30033a977deeSAkihiko Odaki     uint32_t macaddr[2];
30043a977deeSAkihiko Odaki 
30053a977deeSAkihiko Odaki     core->mac[index] = val;
30063a977deeSAkihiko Odaki 
30073a977deeSAkihiko Odaki     macaddr[0] = cpu_to_le32(core->mac[RA]);
30083a977deeSAkihiko Odaki     macaddr[1] = cpu_to_le32(core->mac[RA + 1]);
30093a977deeSAkihiko Odaki     qemu_format_nic_info_str(qemu_get_queue(core->owner_nic),
30103a977deeSAkihiko Odaki         (uint8_t *) macaddr);
30113a977deeSAkihiko Odaki 
30123a977deeSAkihiko Odaki     trace_e1000e_mac_set_sw(MAC_ARG(macaddr));
30133a977deeSAkihiko Odaki }
30143a977deeSAkihiko Odaki 
30153a977deeSAkihiko Odaki static void
igb_set_eecd(IGBCore * core,int index,uint32_t val)30163a977deeSAkihiko Odaki igb_set_eecd(IGBCore *core, int index, uint32_t val)
30173a977deeSAkihiko Odaki {
30183a977deeSAkihiko Odaki     static const uint32_t ro_bits = E1000_EECD_PRES          |
30193a977deeSAkihiko Odaki                                     E1000_EECD_AUTO_RD       |
30203a977deeSAkihiko Odaki                                     E1000_EECD_SIZE_EX_MASK;
30213a977deeSAkihiko Odaki 
30223a977deeSAkihiko Odaki     core->mac[EECD] = (core->mac[EECD] & ro_bits) | (val & ~ro_bits);
30233a977deeSAkihiko Odaki }
30243a977deeSAkihiko Odaki 
30253a977deeSAkihiko Odaki static void
igb_set_eerd(IGBCore * core,int index,uint32_t val)30263a977deeSAkihiko Odaki igb_set_eerd(IGBCore *core, int index, uint32_t val)
30273a977deeSAkihiko Odaki {
30283a977deeSAkihiko Odaki     uint32_t addr = (val >> E1000_EERW_ADDR_SHIFT) & E1000_EERW_ADDR_MASK;
30293a977deeSAkihiko Odaki     uint32_t flags = 0;
30303a977deeSAkihiko Odaki     uint32_t data = 0;
30313a977deeSAkihiko Odaki 
30323a977deeSAkihiko Odaki     if ((addr < IGB_EEPROM_SIZE) && (val & E1000_EERW_START)) {
30333a977deeSAkihiko Odaki         data = core->eeprom[addr];
30343a977deeSAkihiko Odaki         flags = E1000_EERW_DONE;
30353a977deeSAkihiko Odaki     }
30363a977deeSAkihiko Odaki 
30373a977deeSAkihiko Odaki     core->mac[EERD] = flags                           |
30383a977deeSAkihiko Odaki                       (addr << E1000_EERW_ADDR_SHIFT) |
30393a977deeSAkihiko Odaki                       (data << E1000_EERW_DATA_SHIFT);
30403a977deeSAkihiko Odaki }
30413a977deeSAkihiko Odaki 
30423a977deeSAkihiko Odaki static void
igb_set_eitr(IGBCore * core,int index,uint32_t val)30433a977deeSAkihiko Odaki igb_set_eitr(IGBCore *core, int index, uint32_t val)
30443a977deeSAkihiko Odaki {
30453a977deeSAkihiko Odaki     uint32_t eitr_num = index - EITR0;
30463a977deeSAkihiko Odaki 
30473a977deeSAkihiko Odaki     trace_igb_irq_eitr_set(eitr_num, val);
30483a977deeSAkihiko Odaki 
30493a977deeSAkihiko Odaki     core->eitr_guest_value[eitr_num] = val & ~E1000_EITR_CNT_IGNR;
30503a977deeSAkihiko Odaki     core->mac[index] = val & 0x7FFE;
30513a977deeSAkihiko Odaki }
30523a977deeSAkihiko Odaki 
30533a977deeSAkihiko Odaki static void
igb_update_rx_offloads(IGBCore * core)30543a977deeSAkihiko Odaki igb_update_rx_offloads(IGBCore *core)
30553a977deeSAkihiko Odaki {
30563a977deeSAkihiko Odaki     int cso_state = igb_rx_l4_cso_enabled(core);
30573a977deeSAkihiko Odaki 
30583a977deeSAkihiko Odaki     trace_e1000e_rx_set_cso(cso_state);
30593a977deeSAkihiko Odaki 
30603a977deeSAkihiko Odaki     if (core->has_vnet) {
30613a977deeSAkihiko Odaki         qemu_set_offload(qemu_get_queue(core->owner_nic)->peer,
30622ab0ec31SAndrew Melnychenko                          cso_state, 0, 0, 0, 0, 0, 0);
30633a977deeSAkihiko Odaki     }
30643a977deeSAkihiko Odaki }
30653a977deeSAkihiko Odaki 
30663a977deeSAkihiko Odaki static void
igb_set_rxcsum(IGBCore * core,int index,uint32_t val)30673a977deeSAkihiko Odaki igb_set_rxcsum(IGBCore *core, int index, uint32_t val)
30683a977deeSAkihiko Odaki {
30693a977deeSAkihiko Odaki     core->mac[RXCSUM] = val;
30703a977deeSAkihiko Odaki     igb_update_rx_offloads(core);
30713a977deeSAkihiko Odaki }
30723a977deeSAkihiko Odaki 
30733a977deeSAkihiko Odaki static void
igb_set_gcr(IGBCore * core,int index,uint32_t val)30743a977deeSAkihiko Odaki igb_set_gcr(IGBCore *core, int index, uint32_t val)
30753a977deeSAkihiko Odaki {
30763a977deeSAkihiko Odaki     uint32_t ro_bits = core->mac[GCR] & E1000_GCR_RO_BITS;
30773a977deeSAkihiko Odaki     core->mac[GCR] = (val & ~E1000_GCR_RO_BITS) | ro_bits;
30783a977deeSAkihiko Odaki }
30793a977deeSAkihiko Odaki 
igb_get_systiml(IGBCore * core,int index)30803a977deeSAkihiko Odaki static uint32_t igb_get_systiml(IGBCore *core, int index)
30813a977deeSAkihiko Odaki {
30823a977deeSAkihiko Odaki     e1000x_timestamp(core->mac, core->timadj, SYSTIML, SYSTIMH);
30833a977deeSAkihiko Odaki     return core->mac[SYSTIML];
30843a977deeSAkihiko Odaki }
30853a977deeSAkihiko Odaki 
igb_get_rxsatrh(IGBCore * core,int index)30863a977deeSAkihiko Odaki static uint32_t igb_get_rxsatrh(IGBCore *core, int index)
30873a977deeSAkihiko Odaki {
30883a977deeSAkihiko Odaki     core->mac[TSYNCRXCTL] &= ~E1000_TSYNCRXCTL_VALID;
30893a977deeSAkihiko Odaki     return core->mac[RXSATRH];
30903a977deeSAkihiko Odaki }
30913a977deeSAkihiko Odaki 
igb_get_txstmph(IGBCore * core,int index)30923a977deeSAkihiko Odaki static uint32_t igb_get_txstmph(IGBCore *core, int index)
30933a977deeSAkihiko Odaki {
30943a977deeSAkihiko Odaki     core->mac[TSYNCTXCTL] &= ~E1000_TSYNCTXCTL_VALID;
30953a977deeSAkihiko Odaki     return core->mac[TXSTMPH];
30963a977deeSAkihiko Odaki }
30973a977deeSAkihiko Odaki 
igb_set_timinca(IGBCore * core,int index,uint32_t val)30983a977deeSAkihiko Odaki static void igb_set_timinca(IGBCore *core, int index, uint32_t val)
30993a977deeSAkihiko Odaki {
31003a977deeSAkihiko Odaki     e1000x_set_timinca(core->mac, &core->timadj, val);
31013a977deeSAkihiko Odaki }
31023a977deeSAkihiko Odaki 
igb_set_timadjh(IGBCore * core,int index,uint32_t val)31033a977deeSAkihiko Odaki static void igb_set_timadjh(IGBCore *core, int index, uint32_t val)
31043a977deeSAkihiko Odaki {
31053a977deeSAkihiko Odaki     core->mac[TIMADJH] = val;
31063a977deeSAkihiko Odaki     core->timadj += core->mac[TIMADJL] | ((int64_t)core->mac[TIMADJH] << 32);
31073a977deeSAkihiko Odaki }
31083a977deeSAkihiko Odaki 
31093a977deeSAkihiko Odaki #define igb_getreg(x)    [x] = igb_mac_readreg
31103a977deeSAkihiko Odaki typedef uint32_t (*readops)(IGBCore *, int);
31113a977deeSAkihiko Odaki static const readops igb_macreg_readops[] = {
31123a977deeSAkihiko Odaki     igb_getreg(WUFC),
31133a977deeSAkihiko Odaki     igb_getreg(MANC),
31143a977deeSAkihiko Odaki     igb_getreg(TOTL),
31153a977deeSAkihiko Odaki     igb_getreg(RDT0),
31163a977deeSAkihiko Odaki     igb_getreg(RDT1),
31173a977deeSAkihiko Odaki     igb_getreg(RDT2),
31183a977deeSAkihiko Odaki     igb_getreg(RDT3),
31193a977deeSAkihiko Odaki     igb_getreg(RDT4),
31203a977deeSAkihiko Odaki     igb_getreg(RDT5),
31213a977deeSAkihiko Odaki     igb_getreg(RDT6),
31223a977deeSAkihiko Odaki     igb_getreg(RDT7),
31233a977deeSAkihiko Odaki     igb_getreg(RDT8),
31243a977deeSAkihiko Odaki     igb_getreg(RDT9),
31253a977deeSAkihiko Odaki     igb_getreg(RDT10),
31263a977deeSAkihiko Odaki     igb_getreg(RDT11),
31273a977deeSAkihiko Odaki     igb_getreg(RDT12),
31283a977deeSAkihiko Odaki     igb_getreg(RDT13),
31293a977deeSAkihiko Odaki     igb_getreg(RDT14),
31303a977deeSAkihiko Odaki     igb_getreg(RDT15),
31313a977deeSAkihiko Odaki     igb_getreg(RDBAH0),
31323a977deeSAkihiko Odaki     igb_getreg(RDBAH1),
31333a977deeSAkihiko Odaki     igb_getreg(RDBAH2),
31343a977deeSAkihiko Odaki     igb_getreg(RDBAH3),
31353a977deeSAkihiko Odaki     igb_getreg(RDBAH4),
31363a977deeSAkihiko Odaki     igb_getreg(RDBAH5),
31373a977deeSAkihiko Odaki     igb_getreg(RDBAH6),
31383a977deeSAkihiko Odaki     igb_getreg(RDBAH7),
31393a977deeSAkihiko Odaki     igb_getreg(RDBAH8),
31403a977deeSAkihiko Odaki     igb_getreg(RDBAH9),
31413a977deeSAkihiko Odaki     igb_getreg(RDBAH10),
31423a977deeSAkihiko Odaki     igb_getreg(RDBAH11),
31433a977deeSAkihiko Odaki     igb_getreg(RDBAH12),
31443a977deeSAkihiko Odaki     igb_getreg(RDBAH13),
31453a977deeSAkihiko Odaki     igb_getreg(RDBAH14),
31463a977deeSAkihiko Odaki     igb_getreg(RDBAH15),
31473a977deeSAkihiko Odaki     igb_getreg(TDBAL0),
31483a977deeSAkihiko Odaki     igb_getreg(TDBAL1),
31493a977deeSAkihiko Odaki     igb_getreg(TDBAL2),
31503a977deeSAkihiko Odaki     igb_getreg(TDBAL3),
31513a977deeSAkihiko Odaki     igb_getreg(TDBAL4),
31523a977deeSAkihiko Odaki     igb_getreg(TDBAL5),
31533a977deeSAkihiko Odaki     igb_getreg(TDBAL6),
31543a977deeSAkihiko Odaki     igb_getreg(TDBAL7),
31553a977deeSAkihiko Odaki     igb_getreg(TDBAL8),
31563a977deeSAkihiko Odaki     igb_getreg(TDBAL9),
31573a977deeSAkihiko Odaki     igb_getreg(TDBAL10),
31583a977deeSAkihiko Odaki     igb_getreg(TDBAL11),
31593a977deeSAkihiko Odaki     igb_getreg(TDBAL12),
31603a977deeSAkihiko Odaki     igb_getreg(TDBAL13),
31613a977deeSAkihiko Odaki     igb_getreg(TDBAL14),
31623a977deeSAkihiko Odaki     igb_getreg(TDBAL15),
31633a977deeSAkihiko Odaki     igb_getreg(RDLEN0),
31643a977deeSAkihiko Odaki     igb_getreg(RDLEN1),
31653a977deeSAkihiko Odaki     igb_getreg(RDLEN2),
31663a977deeSAkihiko Odaki     igb_getreg(RDLEN3),
31673a977deeSAkihiko Odaki     igb_getreg(RDLEN4),
31683a977deeSAkihiko Odaki     igb_getreg(RDLEN5),
31693a977deeSAkihiko Odaki     igb_getreg(RDLEN6),
31703a977deeSAkihiko Odaki     igb_getreg(RDLEN7),
31713a977deeSAkihiko Odaki     igb_getreg(RDLEN8),
31723a977deeSAkihiko Odaki     igb_getreg(RDLEN9),
31733a977deeSAkihiko Odaki     igb_getreg(RDLEN10),
31743a977deeSAkihiko Odaki     igb_getreg(RDLEN11),
31753a977deeSAkihiko Odaki     igb_getreg(RDLEN12),
31763a977deeSAkihiko Odaki     igb_getreg(RDLEN13),
31773a977deeSAkihiko Odaki     igb_getreg(RDLEN14),
31783a977deeSAkihiko Odaki     igb_getreg(RDLEN15),
31793a977deeSAkihiko Odaki     igb_getreg(SRRCTL0),
31803a977deeSAkihiko Odaki     igb_getreg(SRRCTL1),
31813a977deeSAkihiko Odaki     igb_getreg(SRRCTL2),
31823a977deeSAkihiko Odaki     igb_getreg(SRRCTL3),
31833a977deeSAkihiko Odaki     igb_getreg(SRRCTL4),
31843a977deeSAkihiko Odaki     igb_getreg(SRRCTL5),
31853a977deeSAkihiko Odaki     igb_getreg(SRRCTL6),
31863a977deeSAkihiko Odaki     igb_getreg(SRRCTL7),
31873a977deeSAkihiko Odaki     igb_getreg(SRRCTL8),
31883a977deeSAkihiko Odaki     igb_getreg(SRRCTL9),
31893a977deeSAkihiko Odaki     igb_getreg(SRRCTL10),
31903a977deeSAkihiko Odaki     igb_getreg(SRRCTL11),
31913a977deeSAkihiko Odaki     igb_getreg(SRRCTL12),
31923a977deeSAkihiko Odaki     igb_getreg(SRRCTL13),
31933a977deeSAkihiko Odaki     igb_getreg(SRRCTL14),
31943a977deeSAkihiko Odaki     igb_getreg(SRRCTL15),
31953a977deeSAkihiko Odaki     igb_getreg(LATECOL),
31963a977deeSAkihiko Odaki     igb_getreg(XONTXC),
31973a977deeSAkihiko Odaki     igb_getreg(TDFH),
31983a977deeSAkihiko Odaki     igb_getreg(TDFT),
31993a977deeSAkihiko Odaki     igb_getreg(TDFHS),
32003a977deeSAkihiko Odaki     igb_getreg(TDFTS),
32013a977deeSAkihiko Odaki     igb_getreg(TDFPC),
32023a977deeSAkihiko Odaki     igb_getreg(WUS),
32033a977deeSAkihiko Odaki     igb_getreg(RDFH),
32043a977deeSAkihiko Odaki     igb_getreg(RDFT),
32053a977deeSAkihiko Odaki     igb_getreg(RDFHS),
32063a977deeSAkihiko Odaki     igb_getreg(RDFTS),
32073a977deeSAkihiko Odaki     igb_getreg(RDFPC),
32083a977deeSAkihiko Odaki     igb_getreg(GORCL),
32093a977deeSAkihiko Odaki     igb_getreg(MGTPRC),
32103a977deeSAkihiko Odaki     igb_getreg(EERD),
32113a977deeSAkihiko Odaki     igb_getreg(EIAC),
32123a977deeSAkihiko Odaki     igb_getreg(MANC2H),
32133a977deeSAkihiko Odaki     igb_getreg(RXCSUM),
32143a977deeSAkihiko Odaki     igb_getreg(GSCL_3),
32153a977deeSAkihiko Odaki     igb_getreg(GSCN_2),
32163a977deeSAkihiko Odaki     igb_getreg(FCAH),
32173a977deeSAkihiko Odaki     igb_getreg(FCRTH),
32183a977deeSAkihiko Odaki     igb_getreg(FLOP),
32193a977deeSAkihiko Odaki     igb_getreg(RXSTMPH),
32203a977deeSAkihiko Odaki     igb_getreg(TXSTMPL),
32213a977deeSAkihiko Odaki     igb_getreg(TIMADJL),
32223a977deeSAkihiko Odaki     igb_getreg(RDH0),
32233a977deeSAkihiko Odaki     igb_getreg(RDH1),
32243a977deeSAkihiko Odaki     igb_getreg(RDH2),
32253a977deeSAkihiko Odaki     igb_getreg(RDH3),
32263a977deeSAkihiko Odaki     igb_getreg(RDH4),
32273a977deeSAkihiko Odaki     igb_getreg(RDH5),
32283a977deeSAkihiko Odaki     igb_getreg(RDH6),
32293a977deeSAkihiko Odaki     igb_getreg(RDH7),
32303a977deeSAkihiko Odaki     igb_getreg(RDH8),
32313a977deeSAkihiko Odaki     igb_getreg(RDH9),
32323a977deeSAkihiko Odaki     igb_getreg(RDH10),
32333a977deeSAkihiko Odaki     igb_getreg(RDH11),
32343a977deeSAkihiko Odaki     igb_getreg(RDH12),
32353a977deeSAkihiko Odaki     igb_getreg(RDH13),
32363a977deeSAkihiko Odaki     igb_getreg(RDH14),
32373a977deeSAkihiko Odaki     igb_getreg(RDH15),
32383a977deeSAkihiko Odaki     igb_getreg(TDT0),
32393a977deeSAkihiko Odaki     igb_getreg(TDT1),
32403a977deeSAkihiko Odaki     igb_getreg(TDT2),
32413a977deeSAkihiko Odaki     igb_getreg(TDT3),
32423a977deeSAkihiko Odaki     igb_getreg(TDT4),
32433a977deeSAkihiko Odaki     igb_getreg(TDT5),
32443a977deeSAkihiko Odaki     igb_getreg(TDT6),
32453a977deeSAkihiko Odaki     igb_getreg(TDT7),
32463a977deeSAkihiko Odaki     igb_getreg(TDT8),
32473a977deeSAkihiko Odaki     igb_getreg(TDT9),
32483a977deeSAkihiko Odaki     igb_getreg(TDT10),
32493a977deeSAkihiko Odaki     igb_getreg(TDT11),
32503a977deeSAkihiko Odaki     igb_getreg(TDT12),
32513a977deeSAkihiko Odaki     igb_getreg(TDT13),
32523a977deeSAkihiko Odaki     igb_getreg(TDT14),
32533a977deeSAkihiko Odaki     igb_getreg(TDT15),
32543a977deeSAkihiko Odaki     igb_getreg(TNCRS),
32553a977deeSAkihiko Odaki     igb_getreg(RJC),
32563a977deeSAkihiko Odaki     igb_getreg(IAM),
32573a977deeSAkihiko Odaki     igb_getreg(GSCL_2),
32583a977deeSAkihiko Odaki     igb_getreg(TIPG),
32593a977deeSAkihiko Odaki     igb_getreg(FLMNGCTL),
32603a977deeSAkihiko Odaki     igb_getreg(FLMNGCNT),
32613a977deeSAkihiko Odaki     igb_getreg(TSYNCTXCTL),
32623a977deeSAkihiko Odaki     igb_getreg(EEMNGDATA),
32633a977deeSAkihiko Odaki     igb_getreg(CTRL_EXT),
32643a977deeSAkihiko Odaki     igb_getreg(SYSTIMH),
32653a977deeSAkihiko Odaki     igb_getreg(EEMNGCTL),
32663a977deeSAkihiko Odaki     igb_getreg(FLMNGDATA),
32673a977deeSAkihiko Odaki     igb_getreg(TSYNCRXCTL),
32683a977deeSAkihiko Odaki     igb_getreg(LEDCTL),
32693a977deeSAkihiko Odaki     igb_getreg(TCTL),
32703a977deeSAkihiko Odaki     igb_getreg(TCTL_EXT),
32713a977deeSAkihiko Odaki     igb_getreg(DTXCTL),
32723a977deeSAkihiko Odaki     igb_getreg(RXPBS),
32733a977deeSAkihiko Odaki     igb_getreg(TDH0),
32743a977deeSAkihiko Odaki     igb_getreg(TDH1),
32753a977deeSAkihiko Odaki     igb_getreg(TDH2),
32763a977deeSAkihiko Odaki     igb_getreg(TDH3),
32773a977deeSAkihiko Odaki     igb_getreg(TDH4),
32783a977deeSAkihiko Odaki     igb_getreg(TDH5),
32793a977deeSAkihiko Odaki     igb_getreg(TDH6),
32803a977deeSAkihiko Odaki     igb_getreg(TDH7),
32813a977deeSAkihiko Odaki     igb_getreg(TDH8),
32823a977deeSAkihiko Odaki     igb_getreg(TDH9),
32833a977deeSAkihiko Odaki     igb_getreg(TDH10),
32843a977deeSAkihiko Odaki     igb_getreg(TDH11),
32853a977deeSAkihiko Odaki     igb_getreg(TDH12),
32863a977deeSAkihiko Odaki     igb_getreg(TDH13),
32873a977deeSAkihiko Odaki     igb_getreg(TDH14),
32883a977deeSAkihiko Odaki     igb_getreg(TDH15),
32893a977deeSAkihiko Odaki     igb_getreg(ECOL),
32903a977deeSAkihiko Odaki     igb_getreg(DC),
32913a977deeSAkihiko Odaki     igb_getreg(RLEC),
32923a977deeSAkihiko Odaki     igb_getreg(XOFFTXC),
32933a977deeSAkihiko Odaki     igb_getreg(RFC),
32943a977deeSAkihiko Odaki     igb_getreg(RNBC),
32953a977deeSAkihiko Odaki     igb_getreg(MGTPTC),
32963a977deeSAkihiko Odaki     igb_getreg(TIMINCA),
32973a977deeSAkihiko Odaki     igb_getreg(FACTPS),
32983a977deeSAkihiko Odaki     igb_getreg(GSCL_1),
32993a977deeSAkihiko Odaki     igb_getreg(GSCN_0),
33003a977deeSAkihiko Odaki     igb_getreg(PBACLR),
33013a977deeSAkihiko Odaki     igb_getreg(FCTTV),
33023a977deeSAkihiko Odaki     igb_getreg(RXSATRL),
33033a977deeSAkihiko Odaki     igb_getreg(TORL),
33043a977deeSAkihiko Odaki     igb_getreg(TDLEN0),
33053a977deeSAkihiko Odaki     igb_getreg(TDLEN1),
33063a977deeSAkihiko Odaki     igb_getreg(TDLEN2),
33073a977deeSAkihiko Odaki     igb_getreg(TDLEN3),
33083a977deeSAkihiko Odaki     igb_getreg(TDLEN4),
33093a977deeSAkihiko Odaki     igb_getreg(TDLEN5),
33103a977deeSAkihiko Odaki     igb_getreg(TDLEN6),
33113a977deeSAkihiko Odaki     igb_getreg(TDLEN7),
33123a977deeSAkihiko Odaki     igb_getreg(TDLEN8),
33133a977deeSAkihiko Odaki     igb_getreg(TDLEN9),
33143a977deeSAkihiko Odaki     igb_getreg(TDLEN10),
33153a977deeSAkihiko Odaki     igb_getreg(TDLEN11),
33163a977deeSAkihiko Odaki     igb_getreg(TDLEN12),
33173a977deeSAkihiko Odaki     igb_getreg(TDLEN13),
33183a977deeSAkihiko Odaki     igb_getreg(TDLEN14),
33193a977deeSAkihiko Odaki     igb_getreg(TDLEN15),
33203a977deeSAkihiko Odaki     igb_getreg(MCC),
33213a977deeSAkihiko Odaki     igb_getreg(WUC),
33223a977deeSAkihiko Odaki     igb_getreg(EECD),
33233a977deeSAkihiko Odaki     igb_getreg(FCRTV),
33243a977deeSAkihiko Odaki     igb_getreg(TXDCTL0),
33253a977deeSAkihiko Odaki     igb_getreg(TXDCTL1),
33263a977deeSAkihiko Odaki     igb_getreg(TXDCTL2),
33273a977deeSAkihiko Odaki     igb_getreg(TXDCTL3),
33283a977deeSAkihiko Odaki     igb_getreg(TXDCTL4),
33293a977deeSAkihiko Odaki     igb_getreg(TXDCTL5),
33303a977deeSAkihiko Odaki     igb_getreg(TXDCTL6),
33313a977deeSAkihiko Odaki     igb_getreg(TXDCTL7),
33323a977deeSAkihiko Odaki     igb_getreg(TXDCTL8),
33333a977deeSAkihiko Odaki     igb_getreg(TXDCTL9),
33343a977deeSAkihiko Odaki     igb_getreg(TXDCTL10),
33353a977deeSAkihiko Odaki     igb_getreg(TXDCTL11),
33363a977deeSAkihiko Odaki     igb_getreg(TXDCTL12),
33373a977deeSAkihiko Odaki     igb_getreg(TXDCTL13),
33383a977deeSAkihiko Odaki     igb_getreg(TXDCTL14),
33393a977deeSAkihiko Odaki     igb_getreg(TXDCTL15),
33403a977deeSAkihiko Odaki     igb_getreg(TXCTL0),
33413a977deeSAkihiko Odaki     igb_getreg(TXCTL1),
33423a977deeSAkihiko Odaki     igb_getreg(TXCTL2),
33433a977deeSAkihiko Odaki     igb_getreg(TXCTL3),
33443a977deeSAkihiko Odaki     igb_getreg(TXCTL4),
33453a977deeSAkihiko Odaki     igb_getreg(TXCTL5),
33463a977deeSAkihiko Odaki     igb_getreg(TXCTL6),
33473a977deeSAkihiko Odaki     igb_getreg(TXCTL7),
33483a977deeSAkihiko Odaki     igb_getreg(TXCTL8),
33493a977deeSAkihiko Odaki     igb_getreg(TXCTL9),
33503a977deeSAkihiko Odaki     igb_getreg(TXCTL10),
33513a977deeSAkihiko Odaki     igb_getreg(TXCTL11),
33523a977deeSAkihiko Odaki     igb_getreg(TXCTL12),
33533a977deeSAkihiko Odaki     igb_getreg(TXCTL13),
33543a977deeSAkihiko Odaki     igb_getreg(TXCTL14),
33553a977deeSAkihiko Odaki     igb_getreg(TXCTL15),
33563a977deeSAkihiko Odaki     igb_getreg(TDWBAL0),
33573a977deeSAkihiko Odaki     igb_getreg(TDWBAL1),
33583a977deeSAkihiko Odaki     igb_getreg(TDWBAL2),
33593a977deeSAkihiko Odaki     igb_getreg(TDWBAL3),
33603a977deeSAkihiko Odaki     igb_getreg(TDWBAL4),
33613a977deeSAkihiko Odaki     igb_getreg(TDWBAL5),
33623a977deeSAkihiko Odaki     igb_getreg(TDWBAL6),
33633a977deeSAkihiko Odaki     igb_getreg(TDWBAL7),
33643a977deeSAkihiko Odaki     igb_getreg(TDWBAL8),
33653a977deeSAkihiko Odaki     igb_getreg(TDWBAL9),
33663a977deeSAkihiko Odaki     igb_getreg(TDWBAL10),
33673a977deeSAkihiko Odaki     igb_getreg(TDWBAL11),
33683a977deeSAkihiko Odaki     igb_getreg(TDWBAL12),
33693a977deeSAkihiko Odaki     igb_getreg(TDWBAL13),
33703a977deeSAkihiko Odaki     igb_getreg(TDWBAL14),
33713a977deeSAkihiko Odaki     igb_getreg(TDWBAL15),
33723a977deeSAkihiko Odaki     igb_getreg(TDWBAH0),
33733a977deeSAkihiko Odaki     igb_getreg(TDWBAH1),
33743a977deeSAkihiko Odaki     igb_getreg(TDWBAH2),
33753a977deeSAkihiko Odaki     igb_getreg(TDWBAH3),
33763a977deeSAkihiko Odaki     igb_getreg(TDWBAH4),
33773a977deeSAkihiko Odaki     igb_getreg(TDWBAH5),
33783a977deeSAkihiko Odaki     igb_getreg(TDWBAH6),
33793a977deeSAkihiko Odaki     igb_getreg(TDWBAH7),
33803a977deeSAkihiko Odaki     igb_getreg(TDWBAH8),
33813a977deeSAkihiko Odaki     igb_getreg(TDWBAH9),
33823a977deeSAkihiko Odaki     igb_getreg(TDWBAH10),
33833a977deeSAkihiko Odaki     igb_getreg(TDWBAH11),
33843a977deeSAkihiko Odaki     igb_getreg(TDWBAH12),
33853a977deeSAkihiko Odaki     igb_getreg(TDWBAH13),
33863a977deeSAkihiko Odaki     igb_getreg(TDWBAH14),
33873a977deeSAkihiko Odaki     igb_getreg(TDWBAH15),
33883a977deeSAkihiko Odaki     igb_getreg(PVTCTRL0),
33893a977deeSAkihiko Odaki     igb_getreg(PVTCTRL1),
33903a977deeSAkihiko Odaki     igb_getreg(PVTCTRL2),
33913a977deeSAkihiko Odaki     igb_getreg(PVTCTRL3),
33923a977deeSAkihiko Odaki     igb_getreg(PVTCTRL4),
33933a977deeSAkihiko Odaki     igb_getreg(PVTCTRL5),
33943a977deeSAkihiko Odaki     igb_getreg(PVTCTRL6),
33953a977deeSAkihiko Odaki     igb_getreg(PVTCTRL7),
33963a977deeSAkihiko Odaki     igb_getreg(PVTEIMS0),
33973a977deeSAkihiko Odaki     igb_getreg(PVTEIMS1),
33983a977deeSAkihiko Odaki     igb_getreg(PVTEIMS2),
33993a977deeSAkihiko Odaki     igb_getreg(PVTEIMS3),
34003a977deeSAkihiko Odaki     igb_getreg(PVTEIMS4),
34013a977deeSAkihiko Odaki     igb_getreg(PVTEIMS5),
34023a977deeSAkihiko Odaki     igb_getreg(PVTEIMS6),
34033a977deeSAkihiko Odaki     igb_getreg(PVTEIMS7),
34043a977deeSAkihiko Odaki     igb_getreg(PVTEIAC0),
34053a977deeSAkihiko Odaki     igb_getreg(PVTEIAC1),
34063a977deeSAkihiko Odaki     igb_getreg(PVTEIAC2),
34073a977deeSAkihiko Odaki     igb_getreg(PVTEIAC3),
34083a977deeSAkihiko Odaki     igb_getreg(PVTEIAC4),
34093a977deeSAkihiko Odaki     igb_getreg(PVTEIAC5),
34103a977deeSAkihiko Odaki     igb_getreg(PVTEIAC6),
34113a977deeSAkihiko Odaki     igb_getreg(PVTEIAC7),
34123a977deeSAkihiko Odaki     igb_getreg(PVTEIAM0),
34133a977deeSAkihiko Odaki     igb_getreg(PVTEIAM1),
34143a977deeSAkihiko Odaki     igb_getreg(PVTEIAM2),
34153a977deeSAkihiko Odaki     igb_getreg(PVTEIAM3),
34163a977deeSAkihiko Odaki     igb_getreg(PVTEIAM4),
34173a977deeSAkihiko Odaki     igb_getreg(PVTEIAM5),
34183a977deeSAkihiko Odaki     igb_getreg(PVTEIAM6),
34193a977deeSAkihiko Odaki     igb_getreg(PVTEIAM7),
34203a977deeSAkihiko Odaki     igb_getreg(PVFGPRC0),
34213a977deeSAkihiko Odaki     igb_getreg(PVFGPRC1),
34223a977deeSAkihiko Odaki     igb_getreg(PVFGPRC2),
34233a977deeSAkihiko Odaki     igb_getreg(PVFGPRC3),
34243a977deeSAkihiko Odaki     igb_getreg(PVFGPRC4),
34253a977deeSAkihiko Odaki     igb_getreg(PVFGPRC5),
34263a977deeSAkihiko Odaki     igb_getreg(PVFGPRC6),
34273a977deeSAkihiko Odaki     igb_getreg(PVFGPRC7),
34283a977deeSAkihiko Odaki     igb_getreg(PVFGPTC0),
34293a977deeSAkihiko Odaki     igb_getreg(PVFGPTC1),
34303a977deeSAkihiko Odaki     igb_getreg(PVFGPTC2),
34313a977deeSAkihiko Odaki     igb_getreg(PVFGPTC3),
34323a977deeSAkihiko Odaki     igb_getreg(PVFGPTC4),
34333a977deeSAkihiko Odaki     igb_getreg(PVFGPTC5),
34343a977deeSAkihiko Odaki     igb_getreg(PVFGPTC6),
34353a977deeSAkihiko Odaki     igb_getreg(PVFGPTC7),
34363a977deeSAkihiko Odaki     igb_getreg(PVFGORC0),
34373a977deeSAkihiko Odaki     igb_getreg(PVFGORC1),
34383a977deeSAkihiko Odaki     igb_getreg(PVFGORC2),
34393a977deeSAkihiko Odaki     igb_getreg(PVFGORC3),
34403a977deeSAkihiko Odaki     igb_getreg(PVFGORC4),
34413a977deeSAkihiko Odaki     igb_getreg(PVFGORC5),
34423a977deeSAkihiko Odaki     igb_getreg(PVFGORC6),
34433a977deeSAkihiko Odaki     igb_getreg(PVFGORC7),
34443a977deeSAkihiko Odaki     igb_getreg(PVFGOTC0),
34453a977deeSAkihiko Odaki     igb_getreg(PVFGOTC1),
34463a977deeSAkihiko Odaki     igb_getreg(PVFGOTC2),
34473a977deeSAkihiko Odaki     igb_getreg(PVFGOTC3),
34483a977deeSAkihiko Odaki     igb_getreg(PVFGOTC4),
34493a977deeSAkihiko Odaki     igb_getreg(PVFGOTC5),
34503a977deeSAkihiko Odaki     igb_getreg(PVFGOTC6),
34513a977deeSAkihiko Odaki     igb_getreg(PVFGOTC7),
34523a977deeSAkihiko Odaki     igb_getreg(PVFMPRC0),
34533a977deeSAkihiko Odaki     igb_getreg(PVFMPRC1),
34543a977deeSAkihiko Odaki     igb_getreg(PVFMPRC2),
34553a977deeSAkihiko Odaki     igb_getreg(PVFMPRC3),
34563a977deeSAkihiko Odaki     igb_getreg(PVFMPRC4),
34573a977deeSAkihiko Odaki     igb_getreg(PVFMPRC5),
34583a977deeSAkihiko Odaki     igb_getreg(PVFMPRC6),
34593a977deeSAkihiko Odaki     igb_getreg(PVFMPRC7),
34603a977deeSAkihiko Odaki     igb_getreg(PVFGPRLBC0),
34613a977deeSAkihiko Odaki     igb_getreg(PVFGPRLBC1),
34623a977deeSAkihiko Odaki     igb_getreg(PVFGPRLBC2),
34633a977deeSAkihiko Odaki     igb_getreg(PVFGPRLBC3),
34643a977deeSAkihiko Odaki     igb_getreg(PVFGPRLBC4),
34653a977deeSAkihiko Odaki     igb_getreg(PVFGPRLBC5),
34663a977deeSAkihiko Odaki     igb_getreg(PVFGPRLBC6),
34673a977deeSAkihiko Odaki     igb_getreg(PVFGPRLBC7),
34683a977deeSAkihiko Odaki     igb_getreg(PVFGPTLBC0),
34693a977deeSAkihiko Odaki     igb_getreg(PVFGPTLBC1),
34703a977deeSAkihiko Odaki     igb_getreg(PVFGPTLBC2),
34713a977deeSAkihiko Odaki     igb_getreg(PVFGPTLBC3),
34723a977deeSAkihiko Odaki     igb_getreg(PVFGPTLBC4),
34733a977deeSAkihiko Odaki     igb_getreg(PVFGPTLBC5),
34743a977deeSAkihiko Odaki     igb_getreg(PVFGPTLBC6),
34753a977deeSAkihiko Odaki     igb_getreg(PVFGPTLBC7),
34763a977deeSAkihiko Odaki     igb_getreg(PVFGORLBC0),
34773a977deeSAkihiko Odaki     igb_getreg(PVFGORLBC1),
34783a977deeSAkihiko Odaki     igb_getreg(PVFGORLBC2),
34793a977deeSAkihiko Odaki     igb_getreg(PVFGORLBC3),
34803a977deeSAkihiko Odaki     igb_getreg(PVFGORLBC4),
34813a977deeSAkihiko Odaki     igb_getreg(PVFGORLBC5),
34823a977deeSAkihiko Odaki     igb_getreg(PVFGORLBC6),
34833a977deeSAkihiko Odaki     igb_getreg(PVFGORLBC7),
34843a977deeSAkihiko Odaki     igb_getreg(PVFGOTLBC0),
34853a977deeSAkihiko Odaki     igb_getreg(PVFGOTLBC1),
34863a977deeSAkihiko Odaki     igb_getreg(PVFGOTLBC2),
34873a977deeSAkihiko Odaki     igb_getreg(PVFGOTLBC3),
34883a977deeSAkihiko Odaki     igb_getreg(PVFGOTLBC4),
34893a977deeSAkihiko Odaki     igb_getreg(PVFGOTLBC5),
34903a977deeSAkihiko Odaki     igb_getreg(PVFGOTLBC6),
34913a977deeSAkihiko Odaki     igb_getreg(PVFGOTLBC7),
34923a977deeSAkihiko Odaki     igb_getreg(RCTL),
34933a977deeSAkihiko Odaki     igb_getreg(MDIC),
34943a977deeSAkihiko Odaki     igb_getreg(FCRUC),
34953a977deeSAkihiko Odaki     igb_getreg(VET),
34963a977deeSAkihiko Odaki     igb_getreg(RDBAL0),
34973a977deeSAkihiko Odaki     igb_getreg(RDBAL1),
34983a977deeSAkihiko Odaki     igb_getreg(RDBAL2),
34993a977deeSAkihiko Odaki     igb_getreg(RDBAL3),
35003a977deeSAkihiko Odaki     igb_getreg(RDBAL4),
35013a977deeSAkihiko Odaki     igb_getreg(RDBAL5),
35023a977deeSAkihiko Odaki     igb_getreg(RDBAL6),
35033a977deeSAkihiko Odaki     igb_getreg(RDBAL7),
35043a977deeSAkihiko Odaki     igb_getreg(RDBAL8),
35053a977deeSAkihiko Odaki     igb_getreg(RDBAL9),
35063a977deeSAkihiko Odaki     igb_getreg(RDBAL10),
35073a977deeSAkihiko Odaki     igb_getreg(RDBAL11),
35083a977deeSAkihiko Odaki     igb_getreg(RDBAL12),
35093a977deeSAkihiko Odaki     igb_getreg(RDBAL13),
35103a977deeSAkihiko Odaki     igb_getreg(RDBAL14),
35113a977deeSAkihiko Odaki     igb_getreg(RDBAL15),
35123a977deeSAkihiko Odaki     igb_getreg(TDBAH0),
35133a977deeSAkihiko Odaki     igb_getreg(TDBAH1),
35143a977deeSAkihiko Odaki     igb_getreg(TDBAH2),
35153a977deeSAkihiko Odaki     igb_getreg(TDBAH3),
35163a977deeSAkihiko Odaki     igb_getreg(TDBAH4),
35173a977deeSAkihiko Odaki     igb_getreg(TDBAH5),
35183a977deeSAkihiko Odaki     igb_getreg(TDBAH6),
35193a977deeSAkihiko Odaki     igb_getreg(TDBAH7),
35203a977deeSAkihiko Odaki     igb_getreg(TDBAH8),
35213a977deeSAkihiko Odaki     igb_getreg(TDBAH9),
35223a977deeSAkihiko Odaki     igb_getreg(TDBAH10),
35233a977deeSAkihiko Odaki     igb_getreg(TDBAH11),
35243a977deeSAkihiko Odaki     igb_getreg(TDBAH12),
35253a977deeSAkihiko Odaki     igb_getreg(TDBAH13),
35263a977deeSAkihiko Odaki     igb_getreg(TDBAH14),
35273a977deeSAkihiko Odaki     igb_getreg(TDBAH15),
35283a977deeSAkihiko Odaki     igb_getreg(SCC),
35293a977deeSAkihiko Odaki     igb_getreg(COLC),
35303a977deeSAkihiko Odaki     igb_getreg(XOFFRXC),
35313a977deeSAkihiko Odaki     igb_getreg(IPAV),
35323a977deeSAkihiko Odaki     igb_getreg(GOTCL),
35333a977deeSAkihiko Odaki     igb_getreg(MGTPDC),
35343a977deeSAkihiko Odaki     igb_getreg(GCR),
35353a977deeSAkihiko Odaki     igb_getreg(MFVAL),
35363a977deeSAkihiko Odaki     igb_getreg(FUNCTAG),
35373a977deeSAkihiko Odaki     igb_getreg(GSCL_4),
35383a977deeSAkihiko Odaki     igb_getreg(GSCN_3),
35393a977deeSAkihiko Odaki     igb_getreg(MRQC),
35403a977deeSAkihiko Odaki     igb_getreg(FCT),
35413a977deeSAkihiko Odaki     igb_getreg(FLA),
35423a977deeSAkihiko Odaki     igb_getreg(RXDCTL0),
35433a977deeSAkihiko Odaki     igb_getreg(RXDCTL1),
35443a977deeSAkihiko Odaki     igb_getreg(RXDCTL2),
35453a977deeSAkihiko Odaki     igb_getreg(RXDCTL3),
35463a977deeSAkihiko Odaki     igb_getreg(RXDCTL4),
35473a977deeSAkihiko Odaki     igb_getreg(RXDCTL5),
35483a977deeSAkihiko Odaki     igb_getreg(RXDCTL6),
35493a977deeSAkihiko Odaki     igb_getreg(RXDCTL7),
35503a977deeSAkihiko Odaki     igb_getreg(RXDCTL8),
35513a977deeSAkihiko Odaki     igb_getreg(RXDCTL9),
35523a977deeSAkihiko Odaki     igb_getreg(RXDCTL10),
35533a977deeSAkihiko Odaki     igb_getreg(RXDCTL11),
35543a977deeSAkihiko Odaki     igb_getreg(RXDCTL12),
35553a977deeSAkihiko Odaki     igb_getreg(RXDCTL13),
35563a977deeSAkihiko Odaki     igb_getreg(RXDCTL14),
35573a977deeSAkihiko Odaki     igb_getreg(RXDCTL15),
35583a977deeSAkihiko Odaki     igb_getreg(RXSTMPL),
35593a977deeSAkihiko Odaki     igb_getreg(TIMADJH),
35603a977deeSAkihiko Odaki     igb_getreg(FCRTL),
35613a977deeSAkihiko Odaki     igb_getreg(XONRXC),
35623a977deeSAkihiko Odaki     igb_getreg(RFCTL),
35633a977deeSAkihiko Odaki     igb_getreg(GSCN_1),
35643a977deeSAkihiko Odaki     igb_getreg(FCAL),
35653a977deeSAkihiko Odaki     igb_getreg(GPIE),
35663a977deeSAkihiko Odaki     igb_getreg(TXPBS),
35673a977deeSAkihiko Odaki     igb_getreg(RLPML),
35683a977deeSAkihiko Odaki 
35693a977deeSAkihiko Odaki     [TOTH]    = igb_mac_read_clr8,
35703a977deeSAkihiko Odaki     [GOTCH]   = igb_mac_read_clr8,
35713a977deeSAkihiko Odaki     [PRC64]   = igb_mac_read_clr4,
35723a977deeSAkihiko Odaki     [PRC255]  = igb_mac_read_clr4,
35733a977deeSAkihiko Odaki     [PRC1023] = igb_mac_read_clr4,
35743a977deeSAkihiko Odaki     [PTC64]   = igb_mac_read_clr4,
35753a977deeSAkihiko Odaki     [PTC255]  = igb_mac_read_clr4,
35763a977deeSAkihiko Odaki     [PTC1023] = igb_mac_read_clr4,
35773a977deeSAkihiko Odaki     [GPRC]    = igb_mac_read_clr4,
35783a977deeSAkihiko Odaki     [TPT]     = igb_mac_read_clr4,
35793a977deeSAkihiko Odaki     [RUC]     = igb_mac_read_clr4,
35803a977deeSAkihiko Odaki     [BPRC]    = igb_mac_read_clr4,
35813a977deeSAkihiko Odaki     [MPTC]    = igb_mac_read_clr4,
35823a977deeSAkihiko Odaki     [IAC]     = igb_mac_read_clr4,
35833a977deeSAkihiko Odaki     [ICR]     = igb_mac_icr_read,
35843a977deeSAkihiko Odaki     [STATUS]  = igb_get_status,
35853a977deeSAkihiko Odaki     [ICS]     = igb_mac_ics_read,
35863a977deeSAkihiko Odaki     /*
35873a977deeSAkihiko Odaki      * 8.8.10: Reading the IMC register returns the value of the IMS register.
35883a977deeSAkihiko Odaki      */
35893a977deeSAkihiko Odaki     [IMC]     = igb_mac_ims_read,
35903a977deeSAkihiko Odaki     [TORH]    = igb_mac_read_clr8,
35913a977deeSAkihiko Odaki     [GORCH]   = igb_mac_read_clr8,
35923a977deeSAkihiko Odaki     [PRC127]  = igb_mac_read_clr4,
35933a977deeSAkihiko Odaki     [PRC511]  = igb_mac_read_clr4,
35943a977deeSAkihiko Odaki     [PRC1522] = igb_mac_read_clr4,
35953a977deeSAkihiko Odaki     [PTC127]  = igb_mac_read_clr4,
35963a977deeSAkihiko Odaki     [PTC511]  = igb_mac_read_clr4,
35973a977deeSAkihiko Odaki     [PTC1522] = igb_mac_read_clr4,
35983a977deeSAkihiko Odaki     [GPTC]    = igb_mac_read_clr4,
35993a977deeSAkihiko Odaki     [TPR]     = igb_mac_read_clr4,
36003a977deeSAkihiko Odaki     [ROC]     = igb_mac_read_clr4,
36013a977deeSAkihiko Odaki     [MPRC]    = igb_mac_read_clr4,
36023a977deeSAkihiko Odaki     [BPTC]    = igb_mac_read_clr4,
36033a977deeSAkihiko Odaki     [TSCTC]   = igb_mac_read_clr4,
36043a977deeSAkihiko Odaki     [CTRL]    = igb_get_ctrl,
36053a977deeSAkihiko Odaki     [SWSM]    = igb_mac_swsm_read,
36063a977deeSAkihiko Odaki     [IMS]     = igb_mac_ims_read,
36073a977deeSAkihiko Odaki     [SYSTIML] = igb_get_systiml,
36083a977deeSAkihiko Odaki     [RXSATRH] = igb_get_rxsatrh,
36093a977deeSAkihiko Odaki     [TXSTMPH] = igb_get_txstmph,
36103a977deeSAkihiko Odaki 
36113a977deeSAkihiko Odaki     [CRCERRS ... MPC]      = igb_mac_readreg,
36123a977deeSAkihiko Odaki     [IP6AT ... IP6AT + 3]  = igb_mac_readreg,
36133a977deeSAkihiko Odaki     [IP4AT ... IP4AT + 6]  = igb_mac_readreg,
36143a977deeSAkihiko Odaki     [RA ... RA + 31]       = igb_mac_readreg,
36153a977deeSAkihiko Odaki     [RA2 ... RA2 + 31]     = igb_mac_readreg,
36163a977deeSAkihiko Odaki     [WUPM ... WUPM + 31]   = igb_mac_readreg,
36173a977deeSAkihiko Odaki     [MTA ... MTA + E1000_MC_TBL_SIZE - 1]    = igb_mac_readreg,
36183a977deeSAkihiko Odaki     [VFTA ... VFTA + E1000_VLAN_FILTER_TBL_SIZE - 1]  = igb_mac_readreg,
36193a977deeSAkihiko Odaki     [FFMT ... FFMT + 254]  = igb_mac_readreg,
36203a977deeSAkihiko Odaki     [MDEF ... MDEF + 7]    = igb_mac_readreg,
36213a977deeSAkihiko Odaki     [FTFT ... FTFT + 254]  = igb_mac_readreg,
36223a977deeSAkihiko Odaki     [RETA ... RETA + 31]   = igb_mac_readreg,
36233a977deeSAkihiko Odaki     [RSSRK ... RSSRK + 9]  = igb_mac_readreg,
36243a977deeSAkihiko Odaki     [MAVTV0 ... MAVTV3]    = igb_mac_readreg,
36253a977deeSAkihiko Odaki     [EITR0 ... EITR0 + IGB_INTR_NUM - 1] = igb_mac_eitr_read,
36263a977deeSAkihiko Odaki     [PVTEICR0] = igb_mac_read_clr4,
36273a977deeSAkihiko Odaki     [PVTEICR1] = igb_mac_read_clr4,
36283a977deeSAkihiko Odaki     [PVTEICR2] = igb_mac_read_clr4,
36293a977deeSAkihiko Odaki     [PVTEICR3] = igb_mac_read_clr4,
36303a977deeSAkihiko Odaki     [PVTEICR4] = igb_mac_read_clr4,
36313a977deeSAkihiko Odaki     [PVTEICR5] = igb_mac_read_clr4,
36323a977deeSAkihiko Odaki     [PVTEICR6] = igb_mac_read_clr4,
36333a977deeSAkihiko Odaki     [PVTEICR7] = igb_mac_read_clr4,
36343a977deeSAkihiko Odaki 
36353a977deeSAkihiko Odaki     /* IGB specific: */
36363a977deeSAkihiko Odaki     [FWSM]       = igb_mac_readreg,
36373a977deeSAkihiko Odaki     [SW_FW_SYNC] = igb_mac_readreg,
36383a977deeSAkihiko Odaki     [HTCBDPC]    = igb_mac_read_clr4,
36393a977deeSAkihiko Odaki     [EICR]       = igb_mac_read_clr4,
36403a977deeSAkihiko Odaki     [EIMS]       = igb_mac_readreg,
36413a977deeSAkihiko Odaki     [EIAM]       = igb_mac_readreg,
36423a977deeSAkihiko Odaki     [IVAR0 ... IVAR0 + 7] = igb_mac_readreg,
36433a977deeSAkihiko Odaki     igb_getreg(IVAR_MISC),
36443a9926d9SAkihiko Odaki     igb_getreg(TSYNCRXCFG),
36453a9926d9SAkihiko Odaki     [ETQF0 ... ETQF0 + 7] = igb_mac_readreg,
36463a977deeSAkihiko Odaki     igb_getreg(VT_CTL),
36473a977deeSAkihiko Odaki     [P2VMAILBOX0 ... P2VMAILBOX7] = igb_mac_readreg,
36483a977deeSAkihiko Odaki     [V2PMAILBOX0 ... V2PMAILBOX7] = igb_mac_vfmailbox_read,
36493a977deeSAkihiko Odaki     igb_getreg(MBVFICR),
36503a977deeSAkihiko Odaki     [VMBMEM0 ... VMBMEM0 + 127] = igb_mac_readreg,
36513a977deeSAkihiko Odaki     igb_getreg(MBVFIMR),
36523a977deeSAkihiko Odaki     igb_getreg(VFLRE),
36533a977deeSAkihiko Odaki     igb_getreg(VFRE),
36543a977deeSAkihiko Odaki     igb_getreg(VFTE),
36553a977deeSAkihiko Odaki     igb_getreg(QDE),
36563a977deeSAkihiko Odaki     igb_getreg(DTXSWC),
36573a977deeSAkihiko Odaki     igb_getreg(RPLOLR),
36583a977deeSAkihiko Odaki     [VLVF0 ... VLVF0 + E1000_VLVF_ARRAY_SIZE - 1] = igb_mac_readreg,
36593a977deeSAkihiko Odaki     [VMVIR0 ... VMVIR7] = igb_mac_readreg,
36603a977deeSAkihiko Odaki     [VMOLR0 ... VMOLR7] = igb_mac_readreg,
36613a977deeSAkihiko Odaki     [WVBR] = igb_mac_read_clr4,
36623a977deeSAkihiko Odaki     [RQDPC0] = igb_mac_read_clr4,
36633a977deeSAkihiko Odaki     [RQDPC1] = igb_mac_read_clr4,
36643a977deeSAkihiko Odaki     [RQDPC2] = igb_mac_read_clr4,
36653a977deeSAkihiko Odaki     [RQDPC3] = igb_mac_read_clr4,
36663a977deeSAkihiko Odaki     [RQDPC4] = igb_mac_read_clr4,
36673a977deeSAkihiko Odaki     [RQDPC5] = igb_mac_read_clr4,
36683a977deeSAkihiko Odaki     [RQDPC6] = igb_mac_read_clr4,
36693a977deeSAkihiko Odaki     [RQDPC7] = igb_mac_read_clr4,
36703a977deeSAkihiko Odaki     [RQDPC8] = igb_mac_read_clr4,
36713a977deeSAkihiko Odaki     [RQDPC9] = igb_mac_read_clr4,
36723a977deeSAkihiko Odaki     [RQDPC10] = igb_mac_read_clr4,
36733a977deeSAkihiko Odaki     [RQDPC11] = igb_mac_read_clr4,
36743a977deeSAkihiko Odaki     [RQDPC12] = igb_mac_read_clr4,
36753a977deeSAkihiko Odaki     [RQDPC13] = igb_mac_read_clr4,
36763a977deeSAkihiko Odaki     [RQDPC14] = igb_mac_read_clr4,
36773a977deeSAkihiko Odaki     [RQDPC15] = igb_mac_read_clr4,
36783a977deeSAkihiko Odaki     [VTIVAR ... VTIVAR + 7] = igb_mac_readreg,
36793a977deeSAkihiko Odaki     [VTIVAR_MISC ... VTIVAR_MISC + 7] = igb_mac_readreg,
36803a977deeSAkihiko Odaki };
36813a977deeSAkihiko Odaki enum { IGB_NREADOPS = ARRAY_SIZE(igb_macreg_readops) };
36823a977deeSAkihiko Odaki 
36833a977deeSAkihiko Odaki #define igb_putreg(x)    [x] = igb_mac_writereg
36843a977deeSAkihiko Odaki typedef void (*writeops)(IGBCore *, int, uint32_t);
36853a977deeSAkihiko Odaki static const writeops igb_macreg_writeops[] = {
36863a977deeSAkihiko Odaki     igb_putreg(SWSM),
36873a977deeSAkihiko Odaki     igb_putreg(WUFC),
36883a977deeSAkihiko Odaki     igb_putreg(RDBAH0),
36893a977deeSAkihiko Odaki     igb_putreg(RDBAH1),
36903a977deeSAkihiko Odaki     igb_putreg(RDBAH2),
36913a977deeSAkihiko Odaki     igb_putreg(RDBAH3),
36923a977deeSAkihiko Odaki     igb_putreg(RDBAH4),
36933a977deeSAkihiko Odaki     igb_putreg(RDBAH5),
36943a977deeSAkihiko Odaki     igb_putreg(RDBAH6),
36953a977deeSAkihiko Odaki     igb_putreg(RDBAH7),
36963a977deeSAkihiko Odaki     igb_putreg(RDBAH8),
36973a977deeSAkihiko Odaki     igb_putreg(RDBAH9),
36983a977deeSAkihiko Odaki     igb_putreg(RDBAH10),
36993a977deeSAkihiko Odaki     igb_putreg(RDBAH11),
37003a977deeSAkihiko Odaki     igb_putreg(RDBAH12),
37013a977deeSAkihiko Odaki     igb_putreg(RDBAH13),
37023a977deeSAkihiko Odaki     igb_putreg(RDBAH14),
37033a977deeSAkihiko Odaki     igb_putreg(RDBAH15),
37043a977deeSAkihiko Odaki     igb_putreg(SRRCTL0),
37053a977deeSAkihiko Odaki     igb_putreg(SRRCTL1),
37063a977deeSAkihiko Odaki     igb_putreg(SRRCTL2),
37073a977deeSAkihiko Odaki     igb_putreg(SRRCTL3),
37083a977deeSAkihiko Odaki     igb_putreg(SRRCTL4),
37093a977deeSAkihiko Odaki     igb_putreg(SRRCTL5),
37103a977deeSAkihiko Odaki     igb_putreg(SRRCTL6),
37113a977deeSAkihiko Odaki     igb_putreg(SRRCTL7),
37123a977deeSAkihiko Odaki     igb_putreg(SRRCTL8),
37133a977deeSAkihiko Odaki     igb_putreg(SRRCTL9),
37143a977deeSAkihiko Odaki     igb_putreg(SRRCTL10),
37153a977deeSAkihiko Odaki     igb_putreg(SRRCTL11),
37163a977deeSAkihiko Odaki     igb_putreg(SRRCTL12),
37173a977deeSAkihiko Odaki     igb_putreg(SRRCTL13),
37183a977deeSAkihiko Odaki     igb_putreg(SRRCTL14),
37193a977deeSAkihiko Odaki     igb_putreg(SRRCTL15),
37203a977deeSAkihiko Odaki     igb_putreg(RXDCTL0),
37213a977deeSAkihiko Odaki     igb_putreg(RXDCTL1),
37223a977deeSAkihiko Odaki     igb_putreg(RXDCTL2),
37233a977deeSAkihiko Odaki     igb_putreg(RXDCTL3),
37243a977deeSAkihiko Odaki     igb_putreg(RXDCTL4),
37253a977deeSAkihiko Odaki     igb_putreg(RXDCTL5),
37263a977deeSAkihiko Odaki     igb_putreg(RXDCTL6),
37273a977deeSAkihiko Odaki     igb_putreg(RXDCTL7),
37283a977deeSAkihiko Odaki     igb_putreg(RXDCTL8),
37293a977deeSAkihiko Odaki     igb_putreg(RXDCTL9),
37303a977deeSAkihiko Odaki     igb_putreg(RXDCTL10),
37313a977deeSAkihiko Odaki     igb_putreg(RXDCTL11),
37323a977deeSAkihiko Odaki     igb_putreg(RXDCTL12),
37333a977deeSAkihiko Odaki     igb_putreg(RXDCTL13),
37343a977deeSAkihiko Odaki     igb_putreg(RXDCTL14),
37353a977deeSAkihiko Odaki     igb_putreg(RXDCTL15),
37363a977deeSAkihiko Odaki     igb_putreg(LEDCTL),
37373a977deeSAkihiko Odaki     igb_putreg(TCTL),
37383a977deeSAkihiko Odaki     igb_putreg(TCTL_EXT),
37393a977deeSAkihiko Odaki     igb_putreg(DTXCTL),
37403a977deeSAkihiko Odaki     igb_putreg(RXPBS),
37413a977deeSAkihiko Odaki     igb_putreg(RQDPC0),
37423a977deeSAkihiko Odaki     igb_putreg(FCAL),
37433a977deeSAkihiko Odaki     igb_putreg(FCRUC),
37443a977deeSAkihiko Odaki     igb_putreg(WUC),
37453a977deeSAkihiko Odaki     igb_putreg(WUS),
37463a977deeSAkihiko Odaki     igb_putreg(IPAV),
37473a977deeSAkihiko Odaki     igb_putreg(TDBAH0),
37483a977deeSAkihiko Odaki     igb_putreg(TDBAH1),
37493a977deeSAkihiko Odaki     igb_putreg(TDBAH2),
37503a977deeSAkihiko Odaki     igb_putreg(TDBAH3),
37513a977deeSAkihiko Odaki     igb_putreg(TDBAH4),
37523a977deeSAkihiko Odaki     igb_putreg(TDBAH5),
37533a977deeSAkihiko Odaki     igb_putreg(TDBAH6),
37543a977deeSAkihiko Odaki     igb_putreg(TDBAH7),
37553a977deeSAkihiko Odaki     igb_putreg(TDBAH8),
37563a977deeSAkihiko Odaki     igb_putreg(TDBAH9),
37573a977deeSAkihiko Odaki     igb_putreg(TDBAH10),
37583a977deeSAkihiko Odaki     igb_putreg(TDBAH11),
37593a977deeSAkihiko Odaki     igb_putreg(TDBAH12),
37603a977deeSAkihiko Odaki     igb_putreg(TDBAH13),
37613a977deeSAkihiko Odaki     igb_putreg(TDBAH14),
37623a977deeSAkihiko Odaki     igb_putreg(TDBAH15),
37633a977deeSAkihiko Odaki     igb_putreg(IAM),
37643a977deeSAkihiko Odaki     igb_putreg(MANC),
37653a977deeSAkihiko Odaki     igb_putreg(MANC2H),
37663a977deeSAkihiko Odaki     igb_putreg(MFVAL),
37673a977deeSAkihiko Odaki     igb_putreg(FACTPS),
37683a977deeSAkihiko Odaki     igb_putreg(FUNCTAG),
37693a977deeSAkihiko Odaki     igb_putreg(GSCL_1),
37703a977deeSAkihiko Odaki     igb_putreg(GSCL_2),
37713a977deeSAkihiko Odaki     igb_putreg(GSCL_3),
37723a977deeSAkihiko Odaki     igb_putreg(GSCL_4),
37733a977deeSAkihiko Odaki     igb_putreg(GSCN_0),
37743a977deeSAkihiko Odaki     igb_putreg(GSCN_1),
37753a977deeSAkihiko Odaki     igb_putreg(GSCN_2),
37763a977deeSAkihiko Odaki     igb_putreg(GSCN_3),
37773a977deeSAkihiko Odaki     igb_putreg(MRQC),
37783a977deeSAkihiko Odaki     igb_putreg(FLOP),
37793a977deeSAkihiko Odaki     igb_putreg(FLA),
37803a977deeSAkihiko Odaki     igb_putreg(TXDCTL0),
37813a977deeSAkihiko Odaki     igb_putreg(TXDCTL1),
37823a977deeSAkihiko Odaki     igb_putreg(TXDCTL2),
37833a977deeSAkihiko Odaki     igb_putreg(TXDCTL3),
37843a977deeSAkihiko Odaki     igb_putreg(TXDCTL4),
37853a977deeSAkihiko Odaki     igb_putreg(TXDCTL5),
37863a977deeSAkihiko Odaki     igb_putreg(TXDCTL6),
37873a977deeSAkihiko Odaki     igb_putreg(TXDCTL7),
37883a977deeSAkihiko Odaki     igb_putreg(TXDCTL8),
37893a977deeSAkihiko Odaki     igb_putreg(TXDCTL9),
37903a977deeSAkihiko Odaki     igb_putreg(TXDCTL10),
37913a977deeSAkihiko Odaki     igb_putreg(TXDCTL11),
37923a977deeSAkihiko Odaki     igb_putreg(TXDCTL12),
37933a977deeSAkihiko Odaki     igb_putreg(TXDCTL13),
37943a977deeSAkihiko Odaki     igb_putreg(TXDCTL14),
37953a977deeSAkihiko Odaki     igb_putreg(TXDCTL15),
37963a977deeSAkihiko Odaki     igb_putreg(TXCTL0),
37973a977deeSAkihiko Odaki     igb_putreg(TXCTL1),
37983a977deeSAkihiko Odaki     igb_putreg(TXCTL2),
37993a977deeSAkihiko Odaki     igb_putreg(TXCTL3),
38003a977deeSAkihiko Odaki     igb_putreg(TXCTL4),
38013a977deeSAkihiko Odaki     igb_putreg(TXCTL5),
38023a977deeSAkihiko Odaki     igb_putreg(TXCTL6),
38033a977deeSAkihiko Odaki     igb_putreg(TXCTL7),
38043a977deeSAkihiko Odaki     igb_putreg(TXCTL8),
38053a977deeSAkihiko Odaki     igb_putreg(TXCTL9),
38063a977deeSAkihiko Odaki     igb_putreg(TXCTL10),
38073a977deeSAkihiko Odaki     igb_putreg(TXCTL11),
38083a977deeSAkihiko Odaki     igb_putreg(TXCTL12),
38093a977deeSAkihiko Odaki     igb_putreg(TXCTL13),
38103a977deeSAkihiko Odaki     igb_putreg(TXCTL14),
38113a977deeSAkihiko Odaki     igb_putreg(TXCTL15),
38123a977deeSAkihiko Odaki     igb_putreg(TDWBAL0),
38133a977deeSAkihiko Odaki     igb_putreg(TDWBAL1),
38143a977deeSAkihiko Odaki     igb_putreg(TDWBAL2),
38153a977deeSAkihiko Odaki     igb_putreg(TDWBAL3),
38163a977deeSAkihiko Odaki     igb_putreg(TDWBAL4),
38173a977deeSAkihiko Odaki     igb_putreg(TDWBAL5),
38183a977deeSAkihiko Odaki     igb_putreg(TDWBAL6),
38193a977deeSAkihiko Odaki     igb_putreg(TDWBAL7),
38203a977deeSAkihiko Odaki     igb_putreg(TDWBAL8),
38213a977deeSAkihiko Odaki     igb_putreg(TDWBAL9),
38223a977deeSAkihiko Odaki     igb_putreg(TDWBAL10),
38233a977deeSAkihiko Odaki     igb_putreg(TDWBAL11),
38243a977deeSAkihiko Odaki     igb_putreg(TDWBAL12),
38253a977deeSAkihiko Odaki     igb_putreg(TDWBAL13),
38263a977deeSAkihiko Odaki     igb_putreg(TDWBAL14),
38273a977deeSAkihiko Odaki     igb_putreg(TDWBAL15),
38283a977deeSAkihiko Odaki     igb_putreg(TDWBAH0),
38293a977deeSAkihiko Odaki     igb_putreg(TDWBAH1),
38303a977deeSAkihiko Odaki     igb_putreg(TDWBAH2),
38313a977deeSAkihiko Odaki     igb_putreg(TDWBAH3),
38323a977deeSAkihiko Odaki     igb_putreg(TDWBAH4),
38333a977deeSAkihiko Odaki     igb_putreg(TDWBAH5),
38343a977deeSAkihiko Odaki     igb_putreg(TDWBAH6),
38353a977deeSAkihiko Odaki     igb_putreg(TDWBAH7),
38363a977deeSAkihiko Odaki     igb_putreg(TDWBAH8),
38373a977deeSAkihiko Odaki     igb_putreg(TDWBAH9),
38383a977deeSAkihiko Odaki     igb_putreg(TDWBAH10),
38393a977deeSAkihiko Odaki     igb_putreg(TDWBAH11),
38403a977deeSAkihiko Odaki     igb_putreg(TDWBAH12),
38413a977deeSAkihiko Odaki     igb_putreg(TDWBAH13),
38423a977deeSAkihiko Odaki     igb_putreg(TDWBAH14),
38433a977deeSAkihiko Odaki     igb_putreg(TDWBAH15),
38443a977deeSAkihiko Odaki     igb_putreg(TIPG),
38453a977deeSAkihiko Odaki     igb_putreg(RXSTMPH),
38463a977deeSAkihiko Odaki     igb_putreg(RXSTMPL),
38473a977deeSAkihiko Odaki     igb_putreg(RXSATRL),
38483a977deeSAkihiko Odaki     igb_putreg(RXSATRH),
38493a977deeSAkihiko Odaki     igb_putreg(TXSTMPL),
38503a977deeSAkihiko Odaki     igb_putreg(TXSTMPH),
38513a977deeSAkihiko Odaki     igb_putreg(SYSTIML),
38523a977deeSAkihiko Odaki     igb_putreg(SYSTIMH),
38533a977deeSAkihiko Odaki     igb_putreg(TIMADJL),
38543a977deeSAkihiko Odaki     igb_putreg(TSYNCRXCTL),
38553a977deeSAkihiko Odaki     igb_putreg(TSYNCTXCTL),
38563a977deeSAkihiko Odaki     igb_putreg(EEMNGCTL),
38573a977deeSAkihiko Odaki     igb_putreg(GPIE),
38583a977deeSAkihiko Odaki     igb_putreg(TXPBS),
38593a977deeSAkihiko Odaki     igb_putreg(RLPML),
38603a977deeSAkihiko Odaki     igb_putreg(VET),
38613a977deeSAkihiko Odaki 
38623a977deeSAkihiko Odaki     [TDH0]     = igb_set_16bit,
38633a977deeSAkihiko Odaki     [TDH1]     = igb_set_16bit,
38643a977deeSAkihiko Odaki     [TDH2]     = igb_set_16bit,
38653a977deeSAkihiko Odaki     [TDH3]     = igb_set_16bit,
38663a977deeSAkihiko Odaki     [TDH4]     = igb_set_16bit,
38673a977deeSAkihiko Odaki     [TDH5]     = igb_set_16bit,
38683a977deeSAkihiko Odaki     [TDH6]     = igb_set_16bit,
38693a977deeSAkihiko Odaki     [TDH7]     = igb_set_16bit,
38703a977deeSAkihiko Odaki     [TDH8]     = igb_set_16bit,
38713a977deeSAkihiko Odaki     [TDH9]     = igb_set_16bit,
38723a977deeSAkihiko Odaki     [TDH10]    = igb_set_16bit,
38733a977deeSAkihiko Odaki     [TDH11]    = igb_set_16bit,
38743a977deeSAkihiko Odaki     [TDH12]    = igb_set_16bit,
38753a977deeSAkihiko Odaki     [TDH13]    = igb_set_16bit,
38763a977deeSAkihiko Odaki     [TDH14]    = igb_set_16bit,
38773a977deeSAkihiko Odaki     [TDH15]    = igb_set_16bit,
38783a977deeSAkihiko Odaki     [TDT0]     = igb_set_tdt,
38793a977deeSAkihiko Odaki     [TDT1]     = igb_set_tdt,
38803a977deeSAkihiko Odaki     [TDT2]     = igb_set_tdt,
38813a977deeSAkihiko Odaki     [TDT3]     = igb_set_tdt,
38823a977deeSAkihiko Odaki     [TDT4]     = igb_set_tdt,
38833a977deeSAkihiko Odaki     [TDT5]     = igb_set_tdt,
38843a977deeSAkihiko Odaki     [TDT6]     = igb_set_tdt,
38853a977deeSAkihiko Odaki     [TDT7]     = igb_set_tdt,
38863a977deeSAkihiko Odaki     [TDT8]     = igb_set_tdt,
38873a977deeSAkihiko Odaki     [TDT9]     = igb_set_tdt,
38883a977deeSAkihiko Odaki     [TDT10]    = igb_set_tdt,
38893a977deeSAkihiko Odaki     [TDT11]    = igb_set_tdt,
38903a977deeSAkihiko Odaki     [TDT12]    = igb_set_tdt,
38913a977deeSAkihiko Odaki     [TDT13]    = igb_set_tdt,
38923a977deeSAkihiko Odaki     [TDT14]    = igb_set_tdt,
38933a977deeSAkihiko Odaki     [TDT15]    = igb_set_tdt,
38943a977deeSAkihiko Odaki     [MDIC]     = igb_set_mdic,
38953a977deeSAkihiko Odaki     [ICS]      = igb_set_ics,
38963a977deeSAkihiko Odaki     [RDH0]     = igb_set_16bit,
38973a977deeSAkihiko Odaki     [RDH1]     = igb_set_16bit,
38983a977deeSAkihiko Odaki     [RDH2]     = igb_set_16bit,
38993a977deeSAkihiko Odaki     [RDH3]     = igb_set_16bit,
39003a977deeSAkihiko Odaki     [RDH4]     = igb_set_16bit,
39013a977deeSAkihiko Odaki     [RDH5]     = igb_set_16bit,
39023a977deeSAkihiko Odaki     [RDH6]     = igb_set_16bit,
39033a977deeSAkihiko Odaki     [RDH7]     = igb_set_16bit,
39043a977deeSAkihiko Odaki     [RDH8]     = igb_set_16bit,
39053a977deeSAkihiko Odaki     [RDH9]     = igb_set_16bit,
39063a977deeSAkihiko Odaki     [RDH10]    = igb_set_16bit,
39073a977deeSAkihiko Odaki     [RDH11]    = igb_set_16bit,
39083a977deeSAkihiko Odaki     [RDH12]    = igb_set_16bit,
39093a977deeSAkihiko Odaki     [RDH13]    = igb_set_16bit,
39103a977deeSAkihiko Odaki     [RDH14]    = igb_set_16bit,
39113a977deeSAkihiko Odaki     [RDH15]    = igb_set_16bit,
39123a977deeSAkihiko Odaki     [RDT0]     = igb_set_rdt,
39133a977deeSAkihiko Odaki     [RDT1]     = igb_set_rdt,
39143a977deeSAkihiko Odaki     [RDT2]     = igb_set_rdt,
39153a977deeSAkihiko Odaki     [RDT3]     = igb_set_rdt,
39163a977deeSAkihiko Odaki     [RDT4]     = igb_set_rdt,
39173a977deeSAkihiko Odaki     [RDT5]     = igb_set_rdt,
39183a977deeSAkihiko Odaki     [RDT6]     = igb_set_rdt,
39193a977deeSAkihiko Odaki     [RDT7]     = igb_set_rdt,
39203a977deeSAkihiko Odaki     [RDT8]     = igb_set_rdt,
39213a977deeSAkihiko Odaki     [RDT9]     = igb_set_rdt,
39223a977deeSAkihiko Odaki     [RDT10]    = igb_set_rdt,
39233a977deeSAkihiko Odaki     [RDT11]    = igb_set_rdt,
39243a977deeSAkihiko Odaki     [RDT12]    = igb_set_rdt,
39253a977deeSAkihiko Odaki     [RDT13]    = igb_set_rdt,
39263a977deeSAkihiko Odaki     [RDT14]    = igb_set_rdt,
39273a977deeSAkihiko Odaki     [RDT15]    = igb_set_rdt,
39283a977deeSAkihiko Odaki     [IMC]      = igb_set_imc,
39293a977deeSAkihiko Odaki     [IMS]      = igb_set_ims,
39303a977deeSAkihiko Odaki     [ICR]      = igb_set_icr,
39313a977deeSAkihiko Odaki     [EECD]     = igb_set_eecd,
39323a977deeSAkihiko Odaki     [RCTL]     = igb_set_rx_control,
39333a977deeSAkihiko Odaki     [CTRL]     = igb_set_ctrl,
39343a977deeSAkihiko Odaki     [EERD]     = igb_set_eerd,
39353a977deeSAkihiko Odaki     [TDFH]     = igb_set_13bit,
39363a977deeSAkihiko Odaki     [TDFT]     = igb_set_13bit,
39373a977deeSAkihiko Odaki     [TDFHS]    = igb_set_13bit,
39383a977deeSAkihiko Odaki     [TDFTS]    = igb_set_13bit,
39393a977deeSAkihiko Odaki     [TDFPC]    = igb_set_13bit,
39403a977deeSAkihiko Odaki     [RDFH]     = igb_set_13bit,
39413a977deeSAkihiko Odaki     [RDFT]     = igb_set_13bit,
39423a977deeSAkihiko Odaki     [RDFHS]    = igb_set_13bit,
39433a977deeSAkihiko Odaki     [RDFTS]    = igb_set_13bit,
39443a977deeSAkihiko Odaki     [RDFPC]    = igb_set_13bit,
39453a977deeSAkihiko Odaki     [GCR]      = igb_set_gcr,
39463a977deeSAkihiko Odaki     [RXCSUM]   = igb_set_rxcsum,
39473a977deeSAkihiko Odaki     [TDLEN0]   = igb_set_dlen,
39483a977deeSAkihiko Odaki     [TDLEN1]   = igb_set_dlen,
39493a977deeSAkihiko Odaki     [TDLEN2]   = igb_set_dlen,
39503a977deeSAkihiko Odaki     [TDLEN3]   = igb_set_dlen,
39513a977deeSAkihiko Odaki     [TDLEN4]   = igb_set_dlen,
39523a977deeSAkihiko Odaki     [TDLEN5]   = igb_set_dlen,
39533a977deeSAkihiko Odaki     [TDLEN6]   = igb_set_dlen,
39543a977deeSAkihiko Odaki     [TDLEN7]   = igb_set_dlen,
39553a977deeSAkihiko Odaki     [TDLEN8]   = igb_set_dlen,
39563a977deeSAkihiko Odaki     [TDLEN9]   = igb_set_dlen,
39573a977deeSAkihiko Odaki     [TDLEN10]  = igb_set_dlen,
39583a977deeSAkihiko Odaki     [TDLEN11]  = igb_set_dlen,
39593a977deeSAkihiko Odaki     [TDLEN12]  = igb_set_dlen,
39603a977deeSAkihiko Odaki     [TDLEN13]  = igb_set_dlen,
39613a977deeSAkihiko Odaki     [TDLEN14]  = igb_set_dlen,
39623a977deeSAkihiko Odaki     [TDLEN15]  = igb_set_dlen,
39633a977deeSAkihiko Odaki     [RDLEN0]   = igb_set_dlen,
39643a977deeSAkihiko Odaki     [RDLEN1]   = igb_set_dlen,
39653a977deeSAkihiko Odaki     [RDLEN2]   = igb_set_dlen,
39663a977deeSAkihiko Odaki     [RDLEN3]   = igb_set_dlen,
39673a977deeSAkihiko Odaki     [RDLEN4]   = igb_set_dlen,
39683a977deeSAkihiko Odaki     [RDLEN5]   = igb_set_dlen,
39693a977deeSAkihiko Odaki     [RDLEN6]   = igb_set_dlen,
39703a977deeSAkihiko Odaki     [RDLEN7]   = igb_set_dlen,
39713a977deeSAkihiko Odaki     [RDLEN8]   = igb_set_dlen,
39723a977deeSAkihiko Odaki     [RDLEN9]   = igb_set_dlen,
39733a977deeSAkihiko Odaki     [RDLEN10]  = igb_set_dlen,
39743a977deeSAkihiko Odaki     [RDLEN11]  = igb_set_dlen,
39753a977deeSAkihiko Odaki     [RDLEN12]  = igb_set_dlen,
39763a977deeSAkihiko Odaki     [RDLEN13]  = igb_set_dlen,
39773a977deeSAkihiko Odaki     [RDLEN14]  = igb_set_dlen,
39783a977deeSAkihiko Odaki     [RDLEN15]  = igb_set_dlen,
39793a977deeSAkihiko Odaki     [TDBAL0]   = igb_set_dbal,
39803a977deeSAkihiko Odaki     [TDBAL1]   = igb_set_dbal,
39813a977deeSAkihiko Odaki     [TDBAL2]   = igb_set_dbal,
39823a977deeSAkihiko Odaki     [TDBAL3]   = igb_set_dbal,
39833a977deeSAkihiko Odaki     [TDBAL4]   = igb_set_dbal,
39843a977deeSAkihiko Odaki     [TDBAL5]   = igb_set_dbal,
39853a977deeSAkihiko Odaki     [TDBAL6]   = igb_set_dbal,
39863a977deeSAkihiko Odaki     [TDBAL7]   = igb_set_dbal,
39873a977deeSAkihiko Odaki     [TDBAL8]   = igb_set_dbal,
39883a977deeSAkihiko Odaki     [TDBAL9]   = igb_set_dbal,
39893a977deeSAkihiko Odaki     [TDBAL10]  = igb_set_dbal,
39903a977deeSAkihiko Odaki     [TDBAL11]  = igb_set_dbal,
39913a977deeSAkihiko Odaki     [TDBAL12]  = igb_set_dbal,
39923a977deeSAkihiko Odaki     [TDBAL13]  = igb_set_dbal,
39933a977deeSAkihiko Odaki     [TDBAL14]  = igb_set_dbal,
39943a977deeSAkihiko Odaki     [TDBAL15]  = igb_set_dbal,
39953a977deeSAkihiko Odaki     [RDBAL0]   = igb_set_dbal,
39963a977deeSAkihiko Odaki     [RDBAL1]   = igb_set_dbal,
39973a977deeSAkihiko Odaki     [RDBAL2]   = igb_set_dbal,
39983a977deeSAkihiko Odaki     [RDBAL3]   = igb_set_dbal,
39993a977deeSAkihiko Odaki     [RDBAL4]   = igb_set_dbal,
40003a977deeSAkihiko Odaki     [RDBAL5]   = igb_set_dbal,
40013a977deeSAkihiko Odaki     [RDBAL6]   = igb_set_dbal,
40023a977deeSAkihiko Odaki     [RDBAL7]   = igb_set_dbal,
40033a977deeSAkihiko Odaki     [RDBAL8]   = igb_set_dbal,
40043a977deeSAkihiko Odaki     [RDBAL9]   = igb_set_dbal,
40053a977deeSAkihiko Odaki     [RDBAL10]  = igb_set_dbal,
40063a977deeSAkihiko Odaki     [RDBAL11]  = igb_set_dbal,
40073a977deeSAkihiko Odaki     [RDBAL12]  = igb_set_dbal,
40083a977deeSAkihiko Odaki     [RDBAL13]  = igb_set_dbal,
40093a977deeSAkihiko Odaki     [RDBAL14]  = igb_set_dbal,
40103a977deeSAkihiko Odaki     [RDBAL15]  = igb_set_dbal,
40113a977deeSAkihiko Odaki     [STATUS]   = igb_set_status,
40123a977deeSAkihiko Odaki     [PBACLR]   = igb_set_pbaclr,
40133a977deeSAkihiko Odaki     [CTRL_EXT] = igb_set_ctrlext,
40143a977deeSAkihiko Odaki     [FCAH]     = igb_set_16bit,
40153a977deeSAkihiko Odaki     [FCT]      = igb_set_16bit,
40163a977deeSAkihiko Odaki     [FCTTV]    = igb_set_16bit,
40173a977deeSAkihiko Odaki     [FCRTV]    = igb_set_16bit,
40183a977deeSAkihiko Odaki     [FCRTH]    = igb_set_fcrth,
40193a977deeSAkihiko Odaki     [FCRTL]    = igb_set_fcrtl,
40203a977deeSAkihiko Odaki     [CTRL_DUP] = igb_set_ctrl,
40213a977deeSAkihiko Odaki     [RFCTL]    = igb_set_rfctl,
40223a977deeSAkihiko Odaki     [TIMINCA]  = igb_set_timinca,
40233a977deeSAkihiko Odaki     [TIMADJH]  = igb_set_timadjh,
40243a977deeSAkihiko Odaki 
40253a977deeSAkihiko Odaki     [IP6AT ... IP6AT + 3]    = igb_mac_writereg,
40263a977deeSAkihiko Odaki     [IP4AT ... IP4AT + 6]    = igb_mac_writereg,
40273a977deeSAkihiko Odaki     [RA]                     = igb_mac_writereg,
40283a977deeSAkihiko Odaki     [RA + 1]                 = igb_mac_setmacaddr,
40293a977deeSAkihiko Odaki     [RA + 2 ... RA + 31]     = igb_mac_writereg,
40303a977deeSAkihiko Odaki     [RA2 ... RA2 + 31]       = igb_mac_writereg,
40313a977deeSAkihiko Odaki     [WUPM ... WUPM + 31]     = igb_mac_writereg,
40323a977deeSAkihiko Odaki     [MTA ... MTA + E1000_MC_TBL_SIZE - 1] = igb_mac_writereg,
40333a977deeSAkihiko Odaki     [VFTA ... VFTA + E1000_VLAN_FILTER_TBL_SIZE - 1] = igb_mac_writereg,
40343a977deeSAkihiko Odaki     [FFMT ... FFMT + 254]    = igb_set_4bit,
40353a977deeSAkihiko Odaki     [MDEF ... MDEF + 7]      = igb_mac_writereg,
40363a977deeSAkihiko Odaki     [FTFT ... FTFT + 254]    = igb_mac_writereg,
40373a977deeSAkihiko Odaki     [RETA ... RETA + 31]     = igb_mac_writereg,
40383a977deeSAkihiko Odaki     [RSSRK ... RSSRK + 9]    = igb_mac_writereg,
40393a977deeSAkihiko Odaki     [MAVTV0 ... MAVTV3]      = igb_mac_writereg,
40403a977deeSAkihiko Odaki     [EITR0 ... EITR0 + IGB_INTR_NUM - 1] = igb_set_eitr,
40413a977deeSAkihiko Odaki 
40423a977deeSAkihiko Odaki     /* IGB specific: */
40433a977deeSAkihiko Odaki     [FWSM]     = igb_mac_writereg,
40443a977deeSAkihiko Odaki     [SW_FW_SYNC] = igb_mac_writereg,
40453a977deeSAkihiko Odaki     [EICR] = igb_set_eicr,
40463a977deeSAkihiko Odaki     [EICS] = igb_set_eics,
40473a977deeSAkihiko Odaki     [EIAC] = igb_set_eiac,
40483a977deeSAkihiko Odaki     [EIAM] = igb_set_eiam,
40493a977deeSAkihiko Odaki     [EIMC] = igb_set_eimc,
40503a977deeSAkihiko Odaki     [EIMS] = igb_set_eims,
40513a977deeSAkihiko Odaki     [IVAR0 ... IVAR0 + 7] = igb_mac_writereg,
40523a977deeSAkihiko Odaki     igb_putreg(IVAR_MISC),
40533a9926d9SAkihiko Odaki     igb_putreg(TSYNCRXCFG),
40543a9926d9SAkihiko Odaki     [ETQF0 ... ETQF0 + 7] = igb_mac_writereg,
40553a977deeSAkihiko Odaki     igb_putreg(VT_CTL),
40563a977deeSAkihiko Odaki     [P2VMAILBOX0 ... P2VMAILBOX7] = igb_set_pfmailbox,
40573a977deeSAkihiko Odaki     [V2PMAILBOX0 ... V2PMAILBOX7] = igb_set_vfmailbox,
40583a977deeSAkihiko Odaki     [MBVFICR] = igb_w1c,
40593a977deeSAkihiko Odaki     [VMBMEM0 ... VMBMEM0 + 127] = igb_mac_writereg,
40603a977deeSAkihiko Odaki     igb_putreg(MBVFIMR),
40613a977deeSAkihiko Odaki     [VFLRE] = igb_w1c,
40623a977deeSAkihiko Odaki     igb_putreg(VFRE),
40633a977deeSAkihiko Odaki     igb_putreg(VFTE),
40643a977deeSAkihiko Odaki     igb_putreg(QDE),
40653a977deeSAkihiko Odaki     igb_putreg(DTXSWC),
40663a977deeSAkihiko Odaki     igb_putreg(RPLOLR),
40673a977deeSAkihiko Odaki     [VLVF0 ... VLVF0 + E1000_VLVF_ARRAY_SIZE - 1] = igb_mac_writereg,
40683a977deeSAkihiko Odaki     [VMVIR0 ... VMVIR7] = igb_mac_writereg,
40693a977deeSAkihiko Odaki     [VMOLR0 ... VMOLR7] = igb_mac_writereg,
40703a977deeSAkihiko Odaki     [UTA ... UTA + E1000_MC_TBL_SIZE - 1] = igb_mac_writereg,
40713a977deeSAkihiko Odaki     [PVTCTRL0] = igb_set_vtctrl,
40723a977deeSAkihiko Odaki     [PVTCTRL1] = igb_set_vtctrl,
40733a977deeSAkihiko Odaki     [PVTCTRL2] = igb_set_vtctrl,
40743a977deeSAkihiko Odaki     [PVTCTRL3] = igb_set_vtctrl,
40753a977deeSAkihiko Odaki     [PVTCTRL4] = igb_set_vtctrl,
40763a977deeSAkihiko Odaki     [PVTCTRL5] = igb_set_vtctrl,
40773a977deeSAkihiko Odaki     [PVTCTRL6] = igb_set_vtctrl,
40783a977deeSAkihiko Odaki     [PVTCTRL7] = igb_set_vtctrl,
40793a977deeSAkihiko Odaki     [PVTEICS0] = igb_set_vteics,
40803a977deeSAkihiko Odaki     [PVTEICS1] = igb_set_vteics,
40813a977deeSAkihiko Odaki     [PVTEICS2] = igb_set_vteics,
40823a977deeSAkihiko Odaki     [PVTEICS3] = igb_set_vteics,
40833a977deeSAkihiko Odaki     [PVTEICS4] = igb_set_vteics,
40843a977deeSAkihiko Odaki     [PVTEICS5] = igb_set_vteics,
40853a977deeSAkihiko Odaki     [PVTEICS6] = igb_set_vteics,
40863a977deeSAkihiko Odaki     [PVTEICS7] = igb_set_vteics,
40873a977deeSAkihiko Odaki     [PVTEIMS0] = igb_set_vteims,
40883a977deeSAkihiko Odaki     [PVTEIMS1] = igb_set_vteims,
40893a977deeSAkihiko Odaki     [PVTEIMS2] = igb_set_vteims,
40903a977deeSAkihiko Odaki     [PVTEIMS3] = igb_set_vteims,
40913a977deeSAkihiko Odaki     [PVTEIMS4] = igb_set_vteims,
40923a977deeSAkihiko Odaki     [PVTEIMS5] = igb_set_vteims,
40933a977deeSAkihiko Odaki     [PVTEIMS6] = igb_set_vteims,
40943a977deeSAkihiko Odaki     [PVTEIMS7] = igb_set_vteims,
40953a977deeSAkihiko Odaki     [PVTEIMC0] = igb_set_vteimc,
40963a977deeSAkihiko Odaki     [PVTEIMC1] = igb_set_vteimc,
40973a977deeSAkihiko Odaki     [PVTEIMC2] = igb_set_vteimc,
40983a977deeSAkihiko Odaki     [PVTEIMC3] = igb_set_vteimc,
40993a977deeSAkihiko Odaki     [PVTEIMC4] = igb_set_vteimc,
41003a977deeSAkihiko Odaki     [PVTEIMC5] = igb_set_vteimc,
41013a977deeSAkihiko Odaki     [PVTEIMC6] = igb_set_vteimc,
41023a977deeSAkihiko Odaki     [PVTEIMC7] = igb_set_vteimc,
41033a977deeSAkihiko Odaki     [PVTEIAC0] = igb_set_vteiac,
41043a977deeSAkihiko Odaki     [PVTEIAC1] = igb_set_vteiac,
41053a977deeSAkihiko Odaki     [PVTEIAC2] = igb_set_vteiac,
41063a977deeSAkihiko Odaki     [PVTEIAC3] = igb_set_vteiac,
41073a977deeSAkihiko Odaki     [PVTEIAC4] = igb_set_vteiac,
41083a977deeSAkihiko Odaki     [PVTEIAC5] = igb_set_vteiac,
41093a977deeSAkihiko Odaki     [PVTEIAC6] = igb_set_vteiac,
41103a977deeSAkihiko Odaki     [PVTEIAC7] = igb_set_vteiac,
41113a977deeSAkihiko Odaki     [PVTEIAM0] = igb_set_vteiam,
41123a977deeSAkihiko Odaki     [PVTEIAM1] = igb_set_vteiam,
41133a977deeSAkihiko Odaki     [PVTEIAM2] = igb_set_vteiam,
41143a977deeSAkihiko Odaki     [PVTEIAM3] = igb_set_vteiam,
41153a977deeSAkihiko Odaki     [PVTEIAM4] = igb_set_vteiam,
41163a977deeSAkihiko Odaki     [PVTEIAM5] = igb_set_vteiam,
41173a977deeSAkihiko Odaki     [PVTEIAM6] = igb_set_vteiam,
41183a977deeSAkihiko Odaki     [PVTEIAM7] = igb_set_vteiam,
41193a977deeSAkihiko Odaki     [PVTEICR0] = igb_set_vteicr,
41203a977deeSAkihiko Odaki     [PVTEICR1] = igb_set_vteicr,
41213a977deeSAkihiko Odaki     [PVTEICR2] = igb_set_vteicr,
41223a977deeSAkihiko Odaki     [PVTEICR3] = igb_set_vteicr,
41233a977deeSAkihiko Odaki     [PVTEICR4] = igb_set_vteicr,
41243a977deeSAkihiko Odaki     [PVTEICR5] = igb_set_vteicr,
41253a977deeSAkihiko Odaki     [PVTEICR6] = igb_set_vteicr,
41263a977deeSAkihiko Odaki     [PVTEICR7] = igb_set_vteicr,
41273a977deeSAkihiko Odaki     [VTIVAR ... VTIVAR + 7] = igb_set_vtivar,
41283a977deeSAkihiko Odaki     [VTIVAR_MISC ... VTIVAR_MISC + 7] = igb_mac_writereg
41293a977deeSAkihiko Odaki };
41303a977deeSAkihiko Odaki enum { IGB_NWRITEOPS = ARRAY_SIZE(igb_macreg_writeops) };
41313a977deeSAkihiko Odaki 
41323a977deeSAkihiko Odaki enum { MAC_ACCESS_PARTIAL = 1 };
41333a977deeSAkihiko Odaki 
41343a977deeSAkihiko Odaki /*
41353a977deeSAkihiko Odaki  * The array below combines alias offsets of the index values for the
41363a977deeSAkihiko Odaki  * MAC registers that have aliases, with the indication of not fully
41373a977deeSAkihiko Odaki  * implemented registers (lowest bit). This combination is possible
41383a977deeSAkihiko Odaki  * because all of the offsets are even.
41393a977deeSAkihiko Odaki  */
41403a977deeSAkihiko Odaki static const uint16_t mac_reg_access[E1000E_MAC_SIZE] = {
41413a977deeSAkihiko Odaki     /* Alias index offsets */
41423a977deeSAkihiko Odaki     [FCRTL_A] = 0x07fe,
41433a977deeSAkihiko Odaki     [RDFH_A]  = 0xe904, [RDFT_A]  = 0xe904,
41443a977deeSAkihiko Odaki     [TDFH_A]  = 0xed00, [TDFT_A]  = 0xed00,
41453a977deeSAkihiko Odaki     [RA_A ... RA_A + 31]      = 0x14f0,
41463a977deeSAkihiko Odaki     [VFTA_A ... VFTA_A + E1000_VLAN_FILTER_TBL_SIZE - 1] = 0x1400,
41473a977deeSAkihiko Odaki 
41483a977deeSAkihiko Odaki     [RDBAL0_A] = 0x2600,
41493a977deeSAkihiko Odaki     [RDBAH0_A] = 0x2600,
41503a977deeSAkihiko Odaki     [RDLEN0_A] = 0x2600,
41513a977deeSAkihiko Odaki     [SRRCTL0_A] = 0x2600,
41523a977deeSAkihiko Odaki     [RDH0_A] = 0x2600,
41533a977deeSAkihiko Odaki     [RDT0_A] = 0x2600,
41543a977deeSAkihiko Odaki     [RXDCTL0_A] = 0x2600,
41553a977deeSAkihiko Odaki     [RXCTL0_A] = 0x2600,
41563a977deeSAkihiko Odaki     [RQDPC0_A] = 0x2600,
41573a977deeSAkihiko Odaki     [RDBAL1_A] = 0x25D0,
41583a977deeSAkihiko Odaki     [RDBAL2_A] = 0x25A0,
41593a977deeSAkihiko Odaki     [RDBAL3_A] = 0x2570,
41603a977deeSAkihiko Odaki     [RDBAH1_A] = 0x25D0,
41613a977deeSAkihiko Odaki     [RDBAH2_A] = 0x25A0,
41623a977deeSAkihiko Odaki     [RDBAH3_A] = 0x2570,
41633a977deeSAkihiko Odaki     [RDLEN1_A] = 0x25D0,
41643a977deeSAkihiko Odaki     [RDLEN2_A] = 0x25A0,
41653a977deeSAkihiko Odaki     [RDLEN3_A] = 0x2570,
41663a977deeSAkihiko Odaki     [SRRCTL1_A] = 0x25D0,
41673a977deeSAkihiko Odaki     [SRRCTL2_A] = 0x25A0,
41683a977deeSAkihiko Odaki     [SRRCTL3_A] = 0x2570,
41693a977deeSAkihiko Odaki     [RDH1_A] = 0x25D0,
41703a977deeSAkihiko Odaki     [RDH2_A] = 0x25A0,
41713a977deeSAkihiko Odaki     [RDH3_A] = 0x2570,
41723a977deeSAkihiko Odaki     [RDT1_A] = 0x25D0,
41733a977deeSAkihiko Odaki     [RDT2_A] = 0x25A0,
41743a977deeSAkihiko Odaki     [RDT3_A] = 0x2570,
41753a977deeSAkihiko Odaki     [RXDCTL1_A] = 0x25D0,
41763a977deeSAkihiko Odaki     [RXDCTL2_A] = 0x25A0,
41773a977deeSAkihiko Odaki     [RXDCTL3_A] = 0x2570,
41783a977deeSAkihiko Odaki     [RXCTL1_A] = 0x25D0,
41793a977deeSAkihiko Odaki     [RXCTL2_A] = 0x25A0,
41803a977deeSAkihiko Odaki     [RXCTL3_A] = 0x2570,
41813a977deeSAkihiko Odaki     [RQDPC1_A] = 0x25D0,
41823a977deeSAkihiko Odaki     [RQDPC2_A] = 0x25A0,
41833a977deeSAkihiko Odaki     [RQDPC3_A] = 0x2570,
41843a977deeSAkihiko Odaki     [TDBAL0_A] = 0x2A00,
41853a977deeSAkihiko Odaki     [TDBAH0_A] = 0x2A00,
41863a977deeSAkihiko Odaki     [TDLEN0_A] = 0x2A00,
41873a977deeSAkihiko Odaki     [TDH0_A] = 0x2A00,
41883a977deeSAkihiko Odaki     [TDT0_A] = 0x2A00,
41893a977deeSAkihiko Odaki     [TXCTL0_A] = 0x2A00,
41903a977deeSAkihiko Odaki     [TDWBAL0_A] = 0x2A00,
41913a977deeSAkihiko Odaki     [TDWBAH0_A] = 0x2A00,
41923a977deeSAkihiko Odaki     [TDBAL1_A] = 0x29D0,
41933a977deeSAkihiko Odaki     [TDBAL2_A] = 0x29A0,
41943a977deeSAkihiko Odaki     [TDBAL3_A] = 0x2970,
41953a977deeSAkihiko Odaki     [TDBAH1_A] = 0x29D0,
41963a977deeSAkihiko Odaki     [TDBAH2_A] = 0x29A0,
41973a977deeSAkihiko Odaki     [TDBAH3_A] = 0x2970,
41983a977deeSAkihiko Odaki     [TDLEN1_A] = 0x29D0,
41993a977deeSAkihiko Odaki     [TDLEN2_A] = 0x29A0,
42003a977deeSAkihiko Odaki     [TDLEN3_A] = 0x2970,
42013a977deeSAkihiko Odaki     [TDH1_A] = 0x29D0,
42023a977deeSAkihiko Odaki     [TDH2_A] = 0x29A0,
42033a977deeSAkihiko Odaki     [TDH3_A] = 0x2970,
42043a977deeSAkihiko Odaki     [TDT1_A] = 0x29D0,
42053a977deeSAkihiko Odaki     [TDT2_A] = 0x29A0,
42063a977deeSAkihiko Odaki     [TDT3_A] = 0x2970,
42073a977deeSAkihiko Odaki     [TXDCTL0_A] = 0x2A00,
42083a977deeSAkihiko Odaki     [TXDCTL1_A] = 0x29D0,
42093a977deeSAkihiko Odaki     [TXDCTL2_A] = 0x29A0,
42103a977deeSAkihiko Odaki     [TXDCTL3_A] = 0x2970,
42113a977deeSAkihiko Odaki     [TXCTL1_A] = 0x29D0,
42123a977deeSAkihiko Odaki     [TXCTL2_A] = 0x29A0,
42133a977deeSAkihiko Odaki     [TXCTL3_A] = 0x29D0,
42143a977deeSAkihiko Odaki     [TDWBAL1_A] = 0x29D0,
42153a977deeSAkihiko Odaki     [TDWBAL2_A] = 0x29A0,
42163a977deeSAkihiko Odaki     [TDWBAL3_A] = 0x2970,
42173a977deeSAkihiko Odaki     [TDWBAH1_A] = 0x29D0,
42183a977deeSAkihiko Odaki     [TDWBAH2_A] = 0x29A0,
42193a977deeSAkihiko Odaki     [TDWBAH3_A] = 0x2970,
42203a977deeSAkihiko Odaki 
42213a977deeSAkihiko Odaki     /* Access options */
42223a977deeSAkihiko Odaki     [RDFH]  = MAC_ACCESS_PARTIAL,    [RDFT]  = MAC_ACCESS_PARTIAL,
42233a977deeSAkihiko Odaki     [RDFHS] = MAC_ACCESS_PARTIAL,    [RDFTS] = MAC_ACCESS_PARTIAL,
42243a977deeSAkihiko Odaki     [RDFPC] = MAC_ACCESS_PARTIAL,
42253a977deeSAkihiko Odaki     [TDFH]  = MAC_ACCESS_PARTIAL,    [TDFT]  = MAC_ACCESS_PARTIAL,
42263a977deeSAkihiko Odaki     [TDFHS] = MAC_ACCESS_PARTIAL,    [TDFTS] = MAC_ACCESS_PARTIAL,
42273a977deeSAkihiko Odaki     [TDFPC] = MAC_ACCESS_PARTIAL,    [EECD]  = MAC_ACCESS_PARTIAL,
42283a977deeSAkihiko Odaki     [FLA]   = MAC_ACCESS_PARTIAL,
42293a977deeSAkihiko Odaki     [FCAL]  = MAC_ACCESS_PARTIAL,    [FCAH]  = MAC_ACCESS_PARTIAL,
42303a977deeSAkihiko Odaki     [FCT]   = MAC_ACCESS_PARTIAL,    [FCTTV] = MAC_ACCESS_PARTIAL,
42313a977deeSAkihiko Odaki     [FCRTV] = MAC_ACCESS_PARTIAL,    [FCRTL] = MAC_ACCESS_PARTIAL,
42323a977deeSAkihiko Odaki     [FCRTH] = MAC_ACCESS_PARTIAL,
42333a977deeSAkihiko Odaki     [MAVTV0 ... MAVTV3] = MAC_ACCESS_PARTIAL
42343a977deeSAkihiko Odaki };
42353a977deeSAkihiko Odaki 
42363a977deeSAkihiko Odaki void
igb_core_write(IGBCore * core,hwaddr addr,uint64_t val,unsigned size)42373a977deeSAkihiko Odaki igb_core_write(IGBCore *core, hwaddr addr, uint64_t val, unsigned size)
42383a977deeSAkihiko Odaki {
42393a977deeSAkihiko Odaki     uint16_t index = igb_get_reg_index_with_offset(mac_reg_access, addr);
42403a977deeSAkihiko Odaki 
42413a977deeSAkihiko Odaki     if (index < IGB_NWRITEOPS && igb_macreg_writeops[index]) {
42423a977deeSAkihiko Odaki         if (mac_reg_access[index] & MAC_ACCESS_PARTIAL) {
42433a977deeSAkihiko Odaki             trace_e1000e_wrn_regs_write_trivial(index << 2);
42443a977deeSAkihiko Odaki         }
42453a977deeSAkihiko Odaki         trace_e1000e_core_write(index << 2, size, val);
42463a977deeSAkihiko Odaki         igb_macreg_writeops[index](core, index, val);
42473a977deeSAkihiko Odaki     } else if (index < IGB_NREADOPS && igb_macreg_readops[index]) {
42483a977deeSAkihiko Odaki         trace_e1000e_wrn_regs_write_ro(index << 2, size, val);
42493a977deeSAkihiko Odaki     } else {
42503a977deeSAkihiko Odaki         trace_e1000e_wrn_regs_write_unknown(index << 2, size, val);
42513a977deeSAkihiko Odaki     }
42523a977deeSAkihiko Odaki }
42533a977deeSAkihiko Odaki 
42543a977deeSAkihiko Odaki uint64_t
igb_core_read(IGBCore * core,hwaddr addr,unsigned size)42553a977deeSAkihiko Odaki igb_core_read(IGBCore *core, hwaddr addr, unsigned size)
42563a977deeSAkihiko Odaki {
42573a977deeSAkihiko Odaki     uint64_t val;
42583a977deeSAkihiko Odaki     uint16_t index = igb_get_reg_index_with_offset(mac_reg_access, addr);
42593a977deeSAkihiko Odaki 
42603a977deeSAkihiko Odaki     if (index < IGB_NREADOPS && igb_macreg_readops[index]) {
42613a977deeSAkihiko Odaki         if (mac_reg_access[index] & MAC_ACCESS_PARTIAL) {
42623a977deeSAkihiko Odaki             trace_e1000e_wrn_regs_read_trivial(index << 2);
42633a977deeSAkihiko Odaki         }
42643a977deeSAkihiko Odaki         val = igb_macreg_readops[index](core, index);
42653a977deeSAkihiko Odaki         trace_e1000e_core_read(index << 2, size, val);
42663a977deeSAkihiko Odaki         return val;
42673a977deeSAkihiko Odaki     } else {
42683a977deeSAkihiko Odaki         trace_e1000e_wrn_regs_read_unknown(index << 2, size);
42693a977deeSAkihiko Odaki     }
42703a977deeSAkihiko Odaki     return 0;
42713a977deeSAkihiko Odaki }
42723a977deeSAkihiko Odaki 
42733a977deeSAkihiko Odaki static void
igb_autoneg_resume(IGBCore * core)42743a977deeSAkihiko Odaki igb_autoneg_resume(IGBCore *core)
42753a977deeSAkihiko Odaki {
42763a977deeSAkihiko Odaki     if (igb_have_autoneg(core) &&
42773a977deeSAkihiko Odaki         !(core->phy[MII_BMSR] & MII_BMSR_AN_COMP)) {
42783a977deeSAkihiko Odaki         qemu_get_queue(core->owner_nic)->link_down = false;
42793a977deeSAkihiko Odaki         timer_mod(core->autoneg_timer,
42803a977deeSAkihiko Odaki                   qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
42813a977deeSAkihiko Odaki     }
42823a977deeSAkihiko Odaki }
42833a977deeSAkihiko Odaki 
42843a977deeSAkihiko Odaki void
igb_core_pci_realize(IGBCore * core,const uint16_t * eeprom_templ,uint32_t eeprom_size,const uint8_t * macaddr)42853a977deeSAkihiko Odaki igb_core_pci_realize(IGBCore        *core,
42863a977deeSAkihiko Odaki                      const uint16_t *eeprom_templ,
42873a977deeSAkihiko Odaki                      uint32_t        eeprom_size,
42883a977deeSAkihiko Odaki                      const uint8_t  *macaddr)
42893a977deeSAkihiko Odaki {
42903a977deeSAkihiko Odaki     int i;
42913a977deeSAkihiko Odaki 
42923a977deeSAkihiko Odaki     core->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
42933a977deeSAkihiko Odaki                                        igb_autoneg_timer, core);
42943a977deeSAkihiko Odaki     igb_intrmgr_pci_realize(core);
42953a977deeSAkihiko Odaki 
42963a977deeSAkihiko Odaki     for (i = 0; i < IGB_NUM_QUEUES; i++) {
4297a51db580SAkihiko Odaki         net_tx_pkt_init(&core->tx[i].tx_pkt, E1000E_MAX_TX_FRAGS);
42983a977deeSAkihiko Odaki     }
42993a977deeSAkihiko Odaki 
43003a977deeSAkihiko Odaki     net_rx_pkt_init(&core->rx_pkt);
43013a977deeSAkihiko Odaki 
43023a977deeSAkihiko Odaki     e1000x_core_prepare_eeprom(core->eeprom,
43033a977deeSAkihiko Odaki                                eeprom_templ,
43043a977deeSAkihiko Odaki                                eeprom_size,
43053a977deeSAkihiko Odaki                                PCI_DEVICE_GET_CLASS(core->owner)->device_id,
43063a977deeSAkihiko Odaki                                macaddr);
43073a977deeSAkihiko Odaki     igb_update_rx_offloads(core);
43083a977deeSAkihiko Odaki }
43093a977deeSAkihiko Odaki 
43103a977deeSAkihiko Odaki void
igb_core_pci_uninit(IGBCore * core)43113a977deeSAkihiko Odaki igb_core_pci_uninit(IGBCore *core)
43123a977deeSAkihiko Odaki {
43133a977deeSAkihiko Odaki     int i;
43143a977deeSAkihiko Odaki 
43153a977deeSAkihiko Odaki     timer_free(core->autoneg_timer);
43163a977deeSAkihiko Odaki 
43173a977deeSAkihiko Odaki     igb_intrmgr_pci_unint(core);
43183a977deeSAkihiko Odaki 
43193a977deeSAkihiko Odaki     for (i = 0; i < IGB_NUM_QUEUES; i++) {
43203a977deeSAkihiko Odaki         net_tx_pkt_uninit(core->tx[i].tx_pkt);
43213a977deeSAkihiko Odaki     }
43223a977deeSAkihiko Odaki 
43233a977deeSAkihiko Odaki     net_rx_pkt_uninit(core->rx_pkt);
43243a977deeSAkihiko Odaki }
43253a977deeSAkihiko Odaki 
43263a977deeSAkihiko Odaki static const uint16_t
43273a977deeSAkihiko Odaki igb_phy_reg_init[] = {
43283a977deeSAkihiko Odaki     [MII_BMCR] = MII_BMCR_SPEED1000 |
43293a977deeSAkihiko Odaki                  MII_BMCR_FD        |
43303a977deeSAkihiko Odaki                  MII_BMCR_AUTOEN,
43313a977deeSAkihiko Odaki 
43323a977deeSAkihiko Odaki     [MII_BMSR] = MII_BMSR_EXTCAP    |
43333a977deeSAkihiko Odaki                  MII_BMSR_LINK_ST   |
43343a977deeSAkihiko Odaki                  MII_BMSR_AUTONEG   |
43353a977deeSAkihiko Odaki                  MII_BMSR_MFPS      |
43363a977deeSAkihiko Odaki                  MII_BMSR_EXTSTAT   |
43373a977deeSAkihiko Odaki                  MII_BMSR_10T_HD    |
43383a977deeSAkihiko Odaki                  MII_BMSR_10T_FD    |
43393a977deeSAkihiko Odaki                  MII_BMSR_100TX_HD  |
43403a977deeSAkihiko Odaki                  MII_BMSR_100TX_FD,
43413a977deeSAkihiko Odaki 
43423a977deeSAkihiko Odaki     [MII_PHYID1]            = IGP03E1000_E_PHY_ID >> 16,
43433a977deeSAkihiko Odaki     [MII_PHYID2]            = (IGP03E1000_E_PHY_ID & 0xfff0) | 1,
43443a977deeSAkihiko Odaki     [MII_ANAR]              = MII_ANAR_CSMACD | MII_ANAR_10 |
43453a977deeSAkihiko Odaki                               MII_ANAR_10FD | MII_ANAR_TX |
43463a977deeSAkihiko Odaki                               MII_ANAR_TXFD | MII_ANAR_PAUSE |
43473a977deeSAkihiko Odaki                               MII_ANAR_PAUSE_ASYM,
43483a977deeSAkihiko Odaki     [MII_ANLPAR]            = MII_ANLPAR_10 | MII_ANLPAR_10FD |
43493a977deeSAkihiko Odaki                               MII_ANLPAR_TX | MII_ANLPAR_TXFD |
43503a977deeSAkihiko Odaki                               MII_ANLPAR_T4 | MII_ANLPAR_PAUSE,
43513a977deeSAkihiko Odaki     [MII_ANER]              = MII_ANER_NP | MII_ANER_NWAY,
43523a977deeSAkihiko Odaki     [MII_ANNP]              = 0x1 | MII_ANNP_MP,
43533a977deeSAkihiko Odaki     [MII_CTRL1000]          = MII_CTRL1000_HALF | MII_CTRL1000_FULL |
43543a977deeSAkihiko Odaki                               MII_CTRL1000_PORT | MII_CTRL1000_MASTER,
43553a977deeSAkihiko Odaki     [MII_STAT1000]          = MII_STAT1000_HALF | MII_STAT1000_FULL |
43563a977deeSAkihiko Odaki                               MII_STAT1000_ROK | MII_STAT1000_LOK,
43573a977deeSAkihiko Odaki     [MII_EXTSTAT]           = MII_EXTSTAT_1000T_HD | MII_EXTSTAT_1000T_FD,
43583a977deeSAkihiko Odaki 
43593a977deeSAkihiko Odaki     [IGP01E1000_PHY_PORT_CONFIG] = BIT(5) | BIT(8),
43603a977deeSAkihiko Odaki     [IGP01E1000_PHY_PORT_STATUS] = IGP01E1000_PSSR_SPEED_1000MBPS,
43613a977deeSAkihiko Odaki     [IGP02E1000_PHY_POWER_MGMT]  = BIT(0) | BIT(3) | IGP02E1000_PM_D3_LPLU |
43623a977deeSAkihiko Odaki                                    IGP01E1000_PSCFR_SMART_SPEED
43633a977deeSAkihiko Odaki };
43643a977deeSAkihiko Odaki 
43653a977deeSAkihiko Odaki static const uint32_t igb_mac_reg_init[] = {
43663a977deeSAkihiko Odaki     [LEDCTL]        = 2 | (3 << 8) | BIT(15) | (6 << 16) | (7 << 24),
43673a977deeSAkihiko Odaki     [EEMNGCTL]      = BIT(31),
43683269ebb3SSriram Yagnaraman     [TXDCTL0]       = E1000_TXDCTL_QUEUE_ENABLE,
43693a977deeSAkihiko Odaki     [RXDCTL0]       = E1000_RXDCTL_QUEUE_ENABLE | (1 << 16),
43703a977deeSAkihiko Odaki     [RXDCTL1]       = 1 << 16,
43713a977deeSAkihiko Odaki     [RXDCTL2]       = 1 << 16,
43723a977deeSAkihiko Odaki     [RXDCTL3]       = 1 << 16,
43733a977deeSAkihiko Odaki     [RXDCTL4]       = 1 << 16,
43743a977deeSAkihiko Odaki     [RXDCTL5]       = 1 << 16,
43753a977deeSAkihiko Odaki     [RXDCTL6]       = 1 << 16,
43763a977deeSAkihiko Odaki     [RXDCTL7]       = 1 << 16,
43773a977deeSAkihiko Odaki     [RXDCTL8]       = 1 << 16,
43783a977deeSAkihiko Odaki     [RXDCTL9]       = 1 << 16,
43793a977deeSAkihiko Odaki     [RXDCTL10]      = 1 << 16,
43803a977deeSAkihiko Odaki     [RXDCTL11]      = 1 << 16,
43813a977deeSAkihiko Odaki     [RXDCTL12]      = 1 << 16,
43823a977deeSAkihiko Odaki     [RXDCTL13]      = 1 << 16,
43833a977deeSAkihiko Odaki     [RXDCTL14]      = 1 << 16,
43843a977deeSAkihiko Odaki     [RXDCTL15]      = 1 << 16,
43853a977deeSAkihiko Odaki     [TIPG]          = 0x08 | (0x04 << 10) | (0x06 << 20),
43863a977deeSAkihiko Odaki     [CTRL]          = E1000_CTRL_FD | E1000_CTRL_LRST | E1000_CTRL_SPD_1000 |
43873a977deeSAkihiko Odaki                       E1000_CTRL_ADVD3WUC,
43883a977deeSAkihiko Odaki     [STATUS]        = E1000_STATUS_PHYRA | BIT(31),
43893a977deeSAkihiko Odaki     [EECD]          = E1000_EECD_FWE_DIS | E1000_EECD_PRES |
43903a977deeSAkihiko Odaki                       (2 << E1000_EECD_SIZE_EX_SHIFT),
43913a977deeSAkihiko Odaki     [GCR]           = E1000_L0S_ADJUST |
43923a977deeSAkihiko Odaki                       E1000_GCR_CMPL_TMOUT_RESEND |
43933a977deeSAkihiko Odaki                       E1000_GCR_CAP_VER2 |
43943a977deeSAkihiko Odaki                       E1000_L1_ENTRY_LATENCY_MSB |
43953a977deeSAkihiko Odaki                       E1000_L1_ENTRY_LATENCY_LSB,
43963a977deeSAkihiko Odaki     [RXCSUM]        = E1000_RXCSUM_IPOFLD | E1000_RXCSUM_TUOFLD,
43973a977deeSAkihiko Odaki     [TXPBS]         = 0x28,
43983a977deeSAkihiko Odaki     [RXPBS]         = 0x40,
43993a977deeSAkihiko Odaki     [TCTL]          = E1000_TCTL_PSP | (0xF << E1000_CT_SHIFT) |
44003a977deeSAkihiko Odaki                       (0x40 << E1000_COLD_SHIFT) | (0x1 << 26) | (0xA << 28),
44013a977deeSAkihiko Odaki     [TCTL_EXT]      = 0x40 | (0x42 << 10),
44023a977deeSAkihiko Odaki     [DTXCTL]        = E1000_DTXCTL_8023LL | E1000_DTXCTL_SPOOF_INT,
44033a977deeSAkihiko Odaki     [VET]           = ETH_P_VLAN | (ETH_P_VLAN << 16),
44043a977deeSAkihiko Odaki 
44053a977deeSAkihiko Odaki     [V2PMAILBOX0 ... V2PMAILBOX0 + IGB_MAX_VF_FUNCTIONS - 1] = E1000_V2PMAILBOX_RSTI,
44063a977deeSAkihiko Odaki     [MBVFIMR]       = 0xFF,
44073a977deeSAkihiko Odaki     [VFRE]          = 0xFF,
44083a977deeSAkihiko Odaki     [VFTE]          = 0xFF,
44093a977deeSAkihiko Odaki     [VMOLR0 ... VMOLR0 + 7] = 0x2600 | E1000_VMOLR_STRCRC,
44103a977deeSAkihiko Odaki     [RPLOLR]        = E1000_RPLOLR_STRCRC,
44113a977deeSAkihiko Odaki     [RLPML]         = 0x2600,
44123a977deeSAkihiko Odaki     [TXCTL0]        = E1000_DCA_TXCTRL_DATA_RRO_EN |
44133a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44143a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44153a977deeSAkihiko Odaki     [TXCTL1]        = E1000_DCA_TXCTRL_DATA_RRO_EN |
44163a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44173a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44183a977deeSAkihiko Odaki     [TXCTL2]        = E1000_DCA_TXCTRL_DATA_RRO_EN |
44193a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44203a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44213a977deeSAkihiko Odaki     [TXCTL3]        = E1000_DCA_TXCTRL_DATA_RRO_EN |
44223a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44233a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44243a977deeSAkihiko Odaki     [TXCTL4]        = E1000_DCA_TXCTRL_DATA_RRO_EN |
44253a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44263a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44273a977deeSAkihiko Odaki     [TXCTL5]        = E1000_DCA_TXCTRL_DATA_RRO_EN |
44283a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44293a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44303a977deeSAkihiko Odaki     [TXCTL6]        = E1000_DCA_TXCTRL_DATA_RRO_EN |
44313a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44323a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44333a977deeSAkihiko Odaki     [TXCTL7]        = E1000_DCA_TXCTRL_DATA_RRO_EN |
44343a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44353a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44363a977deeSAkihiko Odaki     [TXCTL8]        = E1000_DCA_TXCTRL_DATA_RRO_EN |
44373a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44383a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44393a977deeSAkihiko Odaki     [TXCTL9]        = E1000_DCA_TXCTRL_DATA_RRO_EN |
44403a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44413a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44423a977deeSAkihiko Odaki     [TXCTL10]       = E1000_DCA_TXCTRL_DATA_RRO_EN |
44433a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44443a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44453a977deeSAkihiko Odaki     [TXCTL11]       = E1000_DCA_TXCTRL_DATA_RRO_EN |
44463a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44473a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44483a977deeSAkihiko Odaki     [TXCTL12]       = E1000_DCA_TXCTRL_DATA_RRO_EN |
44493a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44503a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44513a977deeSAkihiko Odaki     [TXCTL13]       = E1000_DCA_TXCTRL_DATA_RRO_EN |
44523a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44533a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44543a977deeSAkihiko Odaki     [TXCTL14]       = E1000_DCA_TXCTRL_DATA_RRO_EN |
44553a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44563a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44573a977deeSAkihiko Odaki     [TXCTL15]       = E1000_DCA_TXCTRL_DATA_RRO_EN |
44583a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_TX_WB_RO_EN |
44593a977deeSAkihiko Odaki                       E1000_DCA_TXCTRL_DESC_RRO_EN,
44603a977deeSAkihiko Odaki };
44613a977deeSAkihiko Odaki 
igb_reset(IGBCore * core,bool sw)44623a977deeSAkihiko Odaki static void igb_reset(IGBCore *core, bool sw)
44633a977deeSAkihiko Odaki {
44643a977deeSAkihiko Odaki     struct igb_tx *tx;
44653a977deeSAkihiko Odaki     int i;
44663a977deeSAkihiko Odaki 
44673a977deeSAkihiko Odaki     timer_del(core->autoneg_timer);
44683a977deeSAkihiko Odaki 
44693a977deeSAkihiko Odaki     igb_intrmgr_reset(core);
44703a977deeSAkihiko Odaki 
44713a977deeSAkihiko Odaki     memset(core->phy, 0, sizeof core->phy);
44723a977deeSAkihiko Odaki     memcpy(core->phy, igb_phy_reg_init, sizeof igb_phy_reg_init);
44733a977deeSAkihiko Odaki 
44743a977deeSAkihiko Odaki     for (i = 0; i < E1000E_MAC_SIZE; i++) {
44753a977deeSAkihiko Odaki         if (sw &&
44763a977deeSAkihiko Odaki             (i == RXPBS || i == TXPBS ||
44773a977deeSAkihiko Odaki              (i >= EITR0 && i < EITR0 + IGB_INTR_NUM))) {
44783a977deeSAkihiko Odaki             continue;
44793a977deeSAkihiko Odaki         }
44803a977deeSAkihiko Odaki 
44813a977deeSAkihiko Odaki         core->mac[i] = i < ARRAY_SIZE(igb_mac_reg_init) ?
44823a977deeSAkihiko Odaki                        igb_mac_reg_init[i] : 0;
44833a977deeSAkihiko Odaki     }
44843a977deeSAkihiko Odaki 
44853a977deeSAkihiko Odaki     if (qemu_get_queue(core->owner_nic)->link_down) {
44863a977deeSAkihiko Odaki         igb_link_down(core);
44873a977deeSAkihiko Odaki     }
44883a977deeSAkihiko Odaki 
44893a977deeSAkihiko Odaki     e1000x_reset_mac_addr(core->owner_nic, core->mac, core->permanent_mac);
44903a977deeSAkihiko Odaki 
44912e68546aSSriram Yagnaraman     for (int vfn = 0; vfn < IGB_MAX_VF_FUNCTIONS; vfn++) {
44922e68546aSSriram Yagnaraman         /* Set RSTI, so VF can identify a PF reset is in progress */
44932e68546aSSriram Yagnaraman         core->mac[V2PMAILBOX0 + vfn] |= E1000_V2PMAILBOX_RSTI;
44942e68546aSSriram Yagnaraman     }
44952e68546aSSriram Yagnaraman 
44963a977deeSAkihiko Odaki     for (i = 0; i < ARRAY_SIZE(core->tx); i++) {
44973a977deeSAkihiko Odaki         tx = &core->tx[i];
4498212f7b1dSAkihiko Odaki         memset(tx->ctx, 0, sizeof(tx->ctx));
44993a977deeSAkihiko Odaki         tx->first = true;
45003a977deeSAkihiko Odaki         tx->skip_cp = false;
45013a977deeSAkihiko Odaki     }
45023a977deeSAkihiko Odaki }
45033a977deeSAkihiko Odaki 
45043a977deeSAkihiko Odaki void
igb_core_reset(IGBCore * core)45053a977deeSAkihiko Odaki igb_core_reset(IGBCore *core)
45063a977deeSAkihiko Odaki {
45073a977deeSAkihiko Odaki     igb_reset(core, false);
45083a977deeSAkihiko Odaki }
45093a977deeSAkihiko Odaki 
igb_core_pre_save(IGBCore * core)45103a977deeSAkihiko Odaki void igb_core_pre_save(IGBCore *core)
45113a977deeSAkihiko Odaki {
45123a977deeSAkihiko Odaki     int i;
45133a977deeSAkihiko Odaki     NetClientState *nc = qemu_get_queue(core->owner_nic);
45143a977deeSAkihiko Odaki 
45153a977deeSAkihiko Odaki     /*
45163a977deeSAkihiko Odaki      * If link is down and auto-negotiation is supported and ongoing,
45173a977deeSAkihiko Odaki      * complete auto-negotiation immediately. This allows us to look
45183a977deeSAkihiko Odaki      * at MII_BMSR_AN_COMP to infer link status on load.
45193a977deeSAkihiko Odaki      */
45203a977deeSAkihiko Odaki     if (nc->link_down && igb_have_autoneg(core)) {
45213a977deeSAkihiko Odaki         core->phy[MII_BMSR] |= MII_BMSR_AN_COMP;
45223a977deeSAkihiko Odaki         igb_update_flowctl_status(core);
45233a977deeSAkihiko Odaki     }
45243a977deeSAkihiko Odaki 
45253a977deeSAkihiko Odaki     for (i = 0; i < ARRAY_SIZE(core->tx); i++) {
45263a977deeSAkihiko Odaki         if (net_tx_pkt_has_fragments(core->tx[i].tx_pkt)) {
45273a977deeSAkihiko Odaki             core->tx[i].skip_cp = true;
45283a977deeSAkihiko Odaki         }
45293a977deeSAkihiko Odaki     }
45303a977deeSAkihiko Odaki }
45313a977deeSAkihiko Odaki 
45323a977deeSAkihiko Odaki int
igb_core_post_load(IGBCore * core)45333a977deeSAkihiko Odaki igb_core_post_load(IGBCore *core)
45343a977deeSAkihiko Odaki {
45353a977deeSAkihiko Odaki     NetClientState *nc = qemu_get_queue(core->owner_nic);
45363a977deeSAkihiko Odaki 
45373a977deeSAkihiko Odaki     /*
45383a977deeSAkihiko Odaki      * nc.link_down can't be migrated, so infer link_down according
45393a977deeSAkihiko Odaki      * to link status bit in core.mac[STATUS].
45403a977deeSAkihiko Odaki      */
45413a977deeSAkihiko Odaki     nc->link_down = (core->mac[STATUS] & E1000_STATUS_LU) == 0;
45423a977deeSAkihiko Odaki 
454365c2ab80SLaurent Vivier     /*
454465c2ab80SLaurent Vivier      * we need to restart intrmgr timers, as an older version of
454565c2ab80SLaurent Vivier      * QEMU can have stopped them before migration
454665c2ab80SLaurent Vivier      */
454765c2ab80SLaurent Vivier     igb_intrmgr_resume(core);
454865c2ab80SLaurent Vivier     igb_autoneg_resume(core);
454965c2ab80SLaurent Vivier 
45503a977deeSAkihiko Odaki     return 0;
45513a977deeSAkihiko Odaki }
4552