summaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r--drivers/net/sfc/efx.c28
-rw-r--r--drivers/net/sfc/efx.h5
-rw-r--r--drivers/net/sfc/ethtool.c2
-rw-r--r--drivers/net/sfc/ethtool.h2
-rw-r--r--drivers/net/sfc/falcon_hwdefs.h2
-rw-r--r--drivers/net/sfc/falcon_xmac.c8
-rw-r--r--drivers/net/sfc/net_driver.h7
-rw-r--r--drivers/net/sfc/selftest.c3
-rw-r--r--drivers/net/sfc/tx.c18
-rw-r--r--drivers/net/sfc/tx.h3
-rw-r--r--drivers/net/sfc/xfp_phy.c19
11 files changed, 59 insertions, 38 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 343e8da1fa3..07a7e4b8f8f 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1179,6 +1179,8 @@ static void efx_stop_all(struct efx_nic *efx)
/* Isolate the MAC from the TX and RX engines, so that queue
* flushes will complete in a timely fashion. */
+ falcon_deconfigure_mac_wrapper(efx);
+ msleep(10); /* Let the Rx FIFO drain */
falcon_drain_tx_fifo(efx);
/* Stop the kernel transmit interface late, so the watchdog
@@ -1614,21 +1616,24 @@ static int efx_register_netdev(struct efx_nic *efx)
SET_NETDEV_DEV(net_dev, &efx->pci_dev->dev);
SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
- /* Always start with carrier off; PHY events will detect the link */
- netif_carrier_off(efx->net_dev);
-
/* Clear MAC statistics */
efx->mac_op->update_stats(efx);
memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
- rc = register_netdev(net_dev);
- if (rc) {
- EFX_ERR(efx, "could not register net dev\n");
- return rc;
- }
-
rtnl_lock();
+
+ rc = dev_alloc_name(net_dev, net_dev->name);
+ if (rc < 0)
+ goto fail_locked;
efx_update_name(efx);
+
+ rc = register_netdevice(net_dev);
+ if (rc)
+ goto fail_locked;
+
+ /* Always start with carrier off; PHY events will detect the link */
+ netif_carrier_off(efx->net_dev);
+
rtnl_unlock();
rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type);
@@ -1639,6 +1644,11 @@ static int efx_register_netdev(struct efx_nic *efx)
return 0;
+fail_locked:
+ rtnl_unlock();
+ EFX_ERR(efx, "could not register net dev\n");
+ return rc;
+
fail_registered:
unregister_netdev(net_dev);
return rc;
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index da157aa74b8..aecaf62f492 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -20,8 +20,9 @@
#define FALCON_B_P_DEVID 0x0710
/* TX */
-extern int efx_xmit(struct efx_nic *efx,
- struct efx_tx_queue *tx_queue, struct sk_buff *skb);
+extern netdev_tx_t efx_xmit(struct efx_nic *efx,
+ struct efx_tx_queue *tx_queue,
+ struct sk_buff *skb);
extern void efx_stop_queue(struct efx_nic *efx);
extern void efx_wake_queue(struct efx_nic *efx);
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index 997ea2a3d53..45018f283ff 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -731,7 +731,7 @@ static void efx_ethtool_get_pauseparam(struct net_device *net_dev,
}
-struct ethtool_ops efx_ethtool_ops = {
+const struct ethtool_ops efx_ethtool_ops = {
.get_settings = efx_ethtool_get_settings,
.set_settings = efx_ethtool_set_settings,
.get_drvinfo = efx_ethtool_get_drvinfo,
diff --git a/drivers/net/sfc/ethtool.h b/drivers/net/sfc/ethtool.h
index 3628e43df14..295ead40335 100644
--- a/drivers/net/sfc/ethtool.h
+++ b/drivers/net/sfc/ethtool.h
@@ -22,6 +22,6 @@ extern int efx_ethtool_get_settings(struct net_device *net_dev,
extern int efx_ethtool_set_settings(struct net_device *net_dev,
struct ethtool_cmd *ecmd);
-extern struct ethtool_ops efx_ethtool_ops;
+extern const struct ethtool_ops efx_ethtool_ops;
#endif /* EFX_ETHTOOL_H */
diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h
index 375e2a5961e..2d2261117ac 100644
--- a/drivers/net/sfc/falcon_hwdefs.h
+++ b/drivers/net/sfc/falcon_hwdefs.h
@@ -700,6 +700,8 @@
/* XGXS/XAUI powerdown/reset register */
#define XX_PWR_RST_REG 0x1300
+#define XX_SD_RST_ACT_LBN 16
+#define XX_SD_RST_ACT_WIDTH 1
#define XX_PWRDND_EN_LBN 15
#define XX_PWRDND_EN_WIDTH 1
#define XX_PWRDNC_EN_LBN 14
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index 2b3269c0326..bec52ca37ee 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -64,13 +64,15 @@ int falcon_reset_xaui(struct efx_nic *efx)
efx_oword_t reg;
int count;
+ /* Start reset sequence */
EFX_POPULATE_DWORD_1(reg, XX_RST_XX_EN, 1);
falcon_write(efx, &reg, XX_PWR_RST_REG);
- /* Give some time for the link to establish */
- for (count = 0; count < 1000; count++) { /* wait upto 10ms */
+ /* Wait up to 10 ms for completion, then reinitialise */
+ for (count = 0; count < 1000; count++) {
falcon_read(efx, &reg, XX_PWR_RST_REG);
- if (EFX_OWORD_FIELD(reg, XX_RST_XX_EN) == 0) {
+ if (EFX_OWORD_FIELD(reg, XX_RST_XX_EN) == 0 &&
+ EFX_OWORD_FIELD(reg, XX_SD_RST_ACT) == 0) {
falcon_setup_xaui(efx);
return 0;
}
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 5eabede9ac1..298566da638 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -984,9 +984,14 @@ static inline void clear_bit_le(unsigned nr, unsigned char *addr)
*
* The 10G MAC used in Falcon requires 8-byte alignment on the frame
* length, so we round up to the nearest 8.
+ *
+ * Re-clocking by the XGXS on RX can reduce an IPG to 32 bits (half an
+ * XGMII cycle). If the frame length reaches the maximum value in the
+ * same cycle, the XMAC can miss the IPG altogether. We work around
+ * this by adding a further 16 bytes.
*/
#define EFX_MAX_FRAME_LEN(mtu) \
- ((((mtu) + ETH_HLEN + VLAN_HLEN + 4/* FCS */) + 7) & ~7)
+ ((((mtu) + ETH_HLEN + VLAN_HLEN + 4/* FCS */ + 7) & ~7) + 16)
#endif /* EFX_NET_DRIVER_H */
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index b67ccca3fc1..817c7efc11e 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -400,7 +400,8 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
struct efx_loopback_state *state = efx->loopback_selftest;
struct efx_loopback_payload *payload;
struct sk_buff *skb;
- int i, rc;
+ int i;
+ netdev_tx_t rc;
/* Transmit N copies of buffer */
for (i = 0; i < state->packet_count; i++) {
diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c
index 14a14788566..489c4de3144 100644
--- a/drivers/net/sfc/tx.c
+++ b/drivers/net/sfc/tx.c
@@ -138,8 +138,8 @@ static void efx_tsoh_free(struct efx_tx_queue *tx_queue,
* Returns NETDEV_TX_OK or NETDEV_TX_BUSY
* You must hold netif_tx_lock() to call this function.
*/
-static int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
- struct sk_buff *skb)
+static netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue,
+ struct sk_buff *skb)
{
struct efx_nic *efx = tx_queue->efx;
struct pci_dev *pci_dev = efx->pci_dev;
@@ -152,7 +152,7 @@ static int efx_enqueue_skb(struct efx_tx_queue *tx_queue,
unsigned int dma_len;
bool unmap_single;
int q_space, i = 0;
- int rc = NETDEV_TX_OK;
+ netdev_tx_t rc = NETDEV_TX_OK;
EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count);
@@ -353,14 +353,11 @@ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue,
*
* Context: netif_tx_lock held
*/
-inline int efx_xmit(struct efx_nic *efx,
- struct efx_tx_queue *tx_queue, struct sk_buff *skb)
+inline netdev_tx_t efx_xmit(struct efx_nic *efx,
+ struct efx_tx_queue *tx_queue, struct sk_buff *skb)
{
- int rc;
-
/* Map fragments for DMA and add to TX queue */
- rc = efx_enqueue_skb(tx_queue, skb);
- return rc;
+ return efx_enqueue_skb(tx_queue, skb);
}
/* Initiate a packet transmission. We use one channel per CPU
@@ -372,7 +369,8 @@ inline int efx_xmit(struct efx_nic *efx,
* Note that returning anything other than NETDEV_TX_OK will cause the
* OS to free the skb.
*/
-int efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
+netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *net_dev)
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_tx_queue *tx_queue;
diff --git a/drivers/net/sfc/tx.h b/drivers/net/sfc/tx.h
index 5e1cc234e42..e3678962a5b 100644
--- a/drivers/net/sfc/tx.h
+++ b/drivers/net/sfc/tx.h
@@ -18,7 +18,8 @@ void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
void efx_init_tx_queue(struct efx_tx_queue *tx_queue);
void efx_fini_tx_queue(struct efx_tx_queue *tx_queue);
-int efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev);
+netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *net_dev);
void efx_release_tx_buffers(struct efx_tx_queue *tx_queue);
#endif /* EFX_TX_H */
diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c
index bb2e6afd082..e6b3d5eaddb 100644
--- a/drivers/net/sfc/xfp_phy.c
+++ b/drivers/net/sfc/xfp_phy.c
@@ -97,23 +97,24 @@ static int qt2025c_wait_reset(struct efx_nic *efx)
return 0;
}
-/* Reset the PHYXS MMD. This is documented (for the Quake PHYs) as doing
- * a complete soft reset.
- */
static int xfp_reset_phy(struct efx_nic *efx)
{
int rc;
- rc = efx_mdio_reset_mmd(efx, MDIO_MMD_PHYXS,
- XFP_MAX_RESET_TIME / XFP_RESET_WAIT,
- XFP_RESET_WAIT);
- if (rc < 0)
- goto fail;
-
if (efx->phy_type == PHY_TYPE_QT2025C) {
+ /* Wait for the reset triggered by falcon_reset_hw()
+ * to complete */
rc = qt2025c_wait_reset(efx);
if (rc < 0)
goto fail;
+ } else {
+ /* Reset the PHYXS MMD. This is documented as doing
+ * a complete soft reset. */
+ rc = efx_mdio_reset_mmd(efx, MDIO_MMD_PHYXS,
+ XFP_MAX_RESET_TIME / XFP_RESET_WAIT,
+ XFP_RESET_WAIT);
+ if (rc < 0)
+ goto fail;
}
/* Wait 250ms for the PHY to complete bootup */