Skip to content

Commit 8fa10ef

Browse files
ADIsdouthitJeff Kirsher
authored andcommitted
ixgbe: register a mdiobus
Most dsa devices expect a 'struct mii_bus' pointer to talk to switches via the MII interface. While this works for dsa devices, it will not work safely with Linux PHYs in all configurations since the firmware of the ixgbe device may be polling some PHY addresses in the background. Signed-off-by: Stephen Douthit <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Reviewed-by: Florian Fainelli <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 1fb3a7a commit 8fa10ef

File tree

5 files changed

+309
-0
lines changed

5 files changed

+309
-0
lines changed

drivers/net/ethernet/intel/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ config IXGBE
159159
tristate "Intel(R) 10GbE PCI Express adapters support"
160160
depends on PCI
161161
select MDIO
162+
select MDIO_DEVICE
162163
imply PTP_1588_CLOCK
163164
---help---
164165
This driver supports Intel(R) 10GbE PCI Express family of

drivers/net/ethernet/intel/ixgbe/ixgbe.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/aer.h>
1313
#include <linux/if_vlan.h>
1414
#include <linux/jiffies.h>
15+
#include <linux/phy.h>
1516

1617
#include <linux/timecounter.h>
1718
#include <linux/net_tstamp.h>
@@ -561,6 +562,7 @@ struct ixgbe_adapter {
561562
struct net_device *netdev;
562563
struct bpf_prog *xdp_prog;
563564
struct pci_dev *pdev;
565+
struct mii_bus *mii_bus;
564566

565567
unsigned long state;
566568

drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "ixgbe.h"
4040
#include "ixgbe_common.h"
4141
#include "ixgbe_dcb_82599.h"
42+
#include "ixgbe_phy.h"
4243
#include "ixgbe_sriov.h"
4344
#include "ixgbe_model.h"
4445
#include "ixgbe_txrx_common.h"
@@ -11122,6 +11123,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1112211123
IXGBE_LINK_SPEED_10GB_FULL | IXGBE_LINK_SPEED_1GB_FULL,
1112311124
true);
1112411125

11126+
ixgbe_mii_bus_init(hw);
11127+
1112511128
return 0;
1112611129

1112711130
err_register:
@@ -11172,6 +11175,8 @@ static void ixgbe_remove(struct pci_dev *pdev)
1117211175
set_bit(__IXGBE_REMOVING, &adapter->state);
1117311176
cancel_work_sync(&adapter->service_task);
1117411177

11178+
if (adapter->mii_bus)
11179+
mdiobus_unregister(adapter->mii_bus);
1117511180

1117611181
#ifdef CONFIG_IXGBE_DCA
1117711182
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {

drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <linux/pci.h>
55
#include <linux/delay.h>
6+
#include <linux/iopoll.h>
67
#include <linux/sched.h>
78

89
#include "ixgbe.h"
@@ -658,6 +659,304 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
658659
return status;
659660
}
660661

662+
#define IXGBE_HW_READ_REG(addr) IXGBE_READ_REG(hw, addr)
663+
664+
/**
665+
* ixgbe_msca_cmd - Write the command register and poll for completion/timeout
666+
* @hw: pointer to hardware structure
667+
* @cmd: command register value to write
668+
**/
669+
static s32 ixgbe_msca_cmd(struct ixgbe_hw *hw, u32 cmd)
670+
{
671+
IXGBE_WRITE_REG(hw, IXGBE_MSCA, cmd);
672+
673+
return readx_poll_timeout(IXGBE_HW_READ_REG, IXGBE_MSCA, cmd,
674+
!(cmd & IXGBE_MSCA_MDI_COMMAND), 10,
675+
10 * IXGBE_MDIO_COMMAND_TIMEOUT);
676+
}
677+
678+
/**
679+
* ixgbe_mii_bus_read_generic - Read a clause 22/45 register with gssr flags
680+
* @hw: pointer to hardware structure
681+
* @addr: address
682+
* @regnum: register number
683+
* @gssr: semaphore flags to acquire
684+
**/
685+
static s32 ixgbe_mii_bus_read_generic(struct ixgbe_hw *hw, int addr,
686+
int regnum, u32 gssr)
687+
{
688+
u32 hwaddr, cmd;
689+
s32 data;
690+
691+
if (hw->mac.ops.acquire_swfw_sync(hw, gssr))
692+
return -EBUSY;
693+
694+
hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
695+
if (regnum & MII_ADDR_C45) {
696+
hwaddr |= regnum & GENMASK(21, 0);
697+
cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
698+
} else {
699+
hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
700+
cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL |
701+
IXGBE_MSCA_READ_AUTOINC | IXGBE_MSCA_MDI_COMMAND;
702+
}
703+
704+
data = ixgbe_msca_cmd(hw, cmd);
705+
if (data < 0)
706+
goto mii_bus_read_done;
707+
708+
/* For a clause 45 access the address cycle just completed, we still
709+
* need to do the read command, otherwise just get the data
710+
*/
711+
if (!(regnum & MII_ADDR_C45))
712+
goto do_mii_bus_read;
713+
714+
cmd = hwaddr | IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND;
715+
data = ixgbe_msca_cmd(hw, cmd);
716+
if (data < 0)
717+
goto mii_bus_read_done;
718+
719+
do_mii_bus_read:
720+
data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
721+
data = (data >> IXGBE_MSRWD_READ_DATA_SHIFT) & GENMASK(16, 0);
722+
723+
mii_bus_read_done:
724+
hw->mac.ops.release_swfw_sync(hw, gssr);
725+
return data;
726+
}
727+
728+
/**
729+
* ixgbe_mii_bus_write_generic - Write a clause 22/45 register with gssr flags
730+
* @hw: pointer to hardware structure
731+
* @addr: address
732+
* @regnum: register number
733+
* @val: value to write
734+
* @gssr: semaphore flags to acquire
735+
**/
736+
static s32 ixgbe_mii_bus_write_generic(struct ixgbe_hw *hw, int addr,
737+
int regnum, u16 val, u32 gssr)
738+
{
739+
u32 hwaddr, cmd;
740+
s32 err;
741+
742+
if (hw->mac.ops.acquire_swfw_sync(hw, gssr))
743+
return -EBUSY;
744+
745+
IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)val);
746+
747+
hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
748+
if (regnum & MII_ADDR_C45) {
749+
hwaddr |= regnum & GENMASK(21, 0);
750+
cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
751+
} else {
752+
hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
753+
cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE |
754+
IXGBE_MSCA_MDI_COMMAND;
755+
}
756+
757+
/* For clause 45 this is an address cycle, for clause 22 this is the
758+
* entire transaction
759+
*/
760+
err = ixgbe_msca_cmd(hw, cmd);
761+
if (err < 0 || !(regnum & MII_ADDR_C45))
762+
goto mii_bus_write_done;
763+
764+
cmd = hwaddr | IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND;
765+
err = ixgbe_msca_cmd(hw, cmd);
766+
767+
mii_bus_write_done:
768+
hw->mac.ops.release_swfw_sync(hw, gssr);
769+
return err;
770+
}
771+
772+
/**
773+
* ixgbe_mii_bus_read - Read a clause 22/45 register
774+
* @hw: pointer to hardware structure
775+
* @addr: address
776+
* @regnum: register number
777+
**/
778+
static s32 ixgbe_mii_bus_read(struct mii_bus *bus, int addr, int regnum)
779+
{
780+
struct ixgbe_adapter *adapter = bus->priv;
781+
struct ixgbe_hw *hw = &adapter->hw;
782+
u32 gssr = hw->phy.phy_semaphore_mask;
783+
784+
return ixgbe_mii_bus_read_generic(hw, addr, regnum, gssr);
785+
}
786+
787+
/**
788+
* ixgbe_mii_bus_write - Write a clause 22/45 register
789+
* @hw: pointer to hardware structure
790+
* @addr: address
791+
* @regnum: register number
792+
* @val: value to write
793+
**/
794+
static s32 ixgbe_mii_bus_write(struct mii_bus *bus, int addr, int regnum,
795+
u16 val)
796+
{
797+
struct ixgbe_adapter *adapter = bus->priv;
798+
struct ixgbe_hw *hw = &adapter->hw;
799+
u32 gssr = hw->phy.phy_semaphore_mask;
800+
801+
return ixgbe_mii_bus_write_generic(hw, addr, regnum, val, gssr);
802+
}
803+
804+
/**
805+
* ixgbe_x550em_a_mii_bus_read - Read a clause 22/45 register on x550em_a
806+
* @hw: pointer to hardware structure
807+
* @addr: address
808+
* @regnum: register number
809+
**/
810+
static s32 ixgbe_x550em_a_mii_bus_read(struct mii_bus *bus, int addr,
811+
int regnum)
812+
{
813+
struct ixgbe_adapter *adapter = bus->priv;
814+
struct ixgbe_hw *hw = &adapter->hw;
815+
u32 gssr = hw->phy.phy_semaphore_mask;
816+
817+
gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
818+
return ixgbe_mii_bus_read_generic(hw, addr, regnum, gssr);
819+
}
820+
821+
/**
822+
* ixgbe_x550em_a_mii_bus_write - Write a clause 22/45 register on x550em_a
823+
* @hw: pointer to hardware structure
824+
* @addr: address
825+
* @regnum: register number
826+
* @val: value to write
827+
**/
828+
static s32 ixgbe_x550em_a_mii_bus_write(struct mii_bus *bus, int addr,
829+
int regnum, u16 val)
830+
{
831+
struct ixgbe_adapter *adapter = bus->priv;
832+
struct ixgbe_hw *hw = &adapter->hw;
833+
u32 gssr = hw->phy.phy_semaphore_mask;
834+
835+
gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
836+
return ixgbe_mii_bus_write_generic(hw, addr, regnum, val, gssr);
837+
}
838+
839+
/**
840+
* ixgbe_get_first_secondary_devfn - get first device downstream of root port
841+
* @devfn: PCI_DEVFN of root port on domain 0, bus 0
842+
*
843+
* Returns pci_dev pointer to PCI_DEVFN(0, 0) on subordinate side of root
844+
* on domain 0, bus 0, devfn = 'devfn'
845+
**/
846+
static struct pci_dev *ixgbe_get_first_secondary_devfn(unsigned int devfn)
847+
{
848+
struct pci_dev *rp_pdev;
849+
int bus;
850+
851+
rp_pdev = pci_get_domain_bus_and_slot(0, 0, devfn);
852+
if (rp_pdev && rp_pdev->subordinate) {
853+
bus = rp_pdev->subordinate->number;
854+
return pci_get_domain_bus_and_slot(0, bus, 0);
855+
}
856+
857+
return NULL;
858+
}
859+
860+
/**
861+
* ixgbe_x550em_a_has_mii - is this the first ixgbe x550em_a PCI function?
862+
* @hw: pointer to hardware structure
863+
*
864+
* Returns true if hw points to lowest numbered PCI B:D.F x550_em_a device in
865+
* the SoC. There are up to 4 MACs sharing a single MDIO bus on the x550em_a,
866+
* but we only want to register one MDIO bus.
867+
**/
868+
static bool ixgbe_x550em_a_has_mii(struct ixgbe_hw *hw)
869+
{
870+
struct ixgbe_adapter *adapter = hw->back;
871+
struct pci_dev *pdev = adapter->pdev;
872+
struct pci_dev *func0_pdev;
873+
874+
/* For the C3000 family of SoCs (x550em_a) the internal ixgbe devices
875+
* are always downstream of root ports @ 0000:00:16.0 & 0000:00:17.0
876+
* It's not valid for function 0 to be disabled and function 1 is up,
877+
* so the lowest numbered ixgbe dev will be device 0 function 0 on one
878+
* of those two root ports
879+
*/
880+
func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x16, 0));
881+
if (func0_pdev) {
882+
if (func0_pdev == pdev)
883+
return true;
884+
else
885+
return false;
886+
}
887+
func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x17, 0));
888+
if (func0_pdev == pdev)
889+
return true;
890+
891+
return false;
892+
}
893+
894+
/**
895+
* ixgbe_mii_bus_init - mii_bus structure setup
896+
* @hw: pointer to hardware structure
897+
*
898+
* Returns 0 on success, negative on failure
899+
*
900+
* ixgbe_mii_bus_init initializes a mii_bus structure in adapter
901+
**/
902+
s32 ixgbe_mii_bus_init(struct ixgbe_hw *hw)
903+
{
904+
struct ixgbe_adapter *adapter = hw->back;
905+
struct pci_dev *pdev = adapter->pdev;
906+
struct device *dev = &adapter->netdev->dev;
907+
struct mii_bus *bus;
908+
909+
adapter->mii_bus = devm_mdiobus_alloc(dev);
910+
if (!adapter->mii_bus)
911+
return -ENOMEM;
912+
913+
bus = adapter->mii_bus;
914+
915+
switch (hw->device_id) {
916+
/* C3000 SoCs */
917+
case IXGBE_DEV_ID_X550EM_A_KR:
918+
case IXGBE_DEV_ID_X550EM_A_KR_L:
919+
case IXGBE_DEV_ID_X550EM_A_SFP_N:
920+
case IXGBE_DEV_ID_X550EM_A_SGMII:
921+
case IXGBE_DEV_ID_X550EM_A_SGMII_L:
922+
case IXGBE_DEV_ID_X550EM_A_10G_T:
923+
case IXGBE_DEV_ID_X550EM_A_SFP:
924+
case IXGBE_DEV_ID_X550EM_A_1G_T:
925+
case IXGBE_DEV_ID_X550EM_A_1G_T_L:
926+
if (!ixgbe_x550em_a_has_mii(hw))
927+
goto ixgbe_no_mii_bus;
928+
bus->read = &ixgbe_x550em_a_mii_bus_read;
929+
bus->write = &ixgbe_x550em_a_mii_bus_write;
930+
break;
931+
default:
932+
bus->read = &ixgbe_mii_bus_read;
933+
bus->write = &ixgbe_mii_bus_write;
934+
break;
935+
}
936+
937+
/* Use the position of the device in the PCI hierarchy as the id */
938+
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mdio-%s", ixgbe_driver_name,
939+
pci_name(pdev));
940+
941+
bus->name = "ixgbe-mdio";
942+
bus->priv = adapter;
943+
bus->parent = dev;
944+
bus->phy_mask = GENMASK(31, 0);
945+
946+
/* Support clause 22/45 natively. ixgbe_probe() sets MDIO_EMULATE_C22
947+
* unfortunately that causes some clause 22 frames to be sent with
948+
* clause 45 addressing. We don't want that.
949+
*/
950+
hw->phy.mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22;
951+
952+
return mdiobus_register(bus);
953+
954+
ixgbe_no_mii_bus:
955+
devm_mdiobus_free(dev, bus);
956+
adapter->mii_bus = NULL;
957+
return -ENODEV;
958+
}
959+
661960
/**
662961
* ixgbe_setup_phy_link_generic - Set and restart autoneg
663962
* @hw: pointer to hardware structure

drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@
120120
/* SFP+ SFF-8472 Compliance code */
121121
#define IXGBE_SFF_SFF_8472_UNSUP 0x00
122122

123+
s32 ixgbe_mii_bus_init(struct ixgbe_hw *hw);
124+
123125
s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw);
124126
s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw);
125127
s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,

0 commit comments

Comments
 (0)