summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/intel/ixgbe
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/intel/ixgbe')
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.c21
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c27
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c58
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c251
5 files changed, 258 insertions, 101 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index bc68b8f2176d..8736ca4b2628 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -73,6 +73,8 @@
#define IXGBE_RXBUFFER_4K 4096
#define IXGBE_MAX_RXBUFFER 16384 /* largest size for a single descriptor */
+#define IXGBE_PKT_HDR_PAD (ETH_HLEN + ETH_FCS_LEN + (VLAN_HLEN * 2))
+
/* Attempt to maximize the headroom available for incoming frames. We
* use a 2K buffer for receives and need 1536/1534 to store the data for
* the frame. This leaves us with 512 bytes of room. From that we need
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index 38c4609bd429..878dd8dff528 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -3292,13 +3292,14 @@ static bool ixgbe_need_crosstalk_fix(struct ixgbe_hw *hw)
s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
bool *link_up, bool link_up_wait_to_complete)
{
+ bool crosstalk_fix_active = ixgbe_need_crosstalk_fix(hw);
u32 links_reg, links_orig;
u32 i;
/* If Crosstalk fix enabled do the sanity check of making sure
* the SFP+ cage is full.
*/
- if (ixgbe_need_crosstalk_fix(hw)) {
+ if (crosstalk_fix_active) {
u32 sfp_cage_full;
switch (hw->mac.type) {
@@ -3346,10 +3347,24 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
}
} else {
- if (links_reg & IXGBE_LINKS_UP)
+ if (links_reg & IXGBE_LINKS_UP) {
+ if (crosstalk_fix_active) {
+ /* Check the link state again after a delay
+ * to filter out spurious link up
+ * notifications.
+ */
+ mdelay(5);
+ links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
+ if (!(links_reg & IXGBE_LINKS_UP)) {
+ *link_up = false;
+ *speed = IXGBE_LINK_SPEED_UNKNOWN;
+ return 0;
+ }
+ }
*link_up = true;
- else
+ } else {
*link_up = false;
+ }
}
switch (links_reg & IXGBE_LINKS_SPEED_82599) {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index 53a969e34883..13a6fca31004 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -557,8 +557,10 @@ static int ixgbe_ipsec_check_mgmt_ip(struct xfrm_state *xs)
/**
* ixgbe_ipsec_add_sa - program device with a security association
* @xs: pointer to transformer state struct
+ * @extack: extack point to fill failure reason
**/
-static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
+static int ixgbe_ipsec_add_sa(struct xfrm_state *xs,
+ struct netlink_ext_ack *extack)
{
struct net_device *dev = xs->xso.real_dev;
struct ixgbe_adapter *adapter = netdev_priv(dev);
@@ -570,23 +572,22 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
int i;
if (xs->id.proto != IPPROTO_ESP && xs->id.proto != IPPROTO_AH) {
- netdev_err(dev, "Unsupported protocol 0x%04x for ipsec offload\n",
- xs->id.proto);
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported protocol for ipsec offload");
return -EINVAL;
}
if (xs->props.mode != XFRM_MODE_TRANSPORT) {
- netdev_err(dev, "Unsupported mode for ipsec offload\n");
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported mode for ipsec offload");
return -EINVAL;
}
if (ixgbe_ipsec_check_mgmt_ip(xs)) {
- netdev_err(dev, "IPsec IP addr clash with mgmt filters\n");
+ NL_SET_ERR_MSG_MOD(extack, "IPsec IP addr clash with mgmt filters");
return -EINVAL;
}
if (xs->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) {
- netdev_err(dev, "Unsupported ipsec offload type\n");
+ NL_SET_ERR_MSG_MOD(extack, "Unsupported ipsec offload type");
return -EINVAL;
}
@@ -594,14 +595,14 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
struct rx_sa rsa;
if (xs->calg) {
- netdev_err(dev, "Compression offload not supported\n");
+ NL_SET_ERR_MSG_MOD(extack, "Compression offload not supported");
return -EINVAL;
}
/* find the first unused index */
ret = ixgbe_ipsec_find_empty_idx(ipsec, true);
if (ret < 0) {
- netdev_err(dev, "No space for SA in Rx table!\n");
+ NL_SET_ERR_MSG_MOD(extack, "No space for SA in Rx table!");
return ret;
}
sa_idx = (u16)ret;
@@ -616,7 +617,7 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
/* get the key and salt */
ret = ixgbe_ipsec_parse_proto_keys(xs, rsa.key, &rsa.salt);
if (ret) {
- netdev_err(dev, "Failed to get key data for Rx SA table\n");
+ NL_SET_ERR_MSG_MOD(extack, "Failed to get key data for Rx SA table");
return ret;
}
@@ -676,7 +677,7 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
} else {
/* no match and no empty slot */
- netdev_err(dev, "No space for SA in Rx IP SA table\n");
+ NL_SET_ERR_MSG_MOD(extack, "No space for SA in Rx IP SA table");
memset(&rsa, 0, sizeof(rsa));
return -ENOSPC;
}
@@ -711,7 +712,7 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
/* find the first unused index */
ret = ixgbe_ipsec_find_empty_idx(ipsec, false);
if (ret < 0) {
- netdev_err(dev, "No space for SA in Tx table\n");
+ NL_SET_ERR_MSG_MOD(extack, "No space for SA in Tx table");
return ret;
}
sa_idx = (u16)ret;
@@ -725,7 +726,7 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
ret = ixgbe_ipsec_parse_proto_keys(xs, tsa.key, &tsa.salt);
if (ret) {
- netdev_err(dev, "Failed to get key data for Tx SA table\n");
+ NL_SET_ERR_MSG_MOD(extack, "Failed to get key data for Tx SA table");
memset(&tsa, 0, sizeof(tsa));
return ret;
}
@@ -950,7 +951,7 @@ int ixgbe_ipsec_vf_add_sa(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
memcpy(xs->aead->alg_name, aes_gcm_name, sizeof(aes_gcm_name));
/* set up the HW offload */
- err = ixgbe_ipsec_add_sa(xs);
+ err = ixgbe_ipsec_add_sa(xs, NULL);
if (err)
goto err_aead;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index ab8370c413f3..773c35fecace 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -6647,7 +6647,7 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,
rx_ring->queue_index, ixgbe_rx_napi_id(rx_ring)) < 0)
goto err;
- rx_ring->xdp_prog = adapter->xdp_prog;
+ WRITE_ONCE(rx_ring->xdp_prog, adapter->xdp_prog);
return 0;
err:
@@ -6778,6 +6778,18 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter)
}
/**
+ * ixgbe_max_xdp_frame_size - returns the maximum allowed frame size for XDP
+ * @adapter: device handle, pointer to adapter
+ */
+static int ixgbe_max_xdp_frame_size(struct ixgbe_adapter *adapter)
+{
+ if (PAGE_SIZE >= 8192 || adapter->flags2 & IXGBE_FLAG2_RX_LEGACY)
+ return IXGBE_RXBUFFER_2K;
+ else
+ return IXGBE_RXBUFFER_3K;
+}
+
+/**
* ixgbe_change_mtu - Change the Maximum Transfer Unit
* @netdev: network interface device structure
* @new_mtu: new value for maximum frame size
@@ -6788,18 +6800,12 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- if (adapter->xdp_prog) {
- int new_frame_size = new_mtu + ETH_HLEN + ETH_FCS_LEN +
- VLAN_HLEN;
- int i;
-
- for (i = 0; i < adapter->num_rx_queues; i++) {
- struct ixgbe_ring *ring = adapter->rx_ring[i];
+ if (ixgbe_enabled_xdp_adapter(adapter)) {
+ int new_frame_size = new_mtu + IXGBE_PKT_HDR_PAD;
- if (new_frame_size > ixgbe_rx_bufsz(ring)) {
- e_warn(probe, "Requested MTU size is not supported with XDP\n");
- return -EINVAL;
- }
+ if (new_frame_size > ixgbe_max_xdp_frame_size(adapter)) {
+ e_warn(probe, "Requested MTU size is not supported with XDP\n");
+ return -EINVAL;
}
}
@@ -8937,7 +8943,8 @@ ixgbe_mdio_read(struct net_device *netdev, int prtad, int devad, u16 addr)
int regnum = addr;
if (devad != MDIO_DEVAD_NONE)
- regnum |= (devad << 16) | MII_ADDR_C45;
+ return mdiobus_c45_read(adapter->mii_bus, prtad,
+ devad, regnum);
return mdiobus_read(adapter->mii_bus, prtad, regnum);
}
@@ -8960,7 +8967,8 @@ static int ixgbe_mdio_write(struct net_device *netdev, int prtad, int devad,
int regnum = addr;
if (devad != MDIO_DEVAD_NONE)
- regnum |= (devad << 16) | MII_ADDR_C45;
+ return mdiobus_c45_write(adapter->mii_bus, prtad, devad,
+ regnum, value);
return mdiobus_write(adapter->mii_bus, prtad, regnum, value);
}
@@ -10297,14 +10305,15 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
synchronize_rcu();
err = ixgbe_setup_tc(dev, adapter->hw_tcs);
- if (err) {
- rcu_assign_pointer(adapter->xdp_prog, old_prog);
+ if (err)
return -EINVAL;
- }
+ if (!prog)
+ xdp_features_clear_redirect_target(dev);
} else {
- for (i = 0; i < adapter->num_rx_queues; i++)
- (void)xchg(&adapter->rx_ring[i]->xdp_prog,
- adapter->xdp_prog);
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ WRITE_ONCE(adapter->rx_ring[i]->xdp_prog,
+ adapter->xdp_prog);
+ }
}
if (old_prog)
@@ -10320,6 +10329,7 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
if (adapter->xdp_ring[i]->xsk_pool)
(void)ixgbe_xsk_wakeup(adapter->netdev, i,
XDP_WAKEUP_RX);
+ xdp_features_set_redirect_target(dev, true);
}
return 0;
@@ -10808,8 +10818,6 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_pci_reg;
}
- pci_enable_pcie_error_reporting(pdev);
-
pci_set_master(pdev);
pci_save_state(pdev);
@@ -11017,6 +11025,9 @@ skip_sriov:
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->priv_flags |= IFF_SUPP_NOFCS;
+ netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
+ NETDEV_XDP_ACT_XSK_ZEROCOPY;
+
/* MTU range: 68 - 9710 */
netdev->min_mtu = ETH_MIN_MTU;
netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN);
@@ -11237,7 +11248,6 @@ err_ioremap:
disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
free_netdev(netdev);
err_alloc_etherdev:
- pci_disable_pcie_error_reporting(pdev);
pci_release_mem_regions(pdev);
err_pci_reg:
err_dma:
@@ -11326,8 +11336,6 @@ static void ixgbe_remove(struct pci_dev *pdev)
disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
free_netdev(netdev);
- pci_disable_pcie_error_reporting(pdev);
-
if (disable_dev)
pci_disable_device(pdev);
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index 24aa97f993ca..689470c1e8ad 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -680,14 +680,14 @@ static s32 ixgbe_msca_cmd(struct ixgbe_hw *hw, u32 cmd)
}
/**
- * ixgbe_mii_bus_read_generic - Read a clause 22/45 register with gssr flags
+ * ixgbe_mii_bus_read_generic_c22 - Read a clause 22 register with gssr flags
* @hw: pointer to hardware structure
* @addr: address
* @regnum: register number
* @gssr: semaphore flags to acquire
**/
-static s32 ixgbe_mii_bus_read_generic(struct ixgbe_hw *hw, int addr,
- int regnum, u32 gssr)
+static s32 ixgbe_mii_bus_read_generic_c22(struct ixgbe_hw *hw, int addr,
+ int regnum, u32 gssr)
{
u32 hwaddr, cmd;
s32 data;
@@ -696,31 +696,52 @@ static s32 ixgbe_mii_bus_read_generic(struct ixgbe_hw *hw, int addr,
return -EBUSY;
hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
- if (regnum & MII_ADDR_C45) {
- hwaddr |= regnum & GENMASK(21, 0);
- cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
- } else {
- hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
- cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL |
- IXGBE_MSCA_READ_AUTOINC | IXGBE_MSCA_MDI_COMMAND;
- }
+ hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
+ cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL |
+ IXGBE_MSCA_READ_AUTOINC | IXGBE_MSCA_MDI_COMMAND;
data = ixgbe_msca_cmd(hw, cmd);
if (data < 0)
goto mii_bus_read_done;
- /* For a clause 45 access the address cycle just completed, we still
- * need to do the read command, otherwise just get the data
- */
- if (!(regnum & MII_ADDR_C45))
- goto do_mii_bus_read;
+ data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
+ data = (data >> IXGBE_MSRWD_READ_DATA_SHIFT) & GENMASK(16, 0);
+
+mii_bus_read_done:
+ hw->mac.ops.release_swfw_sync(hw, gssr);
+ return data;
+}
+
+/**
+ * ixgbe_mii_bus_read_generic_c45 - Read a clause 45 register with gssr flags
+ * @hw: pointer to hardware structure
+ * @addr: address
+ * @devad: device address to read
+ * @regnum: register number
+ * @gssr: semaphore flags to acquire
+ **/
+static s32 ixgbe_mii_bus_read_generic_c45(struct ixgbe_hw *hw, int addr,
+ int devad, int regnum, u32 gssr)
+{
+ u32 hwaddr, cmd;
+ s32 data;
+
+ if (hw->mac.ops.acquire_swfw_sync(hw, gssr))
+ return -EBUSY;
+
+ hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
+ hwaddr |= devad << 16 | regnum;
+ cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
+
+ data = ixgbe_msca_cmd(hw, cmd);
+ if (data < 0)
+ goto mii_bus_read_done;
cmd = hwaddr | IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND;
data = ixgbe_msca_cmd(hw, cmd);
if (data < 0)
goto mii_bus_read_done;
-do_mii_bus_read:
data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
data = (data >> IXGBE_MSRWD_READ_DATA_SHIFT) & GENMASK(16, 0);
@@ -730,15 +751,15 @@ mii_bus_read_done:
}
/**
- * ixgbe_mii_bus_write_generic - Write a clause 22/45 register with gssr flags
+ * ixgbe_mii_bus_write_generic_c22 - Write a clause 22 register with gssr flags
* @hw: pointer to hardware structure
* @addr: address
* @regnum: register number
* @val: value to write
* @gssr: semaphore flags to acquire
**/
-static s32 ixgbe_mii_bus_write_generic(struct ixgbe_hw *hw, int addr,
- int regnum, u16 val, u32 gssr)
+static s32 ixgbe_mii_bus_write_generic_c22(struct ixgbe_hw *hw, int addr,
+ int regnum, u16 val, u32 gssr)
{
u32 hwaddr, cmd;
s32 err;
@@ -749,20 +770,43 @@ static s32 ixgbe_mii_bus_write_generic(struct ixgbe_hw *hw, int addr,
IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)val);
hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
- if (regnum & MII_ADDR_C45) {
- hwaddr |= regnum & GENMASK(21, 0);
- cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
- } else {
- hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
- cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE |
- IXGBE_MSCA_MDI_COMMAND;
- }
+ hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
+ cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE |
+ IXGBE_MSCA_MDI_COMMAND;
+
+ err = ixgbe_msca_cmd(hw, cmd);
+
+ hw->mac.ops.release_swfw_sync(hw, gssr);
+ return err;
+}
+
+/**
+ * ixgbe_mii_bus_write_generic_c45 - Write a clause 45 register with gssr flags
+ * @hw: pointer to hardware structure
+ * @addr: address
+ * @devad: device address to read
+ * @regnum: register number
+ * @val: value to write
+ * @gssr: semaphore flags to acquire
+ **/
+static s32 ixgbe_mii_bus_write_generic_c45(struct ixgbe_hw *hw, int addr,
+ int devad, int regnum, u16 val,
+ u32 gssr)
+{
+ u32 hwaddr, cmd;
+ s32 err;
+
+ if (hw->mac.ops.acquire_swfw_sync(hw, gssr))
+ return -EBUSY;
+
+ IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)val);
+
+ hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
+ hwaddr |= devad << 16 | regnum;
+ cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
- /* For clause 45 this is an address cycle, for clause 22 this is the
- * entire transaction
- */
err = ixgbe_msca_cmd(hw, cmd);
- if (err < 0 || !(regnum & MII_ADDR_C45))
+ if (err < 0)
goto mii_bus_write_done;
cmd = hwaddr | IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND;
@@ -774,70 +818,144 @@ mii_bus_write_done:
}
/**
- * ixgbe_mii_bus_read - Read a clause 22/45 register
+ * ixgbe_mii_bus_read_c22 - Read a clause 22 register
* @bus: pointer to mii_bus structure which points to our driver private
* @addr: address
* @regnum: register number
**/
-static s32 ixgbe_mii_bus_read(struct mii_bus *bus, int addr, int regnum)
+static s32 ixgbe_mii_bus_read_c22(struct mii_bus *bus, int addr, int regnum)
{
struct ixgbe_adapter *adapter = bus->priv;
struct ixgbe_hw *hw = &adapter->hw;
u32 gssr = hw->phy.phy_semaphore_mask;
- return ixgbe_mii_bus_read_generic(hw, addr, regnum, gssr);
+ return ixgbe_mii_bus_read_generic_c22(hw, addr, regnum, gssr);
}
/**
- * ixgbe_mii_bus_write - Write a clause 22/45 register
+ * ixgbe_mii_bus_read_c45 - Read a clause 45 register
* @bus: pointer to mii_bus structure which points to our driver private
+ * @devad: device address to read
* @addr: address
* @regnum: register number
+ **/
+static s32 ixgbe_mii_bus_read_c45(struct mii_bus *bus, int devad, int addr,
+ int regnum)
+{
+ struct ixgbe_adapter *adapter = bus->priv;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 gssr = hw->phy.phy_semaphore_mask;
+
+ return ixgbe_mii_bus_read_generic_c45(hw, addr, devad, regnum, gssr);
+}
+
+/**
+ * ixgbe_mii_bus_write_c22 - Write a clause 22 register
+ * @bus: pointer to mii_bus structure which points to our driver private
+ * @addr: address
+ * @regnum: register number
+ * @val: value to write
+ **/
+static s32 ixgbe_mii_bus_write_c22(struct mii_bus *bus, int addr, int regnum,
+ u16 val)
+{
+ struct ixgbe_adapter *adapter = bus->priv;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 gssr = hw->phy.phy_semaphore_mask;
+
+ return ixgbe_mii_bus_write_generic_c22(hw, addr, regnum, val, gssr);
+}
+
+/**
+ * ixgbe_mii_bus_write_c45 - Write a clause 45 register
+ * @bus: pointer to mii_bus structure which points to our driver private
+ * @addr: address
+ * @devad: device address to read
+ * @regnum: register number
* @val: value to write
**/
-static s32 ixgbe_mii_bus_write(struct mii_bus *bus, int addr, int regnum,
- u16 val)
+static s32 ixgbe_mii_bus_write_c45(struct mii_bus *bus, int addr, int devad,
+ int regnum, u16 val)
{
struct ixgbe_adapter *adapter = bus->priv;
struct ixgbe_hw *hw = &adapter->hw;
u32 gssr = hw->phy.phy_semaphore_mask;
- return ixgbe_mii_bus_write_generic(hw, addr, regnum, val, gssr);
+ return ixgbe_mii_bus_write_generic_c45(hw, addr, devad, regnum, val,
+ gssr);
}
/**
- * ixgbe_x550em_a_mii_bus_read - Read a clause 22/45 register on x550em_a
+ * ixgbe_x550em_a_mii_bus_read_c22 - Read a clause 22 register on x550em_a
* @bus: pointer to mii_bus structure which points to our driver private
* @addr: address
* @regnum: register number
**/
-static s32 ixgbe_x550em_a_mii_bus_read(struct mii_bus *bus, int addr,
- int regnum)
+static s32 ixgbe_x550em_a_mii_bus_read_c22(struct mii_bus *bus, int addr,
+ int regnum)
{
struct ixgbe_adapter *adapter = bus->priv;
struct ixgbe_hw *hw = &adapter->hw;
u32 gssr = hw->phy.phy_semaphore_mask;
gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
- return ixgbe_mii_bus_read_generic(hw, addr, regnum, gssr);
+ return ixgbe_mii_bus_read_generic_c22(hw, addr, regnum, gssr);
}
/**
- * ixgbe_x550em_a_mii_bus_write - Write a clause 22/45 register on x550em_a
+ * ixgbe_x550em_a_mii_bus_read_c45 - Read a clause 45 register on x550em_a
+ * @bus: pointer to mii_bus structure which points to our driver private
+ * @addr: address
+ * @devad: device address to read
+ * @regnum: register number
+ **/
+static s32 ixgbe_x550em_a_mii_bus_read_c45(struct mii_bus *bus, int addr,
+ int devad, int regnum)
+{
+ struct ixgbe_adapter *adapter = bus->priv;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 gssr = hw->phy.phy_semaphore_mask;
+
+ gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
+ return ixgbe_mii_bus_read_generic_c45(hw, addr, devad, regnum, gssr);
+}
+
+/**
+ * ixgbe_x550em_a_mii_bus_write_c22 - Write a clause 22 register on x550em_a
* @bus: pointer to mii_bus structure which points to our driver private
* @addr: address
* @regnum: register number
* @val: value to write
**/
-static s32 ixgbe_x550em_a_mii_bus_write(struct mii_bus *bus, int addr,
- int regnum, u16 val)
+static s32 ixgbe_x550em_a_mii_bus_write_c22(struct mii_bus *bus, int addr,
+ int regnum, u16 val)
{
struct ixgbe_adapter *adapter = bus->priv;
struct ixgbe_hw *hw = &adapter->hw;
u32 gssr = hw->phy.phy_semaphore_mask;
gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
- return ixgbe_mii_bus_write_generic(hw, addr, regnum, val, gssr);
+ return ixgbe_mii_bus_write_generic_c22(hw, addr, regnum, val, gssr);
+}
+
+/**
+ * ixgbe_x550em_a_mii_bus_write_c45 - Write a clause 45 register on x550em_a
+ * @bus: pointer to mii_bus structure which points to our driver private
+ * @addr: address
+ * @devad: device address to read
+ * @regnum: register number
+ * @val: value to write
+ **/
+static s32 ixgbe_x550em_a_mii_bus_write_c45(struct mii_bus *bus, int addr,
+ int devad, int regnum, u16 val)
+{
+ struct ixgbe_adapter *adapter = bus->priv;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 gssr = hw->phy.phy_semaphore_mask;
+
+ gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
+ return ixgbe_mii_bus_write_generic_c45(hw, addr, devad, regnum, val,
+ gssr);
}
/**
@@ -855,9 +973,11 @@ static struct pci_dev *ixgbe_get_first_secondary_devfn(unsigned int devfn)
rp_pdev = pci_get_domain_bus_and_slot(0, 0, devfn);
if (rp_pdev && rp_pdev->subordinate) {
bus = rp_pdev->subordinate->number;
+ pci_dev_put(rp_pdev);
return pci_get_domain_bus_and_slot(0, bus, 0);
}
+ pci_dev_put(rp_pdev);
return NULL;
}
@@ -874,6 +994,7 @@ static bool ixgbe_x550em_a_has_mii(struct ixgbe_hw *hw)
struct ixgbe_adapter *adapter = hw->back;
struct pci_dev *pdev = adapter->pdev;
struct pci_dev *func0_pdev;
+ bool has_mii = false;
/* For the C3000 family of SoCs (x550em_a) the internal ixgbe devices
* are always downstream of root ports @ 0000:00:16.0 & 0000:00:17.0
@@ -884,15 +1005,16 @@ static bool ixgbe_x550em_a_has_mii(struct ixgbe_hw *hw)
func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x16, 0));
if (func0_pdev) {
if (func0_pdev == pdev)
- return true;
- else
- return false;
+ has_mii = true;
+ goto out;
}
func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x17, 0));
if (func0_pdev == pdev)
- return true;
+ has_mii = true;
- return false;
+out:
+ pci_dev_put(func0_pdev);
+ return has_mii;
}
/**
@@ -905,8 +1027,11 @@ static bool ixgbe_x550em_a_has_mii(struct ixgbe_hw *hw)
**/
s32 ixgbe_mii_bus_init(struct ixgbe_hw *hw)
{
- s32 (*write)(struct mii_bus *bus, int addr, int regnum, u16 val);
- s32 (*read)(struct mii_bus *bus, int addr, int regnum);
+ s32 (*write_c22)(struct mii_bus *bus, int addr, int regnum, u16 val);
+ s32 (*read_c22)(struct mii_bus *bus, int addr, int regnum);
+ s32 (*write_c45)(struct mii_bus *bus, int addr, int devad, int regnum,
+ u16 val);
+ s32 (*read_c45)(struct mii_bus *bus, int addr, int devad, int regnum);
struct ixgbe_adapter *adapter = hw->back;
struct pci_dev *pdev = adapter->pdev;
struct device *dev = &adapter->netdev->dev;
@@ -925,12 +1050,16 @@ s32 ixgbe_mii_bus_init(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_X550EM_A_1G_T_L:
if (!ixgbe_x550em_a_has_mii(hw))
return 0;
- read = &ixgbe_x550em_a_mii_bus_read;
- write = &ixgbe_x550em_a_mii_bus_write;
+ read_c22 = ixgbe_x550em_a_mii_bus_read_c22;
+ write_c22 = ixgbe_x550em_a_mii_bus_write_c22;
+ read_c45 = ixgbe_x550em_a_mii_bus_read_c45;
+ write_c45 = ixgbe_x550em_a_mii_bus_write_c45;
break;
default:
- read = &ixgbe_mii_bus_read;
- write = &ixgbe_mii_bus_write;
+ read_c22 = ixgbe_mii_bus_read_c22;
+ write_c22 = ixgbe_mii_bus_write_c22;
+ read_c45 = ixgbe_mii_bus_read_c45;
+ write_c45 = ixgbe_mii_bus_write_c45;
break;
}
@@ -938,8 +1067,10 @@ s32 ixgbe_mii_bus_init(struct ixgbe_hw *hw)
if (!bus)
return -ENOMEM;
- bus->read = read;
- bus->write = write;
+ bus->read = read_c22;
+ bus->write = write_c22;
+ bus->read_c45 = read_c45;
+ bus->write_c45 = write_c45;
/* Use the position of the device in the PCI hierarchy as the id */
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mdio-%s", ixgbe_driver_name,