diff options
author | David S. Miller <davem@davemloft.net> | 2014-07-16 23:52:18 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-16 23:52:18 -0700 |
commit | 4bbe3f5c7174e989989c04d41e6640ac0b944dac (patch) | |
tree | e51236ab425b90d1b0525b52b4186b1485c76e3b | |
parent | 48e48a70c08a8a68f8697f8b30cb83775bda8001 (diff) | |
parent | 302b46449e2918a30b3f98a54653972d2ad0f072 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next
Jeff Kirsher says:
====================
Intel Wired LAN Driver Updates 2014-07-16
This series contains updates to i40e only.
Neerav adds support to get the port MAC address from firmware and adds
support to the ndo_get_phys_port_id() callback to provide port specific
unique ids to the netdev layer.
Jakub Kicinski provides 2 fixes, first fixes i40e to never generate a software
time stamp if the hardware time stamp is provided. Second fixes a race
condition on queueing skb for hardware time by using a simple bit lock to
avoid race conditions and leaking skbs when multiple transmit rings try
to claim time stamping.
Paul does some general cleanup of the driver to remove unneeded spaces,
comments that are no longer valid, and break that will never get touched.
Jacob Keller adds a verbose warning message when the incorrect PF attempts
to control timestamping for a port to which it was not assigned. The primary
intent of this message is to help debugging the reason why the SIOCSHWSTAMP
ioctl has failed and to help narrow the cause of the issue.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_adminq.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_common.c | 26 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_main.c | 23 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_prototype.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_ptp.c | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_txrx.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_type.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40e_adminq.c | 2 |
9 files changed, 65 insertions, 13 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 0fbb32a8ad42..29cd81ae29f4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -134,6 +134,7 @@ enum i40e_state_t { __I40E_EMP_RESET_REQUESTED, __I40E_FILTER_OVERFLOW_PROMISC, __I40E_SUSPENDED, + __I40E_PTP_TX_IN_PROGRESS, __I40E_BAD_EEPROM, __I40E_DOWN_REQUESTED, }; @@ -279,6 +280,7 @@ struct i40e_pf { #ifdef CONFIG_I40E_VXLAN #define I40E_FLAG_VXLAN_FILTER_SYNC (u64)(1 << 27) #endif +#define I40E_FLAG_PORT_ID_VALID (u64)(1 << 28) #define I40E_FLAG_DCB_CAPABLE (u64)(1 << 29) /* tracks features that get auto disabled by errors */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 2708bcdddd41..0e551f281d59 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -863,7 +863,7 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, /* ugh! delay while spin_lock */ udelay(delay_len); total_delay += delay_len; - } while (total_delay < hw->aq.asq_cmd_timeout); + } while (total_delay < hw->aq.asq_cmd_timeout); } /* if ready, copy the desc back to temp */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index bf808d4cb7b8..c65f4e8e6cee 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -554,7 +554,6 @@ i40e_status i40e_init_shared_code(struct i40e_hw *hw) break; default: return I40E_ERR_DEVICE_NOT_SUPPORTED; - break; } hw->phy.get_link_info = true; @@ -655,6 +654,31 @@ i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr) } /** + * i40e_get_port_mac_addr - get Port MAC address + * @hw: pointer to the HW structure + * @mac_addr: pointer to Port MAC address + * + * Reads the adapter's Port MAC address + **/ +i40e_status i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr) +{ + struct i40e_aqc_mac_address_read_data addrs; + i40e_status status; + u16 flags = 0; + + status = i40e_aq_mac_address_read(hw, &flags, &addrs, NULL); + if (status) + return status; + + if (flags & I40E_AQC_PORT_ADDR_VALID) + memcpy(mac_addr, &addrs.port_mac, sizeof(addrs.port_mac)); + else + status = I40E_ERR_INVALID_MAC_ADDR; + + return status; +} + +/** * i40e_pre_tx_queue_cfg - pre tx queue configure * @hw: pointer to the HW structure * @queue: target pf queue index diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 2899f783ee1d..c34e39009a8f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6773,13 +6773,12 @@ static int i40e_sw_init(struct i40e_pf *pf) * maximum might end up larger than the available queues */ pf->rss_size_max = 0x1 << pf->hw.func_caps.rss_table_entry_width; + pf->rss_size = 1; pf->rss_size_max = min_t(int, pf->rss_size_max, pf->hw.func_caps.num_tx_qp); if (pf->hw.func_caps.rss) { pf->flags |= I40E_FLAG_RSS_ENABLED; pf->rss_size = min_t(int, pf->rss_size_max, num_online_cpus()); - } else { - pf->rss_size = 1; } /* MFP mode enabled */ @@ -7018,6 +7017,22 @@ static void i40e_del_vxlan_port(struct net_device *netdev, } #endif +static int i40e_get_phys_port_id(struct net_device *netdev, + struct netdev_phys_port_id *ppid) +{ + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_pf *pf = np->vsi->back; + struct i40e_hw *hw = &pf->hw; + + if (!(pf->flags & I40E_FLAG_PORT_ID_VALID)) + return -EOPNOTSUPP; + + ppid->id_len = min_t(int, sizeof(hw->mac.port_addr), sizeof(ppid->id)); + memcpy(ppid->id, hw->mac.port_addr, ppid->id_len); + + return 0; +} + #ifdef HAVE_FDB_OPS #ifdef USE_CONST_DEV_UC_CHAR static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], @@ -7137,6 +7152,7 @@ static const struct net_device_ops i40e_netdev_ops = { .ndo_add_vxlan_port = i40e_add_vxlan_port, .ndo_del_vxlan_port = i40e_del_vxlan_port, #endif + .ndo_get_phys_port_id = i40e_get_phys_port_id, #ifdef HAVE_FDB_OPS .ndo_fdb_add = i40e_ndo_fdb_add, #ifndef USE_DEFAULT_FDB_DEL_DUMP @@ -8686,6 +8702,9 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } dev_info(&pdev->dev, "MAC address: %pM\n", hw->mac.addr); ether_addr_copy(hw->mac.perm_addr, hw->mac.addr); + i40e_get_port_mac_addr(hw, hw->mac.port_addr); + if (is_valid_ether_addr(hw->mac.port_addr)) + pf->flags |= I40E_FLAG_PORT_ID_VALID; pci_set_drvdata(pdev, pf); pci_save_state(pdev); diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index b6849fb47db7..9383f08ff4e3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -230,8 +230,8 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw); void i40e_clear_hw(struct i40e_hw *hw); void i40e_clear_pxe_mode(struct i40e_hw *hw); bool i40e_get_link_status(struct i40e_hw *hw); -i40e_status i40e_get_mac_addr(struct i40e_hw *hw, - u8 *mac_addr); +i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr); +i40e_status i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr); i40e_status i40e_validate_mac_addr(u8 *mac_addr); void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable); /* prototype for functions used for NVM access */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index c364781c8160..bb7fe98b3a6c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -314,6 +314,7 @@ void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf) skb_tstamp_tx(pf->ptp_tx_skb, &shhwtstamps); dev_kfree_skb_any(pf->ptp_tx_skb); pf->ptp_tx_skb = NULL; + clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state); } /** @@ -446,8 +447,12 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf, /* Confirm that 1588 is supported on this PF. */ pf_id = (rd32(hw, I40E_PRTTSYN_CTL0) & I40E_PRTTSYN_CTL0_PF_ID_MASK) >> I40E_PRTTSYN_CTL0_PF_ID_SHIFT; - if (hw->pf_id != pf_id) - return -EINVAL; + if (hw->pf_id != pf_id) { + dev_err(&pf->pdev->dev, + "PF %d attempted to control timestamp mode on port %d, which is owned by PF %d\n", + hw->pf_id, hw->port, pf_id); + return -EPERM; + } switch (config->tx_type) { case HWTSTAMP_TX_OFF: @@ -677,6 +682,7 @@ void i40e_ptp_stop(struct i40e_pf *pf) if (pf->ptp_tx_skb) { dev_kfree_skb_any(pf->ptp_tx_skb); pf->ptp_tx_skb = NULL; + clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state); } if (pf->ptp_clock) { diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 2c686e2dfe1d..989866af26e5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -303,7 +303,6 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi, * a specific flow spec * @vsi: pointer to the targeted VSI * @fd_data: the flow director data required for the FDir descriptor - * @raw_packet: the pre-allocated packet buffer for FDir * @add: true adds a filter, false removes it * * Always returns -EOPNOTSUPP @@ -1856,7 +1855,8 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb, * we are not already transmitting a packet to be timestamped */ pf = i40e_netdev_to_pf(tx_ring->netdev); - if (pf->ptp_tx && !pf->ptp_tx_skb) { + if (pf->ptp_tx && + !test_and_set_bit_lock(__I40E_PTP_TX_IN_PROGRESS, &pf->state)) { skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; pf->ptp_tx_skb = skb_get(skb); } else { @@ -2285,13 +2285,13 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, else if (tso) tx_flags |= I40E_TX_FLAGS_TSO; - skb_tx_timestamp(skb); - tsyn = i40e_tsyn(tx_ring, skb, tx_flags, &cd_type_cmd_tso_mss); if (tsyn) tx_flags |= I40E_TX_FLAGS_TSYN; + skb_tx_timestamp(skb); + /* always enable CRC insertion offload */ td_cmd |= I40E_TX_DESC_CMD_ICRC; diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 380eb53a83b3..1fcf2205ffe6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -246,6 +246,7 @@ struct i40e_mac_info { u8 addr[ETH_ALEN]; u8 perm_addr[ETH_ALEN]; u8 san_addr[ETH_ALEN]; + u8 port_addr[ETH_ALEN]; u16 max_fcoeq; }; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c index cc4b6db10b04..8330744b02f1 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c @@ -817,7 +817,7 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw, /* ugh! delay while spin_lock */ udelay(delay_len); total_delay += delay_len; - } while (total_delay < hw->aq.asq_cmd_timeout); + } while (total_delay < hw->aq.asq_cmd_timeout); } /* if ready, copy the desc back to temp */ |