static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index) { u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index)); s32 ret_val = IXGBE_ERR_MBX; if (mbvficr & mask) { ret_val = IXGBE_SUCCESS; IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask); } return ret_val; }
/** * ixgbe_fcoe_ddp_put - free the ddp context for a given xid * @netdev: the corresponding net_device * @xid: the xid that corresponding ddp will be freed * * This is the implementation of net_device_ops.ndo_fcoe_ddp_done * and it is expected to be called by ULD, i.e., FCP layer of libfc * to release the corresponding ddp context when the I/O is done. * * Returns : data length already ddp-ed in bytes */ int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid) { int len = 0; struct ixgbe_fcoe *fcoe; struct ixgbe_adapter *adapter; struct ixgbe_fcoe_ddp *ddp; u32 fcbuff; if (!netdev) goto out_ddp_put; if (xid >= IXGBE_FCOE_DDP_MAX) goto out_ddp_put; adapter = netdev_priv(netdev); fcoe = &adapter->fcoe; ddp = &fcoe->ddp[xid]; if (!ddp->udl) goto out_ddp_put; len = ddp->len; /* if there an error, force to invalidate ddp context */ if (ddp->err) { spin_lock_bh(&fcoe->lock); IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCFLT, 0); IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCFLTRW, (xid | IXGBE_FCFLTRW_WE)); IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCBUFF, 0); IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCDMARW, (xid | IXGBE_FCDMARW_WE)); /* guaranteed to be invalidated after 100us */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCDMARW, (xid | IXGBE_FCDMARW_RE)); fcbuff = IXGBE_READ_REG(&adapter->hw, IXGBE_FCBUFF); spin_unlock_bh(&fcoe->lock); if (fcbuff & IXGBE_FCBUFF_VALID) udelay(100); } if (ddp->sgl) dma_unmap_sg(&adapter->pdev->dev, ddp->sgl, ddp->sgc, DMA_FROM_DEVICE); if (ddp->pool) { dma_pool_free(ddp->pool, ddp->udl, ddp->udp); ddp->pool = NULL; } ixgbe_fcoe_clear_ddp(ddp); out_ddp_put: return len; }
/** * ixgbe_dcb_config_tx_data_arbiter_82598 - Config Tx data arbiter * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Tx Data Arbiter and credits for each traffic class. */ s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw, u16 *refill, u16 *max, u8 *bwg_id, u8 *prio_type) { u32 reg; u8 i; reg = IXGBE_READ_REG(hw, IXGBE_PDPMCS); /* Enable Data Plane Arbiter */ reg &= ~IXGBE_PDPMCS_ARBDIS; /* Enable DFP and Transmit Recycle Mode */ reg |= (IXGBE_PDPMCS_TPPAC | IXGBE_PDPMCS_TRM); IXGBE_WRITE_REG(hw, IXGBE_PDPMCS, reg); /* Configure traffic class credits and priority */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { reg = refill[i]; reg |= (u32)(max[i]) << IXGBE_TDPT2TCCR_MCL_SHIFT; reg |= (u32)(bwg_id[i]) << IXGBE_TDPT2TCCR_BWG_SHIFT; if (prio_type[i] == prio_group) reg |= IXGBE_TDPT2TCCR_GSP; if (prio_type[i] == prio_link) reg |= IXGBE_TDPT2TCCR_LSP; IXGBE_WRITE_REG(hw, IXGBE_TDPT2TCCR(i), reg); } /* Enable Tx packet buffer division */ reg = IXGBE_READ_REG(hw, IXGBE_DTXCTL); reg |= IXGBE_DTXCTL_ENDBUBD; IXGBE_WRITE_REG(hw, IXGBE_DTXCTL, reg); return 0; }
/** * ixgbe_dcb_get_tc_stats_82599 - Returns status for each traffic class * @hw: pointer to hardware structure * @stats: pointer to statistics structure * @tc_count: Number of elements in bwg_array. * * This function returns the status data for each of the Traffic Classes in use. */ s32 ixgbe_dcb_get_tc_stats_82599(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats, u8 tc_count) { int tc; if (tc_count > MAX_TRAFFIC_CLASS) return DCB_ERR_PARAM; /* Statistics pertaining to each traffic class */ for (tc = 0; tc < tc_count; tc++) { /* Transmitted Packets */ stats->qptc[tc] += IXGBE_READ_REG(hw, IXGBE_QPTC(tc)); /* Transmitted Bytes */ stats->qbtc[tc] += IXGBE_READ_REG(hw, IXGBE_QBTC(tc)); /* Received Packets */ stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc)); /* Received Bytes */ stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC(tc)); } return 0; }
/** * ixgbe_ipsec_set_rx_item - set an Rx table item * @hw: hw specific details * @idx: register index to write * @tbl: table selector * * Trigger the device to store into a particular Rx table the * data that has already been loaded into the input register **/ static void ixgbe_ipsec_set_rx_item(struct ixgbe_hw *hw, u16 idx, enum ixgbe_ipsec_tbl_sel tbl) { u32 reg; reg = IXGBE_READ_REG(hw, IXGBE_IPSRXIDX); reg &= IXGBE_RXTXIDX_IPS_EN; reg |= tbl << IXGBE_RXIDX_TBL_SHIFT | idx << IXGBE_RXTXIDX_IDX_SHIFT | IXGBE_RXTXIDX_WRITE; IXGBE_WRITE_REG(hw, IXGBE_IPSRXIDX, reg); IXGBE_WRITE_FLUSH(hw); }
/** * ixgbe_dcb_config_pfc_82599 - Configure priority flow control * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Priority Flow Control (PFC) for each traffic class. */ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, struct ixgbe_dcb_config *dcb_config) { u32 i, reg; /* If PFC is disabled globally then fall back to LFC. */ if (!dcb_config->pfc_mode_enable) { for (i = 0; i < MAX_TRAFFIC_CLASS; i++) hw->mac.ops.setup_fc(hw, i); goto out; } /* Configure PFC Tx thresholds per TC */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { /* Config and remember Tx */ if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full || dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx) { reg = hw->fc.high_water | IXGBE_FCRTH_FCEN; IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg); reg = hw->fc.low_water | IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg); } else { IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), 0); IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); } } /* Configure pause time (2 TCs per register) */ reg = hw->fc.pause_time | (hw->fc.pause_time << 16); for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++) IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg); /* Configure flow control refresh threshold value */ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2); /* Enable Transmit PFC */ reg = IXGBE_FCCFG_TFCE_PRIORITY; IXGBE_WRITE_REG(hw, IXGBE_FCCFG, reg); /* * Enable Receive PFC * We will always honor XOFF frames we receive when * we are in PFC mode. */ reg = IXGBE_READ_REG(hw, IXGBE_MFLCN); reg &= ~IXGBE_MFLCN_RFCE; reg |= IXGBE_MFLCN_RPFCE; IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg); out: return 0; }
/** * ixgbe_get_link_capabilities_82598 - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: boolean auto-negotiation value * * Determines the link capabilities by reading the AUTOC register. **/ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg) { s32 status = 0; u32 autoc = 0; /* * Determine link capabilities based on the stored value of AUTOC, * which represents EEPROM defaults. If AUTOC value has not been * stored, use the current register value. */ if (hw->mac.orig_link_settings_stored) autoc = hw->mac.orig_autoc; else autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); switch (autoc & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = false; break; case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_10GB_FULL; *autoneg = false; break; case IXGBE_AUTOC_LMS_1G_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; case IXGBE_AUTOC_LMS_KX4_AN: case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: *speed = IXGBE_LINK_SPEED_UNKNOWN; if (autoc & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (autoc & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; default: status = IXGBE_ERR_LINK_SETUP; break; } return status; }
/** * ixgbevf_hv_set_rlpml_vf - Set the maximum receive packet length * @hw: pointer to the HW structure * @max_size: value to assign to max frame size * Hyper-V variant. **/ s32 ixgbevf_hv_set_rlpml_vf(struct ixgbe_hw *hw, u16 max_size) { u32 reg; /* If we are on Hyper-V, we implement this functionality * differently. */ reg = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(0)); /* CRC == 4 */ reg |= ((max_size + 4) | IXGBE_RXDCTL_RLPML_EN); IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(0), reg); return IXGBE_SUCCESS; }
/** * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock * @hw: pointer to the HW structure * @vf_number: the VF index * * return SUCCESS if we obtained the mailbox lock **/ static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number) { u32 p2v_mailbox; /* Take ownership of the buffer */ IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU); /* reserve mailbox for vf use */ p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number)); if (p2v_mailbox & IXGBE_PFMAILBOX_PFU) return 0; return IXGBE_ERR_MBX; }
static int ixgbe_txbpacks(char *page, char **start, off_t off, int count, int *eof, void *data) { struct ixgbe_hw *hw; struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data; if (adapter == NULL) return snprintf(page, count, "error: no adapter\n"); hw = &adapter->hw; if (hw == NULL) return snprintf(page, count, "error: no hw data\n"); return snprintf(page, count, "%d\n", IXGBE_READ_REG(hw, IXGBE_BPTC)); }
/** * ixgbe_get_link_capabilities_82598 - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: intean auto-negotiation value * * Determines the link capabilities by reading the AUTOC register. **/ int32_t ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, int *autoneg) { int32_t status = IXGBE_SUCCESS; int32_t autoc_reg; autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); if (hw->mac.link_settings_loaded) { autoc_reg &= ~IXGBE_AUTOC_LMS_ATTACH_TYPE; autoc_reg &= ~IXGBE_AUTOC_LMS_MASK; autoc_reg |= hw->mac.link_attach_type; autoc_reg |= hw->mac.link_mode_select; } switch (autoc_reg & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = FALSE; break; case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_10GB_FULL; *autoneg = FALSE; break; case IXGBE_AUTOC_LMS_1G_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = TRUE; break; case IXGBE_AUTOC_LMS_KX4_AN: case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: *speed = IXGBE_LINK_SPEED_UNKNOWN; if (autoc_reg & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (autoc_reg & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *autoneg = TRUE; break; default: status = IXGBE_ERR_LINK_SETUP; break; } return status; }
static int ixgbe_rxmpacks(char *page, char __always_unused **start, off_t __always_unused off, int count, int __always_unused *eof, void *data) { struct ixgbe_hw *hw; struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data; if (adapter == NULL) return snprintf(page, count, "error: no adapter\n"); hw = &adapter->hw; if (hw == NULL) return snprintf(page, count, "error: no hw data\n"); return snprintf(page, count, "%d\n", IXGBE_READ_REG(hw, IXGBE_MPRC)); }
/** * ixgbe_ptp_tx_hwtstamp - utility function which checks for TX time stamp * @q_vector: structure containing interrupt and ring information * @skb: particular skb to send timestamp with * * if the timestamp is valid, we convert it into the timecounter ns * value, then store that result into the shhwtstamps structure which * is passed up the network stack */ void ixgbe_ptp_tx_hwtstamp(struct ixgbe_q_vector *q_vector, struct sk_buff *skb) { struct ixgbe_adapter *adapter; struct ixgbe_hw *hw; struct skb_shared_hwtstamps shhwtstamps; u64 regval = 0, ns; u32 tsynctxctl; unsigned long flags; /* we cannot process timestamps on a ring without a q_vector */ if (!q_vector || !q_vector->adapter) return; adapter = q_vector->adapter; hw = &adapter->hw; tsynctxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL); regval |= (u64)IXGBE_READ_REG(hw, IXGBE_TXSTMPL); regval |= (u64)IXGBE_READ_REG(hw, IXGBE_TXSTMPH) << 32; /* * if TX timestamp is not valid, exit after clearing the * timestamp registers */ if (!(tsynctxctl & IXGBE_TSYNCTXCTL_VALID)) return; spin_lock_irqsave(&adapter->tmreg_lock, flags); ns = timecounter_cyc2time(&adapter->tc, regval); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); memset(&shhwtstamps, 0, sizeof(shhwtstamps)); shhwtstamps.hwtstamp = ns_to_ktime(ns); skb_tstamp_tx(skb, &shhwtstamps); }
/** * ixgbe_dcb_config_tc_stats_82598 - Configure traffic class statistics * @hw: pointer to hardware structure * * Configure queue statistics registers, all queues belonging to same traffic * class uses a single set of queue statistics counters. */ static s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw) { u32 reg = 0; u8 i = 0; u8 j = 0; /* Receive Queues stats setting - 8 queues per statistics reg */ for (i = 0, j = 0; i < 15 && j < 8; i = i + 2, j++) { reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(i)); reg |= ((0x1010101) * j); IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i), reg); reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(i + 1)); reg |= ((0x1010101) * j); IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i + 1), reg); } /* Transmit Queues stats setting - 4 queues per statistics reg */ for (i = 0; i < 8; i++) { reg = IXGBE_READ_REG(hw, IXGBE_TQSMR(i)); reg |= ((0x1010101) * i); IXGBE_WRITE_REG(hw, IXGBE_TQSMR(i), reg); } return 0; }
/** * ixgbe_get_link_settings_82598 - Determines default link settings * @hw: pointer to hardware structure * @speed: pointer to link speed * @autoneg: boolean auto-negotiation value * * Determines the default link settings by reading the AUTOC register. **/ static s32 ixgbe_get_link_settings_82598(struct ixgbe_hw *hw, u32 *speed, bool *autoneg) { s32 status = 0; s32 autoc_reg; autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); if (hw->mac.link_settings_loaded) { autoc_reg &= ~IXGBE_AUTOC_LMS_ATTACH_TYPE; autoc_reg &= ~IXGBE_AUTOC_LMS_MASK; autoc_reg |= hw->mac.link_attach_type; autoc_reg |= hw->mac.link_mode_select; } switch (autoc_reg & IXGBE_AUTOC_LMS_MASK) { case IXGBE_AUTOC_LMS_1G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = false; break; case IXGBE_AUTOC_LMS_10G_LINK_NO_AN: *speed = IXGBE_LINK_SPEED_10GB_FULL; *autoneg = false; break; case IXGBE_AUTOC_LMS_1G_AN: *speed = IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; case IXGBE_AUTOC_LMS_KX4_AN: case IXGBE_AUTOC_LMS_KX4_AN_1G_AN: *speed = IXGBE_LINK_SPEED_UNKNOWN; if (autoc_reg & IXGBE_AUTOC_KX4_SUPP) *speed |= IXGBE_LINK_SPEED_10GB_FULL; if (autoc_reg & IXGBE_AUTOC_KX_SUPP) *speed |= IXGBE_LINK_SPEED_1GB_FULL; *autoneg = true; break; default: status = IXGBE_ERR_LINK_SETUP; break; } return status; }
/** * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock * @hw: pointer to the HW structure * @vf_number: the VF index * * return SUCCESS if we obtained the mailbox lock **/ static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number) { s32 ret_val = IXGBE_ERR_MBX; u32 p2v_mailbox; DEBUGFUNC("ixgbe_obtain_mbx_lock_pf"); /* Take ownership of the buffer */ IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU); /* reserve mailbox for vf use */ p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number)); if (p2v_mailbox & IXGBE_PFMAILBOX_PFU) ret_val = IXGBE_SUCCESS; return ret_val; }
/** * ixgbe_ipsec_set_tx_sa - set the Tx SA registers * @hw: hw specific details * @idx: register index to write * @key: key byte array * @salt: salt bytes **/ static void ixgbe_ipsec_set_tx_sa(struct ixgbe_hw *hw, u16 idx, u32 key[], u32 salt) { u32 reg; int i; for (i = 0; i < 4; i++) IXGBE_WRITE_REG(hw, IXGBE_IPSTXKEY(i), cpu_to_be32(key[3 - i])); IXGBE_WRITE_REG(hw, IXGBE_IPSTXSALT, cpu_to_be32(salt)); IXGBE_WRITE_FLUSH(hw); reg = IXGBE_READ_REG(hw, IXGBE_IPSTXIDX); reg &= IXGBE_RXTXIDX_IPS_EN; reg |= idx << IXGBE_RXTXIDX_IDX_SHIFT | IXGBE_RXTXIDX_WRITE; IXGBE_WRITE_REG(hw, IXGBE_IPSTXIDX, reg); IXGBE_WRITE_FLUSH(hw); }
/** * ixgbe_check_for_rst_pf - checks to see if the VF has reset * @hw: pointer to the HW structure * @vf_number: the VF index * * returns SUCCESS if the VF has set the Status bit or else ERR_MBX **/ static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number) { u32 reg_offset = (vf_number < 32) ? 0 : 1; u32 vf_shift = vf_number % 32; u32 vflre = 0; s32 ret_val = IXGBE_ERR_MBX; if (hw->mac.type == ixgbe_mac_82599EB) vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset)); if (vflre & (1 << vf_shift)) { ret_val = 0; IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift)); hw->mbx.stats.rsts++; } return ret_val; }
/** * ixgbe_check_mac_link_82598 - Get link/speed status * @hw: pointer to hardware structure * @speed: pointer to link speed * @link_up: true is link is up, false otherwise * * Reads the links register to determine if link is up and the current speed **/ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, u32 *speed, bool *link_up) { u32 links_reg; links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (links_reg & IXGBE_LINKS_UP) *link_up = true; else *link_up = false; if (links_reg & IXGBE_LINKS_SPEED) *speed = IXGBE_LINK_SPEED_10GB_FULL; else *speed = IXGBE_LINK_SPEED_1GB_FULL; return 0; }
/** * ixgbe_init_eeprom_params_X540 - Initialize EEPROM params * @hw: pointer to hardware structure * * Initializes the EEPROM parameters ixgbe_eeprom_info within the * ixgbe_hw struct in order to set up EEPROM access. **/ static s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw) { struct ixgbe_eeprom_info *eeprom = &hw->eeprom; u32 eec; u16 eeprom_size; if (eeprom->type == ixgbe_eeprom_uninitialized) { eeprom->semaphore_delay = 10; eeprom->type = ixgbe_flash; eec = IXGBE_READ_REG(hw, IXGBE_EEC); eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> IXGBE_EEC_SIZE_SHIFT); eeprom->word_size = 1 << (eeprom_size + IXGBE_EEPROM_WORD_SIZE_SHIFT); hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", eeprom->type, eeprom->word_size); }
/** * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock * @hw: pointer to the HW structure * @vf_number: the VF index * * return SUCCESS if we obtained the mailbox lock **/ static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number) { s32 ret_val = IXGBE_ERR_MBX; u32 p2v_mailbox; /* Take ownership of the buffer */ IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU); /* reserve mailbox for vf use */ p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number)); if (p2v_mailbox & IXGBE_PFMAILBOX_PFU) ret_val = 0; else ERROR_REPORT2(IXGBE_ERROR_POLLING, "Failed to obtain mailbox lock for VF%d", vf_number); return ret_val; }
static int ixgbe_phys_id(struct net_device *netdev, u32 data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); u32 i; if (!data || data > 300) data = 300; for (i = 0; i < (data * 1000); i += 400) { hw->mac.ops.led_on(hw, IXGBE_LED_ON); msleep_interruptible(200); hw->mac.ops.led_off(hw, IXGBE_LED_ON); msleep_interruptible(200); } /* Restore LED settings */ IXGBE_WRITE_REG(&adapter->hw, IXGBE_LEDCTL, led_reg); return 0; }
/** * ixgbe_dcb_config_tx_desc_arbiter_82598 - Config Tx Desc. arbiter * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Tx Descriptor Arbiter and credits for each traffic class. */ s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw, u16 *refill, u16 *max, u8 *bwg_id, u8 *prio_type) { u32 reg, max_credits; u8 i; reg = IXGBE_READ_REG(hw, IXGBE_DPMCS); /* Enable arbiter */ reg &= ~IXGBE_DPMCS_ARBDIS; /* Enable DFP and Recycle mode */ reg |= (IXGBE_DPMCS_TDPAC | IXGBE_DPMCS_TRM); reg |= IXGBE_DPMCS_TSOEF; /* Configure Max TSO packet size 34KB including payload and headers */ reg |= (0x4 << IXGBE_DPMCS_MTSOS_SHIFT); IXGBE_WRITE_REG(hw, IXGBE_DPMCS, reg); /* Configure traffic class credits and priority */ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) { max_credits = max[i]; reg = max_credits << IXGBE_TDTQ2TCCR_MCL_SHIFT; reg |= refill[i]; reg |= (u32)(bwg_id[i]) << IXGBE_TDTQ2TCCR_BWG_SHIFT; if (prio_type[i] == prio_group) reg |= IXGBE_TDTQ2TCCR_GSP; if (prio_type[i] == prio_link) reg |= IXGBE_TDTQ2TCCR_LSP; IXGBE_WRITE_REG(hw, IXGBE_TDTQ2TCCR(i), reg); } return 0; }
/** * ixgbe_dcb_config_tx_desc_arbiter_82598 - Config Tx Desc. arbiter * @hw: pointer to hardware structure * @dcb_config: pointer to ixgbe_dcb_config structure * * Configure Tx Descriptor Arbiter and credits for each traffic class. */ s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw, u16 *refill, u16 *max, u8 *bwg_id, u8 *tsa) { u32 reg, max_credits; u8 i; reg = IXGBE_READ_REG(hw, IXGBE_DPMCS); /* Enable arbiter */ reg &= ~IXGBE_DPMCS_ARBDIS; reg |= IXGBE_DPMCS_TSOEF; /* Configure Max TSO packet size 34KB including payload and headers */ reg |= (0x4 << IXGBE_DPMCS_MTSOS_SHIFT); IXGBE_WRITE_REG(hw, IXGBE_DPMCS, reg); /* Configure traffic class credits and priority */ for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) { max_credits = max[i]; reg = max_credits << IXGBE_TDTQ2TCCR_MCL_SHIFT; reg |= refill[i]; reg |= (u32)(bwg_id[i]) << IXGBE_TDTQ2TCCR_BWG_SHIFT; if (tsa[i] == ixgbe_dcb_tsa_group_strict_cee) reg |= IXGBE_TDTQ2TCCR_GSP; if (tsa[i] == ixgbe_dcb_tsa_strict) reg |= IXGBE_TDTQ2TCCR_LSP; IXGBE_WRITE_REG(hw, IXGBE_TDTQ2TCCR(i), reg); } return IXGBE_SUCCESS; }
s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr) { u32 rar_low, rar_high; u32 rar_entries = hw->mac.num_rar_entries; /* Make sure we are using a valid rar index range */ if (index >= rar_entries) { return IXGBE_ERR_INVALID_ARGUMENT; } /* * HW expects these in little endian so we reverse the byte * order from network order (big endian) to little endian */ rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) | ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); /* * Some parts put the VMDq setting in the extra RAH bits, * so save everything except the lower 16 bits that hold part * of the address and the address valid bit. */ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8)); if (enable_addr != 0) rar_high |= IXGBE_RAH_AV; IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); return 0; }
/** * ixgbe_start_hw_generic - Prepare hardware for Tx/Rx * @hw: pointer to hardware structure * * Starts the hardware by filling the bus info structure and media type, clears * all on chip counters, initializes receive address registers, multicast * table, VLAN filter table, calls routine to set up link and flow control * settings, and leaves transmit and receive units disabled and uninitialized **/ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) { u32 ctrl_ext; /* Set the media type */ hw->phy.media_type = hw->mac.ops.get_media_type(hw); /* Identify the PHY */ hw->phy.ops.identify(hw); /* * Store MAC address from RAR0, clear receive address registers, and * clear the multicast table */ hw->mac.ops.init_rx_addrs(hw); /* Clear the VLAN filter table */ hw->mac.ops.clear_vfta(hw); /* Set up link */ hw->mac.ops.setup_link(hw); /* Clear statistics registers */ hw->mac.ops.clear_hw_cntrs(hw); /* Set No Snoop Disable */ ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); ctrl_ext |= IXGBE_CTRL_EXT_NS_DIS; IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); IXGBE_WRITE_FLUSH(hw); /* Clear adapter stopped flag */ hw->adapter_stopped = false; return 0; }
static void ixgbevf_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; u32 *regs_buff = p; u32 regs_len = ixgbevf_get_regs_len(netdev); u8 i; memset(p, 0, regs_len); regs->version = (1 << 24) | hw->revision_id << 16 | hw->device_id; /* General Registers */ regs_buff[0] = IXGBE_READ_REG(hw, IXGBE_VFCTRL); regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_VFSTATUS); regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_VFLINKS); regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_VFRXMEMWRAP); regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_VFFRTIMER); /* Interrupt */ /* don't read EICR because it can clear interrupt causes, instead * read EICS which is a shadow but doesn't clear EICR */ regs_buff[5] = IXGBE_READ_REG(hw, IXGBE_VTEICS); regs_buff[6] = IXGBE_READ_REG(hw, IXGBE_VTEICS); regs_buff[7] = IXGBE_READ_REG(hw, IXGBE_VTEIMS); regs_buff[8] = IXGBE_READ_REG(hw, IXGBE_VTEIMC); regs_buff[9] = IXGBE_READ_REG(hw, IXGBE_VTEIAC); regs_buff[10] = IXGBE_READ_REG(hw, IXGBE_VTEIAM); regs_buff[11] = IXGBE_READ_REG(hw, IXGBE_VTEITR(0)); regs_buff[12] = IXGBE_READ_REG(hw, IXGBE_VTIVAR(0)); regs_buff[13] = IXGBE_READ_REG(hw, IXGBE_VTIVAR_MISC); /* Receive DMA */ for (i = 0; i < 2; i++) regs_buff[14 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDBAL(i)); for (i = 0; i < 2; i++) regs_buff[16 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDBAH(i)); for (i = 0; i < 2; i++) regs_buff[18 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDLEN(i)); for (i = 0; i < 2; i++) regs_buff[20 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDH(i)); for (i = 0; i < 2; i++) regs_buff[22 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDT(i)); for (i = 0; i < 2; i++) regs_buff[24 + i] = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); for (i = 0; i < 2; i++) regs_buff[26 + i] = IXGBE_READ_REG(hw, IXGBE_VFSRRCTL(i)); /* Receive */ regs_buff[28] = IXGBE_READ_REG(hw, IXGBE_VFPSRTYPE); /* Transmit */ for (i = 0; i < 2; i++) regs_buff[29 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDBAL(i)); for (i = 0; i < 2; i++) regs_buff[31 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDBAH(i)); for (i = 0; i < 2; i++) regs_buff[33 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDLEN(i)); for (i = 0; i < 2; i++) regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDH(i)); for (i = 0; i < 2; i++) regs_buff[37 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDT(i)); for (i = 0; i < 2; i++) regs_buff[39 + i] = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i)); for (i = 0; i < 2; i++) regs_buff[41 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDWBAL(i)); for (i = 0; i < 2; i++) regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDWBAH(i)); for (i = 0; i < ARRAY_SIZE(ixgbevf_reg_names); i++) hw_dbg(hw, "%s\t%8.8x\n", ixgbevf_reg_names[i], regs_buff[i]); }
static void ixgbevf_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; u32 *regs_buff = p; u32 regs_len = ixgbevf_get_regs_len(netdev); u8 i; memset(p, 0, regs_len); regs->version = (1 << 24) | hw->revision_id << 16 | hw->device_id; regs_buff[0] = IXGBE_READ_REG(hw, IXGBE_VFCTRL); regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_VFSTATUS); regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_VFLINKS); regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_VFRXMEMWRAP); regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_VFFRTIMER); regs_buff[5] = IXGBE_READ_REG(hw, IXGBE_VTEICS); regs_buff[6] = IXGBE_READ_REG(hw, IXGBE_VTEICS); regs_buff[7] = IXGBE_READ_REG(hw, IXGBE_VTEIMS); regs_buff[8] = IXGBE_READ_REG(hw, IXGBE_VTEIMC); regs_buff[9] = IXGBE_READ_REG(hw, IXGBE_VTEIAC); regs_buff[10] = IXGBE_READ_REG(hw, IXGBE_VTEIAM); regs_buff[11] = IXGBE_READ_REG(hw, IXGBE_VTEITR(0)); regs_buff[12] = IXGBE_READ_REG(hw, IXGBE_VTIVAR(0)); regs_buff[13] = IXGBE_READ_REG(hw, IXGBE_VTIVAR_MISC); for (i = 0; i < 2; i++) regs_buff[14 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDBAL(i)); for (i = 0; i < 2; i++) regs_buff[16 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDBAH(i)); for (i = 0; i < 2; i++) regs_buff[18 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDLEN(i)); for (i = 0; i < 2; i++) regs_buff[20 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDH(i)); for (i = 0; i < 2; i++) regs_buff[22 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDT(i)); for (i = 0; i < 2; i++) regs_buff[24 + i] = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); for (i = 0; i < 2; i++) regs_buff[26 + i] = IXGBE_READ_REG(hw, IXGBE_VFSRRCTL(i)); regs_buff[28] = IXGBE_READ_REG(hw, IXGBE_VFPSRTYPE); for (i = 0; i < 2; i++) regs_buff[29 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDBAL(i)); for (i = 0; i < 2; i++) regs_buff[31 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDBAH(i)); for (i = 0; i < 2; i++) regs_buff[33 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDLEN(i)); for (i = 0; i < 2; i++) regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDH(i)); for (i = 0; i < 2; i++) regs_buff[37 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDT(i)); for (i = 0; i < 2; i++) regs_buff[39 + i] = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i)); for (i = 0; i < 2; i++) regs_buff[41 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDWBAL(i)); for (i = 0; i < 2; i++) regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDWBAH(i)); for (i = 0; i < ARRAY_SIZE(ixgbevf_reg_names); i++) hw_dbg(hw, "%s\t%8.8x\n", ixgbevf_reg_names[i], regs_buff[i]); }
/** * ixgbe_ptp_start_cyclecounter - create the cycle counter from hw * @adapter - pointer to the adapter structure * * this function initializes the timecounter and cyclecounter * structures for use in generated a ns counter from the arbitrary * fixed point cycles registers in the hardware. * * A change in link speed impacts the frequency of the DMA clock on * the device, which is used to generate the cycle counter * registers. Therefor this function is called whenever the link speed * changes. * * This function also turns on the SDP pin for clock out feature (X540 * only), because this is where the shift is first calculated. */ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; u32 incval = 0; u32 timinca = 0; u32 shift = 0; u32 cycle_speed; unsigned long flags; /** * Determine what speed we need to set the cyclecounter * for. It should be different for 100Mb, 1Gb, and 10Gb. Treat * unknown speeds as 10Gb. (Hence why we can't just copy the * link_speed. */ switch (adapter->link_speed) { case IXGBE_LINK_SPEED_100_FULL: case IXGBE_LINK_SPEED_1GB_FULL: case IXGBE_LINK_SPEED_10GB_FULL: cycle_speed = adapter->link_speed; break; default: /* cycle speed should be 10Gb when there is no link */ cycle_speed = IXGBE_LINK_SPEED_10GB_FULL; break; } /* * grab the current TIMINCA value from the register so that it can be * double checked. If the register value has been cleared, it must be * reset to the correct value for generating a cyclecounter. If * TIMINCA is zero, the SYSTIME registers do not increment at all. */ timinca = IXGBE_READ_REG(hw, IXGBE_TIMINCA); /* Bail if the cycle speed didn't change and TIMINCA is non-zero */ if (adapter->cycle_speed == cycle_speed && timinca) return; /* disable the SDP clock out */ ixgbe_ptp_disable_sdp(hw); /** * Scale the NIC cycle counter by a large factor so that * relatively small corrections to the frequency can be added * or subtracted. The drawbacks of a large factor include * (a) the clock register overflows more quickly, (b) the cycle * counter structure must be able to convert the systime value * to nanoseconds using only a multiplier and a right-shift, * and (c) the value must fit within the timinca register space * => math based on internal DMA clock rate and available bits */ switch (cycle_speed) { case IXGBE_LINK_SPEED_100_FULL: incval = IXGBE_INCVAL_100; shift = IXGBE_INCVAL_SHIFT_100; break; case IXGBE_LINK_SPEED_1GB_FULL: incval = IXGBE_INCVAL_1GB; shift = IXGBE_INCVAL_SHIFT_1GB; break; case IXGBE_LINK_SPEED_10GB_FULL: incval = IXGBE_INCVAL_10GB; shift = IXGBE_INCVAL_SHIFT_10GB; break; } /** * Modify the calculated values to fit within the correct * number of bits specified by the hardware. The 82599 doesn't * have the same space as the X540, so bitshift the calculated * values to fit. */ switch (hw->mac.type) { case ixgbe_mac_X540: IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, incval); break; case ixgbe_mac_82599EB: incval >>= IXGBE_INCVAL_SHIFT_82599; shift -= IXGBE_INCVAL_SHIFT_82599; IXGBE_WRITE_REG(hw, IXGBE_TIMINCA, (1 << IXGBE_INCPER_SHIFT_82599) | incval); break; default: /* other devices aren't supported */ return; } /* reset the system time registers */ IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000); IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000); IXGBE_WRITE_FLUSH(hw); /* now that the shift has been calculated and the systime * registers reset, (re-)enable the Clock out feature*/ ixgbe_ptp_enable_sdp(hw, shift); /* store the new cycle speed */ adapter->cycle_speed = cycle_speed; ACCESS_ONCE(adapter->base_incval) = incval; smp_mb(); /* grab the ptp lock */ spin_lock_irqsave(&adapter->tmreg_lock, flags); memset(&adapter->cc, 0, sizeof(adapter->cc)); adapter->cc.read = ixgbe_ptp_read; adapter->cc.mask = CLOCKSOURCE_MASK(64); adapter->cc.shift = shift; adapter->cc.mult = 1; /* reset the ns time counter */ timecounter_init(&adapter->tc, &adapter->cc, ktime_to_ns(ktime_get_real())); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); }
/** * ixgbe_ptp_hwtstamp_ioctl - control hardware time stamping * @adapter: pointer to adapter struct * @ifreq: ioctl data * @cmd: particular ioctl requested * * Outgoing time stamping can be enabled and disabled. Play nice and * disable it when requested, although it shouldn't case any overhead * when no packet needs it. At most one packet in the queue may be * marked for time stamping, otherwise it would be impossible to tell * for sure to which packet the hardware time stamp belongs. * * Incoming time stamping has to be configured via the hardware * filters. Not all combinations are supported, in particular event * type has to be specified. Matching the kind of event packet is * not supported, with the exception of "all V2 events regardless of * level 2 or 4". */ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, struct ifreq *ifr, int cmd) { struct ixgbe_hw *hw = &adapter->hw; struct hwtstamp_config config; u32 tsync_tx_ctl = IXGBE_TSYNCTXCTL_ENABLED; u32 tsync_rx_ctl = IXGBE_TSYNCRXCTL_ENABLED; u32 tsync_rx_mtrl = 0; bool is_l4 = false; bool is_l2 = false; u32 regval; if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) return -EFAULT; /* reserved for future extensions */ if (config.flags) return -EINVAL; switch (config.tx_type) { case HWTSTAMP_TX_OFF: tsync_tx_ctl = 0; case HWTSTAMP_TX_ON: break; default: return -ERANGE; } switch (config.rx_filter) { case HWTSTAMP_FILTER_NONE: tsync_rx_ctl = 0; break; case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; tsync_rx_mtrl = IXGBE_RXMTRL_V1_SYNC_MSG; is_l4 = true; break; case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; tsync_rx_mtrl = IXGBE_RXMTRL_V1_DELAY_REQ_MSG; is_l4 = true; break; case HWTSTAMP_FILTER_PTP_V2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L2_L4_V2; tsync_rx_mtrl = IXGBE_RXMTRL_V2_SYNC_MSG; is_l2 = true; is_l4 = true; config.rx_filter = HWTSTAMP_FILTER_SOME; break; case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L2_L4_V2; tsync_rx_mtrl = IXGBE_RXMTRL_V2_DELAY_REQ_MSG; is_l2 = true; is_l4 = true; config.rx_filter = HWTSTAMP_FILTER_SOME; break; case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: case HWTSTAMP_FILTER_PTP_V2_EVENT: tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_EVENT_V2; config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; is_l2 = true; is_l4 = true; break; case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: case HWTSTAMP_FILTER_ALL: default: /* * register RXMTRL must be set, therefore it is not * possible to time stamp both V1 Sync and Delay_Req messages * and hardware does not support timestamping all packets * => return error */ return -ERANGE; } if (hw->mac.type == ixgbe_mac_82598EB) { if (tsync_rx_ctl | tsync_tx_ctl) return -ERANGE; return 0; } /* define ethertype filter for timestamped packets */ if (is_l2) IXGBE_WRITE_REG(hw, IXGBE_ETQF(3), (IXGBE_ETQF_FILTER_EN | /* enable filter */ IXGBE_ETQF_1588 | /* enable timestamping */ ETH_P_1588)); /* 1588 eth protocol type */ else IXGBE_WRITE_REG(hw, IXGBE_ETQF(3), 0); #define PTP_PORT 319 /* L4 Queue Filter[3]: filter by destination port and protocol */ if (is_l4) { u32 ftqf = (IXGBE_FTQF_PROTOCOL_UDP /* UDP */ | IXGBE_FTQF_POOL_MASK_EN /* Pool not compared */ | IXGBE_FTQF_QUEUE_ENABLE); ftqf |= ((IXGBE_FTQF_PROTOCOL_COMP_MASK /* protocol check */ & IXGBE_FTQF_DEST_PORT_MASK /* dest check */ & IXGBE_FTQF_SOURCE_PORT_MASK) /* source check */ << IXGBE_FTQF_5TUPLE_MASK_SHIFT); IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(3), (3 << IXGBE_IMIR_RX_QUEUE_SHIFT_82599 | IXGBE_IMIR_SIZE_BP_82599)); /* enable port check */ IXGBE_WRITE_REG(hw, IXGBE_SDPQF(3), (htons(PTP_PORT) | htons(PTP_PORT) << 16)); IXGBE_WRITE_REG(hw, IXGBE_FTQF(3), ftqf); tsync_rx_mtrl |= PTP_PORT << 16; } else { IXGBE_WRITE_REG(hw, IXGBE_FTQF(3), 0); } /* enable/disable TX */ regval = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL); regval &= ~IXGBE_TSYNCTXCTL_ENABLED; regval |= tsync_tx_ctl; IXGBE_WRITE_REG(hw, IXGBE_TSYNCTXCTL, regval); /* enable/disable RX */ regval = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); regval &= ~(IXGBE_TSYNCRXCTL_ENABLED | IXGBE_TSYNCRXCTL_TYPE_MASK); regval |= tsync_rx_ctl; IXGBE_WRITE_REG(hw, IXGBE_TSYNCRXCTL, regval); /* define which PTP packets are time stamped */ IXGBE_WRITE_REG(hw, IXGBE_RXMTRL, tsync_rx_mtrl); IXGBE_WRITE_FLUSH(hw); /* clear TX/RX time stamp registers, just to be sure */ regval = IXGBE_READ_REG(hw, IXGBE_TXSTMPH); regval = IXGBE_READ_REG(hw, IXGBE_RXSTMPH); return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0; }