diff options
Diffstat (limited to 'meta-seattle/recipes-kernel/linux/files/319-Update-xgbe-drivers-for-B0-board.patch')
-rw-r--r-- | meta-seattle/recipes-kernel/linux/files/319-Update-xgbe-drivers-for-B0-board.patch | 3560 |
1 files changed, 0 insertions, 3560 deletions
diff --git a/meta-seattle/recipes-kernel/linux/files/319-Update-xgbe-drivers-for-B0-board.patch b/meta-seattle/recipes-kernel/linux/files/319-Update-xgbe-drivers-for-B0-board.patch deleted file mode 100644 index 13344ac8..00000000 --- a/meta-seattle/recipes-kernel/linux/files/319-Update-xgbe-drivers-for-B0-board.patch +++ /dev/null @@ -1,3560 +0,0 @@ -From 675ffdbcc905bc44a9fef9a7f6569493a3a8efe1 Mon Sep 17 00:00:00 2001 -From: Adrian Calianu <adrian.calianu@enea.com> -Date: Fri, 28 Aug 2015 17:35:57 +0200 -Subject: [PATCH] Hierofalcon: Update xgbe drivers for B0 board - -Port ethernet drivers for AMD xgbe from 4.1 kernel to 3.19 -in order to have ethernet working on B0 board - -Upstream-Status: Inappropriate -Support for this board was added starting with kernel version 4.1 - -Signed-off-by: Adrian Calianu <adrian.calianu@enea.com> ---- - drivers/net/ethernet/amd/xgbe/xgbe-common.h | 2 + - drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c | 2 +- - drivers/net/ethernet/amd/xgbe/xgbe-desc.c | 34 +- - drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 147 +++- - drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 309 +++---- - drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 29 +- - drivers/net/ethernet/amd/xgbe/xgbe-main.c | 207 ++++- - drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 29 +- - drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 21 +- - drivers/net/ethernet/amd/xgbe/xgbe.h | 46 +- - drivers/net/phy/amd-xgbe-phy.c | 1142 ++++++++++++++++++-------- - include/linux/clocksource.h | 9 + - 12 files changed, 1284 insertions(+), 693 deletions(-) - -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h -index 29a0927..34c28aa 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h -@@ -365,6 +365,8 @@ - #define MAC_HWF0R_TXCOESEL_WIDTH 1 - #define MAC_HWF0R_VLHASH_INDEX 4 - #define MAC_HWF0R_VLHASH_WIDTH 1 -+#define MAC_HWF1R_ADDR64_INDEX 14 -+#define MAC_HWF1R_ADDR64_WIDTH 2 - #define MAC_HWF1R_ADVTHWORD_INDEX 13 - #define MAC_HWF1R_ADVTHWORD_WIDTH 1 - #define MAC_HWF1R_DBGMEMA_INDEX 19 -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c -index 76479d0..2c063b6 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c -@@ -328,7 +328,7 @@ void xgbe_debugfs_init(struct xgbe_prv_data *pdata) - - buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name); - pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL); -- if (pdata->xgbe_debugfs == NULL) { -+ if (!pdata->xgbe_debugfs) { - netdev_err(pdata->netdev, "debugfs_create_dir failed\n"); - return; - } -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c -index a50891f..5c92fb7 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c -@@ -263,7 +263,7 @@ static int xgbe_alloc_pages(struct xgbe_prv_data *pdata, - int ret; - - /* Try to obtain pages, decreasing order if necessary */ -- gfp |= __GFP_COLD | __GFP_COMP; -+ gfp |= __GFP_COLD | __GFP_COMP | __GFP_NOWARN; - while (order >= 0) { - pages = alloc_pages(gfp, order); - if (pages) -@@ -422,7 +422,6 @@ static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata) - - ring->cur = 0; - ring->dirty = 0; -- memset(&ring->rx, 0, sizeof(ring->rx)); - - hw_if->rx_desc_init(channel); - } -@@ -621,35 +620,6 @@ err_out: - return 0; - } - --static void xgbe_realloc_rx_buffer(struct xgbe_channel *channel) --{ -- struct xgbe_prv_data *pdata = channel->pdata; -- struct xgbe_hw_if *hw_if = &pdata->hw_if; -- struct xgbe_ring *ring = channel->rx_ring; -- struct xgbe_ring_data *rdata; -- int i; -- -- DBGPR("-->xgbe_realloc_rx_buffer: rx_ring->rx.realloc_index = %u\n", -- ring->rx.realloc_index); -- -- for (i = 0; i < ring->dirty; i++) { -- rdata = XGBE_GET_DESC_DATA(ring, ring->rx.realloc_index); -- -- /* Reset rdata values */ -- xgbe_unmap_rdata(pdata, rdata); -- -- if (xgbe_map_rx_buffer(pdata, ring, rdata)) -- break; -- -- hw_if->rx_desc_reset(rdata); -- -- ring->rx.realloc_index++; -- } -- ring->dirty = 0; -- -- DBGPR("<--xgbe_realloc_rx_buffer\n"); --} -- - void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *desc_if) - { - DBGPR("-->xgbe_init_function_ptrs_desc\n"); -@@ -657,7 +627,7 @@ void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *desc_if) - desc_if->alloc_ring_resources = xgbe_alloc_ring_resources; - desc_if->free_ring_resources = xgbe_free_ring_resources; - desc_if->map_tx_skb = xgbe_map_tx_skb; -- desc_if->realloc_rx_buffer = xgbe_realloc_rx_buffer; -+ desc_if->map_rx_buffer = xgbe_map_rx_buffer; - desc_if->unmap_rdata = xgbe_unmap_rdata; - desc_if->wrapper_tx_desc_init = xgbe_wrapper_tx_descriptor_init; - desc_if->wrapper_rx_desc_init = xgbe_wrapper_rx_descriptor_init; -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c -index 4c66cd1..21d9497 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c -@@ -115,6 +115,7 @@ - */ - - #include <linux/phy.h> -+#include <linux/mdio.h> - #include <linux/clk.h> - #include <linux/bitrev.h> - #include <linux/crc32.h> -@@ -130,7 +131,7 @@ static unsigned int xgbe_usec_to_riwt(struct xgbe_prv_data *pdata, - - DBGPR("-->xgbe_usec_to_riwt\n"); - -- rate = clk_get_rate(pdata->sysclk); -+ rate = pdata->sysclk_rate; - - /* - * Convert the input usec value to the watchdog timer value. Each -@@ -153,7 +154,7 @@ static unsigned int xgbe_riwt_to_usec(struct xgbe_prv_data *pdata, - - DBGPR("-->xgbe_riwt_to_usec\n"); - -- rate = clk_get_rate(pdata->sysclk); -+ rate = pdata->sysclk_rate; - - /* - * Convert the input watchdog timer value to the usec value. Each -@@ -673,6 +674,9 @@ static void xgbe_enable_mac_interrupts(struct xgbe_prv_data *pdata) - - static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata) - { -+ if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x3) -+ return 0; -+ - XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x3); - - return 0; -@@ -680,6 +684,9 @@ static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata) - - static int xgbe_set_gmii_2500_speed(struct xgbe_prv_data *pdata) - { -+ if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x2) -+ return 0; -+ - XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x2); - - return 0; -@@ -687,6 +694,9 @@ static int xgbe_set_gmii_2500_speed(struct xgbe_prv_data *pdata) - - static int xgbe_set_xgmii_speed(struct xgbe_prv_data *pdata) - { -+ if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0) -+ return 0; -+ - XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0); - - return 0; -@@ -843,6 +853,22 @@ static int xgbe_set_mac_address(struct xgbe_prv_data *pdata, u8 *addr) - return 0; - } - -+static int xgbe_config_rx_mode(struct xgbe_prv_data *pdata) -+{ -+ struct net_device *netdev = pdata->netdev; -+ unsigned int pr_mode, am_mode; -+ -+ pr_mode = ((netdev->flags & IFF_PROMISC) != 0); -+ am_mode = ((netdev->flags & IFF_ALLMULTI) != 0); -+ -+ xgbe_set_promiscuous_mode(pdata, pr_mode); -+ xgbe_set_all_multicast_mode(pdata, am_mode); -+ -+ xgbe_add_mac_addresses(pdata); -+ -+ return 0; -+} -+ - static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad, - int mmd_reg) - { -@@ -881,6 +907,23 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad, - else - mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff); - -+ /* If the PCS is changing modes, match the MAC speed to it */ -+ if (((mmd_address >> 16) == MDIO_MMD_PCS) && -+ ((mmd_address & 0xffff) == MDIO_CTRL2)) { -+ struct phy_device *phydev = pdata->phydev; -+ -+ if (mmd_data & MDIO_PCS_CTRL2_TYPE) { -+ /* KX mode */ -+ if (phydev->supported & SUPPORTED_1000baseKX_Full) -+ xgbe_set_gmii_speed(pdata); -+ else -+ xgbe_set_gmii_2500_speed(pdata); -+ } else { -+ /* KR mode */ -+ xgbe_set_xgmii_speed(pdata); -+ } -+ } -+ - /* The PCS registers are accessed using mmio. The underlying APB3 - * management interface uses indirect addressing to access the MMD - * register sets. This requires accessing of the PCS register in two -@@ -1041,7 +1084,7 @@ static void xgbe_tx_desc_reset(struct xgbe_ring_data *rdata) - rdesc->desc3 = 0; - - /* Make sure ownership is written to the descriptor */ -- wmb(); -+ dma_wmb(); - } - - static void xgbe_tx_desc_init(struct xgbe_channel *channel) -@@ -1074,9 +1117,24 @@ static void xgbe_tx_desc_init(struct xgbe_channel *channel) - DBGPR("<--tx_desc_init\n"); - } - --static void xgbe_rx_desc_reset(struct xgbe_ring_data *rdata) -+static void xgbe_rx_desc_reset(struct xgbe_prv_data *pdata, -+ struct xgbe_ring_data *rdata, unsigned int index) - { - struct xgbe_ring_desc *rdesc = rdata->rdesc; -+ unsigned int rx_usecs = pdata->rx_usecs; -+ unsigned int rx_frames = pdata->rx_frames; -+ unsigned int inte; -+ -+ if (!rx_usecs && !rx_frames) { -+ /* No coalescing, interrupt for every descriptor */ -+ inte = 1; -+ } else { -+ /* Set interrupt based on Rx frame coalescing setting */ -+ if (rx_frames && !((index + 1) % rx_frames)) -+ inte = 1; -+ else -+ inte = 0; -+ } - - /* Reset the Rx descriptor - * Set buffer 1 (lo) address to header dma address (lo) -@@ -1090,19 +1148,18 @@ static void xgbe_rx_desc_reset(struct xgbe_ring_data *rdata) - rdesc->desc2 = cpu_to_le32(lower_32_bits(rdata->rx.buf.dma)); - rdesc->desc3 = cpu_to_le32(upper_32_bits(rdata->rx.buf.dma)); - -- XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, -- rdata->interrupt ? 1 : 0); -+ XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, inte); - - /* Since the Rx DMA engine is likely running, make sure everything - * is written to the descriptor(s) before setting the OWN bit - * for the descriptor - */ -- wmb(); -+ dma_wmb(); - - XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, OWN, 1); - - /* Make sure ownership is written to the descriptor */ -- wmb(); -+ dma_wmb(); - } - - static void xgbe_rx_desc_init(struct xgbe_channel *channel) -@@ -1111,26 +1168,16 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel) - struct xgbe_ring *ring = channel->rx_ring; - struct xgbe_ring_data *rdata; - unsigned int start_index = ring->cur; -- unsigned int rx_coalesce, rx_frames; - unsigned int i; - - DBGPR("-->rx_desc_init\n"); - -- rx_coalesce = (pdata->rx_riwt || pdata->rx_frames) ? 1 : 0; -- rx_frames = pdata->rx_frames; -- - /* Initialize all descriptors */ - for (i = 0; i < ring->rdesc_count; i++) { - rdata = XGBE_GET_DESC_DATA(ring, i); - -- /* Set interrupt on completion bit as appropriate */ -- if (rx_coalesce && (!rx_frames || ((i + 1) % rx_frames))) -- rdata->interrupt = 0; -- else -- rdata->interrupt = 1; -- - /* Initialize Rx descriptor */ -- xgbe_rx_desc_reset(rdata); -+ xgbe_rx_desc_reset(pdata, rdata, i); - } - - /* Update the total number of Rx descriptors */ -@@ -1331,18 +1378,20 @@ static void xgbe_tx_start_xmit(struct xgbe_channel *channel, - struct xgbe_prv_data *pdata = channel->pdata; - struct xgbe_ring_data *rdata; - -+ /* Make sure everything is written before the register write */ -+ wmb(); -+ - /* Issue a poll command to Tx DMA by writing address - * of next immediate free descriptor */ - rdata = XGBE_GET_DESC_DATA(ring, ring->cur); - XGMAC_DMA_IOWRITE(channel, DMA_CH_TDTR_LO, - lower_32_bits(rdata->rdesc_dma)); - -- /* Start the Tx coalescing timer */ -+ /* Start the Tx timer */ - if (pdata->tx_usecs && !channel->tx_timer_active) { - channel->tx_timer_active = 1; -- hrtimer_start(&channel->tx_timer, -- ktime_set(0, pdata->tx_usecs * NSEC_PER_USEC), -- HRTIMER_MODE_REL); -+ mod_timer(&channel->tx_timer, -+ jiffies + usecs_to_jiffies(pdata->tx_usecs)); - } - - ring->tx.xmit_more = 0; -@@ -1359,6 +1408,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) - unsigned int tso_context, vlan_context; - unsigned int tx_set_ic; - int start_index = ring->cur; -+ int cur_index = ring->cur; - int i; - - DBGPR("-->xgbe_dev_xmit\n"); -@@ -1401,7 +1451,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) - else - tx_set_ic = 0; - -- rdata = XGBE_GET_DESC_DATA(ring, ring->cur); -+ rdata = XGBE_GET_DESC_DATA(ring, cur_index); - rdesc = rdata->rdesc; - - /* Create a context descriptor if this is a TSO packet */ -@@ -1444,8 +1494,8 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) - ring->tx.cur_vlan_ctag = packet->vlan_ctag; - } - -- ring->cur++; -- rdata = XGBE_GET_DESC_DATA(ring, ring->cur); -+ cur_index++; -+ rdata = XGBE_GET_DESC_DATA(ring, cur_index); - rdesc = rdata->rdesc; - } - -@@ -1473,7 +1523,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) - XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CTXT, 0); - - /* Set OWN bit if not the first descriptor */ -- if (ring->cur != start_index) -+ if (cur_index != start_index) - XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1); - - if (tso) { -@@ -1497,9 +1547,9 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) - packet->length); - } - -- for (i = ring->cur - start_index + 1; i < packet->rdesc_count; i++) { -- ring->cur++; -- rdata = XGBE_GET_DESC_DATA(ring, ring->cur); -+ for (i = cur_index - start_index + 1; i < packet->rdesc_count; i++) { -+ cur_index++; -+ rdata = XGBE_GET_DESC_DATA(ring, cur_index); - rdesc = rdata->rdesc; - - /* Update buffer address */ -@@ -1537,7 +1587,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) - * is written to the descriptor(s) before setting the OWN bit - * for the first descriptor - */ -- wmb(); -+ dma_wmb(); - - /* Set OWN bit for the first descriptor */ - rdata = XGBE_GET_DESC_DATA(ring, start_index); -@@ -1549,9 +1599,9 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) - #endif - - /* Make sure ownership is written to the descriptor */ -- wmb(); -+ dma_wmb(); - -- ring->cur++; -+ ring->cur = cur_index + 1; - if (!packet->skb->xmit_more || - netif_xmit_stopped(netdev_get_tx_queue(pdata->netdev, - channel->queue_index))) -@@ -1585,7 +1635,7 @@ static int xgbe_dev_read(struct xgbe_channel *channel) - return 1; - - /* Make sure descriptor fields are read after reading the OWN bit */ -- rmb(); -+ dma_rmb(); - - #ifdef XGMAC_ENABLE_RX_DESC_DUMP - xgbe_dump_rx_desc(ring, rdesc, ring->cur); -@@ -1976,7 +2026,8 @@ static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata) - for (i = 0; i < pdata->tx_q_count; i++) - XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TQS, fifo_size); - -- netdev_notice(pdata->netdev, "%d Tx queues, %d byte fifo per queue\n", -+ netdev_notice(pdata->netdev, -+ "%d Tx hardware queues, %d byte fifo per queue\n", - pdata->tx_q_count, ((fifo_size + 1) * 256)); - } - -@@ -1991,7 +2042,8 @@ static void xgbe_config_rx_fifo_size(struct xgbe_prv_data *pdata) - for (i = 0; i < pdata->rx_q_count; i++) - XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RQS, fifo_size); - -- netdev_notice(pdata->netdev, "%d Rx queues, %d byte fifo per queue\n", -+ netdev_notice(pdata->netdev, -+ "%d Rx hardware queues, %d byte fifo per queue\n", - pdata->rx_q_count, ((fifo_size + 1) * 256)); - } - -@@ -2107,6 +2159,23 @@ static void xgbe_config_jumbo_enable(struct xgbe_prv_data *pdata) - XGMAC_IOWRITE_BITS(pdata, MAC_RCR, JE, val); - } - -+static void xgbe_config_mac_speed(struct xgbe_prv_data *pdata) -+{ -+ switch (pdata->phy_speed) { -+ case SPEED_10000: -+ xgbe_set_xgmii_speed(pdata); -+ break; -+ -+ case SPEED_2500: -+ xgbe_set_gmii_2500_speed(pdata); -+ break; -+ -+ case SPEED_1000: -+ xgbe_set_gmii_speed(pdata); -+ break; -+ } -+} -+ - static void xgbe_config_checksum_offload(struct xgbe_prv_data *pdata) - { - if (pdata->netdev->features & NETIF_F_RXCSUM) -@@ -2755,8 +2824,10 @@ static int xgbe_init(struct xgbe_prv_data *pdata) - * Initialize MAC related features - */ - xgbe_config_mac_address(pdata); -+ xgbe_config_rx_mode(pdata); - xgbe_config_jumbo_enable(pdata); - xgbe_config_flow_control(pdata); -+ xgbe_config_mac_speed(pdata); - xgbe_config_checksum_offload(pdata); - xgbe_config_vlan_support(pdata); - xgbe_config_mmc(pdata); -@@ -2773,10 +2844,8 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if) - - hw_if->tx_complete = xgbe_tx_complete; - -- hw_if->set_promiscuous_mode = xgbe_set_promiscuous_mode; -- hw_if->set_all_multicast_mode = xgbe_set_all_multicast_mode; -- hw_if->add_mac_addresses = xgbe_add_mac_addresses; - hw_if->set_mac_address = xgbe_set_mac_address; -+ hw_if->config_rx_mode = xgbe_config_rx_mode; - - hw_if->enable_rx_csum = xgbe_enable_rx_csum; - hw_if->disable_rx_csum = xgbe_disable_rx_csum; -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c -index e5ffb2c..343bf6a 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c -@@ -129,7 +129,6 @@ - - static int xgbe_one_poll(struct napi_struct *, int); - static int xgbe_all_poll(struct napi_struct *, int); --static void xgbe_set_rx_mode(struct net_device *); - - static int xgbe_alloc_channels(struct xgbe_prv_data *pdata) - { -@@ -225,6 +224,11 @@ static inline unsigned int xgbe_tx_avail_desc(struct xgbe_ring *ring) - return (ring->rdesc_count - (ring->cur - ring->dirty)); - } - -+static inline unsigned int xgbe_rx_dirty_desc(struct xgbe_ring *ring) -+{ -+ return (ring->cur - ring->dirty); -+} -+ - static int xgbe_maybe_stop_tx_queue(struct xgbe_channel *channel, - struct xgbe_ring *ring, unsigned int count) - { -@@ -337,12 +341,13 @@ static irqreturn_t xgbe_isr(int irq, void *data) - dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR); - DBGPR(" DMA_CH%u_ISR = %08x\n", i, dma_ch_isr); - -- /* If we get a TI or RI interrupt that means per channel DMA -- * interrupts are not enabled, so we use the private data napi -- * structure, not the per channel napi structure -+ /* The TI or RI interrupt bits may still be set even if using -+ * per channel DMA interrupts. Check to be sure those are not -+ * enabled before using the private data napi structure. - */ -- if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, TI) || -- XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RI)) { -+ if (!pdata->per_channel_irq && -+ (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, TI) || -+ XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RI))) { - if (napi_schedule_prep(&pdata->napi)) { - /* Disable Tx and Rx interrupts */ - xgbe_disable_rx_tx_ints(pdata); -@@ -405,26 +410,20 @@ static irqreturn_t xgbe_dma_isr(int irq, void *data) - return IRQ_HANDLED; - } - --static enum hrtimer_restart xgbe_tx_timer(struct hrtimer *timer) -+static void xgbe_tx_timer(unsigned long data) - { -- struct xgbe_channel *channel = container_of(timer, -- struct xgbe_channel, -- tx_timer); -- struct xgbe_ring *ring = channel->tx_ring; -+ struct xgbe_channel *channel = (struct xgbe_channel *)data; - struct xgbe_prv_data *pdata = channel->pdata; - struct napi_struct *napi; -- unsigned long flags; - - DBGPR("-->xgbe_tx_timer\n"); - - napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; - -- spin_lock_irqsave(&ring->lock, flags); -- - if (napi_schedule_prep(napi)) { - /* Disable Tx and Rx interrupts */ - if (pdata->per_channel_irq) -- disable_irq(channel->dma_irq); -+ disable_irq_nosync(channel->dma_irq); - else - xgbe_disable_rx_tx_ints(pdata); - -@@ -434,11 +433,7 @@ static enum hrtimer_restart xgbe_tx_timer(struct hrtimer *timer) - - channel->tx_timer_active = 0; - -- spin_unlock_irqrestore(&ring->lock, flags); -- - DBGPR("<--xgbe_tx_timer\n"); -- -- return HRTIMER_NORESTART; - } - - static void xgbe_init_tx_timers(struct xgbe_prv_data *pdata) -@@ -454,9 +449,8 @@ static void xgbe_init_tx_timers(struct xgbe_prv_data *pdata) - break; - - DBGPR(" %s adding tx timer\n", channel->name); -- hrtimer_init(&channel->tx_timer, CLOCK_MONOTONIC, -- HRTIMER_MODE_REL); -- channel->tx_timer.function = xgbe_tx_timer; -+ setup_timer(&channel->tx_timer, xgbe_tx_timer, -+ (unsigned long)channel); - } - - DBGPR("<--xgbe_init_tx_timers\n"); -@@ -475,8 +469,7 @@ static void xgbe_stop_tx_timers(struct xgbe_prv_data *pdata) - break; - - DBGPR(" %s deleting tx timer\n", channel->name); -- channel->tx_timer_active = 0; -- hrtimer_cancel(&channel->tx_timer); -+ del_timer_sync(&channel->tx_timer); - } - - DBGPR("<--xgbe_stop_tx_timers\n"); -@@ -519,6 +512,7 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) - RXFIFOSIZE); - hw_feat->tx_fifo_size = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, - TXFIFOSIZE); -+ hw_feat->dma_width = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, ADDR64); - hw_feat->dcb = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, DCBEN); - hw_feat->sph = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, SPHEN); - hw_feat->tso = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, TSOEN); -@@ -553,6 +547,21 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) - break; - } - -+ /* Translate the address width setting into actual number */ -+ switch (hw_feat->dma_width) { -+ case 0: -+ hw_feat->dma_width = 32; -+ break; -+ case 1: -+ hw_feat->dma_width = 40; -+ break; -+ case 2: -+ hw_feat->dma_width = 48; -+ break; -+ default: -+ hw_feat->dma_width = 32; -+ } -+ - /* The Queue, Channel and TC counts are zero based so increment them - * to get the actual number - */ -@@ -609,6 +618,68 @@ static void xgbe_napi_disable(struct xgbe_prv_data *pdata, unsigned int del) - } - } - -+static int xgbe_request_irqs(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ struct net_device *netdev = pdata->netdev; -+ unsigned int i; -+ int ret; -+ -+ ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0, -+ netdev->name, pdata); -+ if (ret) { -+ netdev_alert(netdev, "error requesting irq %d\n", -+ pdata->dev_irq); -+ return ret; -+ } -+ -+ if (!pdata->per_channel_irq) -+ return 0; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) { -+ snprintf(channel->dma_irq_name, -+ sizeof(channel->dma_irq_name) - 1, -+ "%s-TxRx-%u", netdev_name(netdev), -+ channel->queue_index); -+ -+ ret = devm_request_irq(pdata->dev, channel->dma_irq, -+ xgbe_dma_isr, 0, -+ channel->dma_irq_name, channel); -+ if (ret) { -+ netdev_alert(netdev, "error requesting irq %d\n", -+ channel->dma_irq); -+ goto err_irq; -+ } -+ } -+ -+ return 0; -+ -+err_irq: -+ /* Using an unsigned int, 'i' will go to UINT_MAX and exit */ -+ for (i--, channel--; i < pdata->channel_count; i--, channel--) -+ devm_free_irq(pdata->dev, channel->dma_irq, channel); -+ -+ devm_free_irq(pdata->dev, pdata->dev_irq, pdata); -+ -+ return ret; -+} -+ -+static void xgbe_free_irqs(struct xgbe_prv_data *pdata) -+{ -+ struct xgbe_channel *channel; -+ unsigned int i; -+ -+ devm_free_irq(pdata->dev, pdata->dev_irq, pdata); -+ -+ if (!pdata->per_channel_irq) -+ return; -+ -+ channel = pdata->channel; -+ for (i = 0; i < pdata->channel_count; i++, channel++) -+ devm_free_irq(pdata->dev, channel->dma_irq, channel); -+} -+ - void xgbe_init_tx_coalesce(struct xgbe_prv_data *pdata) - { - struct xgbe_hw_if *hw_if = &pdata->hw_if; -@@ -630,6 +701,7 @@ void xgbe_init_rx_coalesce(struct xgbe_prv_data *pdata) - DBGPR("-->xgbe_init_rx_coalesce\n"); - - pdata->rx_riwt = hw_if->usec_to_riwt(pdata, XGMAC_INIT_DMA_RX_USECS); -+ pdata->rx_usecs = XGMAC_INIT_DMA_RX_USECS; - pdata->rx_frames = XGMAC_INIT_DMA_RX_FRAMES; - - hw_if->config_rx_coalesce(pdata); -@@ -694,7 +766,7 @@ static void xgbe_adjust_link(struct net_device *netdev) - struct phy_device *phydev = pdata->phydev; - int new_state = 0; - -- if (phydev == NULL) -+ if (!phydev) - return; - - if (phydev->link) { -@@ -810,20 +882,20 @@ int xgbe_powerdown(struct net_device *netdev, unsigned int caller) - return -EINVAL; - } - -- phy_stop(pdata->phydev); -- - spin_lock_irqsave(&pdata->lock, flags); - - if (caller == XGMAC_DRIVER_CONTEXT) - netif_device_detach(netdev); - - netif_tx_stop_all_queues(netdev); -- xgbe_napi_disable(pdata, 0); - -- /* Powerdown Tx/Rx */ - hw_if->powerdown_tx(pdata); - hw_if->powerdown_rx(pdata); - -+ xgbe_napi_disable(pdata, 0); -+ -+ phy_stop(pdata->phydev); -+ - pdata->power_down = 1; - - spin_unlock_irqrestore(&pdata->lock, flags); -@@ -854,14 +926,14 @@ int xgbe_powerup(struct net_device *netdev, unsigned int caller) - - phy_start(pdata->phydev); - -- /* Enable Tx/Rx */ -+ xgbe_napi_enable(pdata, 0); -+ - hw_if->powerup_tx(pdata); - hw_if->powerup_rx(pdata); - - if (caller == XGMAC_DRIVER_CONTEXT) - netif_device_attach(netdev); - -- xgbe_napi_enable(pdata, 0); - netif_tx_start_all_queues(netdev); - - spin_unlock_irqrestore(&pdata->lock, flags); -@@ -875,26 +947,39 @@ static int xgbe_start(struct xgbe_prv_data *pdata) - { - struct xgbe_hw_if *hw_if = &pdata->hw_if; - struct net_device *netdev = pdata->netdev; -+ int ret; - - DBGPR("-->xgbe_start\n"); - -- xgbe_set_rx_mode(netdev); -- - hw_if->init(pdata); - - phy_start(pdata->phydev); - -+ xgbe_napi_enable(pdata, 1); -+ -+ ret = xgbe_request_irqs(pdata); -+ if (ret) -+ goto err_napi; -+ - hw_if->enable_tx(pdata); - hw_if->enable_rx(pdata); - - xgbe_init_tx_timers(pdata); - -- xgbe_napi_enable(pdata, 1); - netif_tx_start_all_queues(netdev); - - DBGPR("<--xgbe_start\n"); - - return 0; -+ -+err_napi: -+ xgbe_napi_disable(pdata, 1); -+ -+ phy_stop(pdata->phydev); -+ -+ hw_if->exit(pdata); -+ -+ return ret; - } - - static void xgbe_stop(struct xgbe_prv_data *pdata) -@@ -907,16 +992,21 @@ static void xgbe_stop(struct xgbe_prv_data *pdata) - - DBGPR("-->xgbe_stop\n"); - -- phy_stop(pdata->phydev); -- - netif_tx_stop_all_queues(netdev); -- xgbe_napi_disable(pdata, 1); - - xgbe_stop_tx_timers(pdata); - - hw_if->disable_tx(pdata); - hw_if->disable_rx(pdata); - -+ xgbe_free_irqs(pdata); -+ -+ xgbe_napi_disable(pdata, 1); -+ -+ phy_stop(pdata->phydev); -+ -+ hw_if->exit(pdata); -+ - channel = pdata->channel; - for (i = 0; i < pdata->channel_count; i++, channel++) { - if (!channel->tx_ring) -@@ -929,12 +1019,8 @@ static void xgbe_stop(struct xgbe_prv_data *pdata) - DBGPR("<--xgbe_stop\n"); - } - --static void xgbe_restart_dev(struct xgbe_prv_data *pdata, unsigned int reset) -+static void xgbe_restart_dev(struct xgbe_prv_data *pdata) - { -- struct xgbe_channel *channel; -- struct xgbe_hw_if *hw_if = &pdata->hw_if; -- unsigned int i; -- - DBGPR("-->xgbe_restart_dev\n"); - - /* If not running, "restart" will happen on open */ -@@ -942,20 +1028,10 @@ static void xgbe_restart_dev(struct xgbe_prv_data *pdata, unsigned int reset) - return; - - xgbe_stop(pdata); -- synchronize_irq(pdata->dev_irq); -- if (pdata->per_channel_irq) { -- channel = pdata->channel; -- for (i = 0; i < pdata->channel_count; i++, channel++) -- synchronize_irq(channel->dma_irq); -- } - - xgbe_free_tx_data(pdata); - xgbe_free_rx_data(pdata); - -- /* Issue software reset to device if requested */ -- if (reset) -- hw_if->exit(pdata); -- - xgbe_start(pdata); - - DBGPR("<--xgbe_restart_dev\n"); -@@ -969,7 +1045,7 @@ static void xgbe_restart(struct work_struct *work) - - rtnl_lock(); - -- xgbe_restart_dev(pdata, 1); -+ xgbe_restart_dev(pdata); - - rtnl_unlock(); - } -@@ -1284,10 +1360,7 @@ static void xgbe_packet_info(struct xgbe_prv_data *pdata, - static int xgbe_open(struct net_device *netdev) - { - struct xgbe_prv_data *pdata = netdev_priv(netdev); -- struct xgbe_hw_if *hw_if = &pdata->hw_if; - struct xgbe_desc_if *desc_if = &pdata->desc_if; -- struct xgbe_channel *channel = NULL; -- unsigned int i = 0; - int ret; - - DBGPR("-->xgbe_open\n"); -@@ -1330,55 +1403,14 @@ static int xgbe_open(struct net_device *netdev) - INIT_WORK(&pdata->restart_work, xgbe_restart); - INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp); - -- /* Request interrupts */ -- ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0, -- netdev->name, pdata); -- if (ret) { -- netdev_alert(netdev, "error requesting irq %d\n", -- pdata->dev_irq); -- goto err_rings; -- } -- -- if (pdata->per_channel_irq) { -- channel = pdata->channel; -- for (i = 0; i < pdata->channel_count; i++, channel++) { -- snprintf(channel->dma_irq_name, -- sizeof(channel->dma_irq_name) - 1, -- "%s-TxRx-%u", netdev_name(netdev), -- channel->queue_index); -- -- ret = devm_request_irq(pdata->dev, channel->dma_irq, -- xgbe_dma_isr, 0, -- channel->dma_irq_name, channel); -- if (ret) { -- netdev_alert(netdev, -- "error requesting irq %d\n", -- channel->dma_irq); -- goto err_irq; -- } -- } -- } -- - ret = xgbe_start(pdata); - if (ret) -- goto err_start; -+ goto err_rings; - - DBGPR("<--xgbe_open\n"); - - return 0; - --err_start: -- hw_if->exit(pdata); -- --err_irq: -- if (pdata->per_channel_irq) { -- /* Using an unsigned int, 'i' will go to UINT_MAX and exit */ -- for (i--, channel--; i < pdata->channel_count; i--, channel--) -- devm_free_irq(pdata->dev, channel->dma_irq, channel); -- } -- -- devm_free_irq(pdata->dev, pdata->dev_irq, pdata); -- - err_rings: - desc_if->free_ring_resources(pdata); - -@@ -1400,30 +1432,16 @@ err_phy_init: - static int xgbe_close(struct net_device *netdev) - { - struct xgbe_prv_data *pdata = netdev_priv(netdev); -- struct xgbe_hw_if *hw_if = &pdata->hw_if; - struct xgbe_desc_if *desc_if = &pdata->desc_if; -- struct xgbe_channel *channel; -- unsigned int i; - - DBGPR("-->xgbe_close\n"); - - /* Stop the device */ - xgbe_stop(pdata); - -- /* Issue software reset to device */ -- hw_if->exit(pdata); -- - /* Free the ring descriptors and buffers */ - desc_if->free_ring_resources(pdata); - -- /* Release the interrupts */ -- devm_free_irq(pdata->dev, pdata->dev_irq, pdata); -- if (pdata->per_channel_irq) { -- channel = pdata->channel; -- for (i = 0; i < pdata->channel_count; i++, channel++) -- devm_free_irq(pdata->dev, channel->dma_irq, channel); -- } -- - /* Free the channel and ring structures */ - xgbe_free_channels(pdata); - -@@ -1448,7 +1466,6 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev) - struct xgbe_ring *ring; - struct xgbe_packet_data *packet; - struct netdev_queue *txq; -- unsigned long flags; - int ret; - - DBGPR("-->xgbe_xmit: skb->len = %d\n", skb->len); -@@ -1460,8 +1477,6 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev) - - ret = NETDEV_TX_OK; - -- spin_lock_irqsave(&ring->lock, flags); -- - if (skb->len == 0) { - netdev_err(netdev, "empty skb received from stack\n"); - dev_kfree_skb_any(skb); -@@ -1508,10 +1523,6 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev) - ret = NETDEV_TX_OK; - - tx_netdev_return: -- spin_unlock_irqrestore(&ring->lock, flags); -- -- DBGPR("<--xgbe_xmit\n"); -- - return ret; - } - -@@ -1519,17 +1530,10 @@ static void xgbe_set_rx_mode(struct net_device *netdev) - { - struct xgbe_prv_data *pdata = netdev_priv(netdev); - struct xgbe_hw_if *hw_if = &pdata->hw_if; -- unsigned int pr_mode, am_mode; - - DBGPR("-->xgbe_set_rx_mode\n"); - -- pr_mode = ((netdev->flags & IFF_PROMISC) != 0); -- am_mode = ((netdev->flags & IFF_ALLMULTI) != 0); -- -- hw_if->set_promiscuous_mode(pdata, pr_mode); -- hw_if->set_all_multicast_mode(pdata, am_mode); -- -- hw_if->add_mac_addresses(pdata); -+ hw_if->config_rx_mode(pdata); - - DBGPR("<--xgbe_set_rx_mode\n"); - } -@@ -1589,13 +1593,21 @@ static int xgbe_change_mtu(struct net_device *netdev, int mtu) - pdata->rx_buf_size = ret; - netdev->mtu = mtu; - -- xgbe_restart_dev(pdata, 0); -+ xgbe_restart_dev(pdata); - - DBGPR("<--xgbe_change_mtu\n"); - - return 0; - } - -+static void xgbe_tx_timeout(struct net_device *netdev) -+{ -+ struct xgbe_prv_data *pdata = netdev_priv(netdev); -+ -+ netdev_warn(netdev, "tx timeout, device restarting\n"); -+ schedule_work(&pdata->restart_work); -+} -+ - static struct rtnl_link_stats64 *xgbe_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 *s) - { -@@ -1760,6 +1772,7 @@ static const struct net_device_ops xgbe_netdev_ops = { - .ndo_validate_addr = eth_validate_addr, - .ndo_do_ioctl = xgbe_ioctl, - .ndo_change_mtu = xgbe_change_mtu, -+ .ndo_tx_timeout = xgbe_tx_timeout, - .ndo_get_stats64 = xgbe_get_stats64, - .ndo_vlan_rx_add_vid = xgbe_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = xgbe_vlan_rx_kill_vid, -@@ -1778,29 +1791,44 @@ struct net_device_ops *xgbe_get_netdev_ops(void) - static void xgbe_rx_refresh(struct xgbe_channel *channel) - { - struct xgbe_prv_data *pdata = channel->pdata; -+ struct xgbe_hw_if *hw_if = &pdata->hw_if; - struct xgbe_desc_if *desc_if = &pdata->desc_if; - struct xgbe_ring *ring = channel->rx_ring; - struct xgbe_ring_data *rdata; - -- desc_if->realloc_rx_buffer(channel); -+ while (ring->dirty != ring->cur) { -+ rdata = XGBE_GET_DESC_DATA(ring, ring->dirty); -+ -+ /* Reset rdata values */ -+ desc_if->unmap_rdata(pdata, rdata); -+ -+ if (desc_if->map_rx_buffer(pdata, ring, rdata)) -+ break; -+ -+ hw_if->rx_desc_reset(pdata, rdata, ring->dirty); -+ -+ ring->dirty++; -+ } -+ -+ /* Make sure everything is written before the register write */ -+ wmb(); - - /* Update the Rx Tail Pointer Register with address of - * the last cleaned entry */ -- rdata = XGBE_GET_DESC_DATA(ring, ring->rx.realloc_index - 1); -+ rdata = XGBE_GET_DESC_DATA(ring, ring->dirty - 1); - XGMAC_DMA_IOWRITE(channel, DMA_CH_RDTR_LO, - lower_32_bits(rdata->rdesc_dma)); - } - --static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata, -+static struct sk_buff *xgbe_create_skb(struct napi_struct *napi, - struct xgbe_ring_data *rdata, - unsigned int *len) - { -- struct net_device *netdev = pdata->netdev; - struct sk_buff *skb; - u8 *packet; - unsigned int copy_len; - -- skb = netdev_alloc_skb_ip_align(netdev, rdata->rx.hdr.dma_len); -+ skb = napi_alloc_skb(napi, rdata->rx.hdr.dma_len); - if (!skb) - return NULL; - -@@ -1826,7 +1854,6 @@ static int xgbe_tx_poll(struct xgbe_channel *channel) - struct xgbe_ring_desc *rdesc; - struct net_device *netdev = pdata->netdev; - struct netdev_queue *txq; -- unsigned long flags; - int processed = 0; - unsigned int tx_packets = 0, tx_bytes = 0; - -@@ -1838,8 +1865,6 @@ static int xgbe_tx_poll(struct xgbe_channel *channel) - - txq = netdev_get_tx_queue(netdev, channel->queue_index); - -- spin_lock_irqsave(&ring->lock, flags); -- - while ((processed < XGBE_TX_DESC_MAX_PROC) && - (ring->dirty != ring->cur)) { - rdata = XGBE_GET_DESC_DATA(ring, ring->dirty); -@@ -1850,7 +1875,7 @@ static int xgbe_tx_poll(struct xgbe_channel *channel) - - /* Make sure descriptor fields are read after reading the OWN - * bit */ -- rmb(); -+ dma_rmb(); - - #ifdef XGMAC_ENABLE_TX_DESC_DUMP - xgbe_dump_tx_desc(ring, ring->dirty, 1, 0); -@@ -1870,7 +1895,7 @@ static int xgbe_tx_poll(struct xgbe_channel *channel) - } - - if (!processed) -- goto unlock; -+ return 0; - - netdev_tx_completed_queue(txq, tx_packets, tx_bytes); - -@@ -1882,9 +1907,6 @@ static int xgbe_tx_poll(struct xgbe_channel *channel) - - DBGPR("<--xgbe_tx_poll: processed=%d\n", processed); - --unlock: -- spin_unlock_irqrestore(&ring->lock, flags); -- - return processed; - } - -@@ -1936,7 +1958,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget) - read_again: - rdata = XGBE_GET_DESC_DATA(ring, ring->cur); - -- if (ring->dirty > (XGBE_RX_DESC_CNT >> 3)) -+ if (xgbe_rx_dirty_desc(ring) > (XGBE_RX_DESC_CNT >> 3)) - xgbe_rx_refresh(channel); - - if (hw_if->dev_read(channel)) -@@ -1944,7 +1966,6 @@ read_again: - - received++; - ring->cur++; -- ring->dirty++; - - incomplete = XGMAC_GET_BITS(packet->attributes, - RX_PACKET_ATTRIBUTES, -@@ -1977,7 +1998,7 @@ read_again: - rdata->rx.hdr.dma_len, - DMA_FROM_DEVICE); - -- skb = xgbe_create_skb(pdata, rdata, &put_len); -+ skb = xgbe_create_skb(napi, rdata, &put_len); - if (!skb) { - error = 1; - goto skip_data; -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c -index ebf4893..5f149e8 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c -@@ -291,7 +291,6 @@ static int xgbe_get_settings(struct net_device *netdev, - return -ENODEV; - - ret = phy_ethtool_gset(pdata->phydev, cmd); -- cmd->transceiver = XCVR_EXTERNAL; - - DBGPR("<--xgbe_get_settings\n"); - -@@ -378,18 +377,14 @@ static int xgbe_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) - { - struct xgbe_prv_data *pdata = netdev_priv(netdev); -- struct xgbe_hw_if *hw_if = &pdata->hw_if; -- unsigned int riwt; - - DBGPR("-->xgbe_get_coalesce\n"); - - memset(ec, 0, sizeof(struct ethtool_coalesce)); - -- riwt = pdata->rx_riwt; -- ec->rx_coalesce_usecs = hw_if->riwt_to_usec(pdata, riwt); -+ ec->rx_coalesce_usecs = pdata->rx_usecs; - ec->rx_max_coalesced_frames = pdata->rx_frames; - -- ec->tx_coalesce_usecs = pdata->tx_usecs; - ec->tx_max_coalesced_frames = pdata->tx_frames; - - DBGPR("<--xgbe_get_coalesce\n"); -@@ -403,13 +398,14 @@ static int xgbe_set_coalesce(struct net_device *netdev, - struct xgbe_prv_data *pdata = netdev_priv(netdev); - struct xgbe_hw_if *hw_if = &pdata->hw_if; - unsigned int rx_frames, rx_riwt, rx_usecs; -- unsigned int tx_frames, tx_usecs; -+ unsigned int tx_frames; - - DBGPR("-->xgbe_set_coalesce\n"); - - /* Check for not supported parameters */ - if ((ec->rx_coalesce_usecs_irq) || - (ec->rx_max_coalesced_frames_irq) || -+ (ec->tx_coalesce_usecs) || - (ec->tx_coalesce_usecs_irq) || - (ec->tx_max_coalesced_frames_irq) || - (ec->stats_block_coalesce_usecs) || -@@ -428,28 +424,18 @@ static int xgbe_set_coalesce(struct net_device *netdev, - (ec->rate_sample_interval)) - return -EOPNOTSUPP; - -- /* Can only change rx-frames when interface is down (see -- * rx_descriptor_init in xgbe-dev.c) -- */ -- rx_frames = pdata->rx_frames; -- if (rx_frames != ec->rx_max_coalesced_frames && netif_running(netdev)) { -- netdev_alert(netdev, -- "interface must be down to change rx-frames\n"); -- return -EINVAL; -- } -- - rx_riwt = hw_if->usec_to_riwt(pdata, ec->rx_coalesce_usecs); -+ rx_usecs = ec->rx_coalesce_usecs; - rx_frames = ec->rx_max_coalesced_frames; - - /* Use smallest possible value if conversion resulted in zero */ -- if (ec->rx_coalesce_usecs && !rx_riwt) -+ if (rx_usecs && !rx_riwt) - rx_riwt = 1; - - /* Check the bounds of values for Rx */ - if (rx_riwt > XGMAC_MAX_DMA_RIWT) { -- rx_usecs = hw_if->riwt_to_usec(pdata, XGMAC_MAX_DMA_RIWT); - netdev_alert(netdev, "rx-usec is limited to %d usecs\n", -- rx_usecs); -+ hw_if->riwt_to_usec(pdata, XGMAC_MAX_DMA_RIWT)); - return -EINVAL; - } - if (rx_frames > pdata->rx_desc_count) { -@@ -458,7 +444,6 @@ static int xgbe_set_coalesce(struct net_device *netdev, - return -EINVAL; - } - -- tx_usecs = ec->tx_coalesce_usecs; - tx_frames = ec->tx_max_coalesced_frames; - - /* Check the bounds of values for Tx */ -@@ -469,10 +454,10 @@ static int xgbe_set_coalesce(struct net_device *netdev, - } - - pdata->rx_riwt = rx_riwt; -+ pdata->rx_usecs = rx_usecs; - pdata->rx_frames = rx_frames; - hw_if->config_rx_coalesce(pdata); - -- pdata->tx_usecs = tx_usecs; - pdata->tx_frames = tx_frames; - hw_if->config_tx_coalesce(pdata); - -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c -index dbd3850..7149053 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c -@@ -123,7 +123,10 @@ - #include <linux/io.h> - #include <linux/of.h> - #include <linux/of_net.h> -+#include <linux/of_address.h> - #include <linux/clk.h> -+#include <linux/property.h> -+#include <linux/acpi.h> - - #include "xgbe.h" - #include "xgbe-common.h" -@@ -148,6 +151,7 @@ static void xgbe_default_config(struct xgbe_prv_data *pdata) - pdata->pause_autoneg = 1; - pdata->tx_pause = 1; - pdata->rx_pause = 1; -+ pdata->phy_speed = SPEED_UNKNOWN; - pdata->power_down = 0; - pdata->default_autoneg = AUTONEG_ENABLE; - pdata->default_speed = SPEED_10000; -@@ -161,6 +165,96 @@ static void xgbe_init_all_fptrs(struct xgbe_prv_data *pdata) - xgbe_init_function_ptrs_desc(&pdata->desc_if); - } - -+#ifdef CONFIG_ACPI -+static int xgbe_acpi_support(struct xgbe_prv_data *pdata) -+{ -+ struct acpi_device *adev = pdata->adev; -+ struct device *dev = pdata->dev; -+ u32 property; -+ acpi_handle handle; -+ acpi_status status; -+ unsigned long long data; -+ int cca; -+ int ret; -+ -+ /* Obtain the system clock setting */ -+ ret = device_property_read_u32(dev, XGBE_ACPI_DMA_FREQ, &property); -+ if (ret) { -+ dev_err(dev, "unable to obtain %s property\n", -+ XGBE_ACPI_DMA_FREQ); -+ return ret; -+ } -+ pdata->sysclk_rate = property; -+ -+ /* Obtain the PTP clock setting */ -+ ret = device_property_read_u32(dev, XGBE_ACPI_PTP_FREQ, &property); -+ if (ret) { -+ dev_err(dev, "unable to obtain %s property\n", -+ XGBE_ACPI_PTP_FREQ); -+ return ret; -+ } -+ pdata->ptpclk_rate = property; -+ -+ /* Retrieve the device cache coherency value */ -+ handle = adev->handle; -+ do { -+ status = acpi_evaluate_integer(handle, "_CCA", NULL, &data); -+ if (!ACPI_FAILURE(status)) { -+ cca = data; -+ break; -+ } -+ -+ status = acpi_get_parent(handle, &handle); -+ } while (!ACPI_FAILURE(status)); -+ -+ if (ACPI_FAILURE(status)) { -+ dev_err(dev, "error obtaining acpi coherency value\n"); -+ return -EINVAL; -+ } -+ pdata->coherent = !!cca; -+ -+ return 0; -+} -+#else /* CONFIG_ACPI */ -+static int xgbe_acpi_support(struct xgbe_prv_data *pdata) -+{ -+ return -EINVAL; -+} -+#endif /* CONFIG_ACPI */ -+ -+#ifdef CONFIG_OF -+static int xgbe_of_support(struct xgbe_prv_data *pdata) -+{ -+ struct device *dev = pdata->dev; -+ -+ /* Obtain the system clock setting */ -+ pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK); -+ if (IS_ERR(pdata->sysclk)) { -+ dev_err(dev, "dma devm_clk_get failed\n"); -+ return PTR_ERR(pdata->sysclk); -+ } -+ pdata->sysclk_rate = clk_get_rate(pdata->sysclk); -+ -+ /* Obtain the PTP clock setting */ -+ pdata->ptpclk = devm_clk_get(dev, XGBE_PTP_CLOCK); -+ if (IS_ERR(pdata->ptpclk)) { -+ dev_err(dev, "ptp devm_clk_get failed\n"); -+ return PTR_ERR(pdata->ptpclk); -+ } -+ pdata->ptpclk_rate = clk_get_rate(pdata->ptpclk); -+ -+ /* Retrieve the device cache coherency value */ -+ pdata->coherent = of_dma_is_coherent(dev->of_node); -+ -+ return 0; -+} -+#else /* CONFIG_OF */ -+static int xgbe_of_support(struct xgbe_prv_data *pdata) -+{ -+ return -EINVAL; -+} -+#endif /*CONFIG_OF */ -+ - static int xgbe_probe(struct platform_device *pdev) - { - struct xgbe_prv_data *pdata; -@@ -169,7 +263,7 @@ static int xgbe_probe(struct platform_device *pdev) - struct net_device *netdev; - struct device *dev = &pdev->dev; - struct resource *res; -- const u8 *mac_addr; -+ const char *phy_mode; - unsigned int i; - int ret; - -@@ -186,6 +280,7 @@ static int xgbe_probe(struct platform_device *pdev) - pdata = netdev_priv(netdev); - pdata->netdev = netdev; - pdata->pdev = pdev; -+ pdata->adev = ACPI_COMPANION(dev); - pdata->dev = dev; - platform_set_drvdata(pdev, netdev); - -@@ -194,6 +289,9 @@ static int xgbe_probe(struct platform_device *pdev) - mutex_init(&pdata->rss_mutex); - spin_lock_init(&pdata->tstamp_lock); - -+ /* Check if we should use ACPI or DT */ -+ pdata->use_acpi = (!pdata->adev || acpi_disabled) ? 0 : 1; -+ - /* Set and validate the number of descriptors for a ring */ - BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_TX_DESC_CNT); - pdata->tx_desc_count = XGBE_TX_DESC_CNT; -@@ -212,22 +310,6 @@ static int xgbe_probe(struct platform_device *pdev) - goto err_io; - } - -- /* Obtain the system clock setting */ -- pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK); -- if (IS_ERR(pdata->sysclk)) { -- dev_err(dev, "dma devm_clk_get failed\n"); -- ret = PTR_ERR(pdata->sysclk); -- goto err_io; -- } -- -- /* Obtain the PTP clock setting */ -- pdata->ptpclk = devm_clk_get(dev, XGBE_PTP_CLOCK); -- if (IS_ERR(pdata->ptpclk)) { -- dev_err(dev, "ptp devm_clk_get failed\n"); -- ret = PTR_ERR(pdata->ptpclk); -- goto err_io; -- } -- - /* Obtain the mmio areas for the device */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pdata->xgmac_regs = devm_ioremap_resource(dev, res); -@@ -247,16 +329,42 @@ static int xgbe_probe(struct platform_device *pdev) - } - DBGPR(" xpcs_regs = %p\n", pdata->xpcs_regs); - -- /* Set the DMA mask */ -- if (!dev->dma_mask) -- dev->dma_mask = &dev->coherent_dma_mask; -- ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40)); -- if (ret) { -- dev_err(dev, "dma_set_mask_and_coherent failed\n"); -+ /* Retrieve the MAC address */ -+ ret = device_property_read_u8_array(dev, XGBE_MAC_ADDR_PROPERTY, -+ pdata->mac_addr, -+ sizeof(pdata->mac_addr)); -+ if (ret || !is_valid_ether_addr(pdata->mac_addr)) { -+ dev_err(dev, "invalid %s property\n", XGBE_MAC_ADDR_PROPERTY); -+ if (!ret) -+ ret = -EINVAL; - goto err_io; - } - -- if (of_property_read_bool(dev->of_node, "dma-coherent")) { -+ /* Retrieve the PHY mode - it must be "xgmii" */ -+ ret = device_property_read_string(dev, XGBE_PHY_MODE_PROPERTY, -+ &phy_mode); -+ if (ret || strcmp(phy_mode, phy_modes(PHY_INTERFACE_MODE_XGMII))) { -+ dev_err(dev, "invalid %s property\n", XGBE_PHY_MODE_PROPERTY); -+ if (!ret) -+ ret = -EINVAL; -+ goto err_io; -+ } -+ pdata->phy_mode = PHY_INTERFACE_MODE_XGMII; -+ -+ /* Check for per channel interrupt support */ -+ if (device_property_present(dev, XGBE_DMA_IRQS_PROPERTY)) -+ pdata->per_channel_irq = 1; -+ -+ /* Obtain device settings unique to ACPI/OF */ -+ if (pdata->use_acpi) -+ ret = xgbe_acpi_support(pdata); -+ else -+ ret = xgbe_of_support(pdata); -+ if (ret) -+ goto err_io; -+ -+ /* Set the DMA coherency values */ -+ if (pdata->coherent) { - pdata->axdomain = XGBE_DMA_OS_AXDOMAIN; - pdata->arcache = XGBE_DMA_OS_ARCACHE; - pdata->awcache = XGBE_DMA_OS_AWCACHE; -@@ -266,10 +374,7 @@ static int xgbe_probe(struct platform_device *pdev) - pdata->awcache = XGBE_DMA_SYS_AWCACHE; - } - -- /* Check for per channel interrupt support */ -- if (of_property_read_bool(dev->of_node, XGBE_DMA_IRQS)) -- pdata->per_channel_irq = 1; -- -+ /* Get the device interrupt */ - ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "platform_get_irq 0 failed\n"); -@@ -279,6 +384,7 @@ static int xgbe_probe(struct platform_device *pdev) - - netdev->irq = pdata->dev_irq; - netdev->base_addr = (unsigned long)pdata->xgmac_regs; -+ memcpy(netdev->dev_addr, pdata->mac_addr, netdev->addr_len); - - /* Set all the function pointers */ - xgbe_init_all_fptrs(pdata); -@@ -291,26 +397,19 @@ static int xgbe_probe(struct platform_device *pdev) - /* Populate the hardware features */ - xgbe_get_all_hw_features(pdata); - -- /* Retrieve the MAC address */ -- mac_addr = of_get_mac_address(dev->of_node); -- if (!mac_addr) { -- dev_err(dev, "invalid mac address for this device\n"); -- ret = -EINVAL; -- goto err_io; -- } -- memcpy(netdev->dev_addr, mac_addr, netdev->addr_len); -+ /* Set default configuration data */ -+ xgbe_default_config(pdata); - -- /* Retrieve the PHY mode - it must be "xgmii" */ -- pdata->phy_mode = of_get_phy_mode(dev->of_node); -- if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) { -- dev_err(dev, "invalid phy-mode specified for this device\n"); -- ret = -EINVAL; -+ /* Set the DMA mask */ -+ if (!dev->dma_mask) -+ dev->dma_mask = &dev->coherent_dma_mask; -+ ret = dma_set_mask_and_coherent(dev, -+ DMA_BIT_MASK(pdata->hw_feat.dma_width)); -+ if (ret) { -+ dev_err(dev, "dma_set_mask_and_coherent failed\n"); - goto err_io; - } - -- /* Set default configuration data */ -- xgbe_default_config(pdata); -- - /* Calculate the number of Tx and Rx rings to be created - * -Tx (DMA) Channels map 1-to-1 to Tx Queues so set - * the number of Tx queues to the number of Tx channels -@@ -392,6 +491,9 @@ static int xgbe_probe(struct platform_device *pdev) - - netdev->priv_flags |= IFF_UNICAST_FLT; - -+ /* Use default watchdog timeout */ -+ netdev->watchdog_timeo = 0; -+ - xgbe_init_rx_coalesce(pdata); - xgbe_init_tx_coalesce(pdata); - -@@ -491,18 +593,35 @@ static int xgbe_resume(struct device *dev) - } - #endif /* CONFIG_PM */ - -+#ifdef CONFIG_ACPI -+static const struct acpi_device_id xgbe_acpi_match[] = { -+ { "AMDI8001", 0 }, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(acpi, xgbe_acpi_match); -+#endif -+ -+#ifdef CONFIG_OF - static const struct of_device_id xgbe_of_match[] = { - { .compatible = "amd,xgbe-seattle-v1a", }, - {}, - }; - - MODULE_DEVICE_TABLE(of, xgbe_of_match); -+#endif -+ - static SIMPLE_DEV_PM_OPS(xgbe_pm_ops, xgbe_suspend, xgbe_resume); - - static struct platform_driver xgbe_driver = { - .driver = { - .name = "amd-xgbe", -+#ifdef CONFIG_ACPI -+ .acpi_match_table = xgbe_acpi_match, -+#endif -+#ifdef CONFIG_OF - .of_match_table = xgbe_of_match, -+#endif - .pm = &xgbe_pm_ops, - }, - .probe = xgbe_probe, -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c -index 363b210..59e267f 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c -@@ -205,25 +205,16 @@ void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata) - - int xgbe_mdio_register(struct xgbe_prv_data *pdata) - { -- struct device_node *phy_node; - struct mii_bus *mii; - struct phy_device *phydev; - int ret = 0; - - DBGPR("-->xgbe_mdio_register\n"); - -- /* Retrieve the phy-handle */ -- phy_node = of_parse_phandle(pdata->dev->of_node, "phy-handle", 0); -- if (!phy_node) { -- dev_err(pdata->dev, "unable to parse phy-handle\n"); -- return -EINVAL; -- } -- - mii = mdiobus_alloc(); -- if (mii == NULL) { -+ if (!mii) { - dev_err(pdata->dev, "mdiobus_alloc failed\n"); -- ret = -ENOMEM; -- goto err_node_get; -+ return -ENOMEM; - } - - /* Register on the MDIO bus (don't probe any PHYs) */ -@@ -252,18 +243,19 @@ int xgbe_mdio_register(struct xgbe_prv_data *pdata) - request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, - MDIO_ID_ARGS(phydev->c45_ids.device_ids[MDIO_MMD_PCS])); - -- of_node_get(phy_node); -- phydev->dev.of_node = phy_node; - ret = phy_device_register(phydev); - if (ret) { - dev_err(pdata->dev, "phy_device_register failed\n"); -- of_node_put(phy_node); -+ goto err_phy_device; -+ } -+ if (!phydev->dev.driver) { -+ dev_err(pdata->dev, "phy driver probe failed\n"); -+ ret = -EIO; - goto err_phy_device; - } - - /* Add a reference to the PHY driver so it can't be unloaded */ -- pdata->phy_module = phydev->dev.driver ? -- phydev->dev.driver->owner : NULL; -+ pdata->phy_module = phydev->dev.driver->owner; - if (!try_module_get(pdata->phy_module)) { - dev_err(pdata->dev, "try_module_get failed\n"); - ret = -EIO; -@@ -283,8 +275,6 @@ int xgbe_mdio_register(struct xgbe_prv_data *pdata) - - pdata->phydev = phydev; - -- of_node_put(phy_node); -- - DBGPHY_REGS(pdata); - - DBGPR("<--xgbe_mdio_register\n"); -@@ -300,9 +290,6 @@ err_mdiobus_register: - err_mdiobus_alloc: - mdiobus_free(mii); - --err_node_get: -- of_node_put(phy_node); -- - return ret; - } - -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c -index a1bf9d1c..f0d0ac6 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c -+++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c -@@ -171,21 +171,15 @@ static int xgbe_adjtime(struct ptp_clock_info *info, s64 delta) - struct xgbe_prv_data, - ptp_clock_info); - unsigned long flags; -- u64 nsec; - - spin_lock_irqsave(&pdata->tstamp_lock, flags); -- -- nsec = timecounter_read(&pdata->tstamp_tc); -- -- nsec += delta; -- timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec); -- -+ timecounter_adjtime(&pdata->tstamp_tc, delta); - spin_unlock_irqrestore(&pdata->tstamp_lock, flags); - - return 0; - } - --static int xgbe_gettime(struct ptp_clock_info *info, struct timespec *ts) -+static int xgbe_gettime(struct ptp_clock_info *info, struct timespec64 *ts) - { - struct xgbe_prv_data *pdata = container_of(info, - struct xgbe_prv_data, -@@ -199,12 +193,13 @@ static int xgbe_gettime(struct ptp_clock_info *info, struct timespec *ts) - - spin_unlock_irqrestore(&pdata->tstamp_lock, flags); - -- *ts = ns_to_timespec(nsec); -+ *ts = ns_to_timespec64(nsec); - - return 0; - } - --static int xgbe_settime(struct ptp_clock_info *info, const struct timespec *ts) -+static int xgbe_settime(struct ptp_clock_info *info, -+ const struct timespec64 *ts) - { - struct xgbe_prv_data *pdata = container_of(info, - struct xgbe_prv_data, -@@ -212,7 +207,7 @@ static int xgbe_settime(struct ptp_clock_info *info, const struct timespec *ts) - unsigned long flags; - u64 nsec; - -- nsec = timespec_to_ns(ts); -+ nsec = timespec64_to_ns(ts); - - spin_lock_irqsave(&pdata->tstamp_lock, flags); - -@@ -239,7 +234,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata) - snprintf(info->name, sizeof(info->name), "%s", - netdev_name(pdata->netdev)); - info->owner = THIS_MODULE; -- info->max_adj = clk_get_rate(pdata->ptpclk); -+ info->max_adj = pdata->ptpclk_rate; - info->adjfreq = xgbe_adjfreq; - info->adjtime = xgbe_adjtime; - info->gettime = xgbe_gettime; -@@ -260,7 +255,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata) - */ - dividend = 50000000; - dividend <<= 32; -- pdata->tstamp_addend = div_u64(dividend, clk_get_rate(pdata->ptpclk)); -+ pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate); - - /* Setup the timecounter */ - cc->read = xgbe_cc_read; -diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h -index f9ec762..2ef3ffb 100644 ---- a/drivers/net/ethernet/amd/xgbe/xgbe.h -+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h -@@ -182,10 +182,18 @@ - #define XGBE_PHY_NAME "amd_xgbe_phy" - #define XGBE_PRTAD 0 - -+/* Common property names */ -+#define XGBE_MAC_ADDR_PROPERTY "mac-address" -+#define XGBE_PHY_MODE_PROPERTY "phy-mode" -+#define XGBE_DMA_IRQS_PROPERTY "amd,per-channel-interrupt" -+ - /* Device-tree clock names */ - #define XGBE_DMA_CLOCK "dma_clk" - #define XGBE_PTP_CLOCK "ptp_clk" --#define XGBE_DMA_IRQS "amd,per-channel-interrupt" -+ -+/* ACPI property names */ -+#define XGBE_ACPI_DMA_FREQ "amd,dma-freq" -+#define XGBE_ACPI_PTP_FREQ "amd,ptp-freq" - - /* Timestamp support - values based on 50MHz PTP clock - * 50MHz => 20 nsec -@@ -214,7 +222,7 @@ - ((_idx) & ((_ring)->rdesc_count - 1))) - - /* Default coalescing parameters */ --#define XGMAC_INIT_DMA_TX_USECS 50 -+#define XGMAC_INIT_DMA_TX_USECS 1000 - #define XGMAC_INIT_DMA_TX_FRAMES 25 - - #define XGMAC_MAX_DMA_RIWT 0xff -@@ -317,8 +325,6 @@ struct xgbe_ring_data { - struct xgbe_tx_ring_data tx; /* Tx-related data */ - struct xgbe_rx_ring_data rx; /* Rx-related data */ - -- unsigned int interrupt; /* Interrupt indicator */ -- - unsigned int mapped_as_page; - - /* Incomplete receive save location. If the budget is exhausted -@@ -361,8 +367,7 @@ struct xgbe_ring { - * cur - Tx: index of descriptor to be used for current transfer - * Rx: index of descriptor to check for packet availability - * dirty - Tx: index of descriptor to check for transfer complete -- * Rx: count of descriptors in which a packet has been received -- * (used with skb_realloc_index to refresh the ring) -+ * Rx: index of descriptor to check for buffer reallocation - */ - unsigned int cur; - unsigned int dirty; -@@ -377,11 +382,6 @@ struct xgbe_ring { - unsigned short cur_mss; - unsigned short cur_vlan_ctag; - } tx; -- -- struct { -- unsigned int realloc_index; -- unsigned int realloc_threshold; -- } rx; - }; - } ____cacheline_aligned; - -@@ -408,7 +408,7 @@ struct xgbe_channel { - unsigned int saved_ier; - - unsigned int tx_timer_active; -- struct hrtimer tx_timer; -+ struct timer_list tx_timer; - - struct xgbe_ring *tx_ring; - struct xgbe_ring *rx_ring; -@@ -495,10 +495,8 @@ struct xgbe_mmc_stats { - struct xgbe_hw_if { - int (*tx_complete)(struct xgbe_ring_desc *); - -- int (*set_promiscuous_mode)(struct xgbe_prv_data *, unsigned int); -- int (*set_all_multicast_mode)(struct xgbe_prv_data *, unsigned int); -- int (*add_mac_addresses)(struct xgbe_prv_data *); - int (*set_mac_address)(struct xgbe_prv_data *, u8 *addr); -+ int (*config_rx_mode)(struct xgbe_prv_data *); - - int (*enable_rx_csum)(struct xgbe_prv_data *); - int (*disable_rx_csum)(struct xgbe_prv_data *); -@@ -534,8 +532,9 @@ struct xgbe_hw_if { - int (*dev_read)(struct xgbe_channel *); - void (*tx_desc_init)(struct xgbe_channel *); - void (*rx_desc_init)(struct xgbe_channel *); -- void (*rx_desc_reset)(struct xgbe_ring_data *); - void (*tx_desc_reset)(struct xgbe_ring_data *); -+ void (*rx_desc_reset)(struct xgbe_prv_data *, struct xgbe_ring_data *, -+ unsigned int); - int (*is_last_desc)(struct xgbe_ring_desc *); - int (*is_context_desc)(struct xgbe_ring_desc *); - void (*tx_start_xmit)(struct xgbe_channel *, struct xgbe_ring *); -@@ -596,7 +595,8 @@ struct xgbe_desc_if { - int (*alloc_ring_resources)(struct xgbe_prv_data *); - void (*free_ring_resources)(struct xgbe_prv_data *); - int (*map_tx_skb)(struct xgbe_channel *, struct sk_buff *); -- void (*realloc_rx_buffer)(struct xgbe_channel *); -+ int (*map_rx_buffer)(struct xgbe_prv_data *, struct xgbe_ring *, -+ struct xgbe_ring_data *); - void (*unmap_rdata)(struct xgbe_prv_data *, struct xgbe_ring_data *); - void (*wrapper_tx_desc_init)(struct xgbe_prv_data *); - void (*wrapper_rx_desc_init)(struct xgbe_prv_data *); -@@ -617,7 +617,7 @@ struct xgbe_hw_features { - unsigned int mgk; /* PMT magic packet */ - unsigned int mmc; /* RMON module */ - unsigned int aoe; /* ARP Offload */ -- unsigned int ts; /* IEEE 1588-2008 Adavanced Timestamp */ -+ unsigned int ts; /* IEEE 1588-2008 Advanced Timestamp */ - unsigned int eee; /* Energy Efficient Ethernet */ - unsigned int tx_coe; /* Tx Checksum Offload */ - unsigned int rx_coe; /* Rx Checksum Offload */ -@@ -629,6 +629,7 @@ struct xgbe_hw_features { - unsigned int rx_fifo_size; /* MTL Receive FIFO Size */ - unsigned int tx_fifo_size; /* MTL Transmit FIFO Size */ - unsigned int adv_ts_hi; /* Advance Timestamping High Word */ -+ unsigned int dma_width; /* DMA width */ - unsigned int dcb; /* DCB Feature */ - unsigned int sph; /* Split Header Feature */ - unsigned int tso; /* TCP Segmentation Offload */ -@@ -650,8 +651,12 @@ struct xgbe_hw_features { - struct xgbe_prv_data { - struct net_device *netdev; - struct platform_device *pdev; -+ struct acpi_device *adev; - struct device *dev; - -+ /* ACPI or DT flag */ -+ unsigned int use_acpi; -+ - /* XGMAC/XPCS related mmio registers */ - void __iomem *xgmac_regs; /* XGMAC CSRs */ - void __iomem *xpcs_regs; /* XPCS MMD registers */ -@@ -672,6 +677,7 @@ struct xgbe_prv_data { - struct xgbe_desc_if desc_if; - - /* AXI DMA settings */ -+ unsigned int coherent; - unsigned int axdomain; - unsigned int arcache; - unsigned int awcache; -@@ -707,6 +713,7 @@ struct xgbe_prv_data { - - /* Rx coalescing settings */ - unsigned int rx_riwt; -+ unsigned int rx_usecs; - unsigned int rx_frames; - - /* Current Rx buffer size */ -@@ -739,6 +746,7 @@ struct xgbe_prv_data { - unsigned int phy_rx_pause; - - /* Netdev related settings */ -+ unsigned char mac_addr[ETH_ALEN]; - netdev_features_t netdev_features; - struct napi_struct napi; - struct xgbe_mmc_stats mmc_stats; -@@ -748,7 +756,9 @@ struct xgbe_prv_data { - - /* Device clocks */ - struct clk *sysclk; -+ unsigned long sysclk_rate; - struct clk *ptpclk; -+ unsigned long ptpclk_rate; - - /* Timestamp support */ - spinlock_t tstamp_lock; -diff --git a/drivers/net/phy/amd-xgbe-phy.c b/drivers/net/phy/amd-xgbe-phy.c -index 903dc3d..34a75cb 100644 ---- a/drivers/net/phy/amd-xgbe-phy.c -+++ b/drivers/net/phy/amd-xgbe-phy.c -@@ -60,6 +60,7 @@ - #include <linux/interrupt.h> - #include <linux/init.h> - #include <linux/delay.h> -+#include <linux/workqueue.h> - #include <linux/netdevice.h> - #include <linux/etherdevice.h> - #include <linux/skbuff.h> -@@ -74,6 +75,10 @@ - #include <linux/of_platform.h> - #include <linux/of_device.h> - #include <linux/uaccess.h> -+#include <linux/bitops.h> -+#include <linux/property.h> -+#include <linux/acpi.h> -+#include <linux/jiffies.h> - - MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>"); - MODULE_LICENSE("Dual BSD/GPL"); -@@ -84,22 +89,47 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver"); - #define XGBE_PHY_MASK 0xfffffff0 - - #define XGBE_PHY_SPEEDSET_PROPERTY "amd,speed-set" -+#define XGBE_PHY_BLWC_PROPERTY "amd,serdes-blwc" -+#define XGBE_PHY_CDR_RATE_PROPERTY "amd,serdes-cdr-rate" -+#define XGBE_PHY_PQ_SKEW_PROPERTY "amd,serdes-pq-skew" -+#define XGBE_PHY_TX_AMP_PROPERTY "amd,serdes-tx-amp" -+#define XGBE_PHY_DFE_CFG_PROPERTY "amd,serdes-dfe-tap-config" -+#define XGBE_PHY_DFE_ENA_PROPERTY "amd,serdes-dfe-tap-enable" -+ -+#define XGBE_PHY_SPEEDS 3 -+#define XGBE_PHY_SPEED_1000 0 -+#define XGBE_PHY_SPEED_2500 1 -+#define XGBE_PHY_SPEED_10000 2 -+ -+#define XGBE_AN_MS_TIMEOUT 500 - - #define XGBE_AN_INT_CMPLT 0x01 - #define XGBE_AN_INC_LINK 0x02 - #define XGBE_AN_PG_RCV 0x04 -+#define XGBE_AN_INT_MASK 0x07 - - #define XNP_MCF_NULL_MESSAGE 0x001 --#define XNP_ACK_PROCESSED (1 << 12) --#define XNP_MP_FORMATTED (1 << 13) --#define XNP_NP_EXCHANGE (1 << 15) -+#define XNP_ACK_PROCESSED BIT(12) -+#define XNP_MP_FORMATTED BIT(13) -+#define XNP_NP_EXCHANGE BIT(15) - - #define XGBE_PHY_RATECHANGE_COUNT 500 - -+#define XGBE_PHY_KR_TRAINING_START 0x01 -+#define XGBE_PHY_KR_TRAINING_ENABLE 0x02 -+ -+#define XGBE_PHY_FEC_ENABLE 0x01 -+#define XGBE_PHY_FEC_FORWARD 0x02 -+#define XGBE_PHY_FEC_MASK 0x03 -+ - #ifndef MDIO_PMA_10GBR_PMD_CTRL - #define MDIO_PMA_10GBR_PMD_CTRL 0x0096 - #endif - -+#ifndef MDIO_PMA_10GBR_FEC_ABILITY -+#define MDIO_PMA_10GBR_FEC_ABILITY 0x00aa -+#endif -+ - #ifndef MDIO_PMA_10GBR_FEC_CTRL - #define MDIO_PMA_10GBR_FEC_CTRL 0x00ab - #endif -@@ -108,6 +138,10 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver"); - #define MDIO_AN_XNP 0x0016 - #endif - -+#ifndef MDIO_AN_LPX -+#define MDIO_AN_LPX 0x0019 -+#endif -+ - #ifndef MDIO_AN_INTMASK - #define MDIO_AN_INTMASK 0x8001 - #endif -@@ -116,18 +150,10 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver"); - #define MDIO_AN_INT 0x8002 - #endif - --#ifndef MDIO_AN_KR_CTRL --#define MDIO_AN_KR_CTRL 0x8003 --#endif -- - #ifndef MDIO_CTRL1_SPEED1G - #define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100) - #endif - --#ifndef MDIO_KR_CTRL_PDETECT --#define MDIO_KR_CTRL_PDETECT 0x01 --#endif -- - /* SerDes integration register offsets */ - #define SIR0_KR_RT_1 0x002c - #define SIR0_STATUS 0x0040 -@@ -140,10 +166,10 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver"); - #define SIR0_STATUS_RX_READY_WIDTH 1 - #define SIR0_STATUS_TX_READY_INDEX 8 - #define SIR0_STATUS_TX_READY_WIDTH 1 -+#define SIR1_SPEED_CDR_RATE_INDEX 12 -+#define SIR1_SPEED_CDR_RATE_WIDTH 4 - #define SIR1_SPEED_DATARATE_INDEX 4 - #define SIR1_SPEED_DATARATE_WIDTH 2 --#define SIR1_SPEED_PI_SPD_SEL_INDEX 12 --#define SIR1_SPEED_PI_SPD_SEL_WIDTH 4 - #define SIR1_SPEED_PLLSEL_INDEX 3 - #define SIR1_SPEED_PLLSEL_WIDTH 1 - #define SIR1_SPEED_RATECHANGE_INDEX 6 -@@ -153,42 +179,52 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver"); - #define SIR1_SPEED_WORDMODE_INDEX 0 - #define SIR1_SPEED_WORDMODE_WIDTH 3 - -+#define SPEED_10000_BLWC 0 - #define SPEED_10000_CDR 0x7 - #define SPEED_10000_PLL 0x1 -+#define SPEED_10000_PQ 0x12 - #define SPEED_10000_RATE 0x0 - #define SPEED_10000_TXAMP 0xa - #define SPEED_10000_WORD 0x7 -+#define SPEED_10000_DFE_TAP_CONFIG 0x1 -+#define SPEED_10000_DFE_TAP_ENABLE 0x7f - -+#define SPEED_2500_BLWC 1 - #define SPEED_2500_CDR 0x2 - #define SPEED_2500_PLL 0x0 -+#define SPEED_2500_PQ 0xa - #define SPEED_2500_RATE 0x1 - #define SPEED_2500_TXAMP 0xf - #define SPEED_2500_WORD 0x1 -+#define SPEED_2500_DFE_TAP_CONFIG 0x3 -+#define SPEED_2500_DFE_TAP_ENABLE 0x0 - -+#define SPEED_1000_BLWC 1 - #define SPEED_1000_CDR 0x2 - #define SPEED_1000_PLL 0x0 -+#define SPEED_1000_PQ 0xa - #define SPEED_1000_RATE 0x3 - #define SPEED_1000_TXAMP 0xf - #define SPEED_1000_WORD 0x1 -+#define SPEED_1000_DFE_TAP_CONFIG 0x3 -+#define SPEED_1000_DFE_TAP_ENABLE 0x0 - - /* SerDes RxTx register offsets */ -+#define RXTX_REG6 0x0018 - #define RXTX_REG20 0x0050 -+#define RXTX_REG22 0x0058 - #define RXTX_REG114 0x01c8 -+#define RXTX_REG129 0x0204 - - /* SerDes RxTx register entry bit positions and sizes */ -+#define RXTX_REG6_RESETB_RXD_INDEX 8 -+#define RXTX_REG6_RESETB_RXD_WIDTH 1 - #define RXTX_REG20_BLWC_ENA_INDEX 2 - #define RXTX_REG20_BLWC_ENA_WIDTH 1 - #define RXTX_REG114_PQ_REG_INDEX 9 - #define RXTX_REG114_PQ_REG_WIDTH 7 -- --#define RXTX_10000_BLWC 0 --#define RXTX_10000_PQ 0x1e -- --#define RXTX_2500_BLWC 1 --#define RXTX_2500_PQ 0xa -- --#define RXTX_1000_BLWC 1 --#define RXTX_1000_PQ 0xa -+#define RXTX_REG129_RXDFE_CONFIG_INDEX 14 -+#define RXTX_REG129_RXDFE_CONFIG_WIDTH 2 - - /* Bit setting and getting macros - * The get macro will extract the current bit field value from within -@@ -291,23 +327,56 @@ do { \ - XRXTX_IOWRITE((_priv), _reg, reg_val); \ - } while (0) - -+static const u32 amd_xgbe_phy_serdes_blwc[] = { -+ SPEED_1000_BLWC, -+ SPEED_2500_BLWC, -+ SPEED_10000_BLWC, -+}; -+ -+static const u32 amd_xgbe_phy_serdes_cdr_rate[] = { -+ SPEED_1000_CDR, -+ SPEED_2500_CDR, -+ SPEED_10000_CDR, -+}; -+ -+static const u32 amd_xgbe_phy_serdes_pq_skew[] = { -+ SPEED_1000_PQ, -+ SPEED_2500_PQ, -+ SPEED_10000_PQ, -+}; -+ -+static const u32 amd_xgbe_phy_serdes_tx_amp[] = { -+ SPEED_1000_TXAMP, -+ SPEED_2500_TXAMP, -+ SPEED_10000_TXAMP, -+}; -+ -+static const u32 amd_xgbe_phy_serdes_dfe_tap_cfg[] = { -+ SPEED_1000_DFE_TAP_CONFIG, -+ SPEED_2500_DFE_TAP_CONFIG, -+ SPEED_10000_DFE_TAP_CONFIG, -+}; -+ -+static const u32 amd_xgbe_phy_serdes_dfe_tap_ena[] = { -+ SPEED_1000_DFE_TAP_ENABLE, -+ SPEED_2500_DFE_TAP_ENABLE, -+ SPEED_10000_DFE_TAP_ENABLE, -+}; -+ - enum amd_xgbe_phy_an { - AMD_XGBE_AN_READY = 0, -- AMD_XGBE_AN_START, -- AMD_XGBE_AN_EVENT, - AMD_XGBE_AN_PAGE_RECEIVED, - AMD_XGBE_AN_INCOMPAT_LINK, - AMD_XGBE_AN_COMPLETE, - AMD_XGBE_AN_NO_LINK, -- AMD_XGBE_AN_EXIT, - AMD_XGBE_AN_ERROR, - }; - - enum amd_xgbe_phy_rx { -- AMD_XGBE_RX_READY = 0, -- AMD_XGBE_RX_BPA, -+ AMD_XGBE_RX_BPA = 0, - AMD_XGBE_RX_XNP, - AMD_XGBE_RX_COMPLETE, -+ AMD_XGBE_RX_ERROR, - }; - - enum amd_xgbe_phy_mode { -@@ -316,12 +385,13 @@ enum amd_xgbe_phy_mode { - }; - - enum amd_xgbe_phy_speedset { -- AMD_XGBE_PHY_SPEEDSET_1000_10000, -+ AMD_XGBE_PHY_SPEEDSET_1000_10000 = 0, - AMD_XGBE_PHY_SPEEDSET_2500_10000, - }; - - struct amd_xgbe_phy_priv { - struct platform_device *pdev; -+ struct acpi_device *adev; - struct device *dev; - - struct phy_device *phydev; -@@ -336,10 +406,26 @@ struct amd_xgbe_phy_priv { - void __iomem *sir0_regs; /* SerDes integration registers (1/2) */ - void __iomem *sir1_regs; /* SerDes integration registers (2/2) */ - -- /* Maintain link status for re-starting auto-negotiation */ -- unsigned int link; -+ int an_irq; -+ char an_irq_name[IFNAMSIZ + 32]; -+ struct work_struct an_irq_work; -+ unsigned int an_irq_allocated; -+ - unsigned int speed_set; - -+ /* SerDes UEFI configurable settings. -+ * Switching between modes/speeds requires new values for some -+ * SerDes settings. The values can be supplied as device -+ * properties in array format. The first array entry is for -+ * 1GbE, second for 2.5GbE and third for 10GbE -+ */ -+ u32 serdes_blwc[XGBE_PHY_SPEEDS]; -+ u32 serdes_cdr_rate[XGBE_PHY_SPEEDS]; -+ u32 serdes_pq_skew[XGBE_PHY_SPEEDS]; -+ u32 serdes_tx_amp[XGBE_PHY_SPEEDS]; -+ u32 serdes_dfe_tap_cfg[XGBE_PHY_SPEEDS]; -+ u32 serdes_dfe_tap_ena[XGBE_PHY_SPEEDS]; -+ - /* Auto-negotiation state machine support */ - struct mutex an_mutex; - enum amd_xgbe_phy_an an_result; -@@ -348,7 +434,12 @@ struct amd_xgbe_phy_priv { - enum amd_xgbe_phy_rx kx_state; - struct work_struct an_work; - struct workqueue_struct *an_workqueue; -+ unsigned int an_supported; - unsigned int parallel_detect; -+ unsigned int fec_ability; -+ unsigned long an_start; -+ -+ unsigned int lpm_ctrl; /* CTRL1 for resume */ - }; - - static int amd_xgbe_an_enable_kr_training(struct phy_device *phydev) -@@ -359,7 +450,7 @@ static int amd_xgbe_an_enable_kr_training(struct phy_device *phydev) - if (ret < 0) - return ret; - -- ret |= 0x02; -+ ret |= XGBE_PHY_KR_TRAINING_ENABLE; - phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, ret); - - return 0; -@@ -373,7 +464,7 @@ static int amd_xgbe_an_disable_kr_training(struct phy_device *phydev) - if (ret < 0) - return ret; - -- ret &= ~0x02; -+ ret &= ~XGBE_PHY_KR_TRAINING_ENABLE; - phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, ret); - - return 0; -@@ -423,11 +514,16 @@ static void amd_xgbe_phy_serdes_complete_ratechange(struct phy_device *phydev) - status = XSIR0_IOREAD(priv, SIR0_STATUS); - if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) && - XSIR_GET_BITS(status, SIR0_STATUS, TX_READY)) -- return; -+ goto rx_reset; - } - - netdev_dbg(phydev->attached_dev, "SerDes rx/tx not ready (%#hx)\n", - status); -+ -+rx_reset: -+ /* Perform Rx reset for the DFE changes */ -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RESETB_RXD, 0); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG6, RESETB_RXD, 1); - } - - static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev) -@@ -466,12 +562,20 @@ static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev) - - XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, DATARATE, SPEED_10000_RATE); - XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, WORDMODE, SPEED_10000_WORD); -- XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, TXAMP, SPEED_10000_TXAMP); - XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, PLLSEL, SPEED_10000_PLL); -- XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, PI_SPD_SEL, SPEED_10000_CDR); - -- XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, RXTX_10000_BLWC); -- XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, RXTX_10000_PQ); -+ XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, CDR_RATE, -+ priv->serdes_cdr_rate[XGBE_PHY_SPEED_10000]); -+ XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, TXAMP, -+ priv->serdes_tx_amp[XGBE_PHY_SPEED_10000]); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, -+ priv->serdes_blwc[XGBE_PHY_SPEED_10000]); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, -+ priv->serdes_pq_skew[XGBE_PHY_SPEED_10000]); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG129, RXDFE_CONFIG, -+ priv->serdes_dfe_tap_cfg[XGBE_PHY_SPEED_10000]); -+ XRXTX_IOWRITE(priv, RXTX_REG22, -+ priv->serdes_dfe_tap_ena[XGBE_PHY_SPEED_10000]); - - amd_xgbe_phy_serdes_complete_ratechange(phydev); - -@@ -514,12 +618,20 @@ static int amd_xgbe_phy_gmii_2500_mode(struct phy_device *phydev) - - XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, DATARATE, SPEED_2500_RATE); - XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, WORDMODE, SPEED_2500_WORD); -- XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, TXAMP, SPEED_2500_TXAMP); - XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, PLLSEL, SPEED_2500_PLL); -- XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, PI_SPD_SEL, SPEED_2500_CDR); - -- XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, RXTX_2500_BLWC); -- XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, RXTX_2500_PQ); -+ XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, CDR_RATE, -+ priv->serdes_cdr_rate[XGBE_PHY_SPEED_2500]); -+ XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, TXAMP, -+ priv->serdes_tx_amp[XGBE_PHY_SPEED_2500]); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, -+ priv->serdes_blwc[XGBE_PHY_SPEED_2500]); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, -+ priv->serdes_pq_skew[XGBE_PHY_SPEED_2500]); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG129, RXDFE_CONFIG, -+ priv->serdes_dfe_tap_cfg[XGBE_PHY_SPEED_2500]); -+ XRXTX_IOWRITE(priv, RXTX_REG22, -+ priv->serdes_dfe_tap_ena[XGBE_PHY_SPEED_2500]); - - amd_xgbe_phy_serdes_complete_ratechange(phydev); - -@@ -562,12 +674,20 @@ static int amd_xgbe_phy_gmii_mode(struct phy_device *phydev) - - XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, DATARATE, SPEED_1000_RATE); - XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, WORDMODE, SPEED_1000_WORD); -- XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, TXAMP, SPEED_1000_TXAMP); - XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, PLLSEL, SPEED_1000_PLL); -- XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, PI_SPD_SEL, SPEED_1000_CDR); - -- XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, RXTX_1000_BLWC); -- XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, RXTX_1000_PQ); -+ XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, CDR_RATE, -+ priv->serdes_cdr_rate[XGBE_PHY_SPEED_1000]); -+ XSIR1_IOWRITE_BITS(priv, SIR1_SPEED, TXAMP, -+ priv->serdes_tx_amp[XGBE_PHY_SPEED_1000]); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG20, BLWC_ENA, -+ priv->serdes_blwc[XGBE_PHY_SPEED_1000]); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG114, PQ_REG, -+ priv->serdes_pq_skew[XGBE_PHY_SPEED_1000]); -+ XRXTX_IOWRITE_BITS(priv, RXTX_REG129, RXDFE_CONFIG, -+ priv->serdes_dfe_tap_cfg[XGBE_PHY_SPEED_1000]); -+ XRXTX_IOWRITE(priv, RXTX_REG22, -+ priv->serdes_dfe_tap_ena[XGBE_PHY_SPEED_1000]); - - amd_xgbe_phy_serdes_complete_ratechange(phydev); - -@@ -635,6 +755,77 @@ static int amd_xgbe_phy_set_mode(struct phy_device *phydev, - return ret; - } - -+static bool amd_xgbe_phy_use_xgmii_mode(struct phy_device *phydev) -+{ -+ if (phydev->autoneg == AUTONEG_ENABLE) { -+ if (phydev->advertising & ADVERTISED_10000baseKR_Full) -+ return true; -+ } else { -+ if (phydev->speed == SPEED_10000) -+ return true; -+ } -+ -+ return false; -+} -+ -+static bool amd_xgbe_phy_use_gmii_2500_mode(struct phy_device *phydev) -+{ -+ if (phydev->autoneg == AUTONEG_ENABLE) { -+ if (phydev->advertising & ADVERTISED_2500baseX_Full) -+ return true; -+ } else { -+ if (phydev->speed == SPEED_2500) -+ return true; -+ } -+ -+ return false; -+} -+ -+static bool amd_xgbe_phy_use_gmii_mode(struct phy_device *phydev) -+{ -+ if (phydev->autoneg == AUTONEG_ENABLE) { -+ if (phydev->advertising & ADVERTISED_1000baseKX_Full) -+ return true; -+ } else { -+ if (phydev->speed == SPEED_1000) -+ return true; -+ } -+ -+ return false; -+} -+ -+static int amd_xgbe_phy_set_an(struct phy_device *phydev, bool enable, -+ bool restart) -+{ -+ int ret; -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); -+ if (ret < 0) -+ return ret; -+ -+ ret &= ~MDIO_AN_CTRL1_ENABLE; -+ -+ if (enable) -+ ret |= MDIO_AN_CTRL1_ENABLE; -+ -+ if (restart) -+ ret |= MDIO_AN_CTRL1_RESTART; -+ -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, ret); -+ -+ return 0; -+} -+ -+static int amd_xgbe_phy_restart_an(struct phy_device *phydev) -+{ -+ return amd_xgbe_phy_set_an(phydev, true, true); -+} -+ -+static int amd_xgbe_phy_disable_an(struct phy_device *phydev) -+{ -+ return amd_xgbe_phy_set_an(phydev, false, false); -+} -+ - static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev, - enum amd_xgbe_phy_rx *state) - { -@@ -645,7 +836,7 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev, - - /* If we're not in KR mode then we're done */ - if (!amd_xgbe_phy_in_kr_mode(phydev)) -- return AMD_XGBE_AN_EVENT; -+ return AMD_XGBE_AN_PAGE_RECEIVED; - - /* Enable/Disable FEC */ - ad_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); -@@ -660,10 +851,9 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev, - if (ret < 0) - return AMD_XGBE_AN_ERROR; - -+ ret &= ~XGBE_PHY_FEC_MASK; - if ((ad_reg & 0xc000) && (lp_reg & 0xc000)) -- ret |= 0x01; -- else -- ret &= ~0x01; -+ ret |= priv->fec_ability; - - phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FEC_CTRL, ret); - -@@ -672,14 +862,17 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev, - if (ret < 0) - return AMD_XGBE_AN_ERROR; - -- XSIR0_IOWRITE_BITS(priv, SIR0_KR_RT_1, RESET, 1); -+ if (ret & XGBE_PHY_KR_TRAINING_ENABLE) { -+ XSIR0_IOWRITE_BITS(priv, SIR0_KR_RT_1, RESET, 1); - -- ret |= 0x01; -- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, ret); -+ ret |= XGBE_PHY_KR_TRAINING_START; -+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, -+ ret); - -- XSIR0_IOWRITE_BITS(priv, SIR0_KR_RT_1, RESET, 0); -+ XSIR0_IOWRITE_BITS(priv, SIR0_KR_RT_1, RESET, 0); -+ } - -- return AMD_XGBE_AN_EVENT; -+ return AMD_XGBE_AN_PAGE_RECEIVED; - } - - static enum amd_xgbe_phy_an amd_xgbe_an_tx_xnp(struct phy_device *phydev, -@@ -696,7 +889,7 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_xnp(struct phy_device *phydev, - phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_XNP + 1, 0); - phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_XNP, msg); - -- return AMD_XGBE_AN_EVENT; -+ return AMD_XGBE_AN_PAGE_RECEIVED; - } - - static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev, -@@ -735,11 +928,11 @@ static enum amd_xgbe_phy_an amd_xgbe_an_rx_xnp(struct phy_device *phydev, - int ad_reg, lp_reg; - - /* 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_XNP); - if (ad_reg < 0) - return AMD_XGBE_AN_ERROR; - -- lp_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA); -+ lp_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPX); - if (lp_reg < 0) - return AMD_XGBE_AN_ERROR; - -@@ -748,226 +941,271 @@ static enum amd_xgbe_phy_an amd_xgbe_an_rx_xnp(struct phy_device *phydev, - amd_xgbe_an_tx_training(phydev, state); - } - --static enum amd_xgbe_phy_an amd_xgbe_an_start(struct phy_device *phydev) -+static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev) - { - struct amd_xgbe_phy_priv *priv = phydev->priv; -+ enum amd_xgbe_phy_rx *state; -+ unsigned long an_timeout; - int ret; - -- /* Be sure we aren't looping trying to negotiate */ -- if (amd_xgbe_phy_in_kr_mode(phydev)) { -- if (priv->kr_state != AMD_XGBE_RX_READY) -- return AMD_XGBE_AN_NO_LINK; -- priv->kr_state = AMD_XGBE_RX_BPA; -+ if (!priv->an_start) { -+ priv->an_start = jiffies; - } else { -- if (priv->kx_state != AMD_XGBE_RX_READY) -- return AMD_XGBE_AN_NO_LINK; -- priv->kx_state = AMD_XGBE_RX_BPA; -+ an_timeout = priv->an_start + -+ msecs_to_jiffies(XGBE_AN_MS_TIMEOUT); -+ if (time_after(jiffies, an_timeout)) { -+ /* Auto-negotiation timed out, reset state */ -+ priv->kr_state = AMD_XGBE_RX_BPA; -+ priv->kx_state = AMD_XGBE_RX_BPA; -+ -+ priv->an_start = jiffies; -+ } - } - -- /* Set up Advertisement register 3 first */ -- ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); -- if (ret < 0) -- return AMD_XGBE_AN_ERROR; -- -- if (phydev->supported & SUPPORTED_10000baseR_FEC) -- ret |= 0xc000; -- else -- ret &= ~0xc000; -- -- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2, ret); -+ state = amd_xgbe_phy_in_kr_mode(phydev) ? &priv->kr_state -+ : &priv->kx_state; - -- /* Set up Advertisement register 2 next */ -- ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); -- if (ret < 0) -- return AMD_XGBE_AN_ERROR; -+ switch (*state) { -+ case AMD_XGBE_RX_BPA: -+ ret = amd_xgbe_an_rx_bpa(phydev, state); -+ break; - -- if (phydev->supported & SUPPORTED_10000baseKR_Full) -- ret |= 0x80; -- else -- ret &= ~0x80; -+ case AMD_XGBE_RX_XNP: -+ ret = amd_xgbe_an_rx_xnp(phydev, state); -+ break; - -- if ((phydev->supported & SUPPORTED_1000baseKX_Full) || -- (phydev->supported & SUPPORTED_2500baseX_Full)) -- ret |= 0x20; -- else -- ret &= ~0x20; -+ default: -+ ret = AMD_XGBE_AN_ERROR; -+ } - -- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1, ret); -+ return ret; -+} - -- /* Set up Advertisement register 1 last */ -- ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE); -- if (ret < 0) -- return AMD_XGBE_AN_ERROR; -+static enum amd_xgbe_phy_an amd_xgbe_an_incompat_link(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ int ret; - -- if (phydev->supported & SUPPORTED_Pause) -- ret |= 0x400; -- else -- ret &= ~0x400; -+ /* Be sure we aren't looping trying to negotiate */ -+ if (amd_xgbe_phy_in_kr_mode(phydev)) { -+ priv->kr_state = AMD_XGBE_RX_ERROR; - -- if (phydev->supported & SUPPORTED_Asym_Pause) -- ret |= 0x800; -- else -- ret &= ~0x800; -+ if (!(phydev->advertising & SUPPORTED_1000baseKX_Full) && -+ !(phydev->advertising & SUPPORTED_2500baseX_Full)) -+ return AMD_XGBE_AN_NO_LINK; - -- /* We don't intend to perform XNP */ -- ret &= ~XNP_NP_EXCHANGE; -+ if (priv->kx_state != AMD_XGBE_RX_BPA) -+ return AMD_XGBE_AN_NO_LINK; -+ } else { -+ priv->kx_state = AMD_XGBE_RX_ERROR; - -- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, ret); -+ if (!(phydev->advertising & SUPPORTED_10000baseKR_Full)) -+ return AMD_XGBE_AN_NO_LINK; - -- /* Enable and start auto-negotiation */ -- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); -+ if (priv->kr_state != AMD_XGBE_RX_BPA) -+ return AMD_XGBE_AN_NO_LINK; -+ } - -- ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_KR_CTRL); -- if (ret < 0) -+ ret = amd_xgbe_phy_disable_an(phydev); -+ if (ret) - 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); -- if (ret < 0) -+ ret = amd_xgbe_phy_switch_mode(phydev); -+ if (ret) - return AMD_XGBE_AN_ERROR; - -- ret |= MDIO_AN_CTRL1_ENABLE; -- ret |= MDIO_AN_CTRL1_RESTART; -- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, ret); -+ ret = amd_xgbe_phy_restart_an(phydev); -+ if (ret) -+ return AMD_XGBE_AN_ERROR; - -- return AMD_XGBE_AN_EVENT; -+ return AMD_XGBE_AN_INCOMPAT_LINK; - } - --static enum amd_xgbe_phy_an amd_xgbe_an_event(struct phy_device *phydev) -+static irqreturn_t amd_xgbe_an_isr(int irq, void *data) - { -- enum amd_xgbe_phy_an new_state; -- int ret; -+ struct amd_xgbe_phy_priv *priv = (struct amd_xgbe_phy_priv *)data; - -- ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT); -- if (ret < 0) -- return AMD_XGBE_AN_ERROR; -+ /* Interrupt reason must be read and cleared outside of IRQ context */ -+ disable_irq_nosync(priv->an_irq); - -- new_state = AMD_XGBE_AN_EVENT; -- if (ret & XGBE_AN_PG_RCV) -- new_state = AMD_XGBE_AN_PAGE_RECEIVED; -- else if (ret & XGBE_AN_INC_LINK) -- new_state = AMD_XGBE_AN_INCOMPAT_LINK; -- else if (ret & XGBE_AN_INT_CMPLT) -- new_state = AMD_XGBE_AN_COMPLETE; -+ queue_work(priv->an_workqueue, &priv->an_irq_work); - -- if (new_state != AMD_XGBE_AN_EVENT) -- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); -+ return IRQ_HANDLED; -+} -+ -+static void amd_xgbe_an_irq_work(struct work_struct *work) -+{ -+ struct amd_xgbe_phy_priv *priv = container_of(work, -+ struct amd_xgbe_phy_priv, -+ an_irq_work); - -- return new_state; -+ /* Avoid a race between enabling the IRQ and exiting the work by -+ * waiting for the work to finish and then queueing it -+ */ -+ flush_work(&priv->an_work); -+ queue_work(priv->an_workqueue, &priv->an_work); - } - --static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev) -+static void amd_xgbe_an_state_machine(struct work_struct *work) - { -- struct amd_xgbe_phy_priv *priv = phydev->priv; -- enum amd_xgbe_phy_rx *state; -- int ret; -+ struct amd_xgbe_phy_priv *priv = container_of(work, -+ struct amd_xgbe_phy_priv, -+ an_work); -+ struct phy_device *phydev = priv->phydev; -+ enum amd_xgbe_phy_an cur_state = priv->an_state; -+ int int_reg, int_mask; - -- state = amd_xgbe_phy_in_kr_mode(phydev) ? &priv->kr_state -- : &priv->kx_state; -+ mutex_lock(&priv->an_mutex); - -- switch (*state) { -- case AMD_XGBE_RX_BPA: -- ret = amd_xgbe_an_rx_bpa(phydev, state); -+ /* Read the interrupt */ -+ int_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT); -+ if (!int_reg) -+ goto out; -+ -+next_int: -+ if (int_reg < 0) { -+ priv->an_state = AMD_XGBE_AN_ERROR; -+ int_mask = XGBE_AN_INT_MASK; -+ } else if (int_reg & XGBE_AN_PG_RCV) { -+ priv->an_state = AMD_XGBE_AN_PAGE_RECEIVED; -+ int_mask = XGBE_AN_PG_RCV; -+ } else if (int_reg & XGBE_AN_INC_LINK) { -+ priv->an_state = AMD_XGBE_AN_INCOMPAT_LINK; -+ int_mask = XGBE_AN_INC_LINK; -+ } else if (int_reg & XGBE_AN_INT_CMPLT) { -+ priv->an_state = AMD_XGBE_AN_COMPLETE; -+ int_mask = XGBE_AN_INT_CMPLT; -+ } else { -+ priv->an_state = AMD_XGBE_AN_ERROR; -+ int_mask = 0; -+ } -+ -+ /* Clear the interrupt to be processed */ -+ int_reg &= ~int_mask; -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, int_reg); -+ -+ priv->an_result = priv->an_state; -+ -+again: -+ cur_state = priv->an_state; -+ -+ switch (priv->an_state) { -+ case AMD_XGBE_AN_READY: -+ priv->an_supported = 0; - break; - -- case AMD_XGBE_RX_XNP: -- ret = amd_xgbe_an_rx_xnp(phydev, state); -+ case AMD_XGBE_AN_PAGE_RECEIVED: -+ priv->an_state = amd_xgbe_an_page_received(phydev); -+ priv->an_supported++; -+ break; -+ -+ case AMD_XGBE_AN_INCOMPAT_LINK: -+ priv->an_supported = 0; -+ priv->parallel_detect = 0; -+ priv->an_state = amd_xgbe_an_incompat_link(phydev); -+ break; -+ -+ case AMD_XGBE_AN_COMPLETE: -+ priv->parallel_detect = priv->an_supported ? 0 : 1; -+ netdev_dbg(phydev->attached_dev, "%s successful\n", -+ priv->an_supported ? "Auto negotiation" -+ : "Parallel detection"); -+ break; -+ -+ case AMD_XGBE_AN_NO_LINK: - break; - - default: -- ret = AMD_XGBE_AN_ERROR; -+ priv->an_state = AMD_XGBE_AN_ERROR; - } - -- return ret; --} -+ if (priv->an_state == AMD_XGBE_AN_NO_LINK) { -+ int_reg = 0; -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); -+ } else if (priv->an_state == AMD_XGBE_AN_ERROR) { -+ netdev_err(phydev->attached_dev, -+ "error during auto-negotiation, state=%u\n", -+ cur_state); - --static enum amd_xgbe_phy_an amd_xgbe_an_incompat_link(struct phy_device *phydev) --{ -- int ret; -+ int_reg = 0; -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); -+ } - -- ret = amd_xgbe_phy_switch_mode(phydev); -- if (ret) -- return AMD_XGBE_AN_ERROR; -+ if (priv->an_state >= AMD_XGBE_AN_COMPLETE) { -+ priv->an_result = priv->an_state; -+ priv->an_state = AMD_XGBE_AN_READY; -+ priv->kr_state = AMD_XGBE_RX_BPA; -+ priv->kx_state = AMD_XGBE_RX_BPA; -+ priv->an_start = 0; -+ } - -- return AMD_XGBE_AN_START; --} -+ if (cur_state != priv->an_state) -+ goto again; - --static void amd_xgbe_an_state_machine(struct work_struct *work) --{ -- struct amd_xgbe_phy_priv *priv = container_of(work, -- struct amd_xgbe_phy_priv, -- an_work); -- struct phy_device *phydev = priv->phydev; -- enum amd_xgbe_phy_an cur_state; -- int sleep; -- unsigned int an_supported = 0; -+ if (int_reg) -+ goto next_int; - -- /* Start in KX mode */ -- if (amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX)) -- priv->an_state = AMD_XGBE_AN_ERROR; -+out: -+ enable_irq(priv->an_irq); - -- while (1) { -- mutex_lock(&priv->an_mutex); -+ mutex_unlock(&priv->an_mutex); -+} - -- cur_state = priv->an_state; -+static int amd_xgbe_an_init(struct phy_device *phydev) -+{ -+ int ret; - -- switch (priv->an_state) { -- case AMD_XGBE_AN_START: -- an_supported = 0; -- priv->parallel_detect = 0; -- priv->an_state = amd_xgbe_an_start(phydev); -- break; -+ /* Set up Advertisement register 3 first */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); -+ if (ret < 0) -+ return ret; - -- case AMD_XGBE_AN_EVENT: -- priv->an_state = amd_xgbe_an_event(phydev); -- break; -+ if (phydev->advertising & SUPPORTED_10000baseR_FEC) -+ ret |= 0xc000; -+ else -+ ret &= ~0xc000; - -- case AMD_XGBE_AN_PAGE_RECEIVED: -- priv->an_state = amd_xgbe_an_page_received(phydev); -- an_supported++; -- break; -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2, ret); - -- case AMD_XGBE_AN_INCOMPAT_LINK: -- priv->an_state = amd_xgbe_an_incompat_link(phydev); -- break; -+ /* Set up Advertisement register 2 next */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); -+ if (ret < 0) -+ return ret; - -- case AMD_XGBE_AN_COMPLETE: -- priv->parallel_detect = an_supported ? 0 : 1; -- netdev_info(phydev->attached_dev, "%s successful\n", -- an_supported ? "Auto negotiation" -- : "Parallel detection"); -- /* fall through */ -+ if (phydev->advertising & SUPPORTED_10000baseKR_Full) -+ ret |= 0x80; -+ else -+ ret &= ~0x80; - -- case AMD_XGBE_AN_NO_LINK: -- case AMD_XGBE_AN_EXIT: -- goto exit_unlock; -+ if ((phydev->advertising & SUPPORTED_1000baseKX_Full) || -+ (phydev->advertising & SUPPORTED_2500baseX_Full)) -+ ret |= 0x20; -+ else -+ ret &= ~0x20; - -- default: -- priv->an_state = AMD_XGBE_AN_ERROR; -- } -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1, ret); - -- if (priv->an_state == AMD_XGBE_AN_ERROR) { -- netdev_err(phydev->attached_dev, -- "error during auto-negotiation, state=%u\n", -- cur_state); -- goto exit_unlock; -- } -+ /* Set up Advertisement register 1 last */ -+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE); -+ if (ret < 0) -+ return ret; - -- sleep = (priv->an_state == AMD_XGBE_AN_EVENT) ? 1 : 0; -+ if (phydev->advertising & SUPPORTED_Pause) -+ ret |= 0x400; -+ else -+ ret &= ~0x400; - -- mutex_unlock(&priv->an_mutex); -+ if (phydev->advertising & SUPPORTED_Asym_Pause) -+ ret |= 0x800; -+ else -+ ret &= ~0x800; - -- if (sleep) -- usleep_range(20, 50); -- } -+ /* We don't intend to perform XNP */ -+ ret &= ~XNP_NP_EXCHANGE; - --exit_unlock: -- priv->an_result = priv->an_state; -- priv->an_state = AMD_XGBE_AN_READY; -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, ret); - -- mutex_unlock(&priv->an_mutex); -+ return 0; - } - - static int amd_xgbe_phy_soft_reset(struct phy_device *phydev) -@@ -992,33 +1230,68 @@ static int amd_xgbe_phy_soft_reset(struct phy_device *phydev) - if (ret & MDIO_CTRL1_RESET) - return -ETIMEDOUT; - -- /* Make sure the XPCS and SerDes are in compatible states */ -- return amd_xgbe_phy_xgmii_mode(phydev); -+ /* Disable auto-negotiation for now */ -+ ret = amd_xgbe_phy_disable_an(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* Clear auto-negotiation interrupts */ -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); -+ -+ return 0; - } - - static int amd_xgbe_phy_config_init(struct phy_device *phydev) - { - struct amd_xgbe_phy_priv *priv = phydev->priv; -+ struct net_device *netdev = phydev->attached_dev; -+ int ret; - -- /* Initialize supported features */ -- phydev->supported = SUPPORTED_Autoneg; -- phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; -- phydev->supported |= SUPPORTED_Backplane; -- phydev->supported |= SUPPORTED_10000baseKR_Full | -- SUPPORTED_10000baseR_FEC; -- switch (priv->speed_set) { -- case AMD_XGBE_PHY_SPEEDSET_1000_10000: -- phydev->supported |= SUPPORTED_1000baseKX_Full; -- break; -- case AMD_XGBE_PHY_SPEEDSET_2500_10000: -- phydev->supported |= SUPPORTED_2500baseX_Full; -- break; -+ if (!priv->an_irq_allocated) { -+ /* Allocate the auto-negotiation workqueue and interrupt */ -+ snprintf(priv->an_irq_name, sizeof(priv->an_irq_name) - 1, -+ "%s-pcs", netdev_name(netdev)); -+ -+ priv->an_workqueue = -+ create_singlethread_workqueue(priv->an_irq_name); -+ if (!priv->an_workqueue) { -+ netdev_err(netdev, "phy workqueue creation failed\n"); -+ return -ENOMEM; -+ } -+ -+ ret = devm_request_irq(priv->dev, priv->an_irq, -+ amd_xgbe_an_isr, 0, priv->an_irq_name, -+ priv); -+ if (ret) { -+ netdev_err(netdev, "phy irq request failed\n"); -+ destroy_workqueue(priv->an_workqueue); -+ return ret; -+ } -+ -+ priv->an_irq_allocated = 1; - } -- phydev->advertising = phydev->supported; - -- /* Turn off and clear interrupts */ -- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INTMASK, 0); -- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); -+ /* Set initial mode - call the mode setting routines -+ * directly to insure we are properly configured -+ */ -+ if (amd_xgbe_phy_use_xgmii_mode(phydev)) -+ ret = amd_xgbe_phy_xgmii_mode(phydev); -+ else if (amd_xgbe_phy_use_gmii_mode(phydev)) -+ ret = amd_xgbe_phy_gmii_mode(phydev); -+ else if (amd_xgbe_phy_use_gmii_2500_mode(phydev)) -+ ret = amd_xgbe_phy_gmii_2500_mode(phydev); -+ else -+ ret = -EINVAL; -+ if (ret < 0) -+ return ret; -+ -+ /* Set up advertisement registers based on current settings */ -+ ret = amd_xgbe_an_init(phydev); -+ if (ret) -+ return ret; -+ -+ /* Enable auto-negotiation interrupts */ -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INTMASK, 0x07); - - return 0; - } -@@ -1028,25 +1301,19 @@ static int amd_xgbe_phy_setup_forced(struct phy_device *phydev) - int ret; - - /* Disable auto-negotiation */ -- ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); -+ ret = amd_xgbe_phy_disable_an(phydev); - if (ret < 0) - return ret; - -- ret &= ~MDIO_AN_CTRL1_ENABLE; -- phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, ret); -- - /* Validate/Set specified speed */ - switch (phydev->speed) { - case SPEED_10000: -- ret = amd_xgbe_phy_xgmii_mode(phydev); -+ ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KR); - break; - - case SPEED_2500: -- ret = amd_xgbe_phy_gmii_2500_mode(phydev); -- break; -- - case SPEED_1000: -- ret = amd_xgbe_phy_gmii_mode(phydev); -+ ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX); - break; - - default: -@@ -1066,10 +1333,11 @@ static int amd_xgbe_phy_setup_forced(struct phy_device *phydev) - return 0; - } - --static int amd_xgbe_phy_config_aneg(struct phy_device *phydev) -+static int __amd_xgbe_phy_config_aneg(struct phy_device *phydev) - { - struct amd_xgbe_phy_priv *priv = phydev->priv; - u32 mmd_mask = phydev->c45_ids.devices_in_package; -+ int ret; - - if (phydev->autoneg != AUTONEG_ENABLE) - return amd_xgbe_phy_setup_forced(phydev); -@@ -1078,56 +1346,79 @@ static int amd_xgbe_phy_config_aneg(struct phy_device *phydev) - if (!(mmd_mask & MDIO_DEVS_AN)) - return -EINVAL; - -- /* Start/Restart the auto-negotiation state machine */ -- mutex_lock(&priv->an_mutex); -+ /* Disable auto-negotiation interrupt */ -+ disable_irq(priv->an_irq); -+ -+ /* Start auto-negotiation in a supported mode */ -+ if (phydev->advertising & SUPPORTED_10000baseKR_Full) -+ ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KR); -+ else if ((phydev->advertising & SUPPORTED_1000baseKX_Full) || -+ (phydev->advertising & SUPPORTED_2500baseX_Full)) -+ ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX); -+ else -+ ret = -EINVAL; -+ if (ret < 0) { -+ enable_irq(priv->an_irq); -+ return ret; -+ } -+ -+ /* Disable and stop any in progress auto-negotiation */ -+ ret = amd_xgbe_phy_disable_an(phydev); -+ if (ret < 0) -+ return ret; -+ -+ /* Clear any auto-negotitation interrupts */ -+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); -+ - priv->an_result = AMD_XGBE_AN_READY; -- priv->an_state = AMD_XGBE_AN_START; -- priv->kr_state = AMD_XGBE_RX_READY; -- priv->kx_state = AMD_XGBE_RX_READY; -- mutex_unlock(&priv->an_mutex); -+ priv->an_state = AMD_XGBE_AN_READY; -+ priv->kr_state = AMD_XGBE_RX_BPA; -+ priv->kx_state = AMD_XGBE_RX_BPA; - -- queue_work(priv->an_workqueue, &priv->an_work); -+ /* Re-enable auto-negotiation interrupt */ -+ enable_irq(priv->an_irq); - -- return 0; -+ /* Set up advertisement registers based on current settings */ -+ ret = amd_xgbe_an_init(phydev); -+ if (ret) -+ return ret; -+ -+ /* Enable and start auto-negotiation */ -+ return amd_xgbe_phy_restart_an(phydev); - } - --static int amd_xgbe_phy_aneg_done(struct phy_device *phydev) -+static int amd_xgbe_phy_config_aneg(struct phy_device *phydev) - { - struct amd_xgbe_phy_priv *priv = phydev->priv; -- enum amd_xgbe_phy_an state; -+ int ret; - - mutex_lock(&priv->an_mutex); -- state = priv->an_result; -+ -+ ret = __amd_xgbe_phy_config_aneg(phydev); -+ - mutex_unlock(&priv->an_mutex); - -- return (state == AMD_XGBE_AN_COMPLETE); -+ return ret; -+} -+ -+static int amd_xgbe_phy_aneg_done(struct phy_device *phydev) -+{ -+ struct amd_xgbe_phy_priv *priv = phydev->priv; -+ -+ return (priv->an_result == AMD_XGBE_AN_COMPLETE); - } - - static int amd_xgbe_phy_update_link(struct phy_device *phydev) - { - struct amd_xgbe_phy_priv *priv = phydev->priv; -- enum amd_xgbe_phy_an state; -- unsigned int check_again, autoneg; - int ret; - - /* If we're doing auto-negotiation don't report link down */ -- mutex_lock(&priv->an_mutex); -- state = priv->an_state; -- mutex_unlock(&priv->an_mutex); -- -- if (state != AMD_XGBE_AN_READY) { -+ if (priv->an_state != AMD_XGBE_AN_READY) { - phydev->link = 1; - return 0; - } - -- /* Since the device can be in the wrong mode when a link is -- * (re-)established (cable connected after the interface is -- * up, etc.), the link status may report no link. If there -- * is no link, try switching modes and checking the status -- * again if auto negotiation is enabled. -- */ -- check_again = (phydev->autoneg == AUTONEG_ENABLE) ? 1 : 0; --again: - /* Link status is latched low, so read once to clear - * and then read again to get current state - */ -@@ -1141,25 +1432,6 @@ again: - - phydev->link = (ret & MDIO_STAT1_LSTATUS) ? 1 : 0; - -- if (!phydev->link) { -- if (check_again) { -- ret = amd_xgbe_phy_switch_mode(phydev); -- if (ret < 0) -- return ret; -- check_again = 0; -- goto again; -- } -- } -- -- autoneg = (phydev->link && !priv->link) ? 1 : 0; -- priv->link = phydev->link; -- if (autoneg) { -- /* Link is (back) up, re-start auto-negotiation */ -- ret = amd_xgbe_phy_config_aneg(phydev); -- if (ret < 0) -- return ret; -- } -- - return 0; - } - -@@ -1249,6 +1521,7 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev) - - static int amd_xgbe_phy_suspend(struct phy_device *phydev) - { -+ struct amd_xgbe_phy_priv *priv = phydev->priv; - int ret; - - mutex_lock(&phydev->lock); -@@ -1257,6 +1530,8 @@ static int amd_xgbe_phy_suspend(struct phy_device *phydev) - if (ret < 0) - goto unlock; - -+ priv->lpm_ctrl = ret; -+ - ret |= MDIO_CTRL1_LPOWER; - phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, ret); - -@@ -1270,69 +1545,106 @@ unlock: - - static int amd_xgbe_phy_resume(struct phy_device *phydev) - { -- int ret; -+ struct amd_xgbe_phy_priv *priv = phydev->priv; - - mutex_lock(&phydev->lock); - -- ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1); -- if (ret < 0) -- goto unlock; -+ priv->lpm_ctrl &= ~MDIO_CTRL1_LPOWER; -+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, priv->lpm_ctrl); - -- ret &= ~MDIO_CTRL1_LPOWER; -- phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, ret); -+ mutex_unlock(&phydev->lock); - -- ret = 0; -+ return 0; -+} - --unlock: -- mutex_unlock(&phydev->lock); -+static unsigned int amd_xgbe_phy_resource_count(struct platform_device *pdev, -+ unsigned int type) -+{ -+ unsigned int count; -+ int i; - -- return ret; -+ for (i = 0, count = 0; i < pdev->num_resources; i++) { -+ struct resource *r = &pdev->resource[i]; -+ -+ if (type == resource_type(r)) -+ count++; -+ } -+ -+ return count; - } - - static int amd_xgbe_phy_probe(struct phy_device *phydev) - { - struct amd_xgbe_phy_priv *priv; -- struct platform_device *pdev; -- struct device *dev; -- char *wq_name; -- const __be32 *property; -- unsigned int speed_set; -+ struct platform_device *phy_pdev; -+ struct device *dev, *phy_dev; -+ unsigned int phy_resnum, phy_irqnum; - int ret; - -- if (!phydev->dev.of_node) -+ if (!phydev->bus || !phydev->bus->parent) - return -EINVAL; - -- pdev = of_find_device_by_node(phydev->dev.of_node); -- if (!pdev) -- return -EINVAL; -- dev = &pdev->dev; -- -- wq_name = kasprintf(GFP_KERNEL, "%s-amd-xgbe-phy", phydev->bus->name); -- if (!wq_name) { -- ret = -ENOMEM; -- goto err_pdev; -- } -+ dev = phydev->bus->parent; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); -- if (!priv) { -- ret = -ENOMEM; -- goto err_name; -- } -+ if (!priv) -+ return -ENOMEM; - -- priv->pdev = pdev; -+ priv->pdev = to_platform_device(dev); -+ priv->adev = ACPI_COMPANION(dev); - priv->dev = dev; - priv->phydev = phydev; -+ mutex_init(&priv->an_mutex); -+ INIT_WORK(&priv->an_irq_work, amd_xgbe_an_irq_work); -+ INIT_WORK(&priv->an_work, amd_xgbe_an_state_machine); -+ -+ if (!priv->adev || acpi_disabled) { -+ struct device_node *bus_node; -+ struct device_node *phy_node; -+ -+ bus_node = priv->dev->of_node; -+ phy_node = of_parse_phandle(bus_node, "phy-handle", 0); -+ if (!phy_node) { -+ dev_err(dev, "unable to parse phy-handle\n"); -+ ret = -EINVAL; -+ goto err_priv; -+ } -+ -+ phy_pdev = of_find_device_by_node(phy_node); -+ of_node_put(phy_node); -+ -+ if (!phy_pdev) { -+ dev_err(dev, "unable to obtain phy device\n"); -+ ret = -EINVAL; -+ goto err_priv; -+ } -+ -+ phy_resnum = 0; -+ phy_irqnum = 0; -+ } else { -+ /* In ACPI, the XGBE and PHY resources are the grouped -+ * together with the PHY resources at the end -+ */ -+ phy_pdev = priv->pdev; -+ phy_resnum = amd_xgbe_phy_resource_count(phy_pdev, -+ IORESOURCE_MEM) - 3; -+ phy_irqnum = amd_xgbe_phy_resource_count(phy_pdev, -+ IORESOURCE_IRQ) - 1; -+ } -+ phy_dev = &phy_pdev->dev; - - /* Get the device mmio areas */ -- priv->rxtx_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ priv->rxtx_res = platform_get_resource(phy_pdev, IORESOURCE_MEM, -+ phy_resnum++); - priv->rxtx_regs = devm_ioremap_resource(dev, priv->rxtx_res); - if (IS_ERR(priv->rxtx_regs)) { - dev_err(dev, "rxtx ioremap failed\n"); - ret = PTR_ERR(priv->rxtx_regs); -- goto err_priv; -+ goto err_put; - } - -- priv->sir0_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); -+ priv->sir0_res = platform_get_resource(phy_pdev, IORESOURCE_MEM, -+ phy_resnum++); - priv->sir0_regs = devm_ioremap_resource(dev, priv->sir0_res); - if (IS_ERR(priv->sir0_regs)) { - dev_err(dev, "sir0 ioremap failed\n"); -@@ -1340,7 +1652,8 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev) - goto err_rxtx; - } - -- priv->sir1_res = platform_get_resource(pdev, IORESOURCE_MEM, 2); -+ priv->sir1_res = platform_get_resource(phy_pdev, IORESOURCE_MEM, -+ phy_resnum++); - priv->sir1_regs = devm_ioremap_resource(dev, priv->sir1_res); - if (IS_ERR(priv->sir1_regs)) { - dev_err(dev, "sir1 ioremap failed\n"); -@@ -1348,40 +1661,153 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev) - goto err_sir0; - } - -+ /* Get the auto-negotiation interrupt */ -+ ret = platform_get_irq(phy_pdev, phy_irqnum); -+ if (ret < 0) { -+ dev_err(dev, "platform_get_irq failed\n"); -+ goto err_sir1; -+ } -+ priv->an_irq = ret; -+ - /* Get the device speed set property */ -- speed_set = 0; -- property = of_get_property(dev->of_node, XGBE_PHY_SPEEDSET_PROPERTY, -- NULL); -- if (property) -- speed_set = be32_to_cpu(*property); -- -- switch (speed_set) { -- case 0: -- priv->speed_set = AMD_XGBE_PHY_SPEEDSET_1000_10000; -- break; -- case 1: -- priv->speed_set = AMD_XGBE_PHY_SPEEDSET_2500_10000; -+ ret = device_property_read_u32(phy_dev, XGBE_PHY_SPEEDSET_PROPERTY, -+ &priv->speed_set); -+ if (ret) { -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_SPEEDSET_PROPERTY); -+ goto err_sir1; -+ } -+ -+ switch (priv->speed_set) { -+ case AMD_XGBE_PHY_SPEEDSET_1000_10000: -+ case AMD_XGBE_PHY_SPEEDSET_2500_10000: - break; - default: -- dev_err(dev, "invalid amd,speed-set property\n"); -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_SPEEDSET_PROPERTY); - ret = -EINVAL; - goto err_sir1; - } - -- priv->link = 1; -+ if (device_property_present(phy_dev, XGBE_PHY_BLWC_PROPERTY)) { -+ ret = device_property_read_u32_array(phy_dev, -+ XGBE_PHY_BLWC_PROPERTY, -+ priv->serdes_blwc, -+ XGBE_PHY_SPEEDS); -+ if (ret) { -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_BLWC_PROPERTY); -+ goto err_sir1; -+ } -+ } else { -+ memcpy(priv->serdes_blwc, amd_xgbe_phy_serdes_blwc, -+ sizeof(priv->serdes_blwc)); -+ } - -- mutex_init(&priv->an_mutex); -- INIT_WORK(&priv->an_work, amd_xgbe_an_state_machine); -- priv->an_workqueue = create_singlethread_workqueue(wq_name); -- if (!priv->an_workqueue) { -- ret = -ENOMEM; -- goto err_sir1; -+ if (device_property_present(phy_dev, XGBE_PHY_CDR_RATE_PROPERTY)) { -+ ret = device_property_read_u32_array(phy_dev, -+ XGBE_PHY_CDR_RATE_PROPERTY, -+ priv->serdes_cdr_rate, -+ XGBE_PHY_SPEEDS); -+ if (ret) { -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_CDR_RATE_PROPERTY); -+ goto err_sir1; -+ } -+ } else { -+ memcpy(priv->serdes_cdr_rate, amd_xgbe_phy_serdes_cdr_rate, -+ sizeof(priv->serdes_cdr_rate)); -+ } -+ -+ if (device_property_present(phy_dev, XGBE_PHY_PQ_SKEW_PROPERTY)) { -+ ret = device_property_read_u32_array(phy_dev, -+ XGBE_PHY_PQ_SKEW_PROPERTY, -+ priv->serdes_pq_skew, -+ XGBE_PHY_SPEEDS); -+ if (ret) { -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_PQ_SKEW_PROPERTY); -+ goto err_sir1; -+ } -+ } else { -+ memcpy(priv->serdes_pq_skew, amd_xgbe_phy_serdes_pq_skew, -+ sizeof(priv->serdes_pq_skew)); -+ } -+ -+ if (device_property_present(phy_dev, XGBE_PHY_TX_AMP_PROPERTY)) { -+ ret = device_property_read_u32_array(phy_dev, -+ XGBE_PHY_TX_AMP_PROPERTY, -+ priv->serdes_tx_amp, -+ XGBE_PHY_SPEEDS); -+ if (ret) { -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_TX_AMP_PROPERTY); -+ goto err_sir1; -+ } -+ } else { -+ memcpy(priv->serdes_tx_amp, amd_xgbe_phy_serdes_tx_amp, -+ sizeof(priv->serdes_tx_amp)); -+ } -+ -+ if (device_property_present(phy_dev, XGBE_PHY_DFE_CFG_PROPERTY)) { -+ ret = device_property_read_u32_array(phy_dev, -+ XGBE_PHY_DFE_CFG_PROPERTY, -+ priv->serdes_dfe_tap_cfg, -+ XGBE_PHY_SPEEDS); -+ if (ret) { -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_DFE_CFG_PROPERTY); -+ goto err_sir1; -+ } -+ } else { -+ memcpy(priv->serdes_dfe_tap_cfg, -+ amd_xgbe_phy_serdes_dfe_tap_cfg, -+ sizeof(priv->serdes_dfe_tap_cfg)); - } - -+ if (device_property_present(phy_dev, XGBE_PHY_DFE_ENA_PROPERTY)) { -+ ret = device_property_read_u32_array(phy_dev, -+ XGBE_PHY_DFE_ENA_PROPERTY, -+ priv->serdes_dfe_tap_ena, -+ XGBE_PHY_SPEEDS); -+ if (ret) { -+ dev_err(dev, "invalid %s property\n", -+ XGBE_PHY_DFE_ENA_PROPERTY); -+ goto err_sir1; -+ } -+ } else { -+ memcpy(priv->serdes_dfe_tap_ena, -+ amd_xgbe_phy_serdes_dfe_tap_ena, -+ sizeof(priv->serdes_dfe_tap_ena)); -+ } -+ -+ /* Initialize supported features */ -+ phydev->supported = SUPPORTED_Autoneg; -+ phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; -+ phydev->supported |= SUPPORTED_Backplane; -+ phydev->supported |= SUPPORTED_10000baseKR_Full; -+ switch (priv->speed_set) { -+ case AMD_XGBE_PHY_SPEEDSET_1000_10000: -+ phydev->supported |= SUPPORTED_1000baseKX_Full; -+ break; -+ case AMD_XGBE_PHY_SPEEDSET_2500_10000: -+ phydev->supported |= SUPPORTED_2500baseX_Full; -+ break; -+ } -+ -+ ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FEC_ABILITY); -+ if (ret < 0) -+ return ret; -+ priv->fec_ability = ret & XGBE_PHY_FEC_MASK; -+ if (priv->fec_ability & XGBE_PHY_FEC_ENABLE) -+ phydev->supported |= SUPPORTED_10000baseR_FEC; -+ -+ phydev->advertising = phydev->supported; -+ - phydev->priv = priv; - -- kfree(wq_name); -- of_dev_put(pdev); -+ if (!priv->adev || acpi_disabled) -+ platform_device_put(phy_pdev); - - return 0; - -@@ -1400,15 +1826,13 @@ err_rxtx: - devm_release_mem_region(dev, priv->rxtx_res->start, - resource_size(priv->rxtx_res)); - -+err_put: -+ if (!priv->adev || acpi_disabled) -+ platform_device_put(phy_pdev); -+ - err_priv: - devm_kfree(dev, priv); - --err_name: -- kfree(wq_name); -- --err_pdev: -- of_dev_put(pdev); -- - return ret; - } - -@@ -1417,13 +1841,12 @@ static void amd_xgbe_phy_remove(struct phy_device *phydev) - struct amd_xgbe_phy_priv *priv = phydev->priv; - struct device *dev = priv->dev; - -- /* Stop any in process auto-negotiation */ -- mutex_lock(&priv->an_mutex); -- priv->an_state = AMD_XGBE_AN_EXIT; -- mutex_unlock(&priv->an_mutex); -+ if (priv->an_irq_allocated) { -+ devm_free_irq(dev, priv->an_irq, priv); - -- flush_workqueue(priv->an_workqueue); -- destroy_workqueue(priv->an_workqueue); -+ flush_workqueue(priv->an_workqueue); -+ destroy_workqueue(priv->an_workqueue); -+ } - - /* Release resources */ - devm_iounmap(dev, priv->sir1_regs); -@@ -1452,6 +1875,7 @@ static struct phy_driver amd_xgbe_phy_driver[] = { - .phy_id_mask = XGBE_PHY_MASK, - .name = "AMD XGBE PHY", - .features = 0, -+ .flags = PHY_IS_INTERNAL, - .probe = amd_xgbe_phy_probe, - .remove = amd_xgbe_phy_remove, - .soft_reset = amd_xgbe_phy_soft_reset, -diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h -index abcafaa..6bdf476 100644 ---- a/include/linux/clocksource.h -+++ b/include/linux/clocksource.h -@@ -87,6 +87,15 @@ static inline u64 cyclecounter_cyc2ns(const struct cyclecounter *cc, - } - - /** -+ * timecounter_adjtime - Shifts the time of the clock. -+ * @delta: Desired change in nanoseconds. -+ */ -+static inline void timecounter_adjtime(struct timecounter *tc, s64 delta) -+{ -+ tc->nsec += delta; -+} -+ -+/** - * timecounter_init - initialize a time counter - * @tc: Pointer to time counter which is to be initialized/reset - * @cc: A cycle counter, ready to be used. --- -1.9.1 - |