Commit f35d2a5f authored by David S. Miller's avatar David S. Miller

Merge branch 'amd-xgbe-next'

Tom Lendacky says:

====================
amd-xgbe: AMD XGBE driver updates 2014-09-03

The following series of patches includes fixes/updates to the driver.

- Query the device for the actual speed mode (KR/KX) rather than trying
  to track it
- Update parallel detection logic to support KR mode
- Fix new warnings from checkpatch in the amd-xgbe and amd-xgbe-phy
  driver

This patch series is based on net-next.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e4cf0b75 b73c798b
...@@ -271,7 +271,6 @@ ...@@ -271,7 +271,6 @@
#define DMA_PBL_X8_DISABLE 0x00 #define DMA_PBL_X8_DISABLE 0x00
#define DMA_PBL_X8_ENABLE 0x01 #define DMA_PBL_X8_ENABLE 0x01
/* MAC register offsets */ /* MAC register offsets */
#define MAC_TCR 0x0000 #define MAC_TCR 0x0000
#define MAC_RCR 0x0004 #define MAC_RCR 0x0004
...@@ -792,7 +791,6 @@ ...@@ -792,7 +791,6 @@
#define MTL_Q_DISABLED 0x00 #define MTL_Q_DISABLED 0x00
#define MTL_Q_ENABLED 0x02 #define MTL_Q_ENABLED 0x02
/* MTL traffic class register offsets /* MTL traffic class register offsets
* Multiple traffic classes can be active. The first class has registers * Multiple traffic classes can be active. The first class has registers
* that begin at 0x1100. Each subsequent queue has registers that * that begin at 0x1100. Each subsequent queue has registers that
...@@ -815,7 +813,6 @@ ...@@ -815,7 +813,6 @@
#define MTL_TSA_SP 0x00 #define MTL_TSA_SP 0x00
#define MTL_TSA_ETS 0x02 #define MTL_TSA_ETS 0x02
/* PCS MMD select register offset /* PCS MMD select register offset
* The MMD select register is used for accessing PCS registers * The MMD select register is used for accessing PCS registers
* when the underlying APB3 interface is using indirect addressing. * when the underlying APB3 interface is using indirect addressing.
...@@ -825,7 +822,6 @@ ...@@ -825,7 +822,6 @@
*/ */
#define PCS_MMD_SELECT 0xff #define PCS_MMD_SELECT 0xff
/* Descriptor/Packet entry bit positions and sizes */ /* Descriptor/Packet entry bit positions and sizes */
#define RX_PACKET_ERRORS_CRC_INDEX 2 #define RX_PACKET_ERRORS_CRC_INDEX 2
#define RX_PACKET_ERRORS_CRC_WIDTH 1 #define RX_PACKET_ERRORS_CRC_WIDTH 1
...@@ -929,7 +925,6 @@ ...@@ -929,7 +925,6 @@
#define MDIO_AN_COMP_STAT 0x0030 #define MDIO_AN_COMP_STAT 0x0030
#endif #endif
/* Bit setting and getting macros /* Bit setting and getting macros
* The get macro will extract the current bit field value from within * The get macro will extract the current bit field value from within
* the variable * the variable
...@@ -957,7 +952,6 @@ do { \ ...@@ -957,7 +952,6 @@ do { \
((0x1 << (_width)) - 1)) << (_index))); \ ((0x1 << (_width)) - 1)) << (_index))); \
} while (0) } while (0)
/* Bit setting and getting macros based on register fields /* Bit setting and getting macros based on register fields
* The get macro uses the bit field definitions formed using the input * The get macro uses the bit field definitions formed using the input
* names to extract the current bit field value from within the * names to extract the current bit field value from within the
...@@ -986,7 +980,6 @@ do { \ ...@@ -986,7 +980,6 @@ do { \
_prefix##_##_field##_INDEX, \ _prefix##_##_field##_INDEX, \
_prefix##_##_field##_WIDTH, (_val)) _prefix##_##_field##_WIDTH, (_val))
/* Macros for reading or writing registers /* Macros for reading or writing registers
* The ioread macros will get bit fields or full values using the * The ioread macros will get bit fields or full values using the
* register definitions formed using the input names * register definitions formed using the input names
...@@ -1014,7 +1007,6 @@ do { \ ...@@ -1014,7 +1007,6 @@ do { \
XGMAC_IOWRITE((_pdata), _reg, reg_val); \ XGMAC_IOWRITE((_pdata), _reg, reg_val); \
} while (0) } while (0)
/* Macros for reading or writing MTL queue or traffic class registers /* Macros for reading or writing MTL queue or traffic class registers
* Similar to the standard read and write macros except that the * Similar to the standard read and write macros except that the
* base register value is calculated by the queue or traffic class number * base register value is calculated by the queue or traffic class number
...@@ -1041,7 +1033,6 @@ do { \ ...@@ -1041,7 +1033,6 @@ do { \
XGMAC_MTL_IOWRITE((_pdata), (_n), _reg, reg_val); \ XGMAC_MTL_IOWRITE((_pdata), (_n), _reg, reg_val); \
} while (0) } while (0)
/* Macros for reading or writing DMA channel registers /* Macros for reading or writing DMA channel registers
* Similar to the standard read and write macros except that the * Similar to the standard read and write macros except that the
* base register value is obtained from the ring * base register value is obtained from the ring
...@@ -1066,7 +1057,6 @@ do { \ ...@@ -1066,7 +1057,6 @@ do { \
XGMAC_DMA_IOWRITE((_channel), _reg, reg_val); \ XGMAC_DMA_IOWRITE((_channel), _reg, reg_val); \
} while (0) } while (0)
/* Macros for building, reading or writing register values or bits /* Macros for building, reading or writing register values or bits
* within the register values of XPCS registers. * within the register values of XPCS registers.
*/ */
...@@ -1076,7 +1066,6 @@ do { \ ...@@ -1076,7 +1066,6 @@ do { \
#define XPCS_IOREAD(_pdata, _off) \ #define XPCS_IOREAD(_pdata, _off) \
ioread32((_pdata)->xpcs_regs + (_off)) ioread32((_pdata)->xpcs_regs + (_off))
/* Macros for building, reading or writing register values or bits /* Macros for building, reading or writing register values or bits
* using MDIO. Different from above because of the use of standardized * using MDIO. Different from above because of the use of standardized
* Linux include values. No shifting is performed with the bit * Linux include values. No shifting is performed with the bit
......
...@@ -120,7 +120,6 @@ ...@@ -120,7 +120,6 @@
#include "xgbe.h" #include "xgbe.h"
#include "xgbe-common.h" #include "xgbe-common.h"
static int xgbe_dcb_ieee_getets(struct net_device *netdev, static int xgbe_dcb_ieee_getets(struct net_device *netdev,
struct ieee_ets *ets) struct ieee_ets *ets)
{ {
......
...@@ -121,7 +121,6 @@ ...@@ -121,7 +121,6 @@
#include "xgbe.h" #include "xgbe.h"
#include "xgbe-common.h" #include "xgbe-common.h"
static ssize_t xgbe_common_read(char __user *buffer, size_t count, static ssize_t xgbe_common_read(char __user *buffer, size_t count,
loff_t *ppos, unsigned int value) loff_t *ppos, unsigned int value)
{ {
......
...@@ -117,7 +117,6 @@ ...@@ -117,7 +117,6 @@
#include "xgbe.h" #include "xgbe.h"
#include "xgbe-common.h" #include "xgbe-common.h"
static void xgbe_unmap_skb(struct xgbe_prv_data *, struct xgbe_ring_data *); static void xgbe_unmap_skb(struct xgbe_prv_data *, struct xgbe_ring_data *);
static void xgbe_free_ring(struct xgbe_prv_data *pdata, static void xgbe_free_ring(struct xgbe_prv_data *pdata,
...@@ -524,11 +523,8 @@ static void xgbe_realloc_skb(struct xgbe_channel *channel) ...@@ -524,11 +523,8 @@ static void xgbe_realloc_skb(struct xgbe_channel *channel)
/* Allocate skb & assign to each rdesc */ /* Allocate skb & assign to each rdesc */
skb = dev_alloc_skb(pdata->rx_buf_size); skb = dev_alloc_skb(pdata->rx_buf_size);
if (skb == NULL) { if (skb == NULL)
netdev_alert(pdata->netdev,
"failed to allocate skb\n");
break; break;
}
skb_dma = dma_map_single(pdata->dev, skb->data, skb_dma = dma_map_single(pdata->dev, skb->data,
pdata->rx_buf_size, DMA_FROM_DEVICE); pdata->rx_buf_size, DMA_FROM_DEVICE);
if (dma_mapping_error(pdata->dev, skb_dma)) { if (dma_mapping_error(pdata->dev, skb_dma)) {
......
...@@ -122,7 +122,6 @@ ...@@ -122,7 +122,6 @@
#include "xgbe.h" #include "xgbe.h"
#include "xgbe-common.h" #include "xgbe-common.h"
static unsigned int xgbe_usec_to_riwt(struct xgbe_prv_data *pdata, static unsigned int xgbe_usec_to_riwt(struct xgbe_prv_data *pdata,
unsigned int usec) unsigned int usec)
{ {
......
...@@ -126,7 +126,6 @@ ...@@ -126,7 +126,6 @@
#include "xgbe.h" #include "xgbe.h"
#include "xgbe-common.h" #include "xgbe-common.h"
static int xgbe_poll(struct napi_struct *, int); static int xgbe_poll(struct napi_struct *, int);
static void xgbe_set_rx_mode(struct net_device *); static void xgbe_set_rx_mode(struct net_device *);
......
...@@ -121,7 +121,6 @@ ...@@ -121,7 +121,6 @@
#include "xgbe.h" #include "xgbe.h"
#include "xgbe-common.h" #include "xgbe-common.h"
struct xgbe_stats { struct xgbe_stats {
char stat_string[ETH_GSTRING_LEN]; char stat_string[ETH_GSTRING_LEN];
int stat_size; int stat_size;
...@@ -173,6 +172,7 @@ static const struct xgbe_stats xgbe_gstring_stats[] = { ...@@ -173,6 +172,7 @@ static const struct xgbe_stats xgbe_gstring_stats[] = {
XGMAC_MMC_STAT("rx_watchdog_errors", rxwatchdogerror), XGMAC_MMC_STAT("rx_watchdog_errors", rxwatchdogerror),
XGMAC_MMC_STAT("rx_pause_frames", rxpauseframes), XGMAC_MMC_STAT("rx_pause_frames", rxpauseframes),
}; };
#define XGBE_STATS_COUNT ARRAY_SIZE(xgbe_gstring_stats) #define XGBE_STATS_COUNT ARRAY_SIZE(xgbe_gstring_stats)
static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data) static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
......
...@@ -128,7 +128,6 @@ ...@@ -128,7 +128,6 @@
#include "xgbe.h" #include "xgbe.h"
#include "xgbe-common.h" #include "xgbe-common.h"
MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>"); MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>");
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(XGBE_DRV_VERSION); MODULE_VERSION(XGBE_DRV_VERSION);
......
...@@ -123,7 +123,6 @@ ...@@ -123,7 +123,6 @@
#include "xgbe.h" #include "xgbe.h"
#include "xgbe-common.h" #include "xgbe-common.h"
static int xgbe_mdio_read(struct mii_bus *mii, int prtad, int mmd_reg) static int xgbe_mdio_read(struct mii_bus *mii, int prtad, int mmd_reg)
{ {
struct xgbe_prv_data *pdata = mii->priv; struct xgbe_prv_data *pdata = mii->priv;
......
...@@ -122,7 +122,6 @@ ...@@ -122,7 +122,6 @@
#include "xgbe.h" #include "xgbe.h"
#include "xgbe-common.h" #include "xgbe-common.h"
static cycle_t xgbe_cc_read(const struct cyclecounter *cc) static cycle_t xgbe_cc_read(const struct cyclecounter *cc)
{ {
struct xgbe_prv_data *pdata = container_of(cc, struct xgbe_prv_data *pdata = container_of(cc,
......
...@@ -128,7 +128,6 @@ ...@@ -128,7 +128,6 @@
#include <linux/net_tstamp.h> #include <linux/net_tstamp.h>
#include <net/dcbnl.h> #include <net/dcbnl.h>
#define XGBE_DRV_NAME "amd-xgbe" #define XGBE_DRV_NAME "amd-xgbe"
#define XGBE_DRV_VERSION "1.0.0-a" #define XGBE_DRV_VERSION "1.0.0-a"
#define XGBE_DRV_DESC "AMD 10 Gigabit Ethernet Driver" #define XGBE_DRV_DESC "AMD 10 Gigabit Ethernet Driver"
...@@ -198,7 +197,6 @@ ...@@ -198,7 +197,6 @@
((_ring)->rdata + \ ((_ring)->rdata + \
((_idx) & ((_ring)->rdesc_count - 1))) ((_idx) & ((_ring)->rdesc_count - 1)))
/* Default coalescing parameters */ /* Default coalescing parameters */
#define XGMAC_INIT_DMA_TX_USECS 50 #define XGMAC_INIT_DMA_TX_USECS 50
#define XGMAC_INIT_DMA_TX_FRAMES 25 #define XGMAC_INIT_DMA_TX_FRAMES 25
......
...@@ -75,7 +75,6 @@ ...@@ -75,7 +75,6 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>"); MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>");
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION("1.0.0-a"); MODULE_VERSION("1.0.0-a");
...@@ -100,9 +99,11 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver"); ...@@ -100,9 +99,11 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver");
#ifndef MDIO_PMA_10GBR_PMD_CTRL #ifndef MDIO_PMA_10GBR_PMD_CTRL
#define MDIO_PMA_10GBR_PMD_CTRL 0x0096 #define MDIO_PMA_10GBR_PMD_CTRL 0x0096
#endif #endif
#ifndef MDIO_PMA_10GBR_FEC_CTRL #ifndef MDIO_PMA_10GBR_FEC_CTRL
#define MDIO_PMA_10GBR_FEC_CTRL 0x00ab #define MDIO_PMA_10GBR_FEC_CTRL 0x00ab
#endif #endif
#ifndef MDIO_AN_XNP #ifndef MDIO_AN_XNP
#define MDIO_AN_XNP 0x0016 #define MDIO_AN_XNP 0x0016
#endif #endif
...@@ -110,14 +111,23 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver"); ...@@ -110,14 +111,23 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver");
#ifndef MDIO_AN_INTMASK #ifndef MDIO_AN_INTMASK
#define MDIO_AN_INTMASK 0x8001 #define MDIO_AN_INTMASK 0x8001
#endif #endif
#ifndef MDIO_AN_INT #ifndef MDIO_AN_INT
#define MDIO_AN_INT 0x8002 #define MDIO_AN_INT 0x8002
#endif #endif
#ifndef MDIO_AN_KR_CTRL
#define MDIO_AN_KR_CTRL 0x8003
#endif
#ifndef MDIO_CTRL1_SPEED1G #ifndef MDIO_CTRL1_SPEED1G
#define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100) #define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100)
#endif #endif
#ifndef MDIO_KR_CTRL_PDETECT
#define MDIO_KR_CTRL_PDETECT 0x01
#endif
/* SerDes integration register offsets */ /* SerDes integration register offsets */
#define SIR0_KR_RT_1 0x002c #define SIR0_KR_RT_1 0x002c
#define SIR0_STATUS 0x0040 #define SIR0_STATUS 0x0040
...@@ -161,7 +171,6 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver"); ...@@ -161,7 +171,6 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver");
#define SPEED_1000_TXAMP 0xf #define SPEED_1000_TXAMP 0xf
#define SPEED_1000_WORD 0x1 #define SPEED_1000_WORD 0x1
/* SerDes RxTx register offsets */ /* SerDes RxTx register offsets */
#define RXTX_REG20 0x0050 #define RXTX_REG20 0x0050
#define RXTX_REG114 0x01c8 #define RXTX_REG114 0x01c8
...@@ -255,7 +264,6 @@ do { \ ...@@ -255,7 +264,6 @@ do { \
XSIR1_IOWRITE((_priv), _reg, reg_val); \ XSIR1_IOWRITE((_priv), _reg, reg_val); \
} while (0) } while (0)
/* Macros for reading or writing SerDes RxTx registers /* Macros for reading or writing SerDes RxTx registers
* The ioread macros will get bit fields or full values using the * The ioread macros will get bit fields or full values using the
* register definitions formed using the input names * register definitions formed using the input names
...@@ -283,7 +291,6 @@ do { \ ...@@ -283,7 +291,6 @@ do { \
XRXTX_IOWRITE((_priv), _reg, reg_val); \ XRXTX_IOWRITE((_priv), _reg, reg_val); \
} while (0) } while (0)
enum amd_xgbe_phy_an { enum amd_xgbe_phy_an {
AMD_XGBE_AN_READY = 0, AMD_XGBE_AN_READY = 0,
AMD_XGBE_AN_START, AMD_XGBE_AN_START,
...@@ -331,7 +338,6 @@ struct amd_xgbe_phy_priv { ...@@ -331,7 +338,6 @@ struct amd_xgbe_phy_priv {
/* Maintain link status for re-starting auto-negotiation */ /* Maintain link status for re-starting auto-negotiation */
unsigned int link; unsigned int link;
enum amd_xgbe_phy_mode mode;
unsigned int speed_set; unsigned int speed_set;
/* Auto-negotiation state machine support */ /* Auto-negotiation state machine support */
...@@ -342,6 +348,7 @@ struct amd_xgbe_phy_priv { ...@@ -342,6 +348,7 @@ struct amd_xgbe_phy_priv {
enum amd_xgbe_phy_rx kx_state; enum amd_xgbe_phy_rx kx_state;
struct work_struct an_work; struct work_struct an_work;
struct workqueue_struct *an_workqueue; struct workqueue_struct *an_workqueue;
unsigned int parallel_detect;
}; };
static int amd_xgbe_an_enable_kr_training(struct phy_device *phydev) static int amd_xgbe_an_enable_kr_training(struct phy_device *phydev)
...@@ -468,8 +475,6 @@ static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev) ...@@ -468,8 +475,6 @@ static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev)
amd_xgbe_phy_serdes_complete_ratechange(phydev); amd_xgbe_phy_serdes_complete_ratechange(phydev);
priv->mode = AMD_XGBE_MODE_KR;
return 0; return 0;
} }
...@@ -518,8 +523,6 @@ static int amd_xgbe_phy_gmii_2500_mode(struct phy_device *phydev) ...@@ -518,8 +523,6 @@ static int amd_xgbe_phy_gmii_2500_mode(struct phy_device *phydev)
amd_xgbe_phy_serdes_complete_ratechange(phydev); amd_xgbe_phy_serdes_complete_ratechange(phydev);
priv->mode = AMD_XGBE_MODE_KX;
return 0; return 0;
} }
...@@ -568,18 +571,43 @@ static int amd_xgbe_phy_gmii_mode(struct phy_device *phydev) ...@@ -568,18 +571,43 @@ static int amd_xgbe_phy_gmii_mode(struct phy_device *phydev)
amd_xgbe_phy_serdes_complete_ratechange(phydev); amd_xgbe_phy_serdes_complete_ratechange(phydev);
priv->mode = AMD_XGBE_MODE_KX; return 0;
}
static int amd_xgbe_phy_cur_mode(struct phy_device *phydev,
enum amd_xgbe_phy_mode *mode)
{
int ret;
ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2);
if (ret < 0)
return ret;
if ((ret & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR)
*mode = AMD_XGBE_MODE_KR;
else
*mode = AMD_XGBE_MODE_KX;
return 0; return 0;
} }
static bool amd_xgbe_phy_in_kr_mode(struct phy_device *phydev)
{
enum amd_xgbe_phy_mode mode;
if (amd_xgbe_phy_cur_mode(phydev, &mode))
return false;
return (mode == AMD_XGBE_MODE_KR);
}
static int amd_xgbe_phy_switch_mode(struct phy_device *phydev) static int amd_xgbe_phy_switch_mode(struct phy_device *phydev)
{ {
struct amd_xgbe_phy_priv *priv = phydev->priv; struct amd_xgbe_phy_priv *priv = phydev->priv;
int ret; int ret;
/* If we are in KR switch to KX, and vice-versa */ /* If we are in KR switch to KX, and vice-versa */
if (priv->mode == AMD_XGBE_MODE_KR) { if (amd_xgbe_phy_in_kr_mode(phydev)) {
if (priv->speed_set == AMD_XGBE_PHY_SPEEDSET_1000_10000) if (priv->speed_set == AMD_XGBE_PHY_SPEEDSET_1000_10000)
ret = amd_xgbe_phy_gmii_mode(phydev); ret = amd_xgbe_phy_gmii_mode(phydev);
else else
...@@ -591,27 +619,31 @@ static int amd_xgbe_phy_switch_mode(struct phy_device *phydev) ...@@ -591,27 +619,31 @@ static int amd_xgbe_phy_switch_mode(struct phy_device *phydev)
return ret; return ret;
} }
static enum amd_xgbe_phy_an amd_xgbe_an_switch_mode(struct phy_device *phydev) static int amd_xgbe_phy_set_mode(struct phy_device *phydev,
enum amd_xgbe_phy_mode mode)
{ {
enum amd_xgbe_phy_mode cur_mode;
int ret; int ret;
ret = amd_xgbe_phy_switch_mode(phydev); ret = amd_xgbe_phy_cur_mode(phydev, &cur_mode);
if (ret < 0) if (ret)
return AMD_XGBE_AN_ERROR; return ret;
return AMD_XGBE_AN_START; if (mode != cur_mode)
ret = amd_xgbe_phy_switch_mode(phydev);
return ret;
} }
static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev, static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev,
enum amd_xgbe_phy_rx *state) enum amd_xgbe_phy_rx *state)
{ {
struct amd_xgbe_phy_priv *priv = phydev->priv;
int ad_reg, lp_reg, ret; int ad_reg, lp_reg, ret;
*state = AMD_XGBE_RX_COMPLETE; *state = AMD_XGBE_RX_COMPLETE;
/* If we're in KX mode then we're done */ /* If we're not in KR mode then we're done */
if (priv->mode == AMD_XGBE_MODE_KX) if (!amd_xgbe_phy_in_kr_mode(phydev))
return AMD_XGBE_AN_EVENT; return AMD_XGBE_AN_EVENT;
/* Enable/Disable FEC */ /* Enable/Disable FEC */
...@@ -669,7 +701,6 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_xnp(struct phy_device *phydev, ...@@ -669,7 +701,6 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_xnp(struct phy_device *phydev,
static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev, static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev,
enum amd_xgbe_phy_rx *state) enum amd_xgbe_phy_rx *state)
{ {
struct amd_xgbe_phy_priv *priv = phydev->priv;
unsigned int link_support; unsigned int link_support;
int ret, ad_reg, lp_reg; int ret, ad_reg, lp_reg;
...@@ -679,9 +710,9 @@ static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev, ...@@ -679,9 +710,9 @@ static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev,
return AMD_XGBE_AN_ERROR; return AMD_XGBE_AN_ERROR;
/* Check for a supported mode, otherwise restart in a different one */ /* Check for a supported mode, otherwise restart in a different one */
link_support = (priv->mode == AMD_XGBE_MODE_KR) ? 0x80 : 0x20; link_support = amd_xgbe_phy_in_kr_mode(phydev) ? 0x80 : 0x20;
if (!(ret & link_support)) if (!(ret & link_support))
return amd_xgbe_an_switch_mode(phydev); return AMD_XGBE_AN_INCOMPAT_LINK;
/* Check Extended Next Page support */ /* Check Extended Next Page support */
ad_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE); ad_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
...@@ -722,7 +753,7 @@ static enum amd_xgbe_phy_an amd_xgbe_an_start(struct phy_device *phydev) ...@@ -722,7 +753,7 @@ static enum amd_xgbe_phy_an amd_xgbe_an_start(struct phy_device *phydev)
int ret; int ret;
/* Be sure we aren't looping trying to negotiate */ /* Be sure we aren't looping trying to negotiate */
if (priv->mode == AMD_XGBE_MODE_KR) { if (amd_xgbe_phy_in_kr_mode(phydev)) {
if (priv->kr_state != AMD_XGBE_RX_READY) if (priv->kr_state != AMD_XGBE_RX_READY)
return AMD_XGBE_AN_NO_LINK; return AMD_XGBE_AN_NO_LINK;
priv->kr_state = AMD_XGBE_RX_BPA; priv->kr_state = AMD_XGBE_RX_BPA;
...@@ -785,6 +816,13 @@ static enum amd_xgbe_phy_an amd_xgbe_an_start(struct phy_device *phydev) ...@@ -785,6 +816,13 @@ static enum amd_xgbe_phy_an amd_xgbe_an_start(struct phy_device *phydev)
/* Enable and start auto-negotiation */ /* Enable and start auto-negotiation */
phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0);
ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_KR_CTRL);
if (ret < 0)
return AMD_XGBE_AN_ERROR;
ret |= MDIO_KR_CTRL_PDETECT;
phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_KR_CTRL, ret);
ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
if (ret < 0) if (ret < 0)
return AMD_XGBE_AN_ERROR; return AMD_XGBE_AN_ERROR;
...@@ -825,8 +863,8 @@ static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev) ...@@ -825,8 +863,8 @@ static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev)
enum amd_xgbe_phy_rx *state; enum amd_xgbe_phy_rx *state;
int ret; int ret;
state = (priv->mode == AMD_XGBE_MODE_KR) ? &priv->kr_state state = amd_xgbe_phy_in_kr_mode(phydev) ? &priv->kr_state
: &priv->kx_state; : &priv->kx_state;
switch (*state) { switch (*state) {
case AMD_XGBE_RX_BPA: case AMD_XGBE_RX_BPA:
...@@ -846,7 +884,13 @@ static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev) ...@@ -846,7 +884,13 @@ static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev)
static enum amd_xgbe_phy_an amd_xgbe_an_incompat_link(struct phy_device *phydev) static enum amd_xgbe_phy_an amd_xgbe_an_incompat_link(struct phy_device *phydev)
{ {
return amd_xgbe_an_switch_mode(phydev); int ret;
ret = amd_xgbe_phy_switch_mode(phydev);
if (ret)
return AMD_XGBE_AN_ERROR;
return AMD_XGBE_AN_START;
} }
static void amd_xgbe_an_state_machine(struct work_struct *work) static void amd_xgbe_an_state_machine(struct work_struct *work)
...@@ -859,6 +903,10 @@ static void amd_xgbe_an_state_machine(struct work_struct *work) ...@@ -859,6 +903,10 @@ static void amd_xgbe_an_state_machine(struct work_struct *work)
int sleep; int sleep;
unsigned int an_supported = 0; unsigned int an_supported = 0;
/* Start in KX mode */
if (amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX))
priv->an_state = AMD_XGBE_AN_ERROR;
while (1) { while (1) {
mutex_lock(&priv->an_mutex); mutex_lock(&priv->an_mutex);
...@@ -866,8 +914,9 @@ static void amd_xgbe_an_state_machine(struct work_struct *work) ...@@ -866,8 +914,9 @@ static void amd_xgbe_an_state_machine(struct work_struct *work)
switch (priv->an_state) { switch (priv->an_state) {
case AMD_XGBE_AN_START: case AMD_XGBE_AN_START:
priv->an_state = amd_xgbe_an_start(phydev);
an_supported = 0; an_supported = 0;
priv->parallel_detect = 0;
priv->an_state = amd_xgbe_an_start(phydev);
break; break;
case AMD_XGBE_AN_EVENT: case AMD_XGBE_AN_EVENT:
...@@ -884,6 +933,7 @@ static void amd_xgbe_an_state_machine(struct work_struct *work) ...@@ -884,6 +933,7 @@ static void amd_xgbe_an_state_machine(struct work_struct *work)
break; break;
case AMD_XGBE_AN_COMPLETE: case AMD_XGBE_AN_COMPLETE:
priv->parallel_detect = an_supported ? 0 : 1;
netdev_info(phydev->attached_dev, "%s successful\n", netdev_info(phydev->attached_dev, "%s successful\n",
an_supported ? "Auto negotiation" an_supported ? "Auto negotiation"
: "Parallel detection"); : "Parallel detection");
...@@ -1018,7 +1068,6 @@ static int amd_xgbe_phy_config_aneg(struct phy_device *phydev) ...@@ -1018,7 +1068,6 @@ static int amd_xgbe_phy_config_aneg(struct phy_device *phydev)
{ {
struct amd_xgbe_phy_priv *priv = phydev->priv; struct amd_xgbe_phy_priv *priv = phydev->priv;
u32 mmd_mask = phydev->c45_ids.devices_in_package; u32 mmd_mask = phydev->c45_ids.devices_in_package;
int ret;
if (phydev->autoneg != AUTONEG_ENABLE) if (phydev->autoneg != AUTONEG_ENABLE)
return amd_xgbe_phy_setup_forced(phydev); return amd_xgbe_phy_setup_forced(phydev);
...@@ -1027,11 +1076,6 @@ static int amd_xgbe_phy_config_aneg(struct phy_device *phydev) ...@@ -1027,11 +1076,6 @@ static int amd_xgbe_phy_config_aneg(struct phy_device *phydev)
if (!(mmd_mask & MDIO_DEVS_AN)) if (!(mmd_mask & MDIO_DEVS_AN))
return -EINVAL; return -EINVAL;
/* Get the current speed mode */
ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2);
if (ret < 0)
return ret;
/* Start/Restart the auto-negotiation state machine */ /* Start/Restart the auto-negotiation state machine */
mutex_lock(&priv->an_mutex); mutex_lock(&priv->an_mutex);
priv->an_result = AMD_XGBE_AN_READY; priv->an_result = AMD_XGBE_AN_READY;
...@@ -1121,18 +1165,14 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev) ...@@ -1121,18 +1165,14 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev)
{ {
struct amd_xgbe_phy_priv *priv = phydev->priv; struct amd_xgbe_phy_priv *priv = phydev->priv;
u32 mmd_mask = phydev->c45_ids.devices_in_package; u32 mmd_mask = phydev->c45_ids.devices_in_package;
int ret, mode, ad_ret, lp_ret; int ret, ad_ret, lp_ret;
ret = amd_xgbe_phy_update_link(phydev); ret = amd_xgbe_phy_update_link(phydev);
if (ret) if (ret)
return ret; return ret;
mode = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2); if ((phydev->autoneg == AUTONEG_ENABLE) &&
if (mode < 0) !priv->parallel_detect) {
return mode;
mode &= MDIO_PCS_CTRL2_TYPE;
if (phydev->autoneg == AUTONEG_ENABLE) {
if (!(mmd_mask & MDIO_DEVS_AN)) if (!(mmd_mask & MDIO_DEVS_AN))
return -EINVAL; return -EINVAL;
...@@ -1163,40 +1203,39 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev) ...@@ -1163,40 +1203,39 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev)
ad_ret &= lp_ret; ad_ret &= lp_ret;
if (ad_ret & 0x80) { if (ad_ret & 0x80) {
phydev->speed = SPEED_10000; phydev->speed = SPEED_10000;
if (mode != MDIO_PCS_CTRL2_10GBR) { ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KR);
ret = amd_xgbe_phy_xgmii_mode(phydev); if (ret)
if (ret < 0) return ret;
return ret;
}
} else { } else {
int (*mode_fcn)(struct phy_device *); switch (priv->speed_set) {
case AMD_XGBE_PHY_SPEEDSET_1000_10000:
if (priv->speed_set ==
AMD_XGBE_PHY_SPEEDSET_1000_10000) {
phydev->speed = SPEED_1000; phydev->speed = SPEED_1000;
mode_fcn = amd_xgbe_phy_gmii_mode; break;
} else {
case AMD_XGBE_PHY_SPEEDSET_2500_10000:
phydev->speed = SPEED_2500; phydev->speed = SPEED_2500;
mode_fcn = amd_xgbe_phy_gmii_2500_mode; break;
} }
if (mode == MDIO_PCS_CTRL2_10GBR) { ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX);
ret = mode_fcn(phydev); if (ret)
if (ret < 0) return ret;
return ret;
}
} }
phydev->duplex = DUPLEX_FULL; phydev->duplex = DUPLEX_FULL;
} else { } else {
if (mode == MDIO_PCS_CTRL2_10GBR) { if (amd_xgbe_phy_in_kr_mode(phydev)) {
phydev->speed = SPEED_10000; phydev->speed = SPEED_10000;
} else { } else {
if (priv->speed_set == switch (priv->speed_set) {
AMD_XGBE_PHY_SPEEDSET_1000_10000) case AMD_XGBE_PHY_SPEEDSET_1000_10000:
phydev->speed = SPEED_1000; phydev->speed = SPEED_1000;
else break;
case AMD_XGBE_PHY_SPEEDSET_2500_10000:
phydev->speed = SPEED_2500; phydev->speed = SPEED_2500;
break;
}
} }
phydev->duplex = DUPLEX_FULL; phydev->duplex = DUPLEX_FULL;
phydev->pause = 0; phydev->pause = 0;
...@@ -1329,14 +1368,6 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev) ...@@ -1329,14 +1368,6 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev)
priv->link = 1; priv->link = 1;
ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2);
if (ret < 0)
goto err_sir1;
if ((ret & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR)
priv->mode = AMD_XGBE_MODE_KR;
else
priv->mode = AMD_XGBE_MODE_KX;
mutex_init(&priv->an_mutex); mutex_init(&priv->an_mutex);
INIT_WORK(&priv->an_work, amd_xgbe_an_state_machine); INIT_WORK(&priv->an_work, amd_xgbe_an_state_machine);
priv->an_workqueue = create_singlethread_workqueue(wq_name); priv->an_workqueue = create_singlethread_workqueue(wq_name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment