Merge branch 'amd-xgbe-next'
Tom Lendacky says: ==================== amd-xgbe: AMD XGBE driver updates 2015-03-19 The following series of patches includes functional updates and changes to the driver. - Use the phydev->advertising field instead of the phydev->supported field when configuring for auto-negotiation, etc. - Use the phy_driver flags field for setting the transceiver type instead of hardcoding it in the ethtool support. - Provide an auto-negotiation timeout check - Clarify the Tx/Rx queue information messages - Use the new DMA memory barrier operations - Set the device DMA mask based on what the hardware reports - Remove the software implementation of Tx coalescing - Fix the reporting of the Rx coalescing value - Use napi_alloc_skb when allocating an SKB in softirq This patch series is based on net-next. Changes from v2: - Use jiffies instead of timespec for the auto-negotiation timeout check - Remove the Rx path SKB allocation re-work patch since we should only inline the headers and the current code guards better against any hardware bugs Changes from v1: - Default to 32-bit DMA width (minimum supported) if hardware returns an unexpected DMA width value ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
b4c11cb437
@ -365,6 +365,8 @@
|
|||||||
#define MAC_HWF0R_TXCOESEL_WIDTH 1
|
#define MAC_HWF0R_TXCOESEL_WIDTH 1
|
||||||
#define MAC_HWF0R_VLHASH_INDEX 4
|
#define MAC_HWF0R_VLHASH_INDEX 4
|
||||||
#define MAC_HWF0R_VLHASH_WIDTH 1
|
#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_INDEX 13
|
||||||
#define MAC_HWF1R_ADVTHWORD_WIDTH 1
|
#define MAC_HWF1R_ADVTHWORD_WIDTH 1
|
||||||
#define MAC_HWF1R_DBGMEMA_INDEX 19
|
#define MAC_HWF1R_DBGMEMA_INDEX 19
|
||||||
|
@ -1068,7 +1068,7 @@ static void xgbe_tx_desc_reset(struct xgbe_ring_data *rdata)
|
|||||||
rdesc->desc3 = 0;
|
rdesc->desc3 = 0;
|
||||||
|
|
||||||
/* Make sure ownership is written to the descriptor */
|
/* Make sure ownership is written to the descriptor */
|
||||||
wmb();
|
dma_wmb();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xgbe_tx_desc_init(struct xgbe_channel *channel)
|
static void xgbe_tx_desc_init(struct xgbe_channel *channel)
|
||||||
@ -1124,12 +1124,12 @@ static void xgbe_rx_desc_reset(struct xgbe_ring_data *rdata)
|
|||||||
* is written to the descriptor(s) before setting the OWN bit
|
* is written to the descriptor(s) before setting the OWN bit
|
||||||
* for the descriptor
|
* for the descriptor
|
||||||
*/
|
*/
|
||||||
wmb();
|
dma_wmb();
|
||||||
|
|
||||||
XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, OWN, 1);
|
XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, OWN, 1);
|
||||||
|
|
||||||
/* Make sure ownership is written to the descriptor */
|
/* Make sure ownership is written to the descriptor */
|
||||||
wmb();
|
dma_wmb();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xgbe_rx_desc_init(struct xgbe_channel *channel)
|
static void xgbe_rx_desc_init(struct xgbe_channel *channel)
|
||||||
@ -1358,18 +1358,20 @@ static void xgbe_tx_start_xmit(struct xgbe_channel *channel,
|
|||||||
struct xgbe_prv_data *pdata = channel->pdata;
|
struct xgbe_prv_data *pdata = channel->pdata;
|
||||||
struct xgbe_ring_data *rdata;
|
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
|
/* Issue a poll command to Tx DMA by writing address
|
||||||
* of next immediate free descriptor */
|
* of next immediate free descriptor */
|
||||||
rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
|
rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
|
||||||
XGMAC_DMA_IOWRITE(channel, DMA_CH_TDTR_LO,
|
XGMAC_DMA_IOWRITE(channel, DMA_CH_TDTR_LO,
|
||||||
lower_32_bits(rdata->rdesc_dma));
|
lower_32_bits(rdata->rdesc_dma));
|
||||||
|
|
||||||
/* Start the Tx coalescing timer */
|
/* Start the Tx timer */
|
||||||
if (pdata->tx_usecs && !channel->tx_timer_active) {
|
if (pdata->tx_usecs && !channel->tx_timer_active) {
|
||||||
channel->tx_timer_active = 1;
|
channel->tx_timer_active = 1;
|
||||||
hrtimer_start(&channel->tx_timer,
|
mod_timer(&channel->tx_timer,
|
||||||
ktime_set(0, pdata->tx_usecs * NSEC_PER_USEC),
|
jiffies + usecs_to_jiffies(pdata->tx_usecs));
|
||||||
HRTIMER_MODE_REL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ring->tx.xmit_more = 0;
|
ring->tx.xmit_more = 0;
|
||||||
@ -1565,7 +1567,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
|
|||||||
* is written to the descriptor(s) before setting the OWN bit
|
* is written to the descriptor(s) before setting the OWN bit
|
||||||
* for the first descriptor
|
* for the first descriptor
|
||||||
*/
|
*/
|
||||||
wmb();
|
dma_wmb();
|
||||||
|
|
||||||
/* Set OWN bit for the first descriptor */
|
/* Set OWN bit for the first descriptor */
|
||||||
rdata = XGBE_GET_DESC_DATA(ring, start_index);
|
rdata = XGBE_GET_DESC_DATA(ring, start_index);
|
||||||
@ -1577,7 +1579,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Make sure ownership is written to the descriptor */
|
/* Make sure ownership is written to the descriptor */
|
||||||
wmb();
|
dma_wmb();
|
||||||
|
|
||||||
ring->cur = cur_index + 1;
|
ring->cur = cur_index + 1;
|
||||||
if (!packet->skb->xmit_more ||
|
if (!packet->skb->xmit_more ||
|
||||||
@ -1613,7 +1615,7 @@ static int xgbe_dev_read(struct xgbe_channel *channel)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Make sure descriptor fields are read after reading the OWN bit */
|
/* Make sure descriptor fields are read after reading the OWN bit */
|
||||||
rmb();
|
dma_rmb();
|
||||||
|
|
||||||
#ifdef XGMAC_ENABLE_RX_DESC_DUMP
|
#ifdef XGMAC_ENABLE_RX_DESC_DUMP
|
||||||
xgbe_dump_rx_desc(ring, rdesc, ring->cur);
|
xgbe_dump_rx_desc(ring, rdesc, ring->cur);
|
||||||
@ -2004,7 +2006,8 @@ static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata)
|
|||||||
for (i = 0; i < pdata->tx_q_count; i++)
|
for (i = 0; i < pdata->tx_q_count; i++)
|
||||||
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TQS, fifo_size);
|
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));
|
pdata->tx_q_count, ((fifo_size + 1) * 256));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2019,7 +2022,8 @@ static void xgbe_config_rx_fifo_size(struct xgbe_prv_data *pdata)
|
|||||||
for (i = 0; i < pdata->rx_q_count; i++)
|
for (i = 0; i < pdata->rx_q_count; i++)
|
||||||
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RQS, fifo_size);
|
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));
|
pdata->rx_q_count, ((fifo_size + 1) * 256));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,11 +411,9 @@ static irqreturn_t xgbe_dma_isr(int irq, void *data)
|
|||||||
return IRQ_HANDLED;
|
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 *channel = (struct xgbe_channel *)data;
|
||||||
struct xgbe_channel,
|
|
||||||
tx_timer);
|
|
||||||
struct xgbe_prv_data *pdata = channel->pdata;
|
struct xgbe_prv_data *pdata = channel->pdata;
|
||||||
struct napi_struct *napi;
|
struct napi_struct *napi;
|
||||||
|
|
||||||
@ -437,8 +435,6 @@ static enum hrtimer_restart xgbe_tx_timer(struct hrtimer *timer)
|
|||||||
channel->tx_timer_active = 0;
|
channel->tx_timer_active = 0;
|
||||||
|
|
||||||
DBGPR("<--xgbe_tx_timer\n");
|
DBGPR("<--xgbe_tx_timer\n");
|
||||||
|
|
||||||
return HRTIMER_NORESTART;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xgbe_init_tx_timers(struct xgbe_prv_data *pdata)
|
static void xgbe_init_tx_timers(struct xgbe_prv_data *pdata)
|
||||||
@ -454,9 +450,8 @@ static void xgbe_init_tx_timers(struct xgbe_prv_data *pdata)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
DBGPR(" %s adding tx timer\n", channel->name);
|
DBGPR(" %s adding tx timer\n", channel->name);
|
||||||
hrtimer_init(&channel->tx_timer, CLOCK_MONOTONIC,
|
setup_timer(&channel->tx_timer, xgbe_tx_timer,
|
||||||
HRTIMER_MODE_REL);
|
(unsigned long)channel);
|
||||||
channel->tx_timer.function = xgbe_tx_timer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBGPR("<--xgbe_init_tx_timers\n");
|
DBGPR("<--xgbe_init_tx_timers\n");
|
||||||
@ -475,8 +470,7 @@ static void xgbe_stop_tx_timers(struct xgbe_prv_data *pdata)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
DBGPR(" %s deleting tx timer\n", channel->name);
|
DBGPR(" %s deleting tx timer\n", channel->name);
|
||||||
channel->tx_timer_active = 0;
|
del_timer_sync(&channel->tx_timer);
|
||||||
hrtimer_cancel(&channel->tx_timer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBGPR("<--xgbe_stop_tx_timers\n");
|
DBGPR("<--xgbe_stop_tx_timers\n");
|
||||||
@ -519,6 +513,7 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata)
|
|||||||
RXFIFOSIZE);
|
RXFIFOSIZE);
|
||||||
hw_feat->tx_fifo_size = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R,
|
hw_feat->tx_fifo_size = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R,
|
||||||
TXFIFOSIZE);
|
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->dcb = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, DCBEN);
|
||||||
hw_feat->sph = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, SPHEN);
|
hw_feat->sph = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, SPHEN);
|
||||||
hw_feat->tso = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, TSOEN);
|
hw_feat->tso = XGMAC_GET_BITS(mac_hfr1, MAC_HWF1R, TSOEN);
|
||||||
@ -553,6 +548,21 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata)
|
|||||||
break;
|
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
|
/* The Queue, Channel and TC counts are zero based so increment them
|
||||||
* to get the actual number
|
* to get the actual number
|
||||||
*/
|
*/
|
||||||
@ -692,6 +702,7 @@ void xgbe_init_rx_coalesce(struct xgbe_prv_data *pdata)
|
|||||||
DBGPR("-->xgbe_init_rx_coalesce\n");
|
DBGPR("-->xgbe_init_rx_coalesce\n");
|
||||||
|
|
||||||
pdata->rx_riwt = hw_if->usec_to_riwt(pdata, XGMAC_INIT_DMA_RX_USECS);
|
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;
|
pdata->rx_frames = XGMAC_INIT_DMA_RX_FRAMES;
|
||||||
|
|
||||||
hw_if->config_rx_coalesce(pdata);
|
hw_if->config_rx_coalesce(pdata);
|
||||||
@ -1800,6 +1811,9 @@ static void xgbe_rx_refresh(struct xgbe_channel *channel)
|
|||||||
ring->dirty++;
|
ring->dirty++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure everything is written before the register write */
|
||||||
|
wmb();
|
||||||
|
|
||||||
/* Update the Rx Tail Pointer Register with address of
|
/* Update the Rx Tail Pointer Register with address of
|
||||||
* the last cleaned entry */
|
* the last cleaned entry */
|
||||||
rdata = XGBE_GET_DESC_DATA(ring, ring->dirty - 1);
|
rdata = XGBE_GET_DESC_DATA(ring, ring->dirty - 1);
|
||||||
@ -1807,16 +1821,15 @@ static void xgbe_rx_refresh(struct xgbe_channel *channel)
|
|||||||
lower_32_bits(rdata->rdesc_dma));
|
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,
|
struct xgbe_ring_data *rdata,
|
||||||
unsigned int *len)
|
unsigned int *len)
|
||||||
{
|
{
|
||||||
struct net_device *netdev = pdata->netdev;
|
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
u8 *packet;
|
u8 *packet;
|
||||||
unsigned int copy_len;
|
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)
|
if (!skb)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -1863,7 +1876,7 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
|
|||||||
|
|
||||||
/* Make sure descriptor fields are read after reading the OWN
|
/* Make sure descriptor fields are read after reading the OWN
|
||||||
* bit */
|
* bit */
|
||||||
rmb();
|
dma_rmb();
|
||||||
|
|
||||||
#ifdef XGMAC_ENABLE_TX_DESC_DUMP
|
#ifdef XGMAC_ENABLE_TX_DESC_DUMP
|
||||||
xgbe_dump_tx_desc(ring, ring->dirty, 1, 0);
|
xgbe_dump_tx_desc(ring, ring->dirty, 1, 0);
|
||||||
@ -1986,7 +1999,7 @@ read_again:
|
|||||||
rdata->rx.hdr.dma_len,
|
rdata->rx.hdr.dma_len,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
|
|
||||||
skb = xgbe_create_skb(pdata, rdata, &put_len);
|
skb = xgbe_create_skb(napi, rdata, &put_len);
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
error = 1;
|
error = 1;
|
||||||
goto skip_data;
|
goto skip_data;
|
||||||
|
@ -291,7 +291,6 @@ static int xgbe_get_settings(struct net_device *netdev,
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
ret = phy_ethtool_gset(pdata->phydev, cmd);
|
ret = phy_ethtool_gset(pdata->phydev, cmd);
|
||||||
cmd->transceiver = XCVR_EXTERNAL;
|
|
||||||
|
|
||||||
DBGPR("<--xgbe_get_settings\n");
|
DBGPR("<--xgbe_get_settings\n");
|
||||||
|
|
||||||
@ -378,18 +377,14 @@ static int xgbe_get_coalesce(struct net_device *netdev,
|
|||||||
struct ethtool_coalesce *ec)
|
struct ethtool_coalesce *ec)
|
||||||
{
|
{
|
||||||
struct xgbe_prv_data *pdata = netdev_priv(netdev);
|
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");
|
DBGPR("-->xgbe_get_coalesce\n");
|
||||||
|
|
||||||
memset(ec, 0, sizeof(struct ethtool_coalesce));
|
memset(ec, 0, sizeof(struct ethtool_coalesce));
|
||||||
|
|
||||||
riwt = pdata->rx_riwt;
|
ec->rx_coalesce_usecs = pdata->rx_usecs;
|
||||||
ec->rx_coalesce_usecs = hw_if->riwt_to_usec(pdata, riwt);
|
|
||||||
ec->rx_max_coalesced_frames = pdata->rx_frames;
|
ec->rx_max_coalesced_frames = pdata->rx_frames;
|
||||||
|
|
||||||
ec->tx_coalesce_usecs = pdata->tx_usecs;
|
|
||||||
ec->tx_max_coalesced_frames = pdata->tx_frames;
|
ec->tx_max_coalesced_frames = pdata->tx_frames;
|
||||||
|
|
||||||
DBGPR("<--xgbe_get_coalesce\n");
|
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_prv_data *pdata = netdev_priv(netdev);
|
||||||
struct xgbe_hw_if *hw_if = &pdata->hw_if;
|
struct xgbe_hw_if *hw_if = &pdata->hw_if;
|
||||||
unsigned int rx_frames, rx_riwt, rx_usecs;
|
unsigned int rx_frames, rx_riwt, rx_usecs;
|
||||||
unsigned int tx_frames, tx_usecs;
|
unsigned int tx_frames;
|
||||||
|
|
||||||
DBGPR("-->xgbe_set_coalesce\n");
|
DBGPR("-->xgbe_set_coalesce\n");
|
||||||
|
|
||||||
/* Check for not supported parameters */
|
/* Check for not supported parameters */
|
||||||
if ((ec->rx_coalesce_usecs_irq) ||
|
if ((ec->rx_coalesce_usecs_irq) ||
|
||||||
(ec->rx_max_coalesced_frames_irq) ||
|
(ec->rx_max_coalesced_frames_irq) ||
|
||||||
|
(ec->tx_coalesce_usecs) ||
|
||||||
(ec->tx_coalesce_usecs_irq) ||
|
(ec->tx_coalesce_usecs_irq) ||
|
||||||
(ec->tx_max_coalesced_frames_irq) ||
|
(ec->tx_max_coalesced_frames_irq) ||
|
||||||
(ec->stats_block_coalesce_usecs) ||
|
(ec->stats_block_coalesce_usecs) ||
|
||||||
@ -439,17 +435,17 @@ static int xgbe_set_coalesce(struct net_device *netdev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rx_riwt = hw_if->usec_to_riwt(pdata, ec->rx_coalesce_usecs);
|
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;
|
rx_frames = ec->rx_max_coalesced_frames;
|
||||||
|
|
||||||
/* Use smallest possible value if conversion resulted in zero */
|
/* Use smallest possible value if conversion resulted in zero */
|
||||||
if (ec->rx_coalesce_usecs && !rx_riwt)
|
if (rx_usecs && !rx_riwt)
|
||||||
rx_riwt = 1;
|
rx_riwt = 1;
|
||||||
|
|
||||||
/* Check the bounds of values for Rx */
|
/* Check the bounds of values for Rx */
|
||||||
if (rx_riwt > XGMAC_MAX_DMA_RIWT) {
|
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",
|
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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (rx_frames > pdata->rx_desc_count) {
|
if (rx_frames > pdata->rx_desc_count) {
|
||||||
@ -458,7 +454,6 @@ static int xgbe_set_coalesce(struct net_device *netdev,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tx_usecs = ec->tx_coalesce_usecs;
|
|
||||||
tx_frames = ec->tx_max_coalesced_frames;
|
tx_frames = ec->tx_max_coalesced_frames;
|
||||||
|
|
||||||
/* Check the bounds of values for Tx */
|
/* Check the bounds of values for Tx */
|
||||||
@ -469,10 +464,10 @@ static int xgbe_set_coalesce(struct net_device *netdev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pdata->rx_riwt = rx_riwt;
|
pdata->rx_riwt = rx_riwt;
|
||||||
|
pdata->rx_usecs = rx_usecs;
|
||||||
pdata->rx_frames = rx_frames;
|
pdata->rx_frames = rx_frames;
|
||||||
hw_if->config_rx_coalesce(pdata);
|
hw_if->config_rx_coalesce(pdata);
|
||||||
|
|
||||||
pdata->tx_usecs = tx_usecs;
|
|
||||||
pdata->tx_frames = tx_frames;
|
pdata->tx_frames = tx_frames;
|
||||||
hw_if->config_tx_coalesce(pdata);
|
hw_if->config_tx_coalesce(pdata);
|
||||||
|
|
||||||
|
@ -374,15 +374,6 @@ static int xgbe_probe(struct platform_device *pdev)
|
|||||||
pdata->awcache = XGBE_DMA_SYS_AWCACHE;
|
pdata->awcache = XGBE_DMA_SYS_AWCACHE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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");
|
|
||||||
goto err_io;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the device interrupt */
|
/* Get the device interrupt */
|
||||||
ret = platform_get_irq(pdev, 0);
|
ret = platform_get_irq(pdev, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -409,6 +400,16 @@ static int xgbe_probe(struct platform_device *pdev)
|
|||||||
/* Set default configuration data */
|
/* Set default configuration data */
|
||||||
xgbe_default_config(pdata);
|
xgbe_default_config(pdata);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate the number of Tx and Rx rings to be created
|
/* Calculate the number of Tx and Rx rings to be created
|
||||||
* -Tx (DMA) Channels map 1-to-1 to Tx Queues so set
|
* -Tx (DMA) Channels map 1-to-1 to Tx Queues so set
|
||||||
* the number of Tx queues to the number of Tx channels
|
* the number of Tx queues to the number of Tx channels
|
||||||
|
@ -222,7 +222,7 @@
|
|||||||
((_idx) & ((_ring)->rdesc_count - 1)))
|
((_idx) & ((_ring)->rdesc_count - 1)))
|
||||||
|
|
||||||
/* Default coalescing parameters */
|
/* Default coalescing parameters */
|
||||||
#define XGMAC_INIT_DMA_TX_USECS 50
|
#define XGMAC_INIT_DMA_TX_USECS 1000
|
||||||
#define XGMAC_INIT_DMA_TX_FRAMES 25
|
#define XGMAC_INIT_DMA_TX_FRAMES 25
|
||||||
|
|
||||||
#define XGMAC_MAX_DMA_RIWT 0xff
|
#define XGMAC_MAX_DMA_RIWT 0xff
|
||||||
@ -410,7 +410,7 @@ struct xgbe_channel {
|
|||||||
unsigned int saved_ier;
|
unsigned int saved_ier;
|
||||||
|
|
||||||
unsigned int tx_timer_active;
|
unsigned int tx_timer_active;
|
||||||
struct hrtimer tx_timer;
|
struct timer_list tx_timer;
|
||||||
|
|
||||||
struct xgbe_ring *tx_ring;
|
struct xgbe_ring *tx_ring;
|
||||||
struct xgbe_ring *rx_ring;
|
struct xgbe_ring *rx_ring;
|
||||||
@ -632,6 +632,7 @@ struct xgbe_hw_features {
|
|||||||
unsigned int rx_fifo_size; /* MTL Receive FIFO Size */
|
unsigned int rx_fifo_size; /* MTL Receive FIFO Size */
|
||||||
unsigned int tx_fifo_size; /* MTL Transmit FIFO Size */
|
unsigned int tx_fifo_size; /* MTL Transmit FIFO Size */
|
||||||
unsigned int adv_ts_hi; /* Advance Timestamping High Word */
|
unsigned int adv_ts_hi; /* Advance Timestamping High Word */
|
||||||
|
unsigned int dma_width; /* DMA width */
|
||||||
unsigned int dcb; /* DCB Feature */
|
unsigned int dcb; /* DCB Feature */
|
||||||
unsigned int sph; /* Split Header Feature */
|
unsigned int sph; /* Split Header Feature */
|
||||||
unsigned int tso; /* TCP Segmentation Offload */
|
unsigned int tso; /* TCP Segmentation Offload */
|
||||||
@ -715,6 +716,7 @@ struct xgbe_prv_data {
|
|||||||
|
|
||||||
/* Rx coalescing settings */
|
/* Rx coalescing settings */
|
||||||
unsigned int rx_riwt;
|
unsigned int rx_riwt;
|
||||||
|
unsigned int rx_usecs;
|
||||||
unsigned int rx_frames;
|
unsigned int rx_frames;
|
||||||
|
|
||||||
/* Current Rx buffer size */
|
/* Current Rx buffer size */
|
||||||
|
@ -78,6 +78,7 @@
|
|||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/property.h>
|
#include <linux/property.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
|
||||||
MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>");
|
MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>");
|
||||||
MODULE_LICENSE("Dual BSD/GPL");
|
MODULE_LICENSE("Dual BSD/GPL");
|
||||||
@ -100,6 +101,8 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver");
|
|||||||
#define XGBE_PHY_SPEED_2500 1
|
#define XGBE_PHY_SPEED_2500 1
|
||||||
#define XGBE_PHY_SPEED_10000 2
|
#define XGBE_PHY_SPEED_10000 2
|
||||||
|
|
||||||
|
#define XGBE_AN_MS_TIMEOUT 500
|
||||||
|
|
||||||
#define XGBE_AN_INT_CMPLT 0x01
|
#define XGBE_AN_INT_CMPLT 0x01
|
||||||
#define XGBE_AN_INC_LINK 0x02
|
#define XGBE_AN_INC_LINK 0x02
|
||||||
#define XGBE_AN_PG_RCV 0x04
|
#define XGBE_AN_PG_RCV 0x04
|
||||||
@ -434,6 +437,7 @@ struct amd_xgbe_phy_priv {
|
|||||||
unsigned int an_supported;
|
unsigned int an_supported;
|
||||||
unsigned int parallel_detect;
|
unsigned int parallel_detect;
|
||||||
unsigned int fec_ability;
|
unsigned int fec_ability;
|
||||||
|
unsigned long an_start;
|
||||||
|
|
||||||
unsigned int lpm_ctrl; /* CTRL1 for resume */
|
unsigned int lpm_ctrl; /* CTRL1 for resume */
|
||||||
};
|
};
|
||||||
@ -902,8 +906,23 @@ static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev)
|
|||||||
{
|
{
|
||||||
struct amd_xgbe_phy_priv *priv = phydev->priv;
|
struct amd_xgbe_phy_priv *priv = phydev->priv;
|
||||||
enum amd_xgbe_phy_rx *state;
|
enum amd_xgbe_phy_rx *state;
|
||||||
|
unsigned long an_timeout;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!priv->an_start) {
|
||||||
|
priv->an_start = jiffies;
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
state = amd_xgbe_phy_in_kr_mode(phydev) ? &priv->kr_state
|
state = amd_xgbe_phy_in_kr_mode(phydev) ? &priv->kr_state
|
||||||
: &priv->kx_state;
|
: &priv->kx_state;
|
||||||
|
|
||||||
@ -932,8 +951,8 @@ static enum amd_xgbe_phy_an amd_xgbe_an_incompat_link(struct phy_device *phydev)
|
|||||||
if (amd_xgbe_phy_in_kr_mode(phydev)) {
|
if (amd_xgbe_phy_in_kr_mode(phydev)) {
|
||||||
priv->kr_state = AMD_XGBE_RX_ERROR;
|
priv->kr_state = AMD_XGBE_RX_ERROR;
|
||||||
|
|
||||||
if (!(phydev->supported & SUPPORTED_1000baseKX_Full) &&
|
if (!(phydev->advertising & SUPPORTED_1000baseKX_Full) &&
|
||||||
!(phydev->supported & SUPPORTED_2500baseX_Full))
|
!(phydev->advertising & SUPPORTED_2500baseX_Full))
|
||||||
return AMD_XGBE_AN_NO_LINK;
|
return AMD_XGBE_AN_NO_LINK;
|
||||||
|
|
||||||
if (priv->kx_state != AMD_XGBE_RX_BPA)
|
if (priv->kx_state != AMD_XGBE_RX_BPA)
|
||||||
@ -941,7 +960,7 @@ static enum amd_xgbe_phy_an amd_xgbe_an_incompat_link(struct phy_device *phydev)
|
|||||||
} else {
|
} else {
|
||||||
priv->kx_state = AMD_XGBE_RX_ERROR;
|
priv->kx_state = AMD_XGBE_RX_ERROR;
|
||||||
|
|
||||||
if (!(phydev->supported & SUPPORTED_10000baseKR_Full))
|
if (!(phydev->advertising & SUPPORTED_10000baseKR_Full))
|
||||||
return AMD_XGBE_AN_NO_LINK;
|
return AMD_XGBE_AN_NO_LINK;
|
||||||
|
|
||||||
if (priv->kr_state != AMD_XGBE_RX_BPA)
|
if (priv->kr_state != AMD_XGBE_RX_BPA)
|
||||||
@ -1078,6 +1097,7 @@ again:
|
|||||||
priv->an_state = AMD_XGBE_AN_READY;
|
priv->an_state = AMD_XGBE_AN_READY;
|
||||||
priv->kr_state = AMD_XGBE_RX_BPA;
|
priv->kr_state = AMD_XGBE_RX_BPA;
|
||||||
priv->kx_state = AMD_XGBE_RX_BPA;
|
priv->kx_state = AMD_XGBE_RX_BPA;
|
||||||
|
priv->an_start = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur_state != priv->an_state)
|
if (cur_state != priv->an_state)
|
||||||
@ -1101,7 +1121,7 @@ static int amd_xgbe_an_init(struct phy_device *phydev)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (phydev->supported & SUPPORTED_10000baseR_FEC)
|
if (phydev->advertising & SUPPORTED_10000baseR_FEC)
|
||||||
ret |= 0xc000;
|
ret |= 0xc000;
|
||||||
else
|
else
|
||||||
ret &= ~0xc000;
|
ret &= ~0xc000;
|
||||||
@ -1113,13 +1133,13 @@ static int amd_xgbe_an_init(struct phy_device *phydev)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (phydev->supported & SUPPORTED_10000baseKR_Full)
|
if (phydev->advertising & SUPPORTED_10000baseKR_Full)
|
||||||
ret |= 0x80;
|
ret |= 0x80;
|
||||||
else
|
else
|
||||||
ret &= ~0x80;
|
ret &= ~0x80;
|
||||||
|
|
||||||
if ((phydev->supported & SUPPORTED_1000baseKX_Full) ||
|
if ((phydev->advertising & SUPPORTED_1000baseKX_Full) ||
|
||||||
(phydev->supported & SUPPORTED_2500baseX_Full))
|
(phydev->advertising & SUPPORTED_2500baseX_Full))
|
||||||
ret |= 0x20;
|
ret |= 0x20;
|
||||||
else
|
else
|
||||||
ret &= ~0x20;
|
ret &= ~0x20;
|
||||||
@ -1131,12 +1151,12 @@ static int amd_xgbe_an_init(struct phy_device *phydev)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (phydev->supported & SUPPORTED_Pause)
|
if (phydev->advertising & SUPPORTED_Pause)
|
||||||
ret |= 0x400;
|
ret |= 0x400;
|
||||||
else
|
else
|
||||||
ret &= ~0x400;
|
ret &= ~0x400;
|
||||||
|
|
||||||
if (phydev->supported & SUPPORTED_Asym_Pause)
|
if (phydev->advertising & SUPPORTED_Asym_Pause)
|
||||||
ret |= 0x800;
|
ret |= 0x800;
|
||||||
else
|
else
|
||||||
ret &= ~0x800;
|
ret &= ~0x800;
|
||||||
@ -1212,38 +1232,14 @@ static int amd_xgbe_phy_config_init(struct phy_device *phydev)
|
|||||||
priv->an_irq_allocated = 1;
|
priv->an_irq_allocated = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->fec_ability & XGBE_PHY_FEC_ENABLE)
|
|
||||||
phydev->supported |= SUPPORTED_10000baseR_FEC;
|
|
||||||
|
|
||||||
phydev->advertising = phydev->supported;
|
|
||||||
|
|
||||||
/* Set initial mode - call the mode setting routines
|
/* Set initial mode - call the mode setting routines
|
||||||
* directly to insure we are properly configured
|
* directly to insure we are properly configured
|
||||||
*/
|
*/
|
||||||
if (phydev->supported & SUPPORTED_10000baseKR_Full)
|
if (phydev->advertising & SUPPORTED_10000baseKR_Full)
|
||||||
ret = amd_xgbe_phy_xgmii_mode(phydev);
|
ret = amd_xgbe_phy_xgmii_mode(phydev);
|
||||||
else if (phydev->supported & SUPPORTED_1000baseKX_Full)
|
else if (phydev->advertising & SUPPORTED_1000baseKX_Full)
|
||||||
ret = amd_xgbe_phy_gmii_mode(phydev);
|
ret = amd_xgbe_phy_gmii_mode(phydev);
|
||||||
else if (phydev->supported & SUPPORTED_2500baseX_Full)
|
else if (phydev->advertising & SUPPORTED_2500baseX_Full)
|
||||||
ret = amd_xgbe_phy_gmii_2500_mode(phydev);
|
ret = amd_xgbe_phy_gmii_2500_mode(phydev);
|
||||||
else
|
else
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
@ -1315,10 +1311,10 @@ static int __amd_xgbe_phy_config_aneg(struct phy_device *phydev)
|
|||||||
disable_irq(priv->an_irq);
|
disable_irq(priv->an_irq);
|
||||||
|
|
||||||
/* Start auto-negotiation in a supported mode */
|
/* Start auto-negotiation in a supported mode */
|
||||||
if (phydev->supported & SUPPORTED_10000baseKR_Full)
|
if (phydev->advertising & SUPPORTED_10000baseKR_Full)
|
||||||
ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KR);
|
ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KR);
|
||||||
else if ((phydev->supported & SUPPORTED_1000baseKX_Full) ||
|
else if ((phydev->advertising & SUPPORTED_1000baseKX_Full) ||
|
||||||
(phydev->supported & SUPPORTED_2500baseX_Full))
|
(phydev->advertising & SUPPORTED_2500baseX_Full))
|
||||||
ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX);
|
ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX);
|
||||||
else
|
else
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
@ -1746,6 +1742,29 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev)
|
|||||||
sizeof(priv->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;
|
phydev->priv = priv;
|
||||||
|
|
||||||
if (!priv->adev || acpi_disabled)
|
if (!priv->adev || acpi_disabled)
|
||||||
@ -1817,6 +1836,7 @@ static struct phy_driver amd_xgbe_phy_driver[] = {
|
|||||||
.phy_id_mask = XGBE_PHY_MASK,
|
.phy_id_mask = XGBE_PHY_MASK,
|
||||||
.name = "AMD XGBE PHY",
|
.name = "AMD XGBE PHY",
|
||||||
.features = 0,
|
.features = 0,
|
||||||
|
.flags = PHY_IS_INTERNAL,
|
||||||
.probe = amd_xgbe_phy_probe,
|
.probe = amd_xgbe_phy_probe,
|
||||||
.remove = amd_xgbe_phy_remove,
|
.remove = amd_xgbe_phy_remove,
|
||||||
.soft_reset = amd_xgbe_phy_soft_reset,
|
.soft_reset = amd_xgbe_phy_soft_reset,
|
||||||
|
Loading…
Reference in New Issue
Block a user