mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-16 03:41:26 +00:00
Merge MVEBU to stable
This commit is contained in:
parent
5783fad9b5
commit
4af7efa568
39 changed files with 27696 additions and 30 deletions
|
@ -1,6 +1,6 @@
|
|||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Linux/arm 4.14.20 Kernel Configuration
|
||||
# Linux/arm 4.14.40 Kernel Configuration
|
||||
#
|
||||
CONFIG_ARM=y
|
||||
CONFIG_ARM_HAS_SG_CHAIN=y
|
||||
|
@ -482,7 +482,7 @@ CONFIG_CACHE_L2X0=y
|
|||
# CONFIG_CACHE_L2X0_PMU is not set
|
||||
# CONFIG_PL310_ERRATA_588369 is not set
|
||||
# CONFIG_PL310_ERRATA_727915 is not set
|
||||
# CONFIG_PL310_ERRATA_753970 is not set
|
||||
CONFIG_PL310_ERRATA_753970=y
|
||||
# CONFIG_PL310_ERRATA_769419 is not set
|
||||
CONFIG_CACHE_TAUROS2=y
|
||||
CONFIG_ARM_L1_CACHE_SHIFT_6=y
|
||||
|
@ -2165,7 +2165,14 @@ CONFIG_MVPP2=y
|
|||
# CONFIG_NET_PACKET_ENGINE is not set
|
||||
# CONFIG_NET_VENDOR_QLOGIC is not set
|
||||
# CONFIG_NET_VENDOR_QUALCOMM is not set
|
||||
# CONFIG_NET_VENDOR_REALTEK is not set
|
||||
CONFIG_NET_VENDOR_REALTEK=y
|
||||
CONFIG_8139CP=m
|
||||
CONFIG_8139TOO=m
|
||||
CONFIG_8139TOO_PIO=y
|
||||
CONFIG_8139TOO_TUNE_TWISTER=y
|
||||
# CONFIG_8139TOO_8129 is not set
|
||||
# CONFIG_8139_OLD_RX_RESET is not set
|
||||
CONFIG_R8169=m
|
||||
# CONFIG_NET_VENDOR_RENESAS is not set
|
||||
# CONFIG_NET_VENDOR_RDC is not set
|
||||
# CONFIG_NET_VENDOR_ROCKER is not set
|
||||
|
@ -2192,6 +2199,8 @@ CONFIG_MDIO_BUS=y
|
|||
# CONFIG_MDIO_BUS_MUX_GPIO is not set
|
||||
# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
|
||||
# CONFIG_MDIO_HISI_FEMAC is not set
|
||||
CONFIG_MDIO_I2C=m
|
||||
CONFIG_PHYLINK=y
|
||||
CONFIG_PHYLIB=y
|
||||
CONFIG_SWPHY=y
|
||||
CONFIG_LED_TRIGGER_PHY=y
|
||||
|
@ -2199,6 +2208,7 @@ CONFIG_LED_TRIGGER_PHY=y
|
|||
#
|
||||
# MII PHY device drivers
|
||||
#
|
||||
CONFIG_SFP=m
|
||||
# CONFIG_AMD_PHY is not set
|
||||
# CONFIG_AQUANTIA_PHY is not set
|
||||
# CONFIG_AT803X_PHY is not set
|
||||
|
@ -2240,16 +2250,19 @@ CONFIG_PPP_MULTILINK=y
|
|||
CONFIG_PPPOE=m
|
||||
CONFIG_PPTP=m
|
||||
CONFIG_PPPOL2TP=m
|
||||
# CONFIG_PPP_ASYNC is not set
|
||||
# CONFIG_PPP_SYNC_TTY is not set
|
||||
# CONFIG_SLIP is not set
|
||||
CONFIG_PPP_ASYNC=m
|
||||
CONFIG_PPP_SYNC_TTY=m
|
||||
CONFIG_SLIP=m
|
||||
CONFIG_SLHC=m
|
||||
CONFIG_SLIP_COMPRESSED=y
|
||||
CONFIG_SLIP_SMART=y
|
||||
CONFIG_SLIP_MODE_SLIP6=y
|
||||
CONFIG_USB_NET_DRIVERS=m
|
||||
# CONFIG_USB_CATC is not set
|
||||
# CONFIG_USB_KAWETH is not set
|
||||
# CONFIG_USB_PEGASUS is not set
|
||||
# CONFIG_USB_RTL8150 is not set
|
||||
# CONFIG_USB_RTL8152 is not set
|
||||
CONFIG_USB_RTL8150=m
|
||||
CONFIG_USB_RTL8152=m
|
||||
# CONFIG_USB_LAN78XX is not set
|
||||
CONFIG_USB_USBNET=m
|
||||
CONFIG_USB_NET_AX8817X=m
|
||||
|
@ -3426,7 +3439,7 @@ CONFIG_USB_SUPPORT=y
|
|||
CONFIG_USB_COMMON=y
|
||||
CONFIG_USB_ARCH_HAS_HCD=y
|
||||
CONFIG_USB=y
|
||||
# CONFIG_USB_PCI is not set
|
||||
CONFIG_USB_PCI=y
|
||||
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
|
||||
|
||||
#
|
||||
|
@ -3445,19 +3458,22 @@ CONFIG_USB_LEDS_TRIGGER_USBPORT=y
|
|||
#
|
||||
# CONFIG_USB_C67X00_HCD is not set
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
CONFIG_USB_XHCI_PCI=y
|
||||
CONFIG_USB_XHCI_PLATFORM=y
|
||||
CONFIG_USB_XHCI_MVEBU=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_EHCI_ROOT_HUB_TT=y
|
||||
CONFIG_USB_EHCI_TT_NEWSCHED=y
|
||||
CONFIG_USB_EHCI_PCI=y
|
||||
CONFIG_USB_EHCI_HCD_ORION=y
|
||||
# CONFIG_USB_EHCI_HCD_PLATFORM is not set
|
||||
CONFIG_USB_EHCI_HCD_PLATFORM=m
|
||||
# CONFIG_USB_OXU210HP_HCD is not set
|
||||
# CONFIG_USB_ISP116X_HCD is not set
|
||||
# CONFIG_USB_ISP1362_HCD is not set
|
||||
# CONFIG_USB_FOTG210_HCD is not set
|
||||
# CONFIG_USB_MAX3421_HCD is not set
|
||||
# CONFIG_USB_OHCI_HCD is not set
|
||||
# CONFIG_USB_UHCI_HCD is not set
|
||||
# CONFIG_USB_SL811_HCD is not set
|
||||
# CONFIG_USB_R8A66597_HCD is not set
|
||||
# CONFIG_USB_HCD_BCMA is not set
|
||||
|
@ -3468,7 +3484,7 @@ CONFIG_USB_EHCI_HCD_ORION=y
|
|||
# USB Device Class drivers
|
||||
#
|
||||
CONFIG_USB_ACM=m
|
||||
# CONFIG_USB_PRINTER is not set
|
||||
CONFIG_USB_PRINTER=m
|
||||
CONFIG_USB_WDM=m
|
||||
# CONFIG_USB_TMC is not set
|
||||
|
||||
|
@ -3481,7 +3497,8 @@ CONFIG_USB_WDM=m
|
|||
#
|
||||
CONFIG_USB_STORAGE=y
|
||||
# CONFIG_USB_STORAGE_DEBUG is not set
|
||||
# CONFIG_USB_STORAGE_REALTEK is not set
|
||||
CONFIG_USB_STORAGE_REALTEK=m
|
||||
CONFIG_REALTEK_AUTOPM=y
|
||||
# CONFIG_USB_STORAGE_DATAFAB is not set
|
||||
# CONFIG_USB_STORAGE_FREECOM is not set
|
||||
# CONFIG_USB_STORAGE_ISD200 is not set
|
||||
|
|
1104
patch/kernel/mvebu-default/04-patch-4.4.119-120.patch
Normal file
1104
patch/kernel/mvebu-default/04-patch-4.4.119-120.patch
Normal file
File diff suppressed because it is too large
Load diff
1085
patch/kernel/mvebu-default/04-patch-4.4.120-121.patch
Normal file
1085
patch/kernel/mvebu-default/04-patch-4.4.120-121.patch
Normal file
File diff suppressed because it is too large
Load diff
2177
patch/kernel/mvebu-default/04-patch-4.4.121-122.patch
Normal file
2177
patch/kernel/mvebu-default/04-patch-4.4.121-122.patch
Normal file
File diff suppressed because it is too large
Load diff
3500
patch/kernel/mvebu-default/04-patch-4.4.122-123.patch
Normal file
3500
patch/kernel/mvebu-default/04-patch-4.4.122-123.patch
Normal file
File diff suppressed because it is too large
Load diff
3077
patch/kernel/mvebu-default/04-patch-4.4.123-124.patch
Normal file
3077
patch/kernel/mvebu-default/04-patch-4.4.123-124.patch
Normal file
File diff suppressed because it is too large
Load diff
1326
patch/kernel/mvebu-default/04-patch-4.4.124-125.patch
Normal file
1326
patch/kernel/mvebu-default/04-patch-4.4.124-125.patch
Normal file
File diff suppressed because it is too large
Load diff
455
patch/kernel/mvebu-default/04-patch-4.4.125-126.patch
Normal file
455
patch/kernel/mvebu-default/04-patch-4.4.125-126.patch
Normal file
|
@ -0,0 +1,455 @@
|
|||
diff --git a/Makefile b/Makefile
|
||||
index 7dcafa5dcd34..2b699c5f6de4 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
-SUBLEVEL = 125
|
||||
+SUBLEVEL = 126
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c
|
||||
index c31c7407b753..425dae560322 100644
|
||||
--- a/drivers/net/ethernet/arc/emac_rockchip.c
|
||||
+++ b/drivers/net/ethernet/arc/emac_rockchip.c
|
||||
@@ -150,8 +150,10 @@ static int emac_rockchip_probe(struct platform_device *pdev)
|
||||
/* Optional regulator for PHY */
|
||||
priv->regulator = devm_regulator_get_optional(dev, "phy");
|
||||
if (IS_ERR(priv->regulator)) {
|
||||
- if (PTR_ERR(priv->regulator) == -EPROBE_DEFER)
|
||||
- return -EPROBE_DEFER;
|
||||
+ if (PTR_ERR(priv->regulator) == -EPROBE_DEFER) {
|
||||
+ err = -EPROBE_DEFER;
|
||||
+ goto out_clk_disable;
|
||||
+ }
|
||||
dev_err(dev, "no regulator found\n");
|
||||
priv->regulator = NULL;
|
||||
}
|
||||
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
|
||||
index 027705117086..af9ec57bbebf 100644
|
||||
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
|
||||
@@ -729,37 +729,33 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
|
||||
struct bcm_sysport_tx_ring *ring)
|
||||
{
|
||||
struct net_device *ndev = priv->netdev;
|
||||
- unsigned int c_index, last_c_index, last_tx_cn, num_tx_cbs;
|
||||
unsigned int pkts_compl = 0, bytes_compl = 0;
|
||||
+ unsigned int txbds_processed = 0;
|
||||
struct bcm_sysport_cb *cb;
|
||||
+ unsigned int txbds_ready;
|
||||
+ unsigned int c_index;
|
||||
u32 hw_ind;
|
||||
|
||||
/* Compute how many descriptors have been processed since last call */
|
||||
hw_ind = tdma_readl(priv, TDMA_DESC_RING_PROD_CONS_INDEX(ring->index));
|
||||
c_index = (hw_ind >> RING_CONS_INDEX_SHIFT) & RING_CONS_INDEX_MASK;
|
||||
- ring->p_index = (hw_ind & RING_PROD_INDEX_MASK);
|
||||
-
|
||||
- last_c_index = ring->c_index;
|
||||
- num_tx_cbs = ring->size;
|
||||
-
|
||||
- c_index &= (num_tx_cbs - 1);
|
||||
-
|
||||
- if (c_index >= last_c_index)
|
||||
- last_tx_cn = c_index - last_c_index;
|
||||
- else
|
||||
- last_tx_cn = num_tx_cbs - last_c_index + c_index;
|
||||
+ txbds_ready = (c_index - ring->c_index) & RING_CONS_INDEX_MASK;
|
||||
|
||||
netif_dbg(priv, tx_done, ndev,
|
||||
- "ring=%d c_index=%d last_tx_cn=%d last_c_index=%d\n",
|
||||
- ring->index, c_index, last_tx_cn, last_c_index);
|
||||
+ "ring=%d old_c_index=%u c_index=%u txbds_ready=%u\n",
|
||||
+ ring->index, ring->c_index, c_index, txbds_ready);
|
||||
|
||||
- while (last_tx_cn-- > 0) {
|
||||
- cb = ring->cbs + last_c_index;
|
||||
+ while (txbds_processed < txbds_ready) {
|
||||
+ cb = &ring->cbs[ring->clean_index];
|
||||
bcm_sysport_tx_reclaim_one(priv, cb, &bytes_compl, &pkts_compl);
|
||||
|
||||
ring->desc_count++;
|
||||
- last_c_index++;
|
||||
- last_c_index &= (num_tx_cbs - 1);
|
||||
+ txbds_processed++;
|
||||
+
|
||||
+ if (likely(ring->clean_index < ring->size - 1))
|
||||
+ ring->clean_index++;
|
||||
+ else
|
||||
+ ring->clean_index = 0;
|
||||
}
|
||||
|
||||
ring->c_index = c_index;
|
||||
@@ -1229,6 +1225,7 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
|
||||
netif_napi_add(priv->netdev, &ring->napi, bcm_sysport_tx_poll, 64);
|
||||
ring->index = index;
|
||||
ring->size = size;
|
||||
+ ring->clean_index = 0;
|
||||
ring->alloc_size = ring->size;
|
||||
ring->desc_cpu = p;
|
||||
ring->desc_count = ring->size;
|
||||
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h
|
||||
index f28bf545d7f4..8ace6ecb5f79 100644
|
||||
--- a/drivers/net/ethernet/broadcom/bcmsysport.h
|
||||
+++ b/drivers/net/ethernet/broadcom/bcmsysport.h
|
||||
@@ -638,7 +638,7 @@ struct bcm_sysport_tx_ring {
|
||||
unsigned int desc_count; /* Number of descriptors */
|
||||
unsigned int curr_desc; /* Current descriptor */
|
||||
unsigned int c_index; /* Last consumer index */
|
||||
- unsigned int p_index; /* Current producer index */
|
||||
+ unsigned int clean_index; /* Current clean index */
|
||||
struct bcm_sysport_cb *cbs; /* Transmit control blocks */
|
||||
struct dma_desc *desc_cpu; /* CPU view of the descriptor */
|
||||
struct bcm_sysport_priv *priv; /* private context backpointer */
|
||||
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
|
||||
index 458e2d97d096..ae8e4fc22e7b 100644
|
||||
--- a/drivers/net/ethernet/freescale/fec_main.c
|
||||
+++ b/drivers/net/ethernet/freescale/fec_main.c
|
||||
@@ -3539,6 +3539,8 @@ fec_drv_remove(struct platform_device *pdev)
|
||||
fec_enet_mii_remove(fep);
|
||||
if (fep->reg_phy)
|
||||
regulator_disable(fep->reg_phy);
|
||||
+ pm_runtime_put(&pdev->dev);
|
||||
+ pm_runtime_disable(&pdev->dev);
|
||||
of_node_put(fep->phy_node);
|
||||
free_netdev(ndev);
|
||||
|
||||
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
|
||||
index fc958067d10a..435466c17852 100644
|
||||
--- a/drivers/net/ethernet/ti/cpsw.c
|
||||
+++ b/drivers/net/ethernet/ti/cpsw.c
|
||||
@@ -878,7 +878,8 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave,
|
||||
/* set speed_in input in case RMII mode is used in 100Mbps */
|
||||
if (phy->speed == 100)
|
||||
mac_control |= BIT(15);
|
||||
- else if (phy->speed == 10)
|
||||
+ /* in band mode only works in 10Mbps RGMII mode */
|
||||
+ else if ((phy->speed == 10) && phy_interface_is_rgmii(phy))
|
||||
mac_control |= BIT(18); /* In Band mode */
|
||||
|
||||
if (priv->rx_pause)
|
||||
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
|
||||
index 61cd53838360..9bca36e1fefd 100644
|
||||
--- a/drivers/net/team/team.c
|
||||
+++ b/drivers/net/team/team.c
|
||||
@@ -2380,7 +2380,7 @@ send_done:
|
||||
if (!nlh) {
|
||||
err = __send_and_alloc_skb(&skb, team, portid, send_func);
|
||||
if (err)
|
||||
- goto errout;
|
||||
+ return err;
|
||||
goto send_done;
|
||||
}
|
||||
|
||||
@@ -2660,7 +2660,7 @@ send_done:
|
||||
if (!nlh) {
|
||||
err = __send_and_alloc_skb(&skb, team, portid, send_func);
|
||||
if (err)
|
||||
- goto errout;
|
||||
+ return err;
|
||||
goto send_done;
|
||||
}
|
||||
|
||||
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
|
||||
index 75d37148c8cd..95c631125a20 100644
|
||||
--- a/drivers/s390/net/qeth_core_main.c
|
||||
+++ b/drivers/s390/net/qeth_core_main.c
|
||||
@@ -517,8 +517,7 @@ static inline int qeth_is_cq(struct qeth_card *card, unsigned int queue)
|
||||
queue == card->qdio.no_in_queues - 1;
|
||||
}
|
||||
|
||||
-
|
||||
-static int qeth_issue_next_read(struct qeth_card *card)
|
||||
+static int __qeth_issue_next_read(struct qeth_card *card)
|
||||
{
|
||||
int rc;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
@@ -549,6 +548,17 @@ static int qeth_issue_next_read(struct qeth_card *card)
|
||||
return rc;
|
||||
}
|
||||
|
||||
+static int qeth_issue_next_read(struct qeth_card *card)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ spin_lock_irq(get_ccwdev_lock(CARD_RDEV(card)));
|
||||
+ ret = __qeth_issue_next_read(card);
|
||||
+ spin_unlock_irq(get_ccwdev_lock(CARD_RDEV(card)));
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card)
|
||||
{
|
||||
struct qeth_reply *reply;
|
||||
@@ -952,7 +962,7 @@ void qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread)
|
||||
spin_lock_irqsave(&card->thread_mask_lock, flags);
|
||||
card->thread_running_mask &= ~thread;
|
||||
spin_unlock_irqrestore(&card->thread_mask_lock, flags);
|
||||
- wake_up(&card->wait_q);
|
||||
+ wake_up_all(&card->wait_q);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_clear_thread_running_bit);
|
||||
|
||||
@@ -1156,6 +1166,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
||||
}
|
||||
rc = qeth_get_problem(cdev, irb);
|
||||
if (rc) {
|
||||
+ card->read_or_write_problem = 1;
|
||||
qeth_clear_ipacmd_list(card);
|
||||
qeth_schedule_recovery(card);
|
||||
goto out;
|
||||
@@ -1174,7 +1185,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
||||
return;
|
||||
if (channel == &card->read &&
|
||||
channel->state == CH_STATE_UP)
|
||||
- qeth_issue_next_read(card);
|
||||
+ __qeth_issue_next_read(card);
|
||||
|
||||
iob = channel->iob;
|
||||
index = channel->buf_no;
|
||||
@@ -4969,8 +4980,6 @@ static void qeth_core_free_card(struct qeth_card *card)
|
||||
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
|
||||
qeth_clean_channel(&card->read);
|
||||
qeth_clean_channel(&card->write);
|
||||
- if (card->dev)
|
||||
- free_netdev(card->dev);
|
||||
kfree(card->ip_tbd_list);
|
||||
qeth_free_qdio_buffers(card);
|
||||
unregister_service_level(&card->qeth_service_level);
|
||||
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
|
||||
index 58bcb3c9a86a..acdb5ccb0ab9 100644
|
||||
--- a/drivers/s390/net/qeth_l2_main.c
|
||||
+++ b/drivers/s390/net/qeth_l2_main.c
|
||||
@@ -1062,8 +1062,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
|
||||
qeth_l2_set_offline(cgdev);
|
||||
|
||||
if (card->dev) {
|
||||
- netif_napi_del(&card->napi);
|
||||
unregister_netdev(card->dev);
|
||||
+ free_netdev(card->dev);
|
||||
card->dev = NULL;
|
||||
}
|
||||
return;
|
||||
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
|
||||
index 0d6888cbd96e..bbdb3b6c54bb 100644
|
||||
--- a/drivers/s390/net/qeth_l3_main.c
|
||||
+++ b/drivers/s390/net/qeth_l3_main.c
|
||||
@@ -3243,8 +3243,8 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
|
||||
qeth_l3_set_offline(cgdev);
|
||||
|
||||
if (card->dev) {
|
||||
- netif_napi_del(&card->napi);
|
||||
unregister_netdev(card->dev);
|
||||
+ free_netdev(card->dev);
|
||||
card->dev = NULL;
|
||||
}
|
||||
|
||||
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
|
||||
index 4b43effbf4fc..cb19c9ad1b57 100644
|
||||
--- a/drivers/scsi/sg.c
|
||||
+++ b/drivers/scsi/sg.c
|
||||
@@ -2074,11 +2074,12 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id)
|
||||
if ((1 == resp->done) && (!resp->sg_io_owned) &&
|
||||
((-1 == pack_id) || (resp->header.pack_id == pack_id))) {
|
||||
resp->done = 2; /* guard against other readers */
|
||||
- break;
|
||||
+ write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
||||
+ return resp;
|
||||
}
|
||||
}
|
||||
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
||||
- return resp;
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
/* always adds to end of list */
|
||||
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
|
||||
index 4889a8ab77ce..a079ed14f230 100644
|
||||
--- a/kernel/irq/manage.c
|
||||
+++ b/kernel/irq/manage.c
|
||||
@@ -1189,10 +1189,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
|
||||
* set the trigger type must match. Also all must
|
||||
* agree on ONESHOT.
|
||||
*/
|
||||
- unsigned int oldtype = irqd_get_trigger_type(&desc->irq_data);
|
||||
-
|
||||
if (!((old->flags & new->flags) & IRQF_SHARED) ||
|
||||
- (oldtype != (new->flags & IRQF_TRIGGER_MASK)) ||
|
||||
+ ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) ||
|
||||
((old->flags ^ new->flags) & IRQF_ONESHOT))
|
||||
goto mismatch;
|
||||
|
||||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
|
||||
index 86b619501350..284370b61b8c 100644
|
||||
--- a/net/core/skbuff.c
|
||||
+++ b/net/core/skbuff.c
|
||||
@@ -3571,7 +3571,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
|
||||
|
||||
skb_queue_tail(&sk->sk_error_queue, skb);
|
||||
if (!sock_flag(sk, SOCK_DEAD))
|
||||
- sk->sk_data_ready(sk);
|
||||
+ sk->sk_error_report(sk);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(sock_queue_err_skb);
|
||||
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
|
||||
index 9d43c1f40274..ff3b058cf58c 100644
|
||||
--- a/net/dccp/proto.c
|
||||
+++ b/net/dccp/proto.c
|
||||
@@ -789,6 +789,11 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
if (skb == NULL)
|
||||
goto out_release;
|
||||
|
||||
+ if (sk->sk_state == DCCP_CLOSED) {
|
||||
+ rc = -ENOTCONN;
|
||||
+ goto out_discard;
|
||||
+ }
|
||||
+
|
||||
skb_reserve(skb, sk->sk_prot->max_header);
|
||||
rc = memcpy_from_msg(skb_put(skb, len), msg, len);
|
||||
if (rc != 0)
|
||||
diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c
|
||||
index 20c49c724ba0..e8b279443d37 100644
|
||||
--- a/net/ieee802154/6lowpan/core.c
|
||||
+++ b/net/ieee802154/6lowpan/core.c
|
||||
@@ -206,9 +206,13 @@ static inline void lowpan_netlink_fini(void)
|
||||
static int lowpan_device_event(struct notifier_block *unused,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
- struct net_device *wdev = netdev_notifier_info_to_dev(ptr);
|
||||
+ struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
|
||||
+ struct wpan_dev *wpan_dev;
|
||||
|
||||
- if (wdev->type != ARPHRD_IEEE802154)
|
||||
+ if (ndev->type != ARPHRD_IEEE802154)
|
||||
+ return NOTIFY_DONE;
|
||||
+ wpan_dev = ndev->ieee802154_ptr;
|
||||
+ if (!wpan_dev)
|
||||
goto out;
|
||||
|
||||
switch (event) {
|
||||
@@ -217,8 +221,8 @@ static int lowpan_device_event(struct notifier_block *unused,
|
||||
* also delete possible lowpan interfaces which belongs
|
||||
* to the wpan interface.
|
||||
*/
|
||||
- if (wdev->ieee802154_ptr->lowpan_dev)
|
||||
- lowpan_dellink(wdev->ieee802154_ptr->lowpan_dev, NULL);
|
||||
+ if (wpan_dev->lowpan_dev)
|
||||
+ lowpan_dellink(wpan_dev->lowpan_dev, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
|
||||
index c5fb2f694ed0..b34fa1bb278f 100644
|
||||
--- a/net/ipv4/inet_fragment.c
|
||||
+++ b/net/ipv4/inet_fragment.c
|
||||
@@ -119,6 +119,9 @@ out:
|
||||
|
||||
static bool inet_fragq_should_evict(const struct inet_frag_queue *q)
|
||||
{
|
||||
+ if (!hlist_unhashed(&q->list_evictor))
|
||||
+ return false;
|
||||
+
|
||||
return q->net->low_thresh == 0 ||
|
||||
frag_mem_limit(q->net) >= q->net->low_thresh;
|
||||
}
|
||||
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
|
||||
index d35509212013..1b93ea766916 100644
|
||||
--- a/net/ipv4/ip_sockglue.c
|
||||
+++ b/net/ipv4/ip_sockglue.c
|
||||
@@ -241,7 +241,8 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc,
|
||||
src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg);
|
||||
if (!ipv6_addr_v4mapped(&src_info->ipi6_addr))
|
||||
return -EINVAL;
|
||||
- ipc->oif = src_info->ipi6_ifindex;
|
||||
+ if (src_info->ipi6_ifindex)
|
||||
+ ipc->oif = src_info->ipi6_ifindex;
|
||||
ipc->addr = src_info->ipi6_addr.s6_addr32[3];
|
||||
continue;
|
||||
}
|
||||
@@ -264,7 +265,8 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc,
|
||||
if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct in_pktinfo)))
|
||||
return -EINVAL;
|
||||
info = (struct in_pktinfo *)CMSG_DATA(cmsg);
|
||||
- ipc->oif = info->ipi_ifindex;
|
||||
+ if (info->ipi_ifindex)
|
||||
+ ipc->oif = info->ipi_ifindex;
|
||||
ipc->addr = info->ipi_spec_dst.s_addr;
|
||||
break;
|
||||
}
|
||||
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
|
||||
index 55810e4899f1..3db8d7d1a986 100644
|
||||
--- a/net/ipv6/ndisc.c
|
||||
+++ b/net/ipv6/ndisc.c
|
||||
@@ -1478,7 +1478,8 @@ static void ndisc_fill_redirect_hdr_option(struct sk_buff *skb,
|
||||
*(opt++) = (rd_len >> 3);
|
||||
opt += 6;
|
||||
|
||||
- memcpy(opt, ipv6_hdr(orig_skb), rd_len - 8);
|
||||
+ skb_copy_bits(orig_skb, skb_network_offset(orig_skb), opt,
|
||||
+ rd_len - 8);
|
||||
}
|
||||
|
||||
void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
|
||||
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
|
||||
index 20ab7b2ec463..aeffb65181f5 100644
|
||||
--- a/net/iucv/af_iucv.c
|
||||
+++ b/net/iucv/af_iucv.c
|
||||
@@ -2381,9 +2381,11 @@ static int afiucv_iucv_init(void)
|
||||
af_iucv_dev->driver = &af_iucv_driver;
|
||||
err = device_register(af_iucv_dev);
|
||||
if (err)
|
||||
- goto out_driver;
|
||||
+ goto out_iucv_dev;
|
||||
return 0;
|
||||
|
||||
+out_iucv_dev:
|
||||
+ put_device(af_iucv_dev);
|
||||
out_driver:
|
||||
driver_unregister(&af_iucv_driver);
|
||||
out_iucv:
|
||||
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
|
||||
index ec8f6a6485e3..92df832a1896 100644
|
||||
--- a/net/l2tp/l2tp_core.c
|
||||
+++ b/net/l2tp/l2tp_core.c
|
||||
@@ -1518,9 +1518,14 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
|
||||
encap = cfg->encap;
|
||||
|
||||
/* Quick sanity checks */
|
||||
+ err = -EPROTONOSUPPORT;
|
||||
+ if (sk->sk_type != SOCK_DGRAM) {
|
||||
+ pr_debug("tunl %hu: fd %d wrong socket type\n",
|
||||
+ tunnel_id, fd);
|
||||
+ goto err;
|
||||
+ }
|
||||
switch (encap) {
|
||||
case L2TP_ENCAPTYPE_UDP:
|
||||
- err = -EPROTONOSUPPORT;
|
||||
if (sk->sk_protocol != IPPROTO_UDP) {
|
||||
pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n",
|
||||
tunnel_id, fd, sk->sk_protocol, IPPROTO_UDP);
|
||||
@@ -1528,7 +1533,6 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
|
||||
}
|
||||
break;
|
||||
case L2TP_ENCAPTYPE_IP:
|
||||
- err = -EPROTONOSUPPORT;
|
||||
if (sk->sk_protocol != IPPROTO_L2TP) {
|
||||
pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n",
|
||||
tunnel_id, fd, sk->sk_protocol, IPPROTO_L2TP);
|
||||
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
|
||||
index 30c46aaf4575..d681dbaf00c1 100644
|
||||
--- a/net/netlink/genetlink.c
|
||||
+++ b/net/netlink/genetlink.c
|
||||
@@ -1143,7 +1143,7 @@ static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
|
||||
if (!err)
|
||||
delivered = true;
|
||||
else if (err != -ESRCH)
|
||||
- goto error;
|
||||
+ return err;
|
||||
return delivered ? 0 : -ESRCH;
|
||||
error:
|
||||
kfree_skb(skb);
|
2344
patch/kernel/mvebu-default/04-patch-4.4.126-127.patch
Normal file
2344
patch/kernel/mvebu-default/04-patch-4.4.126-127.patch
Normal file
File diff suppressed because it is too large
Load diff
5371
patch/kernel/mvebu-default/04-patch-4.4.127-128.patch
Normal file
5371
patch/kernel/mvebu-default/04-patch-4.4.127-128.patch
Normal file
File diff suppressed because it is too large
Load diff
15
patch/kernel/mvebu-next/102-revert_i2c_delay.patch
Normal file
15
patch/kernel/mvebu-next/102-revert_i2c_delay.patch
Normal file
|
@ -0,0 +1,15 @@
|
|||
--- a/arch/arm/boot/dts/armada-xp.dtsi
|
||||
+++ b/arch/arm/boot/dts/armada-xp.dtsi
|
||||
@@ -274,12 +274,10 @@
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
- compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
|
||||
reg = <0x11000 0x100>;
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
- compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
|
||||
reg = <0x11100 0x100>;
|
||||
};
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
diff --git a/arch/arm/boot/dts/armada-388-clearfog.dtsi b/arch/arm/boot/dts/armada-388-clearfog.dtsi
|
||||
index 0e3b1f140e6d..a44bf20ab7f8 100644
|
||||
--- a/arch/arm/boot/dts/armada-388-clearfog.dtsi
|
||||
+++ b/arch/arm/boot/dts/armada-388-clearfog.dtsi
|
||||
@@ -117,6 +117,16 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
+
|
||||
+ sfp: sfp {
|
||||
+ compatible = "sff,sfp";
|
||||
+ i2c-bus = <&i2c1>;
|
||||
+ los-gpio = <&expander0 12 GPIO_ACTIVE_HIGH>;
|
||||
+ mod-def0-gpio = <&expander0 15 GPIO_ACTIVE_LOW>;
|
||||
+ tx-disable-gpio = <&expander0 14 GPIO_ACTIVE_HIGH>;
|
||||
+ tx-fault-gpio = <&expander0 13 GPIO_ACTIVE_HIGH>;
|
||||
+ maximum-power-milliwatt = <2000>;
|
||||
+ };
|
||||
};
|
||||
|
||||
ð1 {
|
||||
@@ -133,13 +143,10 @@
|
||||
bm,pool-long = <3>;
|
||||
bm,pool-short = <1>;
|
||||
buffer-manager = <&bm>;
|
||||
+ managed = "in-band-status";
|
||||
phy-mode = "sgmii";
|
||||
+ sfp = <&sfp>;
|
||||
status = "okay";
|
||||
-
|
||||
- fixed-link {
|
||||
- speed = <1000>;
|
||||
- full-duplex;
|
||||
- };
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
@@ -208,34 +215,6 @@
|
||||
output-low;
|
||||
line-name = "m.2 devslp";
|
||||
};
|
||||
- sfp_los {
|
||||
- /* SFP loss of signal */
|
||||
- gpio-hog;
|
||||
- gpios = <12 GPIO_ACTIVE_HIGH>;
|
||||
- input;
|
||||
- line-name = "sfp-los";
|
||||
- };
|
||||
- sfp_tx_fault {
|
||||
- /* SFP laser fault */
|
||||
- gpio-hog;
|
||||
- gpios = <13 GPIO_ACTIVE_HIGH>;
|
||||
- input;
|
||||
- line-name = "sfp-tx-fault";
|
||||
- };
|
||||
- sfp_tx_disable {
|
||||
- /* SFP transmit disable */
|
||||
- gpio-hog;
|
||||
- gpios = <14 GPIO_ACTIVE_HIGH>;
|
||||
- output-low;
|
||||
- line-name = "sfp-tx-disable";
|
||||
- };
|
||||
- sfp_mod_def0 {
|
||||
- /* SFP module present */
|
||||
- gpio-hog;
|
||||
- gpios = <15 GPIO_ACTIVE_LOW>;
|
||||
- input;
|
||||
- line-name = "sfp-mod-def0";
|
||||
- };
|
||||
};
|
||||
|
||||
/* The MCP3021 supports standard and fast modes */
|
21
patch/kernel/mvebu-next/210-clearfog_switch_node.patch
Normal file
21
patch/kernel/mvebu-next/210-clearfog_switch_node.patch
Normal file
|
@ -0,0 +1,21 @@
|
|||
--- a/arch/arm/boot/dts/armada-388-clearfog.dts
|
||||
+++ b/arch/arm/boot/dts/armada-388-clearfog.dts
|
||||
@@ -129,6 +129,18 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ mvsw61xx {
|
||||
+ #address-cells = <1>;
|
||||
+ #size-cells = <0>;
|
||||
+ compatible = "marvell,88e6176";
|
||||
+ status = "okay";
|
||||
+ reg = <0x4>;
|
||||
+ is-indirect;
|
||||
+
|
||||
+ mii-bus = <&mdio>;
|
||||
+ cpu-port-0 = <5>;
|
||||
+ };
|
||||
+
|
||||
gpio-keys {
|
||||
compatible = "gpio-keys";
|
||||
pinctrl-0 = <&rear_button_pins>;
|
35
patch/kernel/mvebu-next/300-mvneta-tx-queue-workaround.patch
Normal file
35
patch/kernel/mvebu-next/300-mvneta-tx-queue-workaround.patch
Normal file
|
@ -0,0 +1,35 @@
|
|||
The hardware queue scheduling is apparently configured with fixed
|
||||
priorities, which creates a nasty fairness issue where traffic from one
|
||||
CPU can starve traffic from all other CPUs.
|
||||
|
||||
Work around this issue by forcing all tx packets to go through one CPU,
|
||||
until this issue is fixed properly.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
--- a/drivers/net/ethernet/marvell/mvneta.c
|
||||
+++ b/drivers/net/ethernet/marvell/mvneta.c
|
||||
@@ -3961,6 +3961,15 @@ static int mvneta_ethtool_set_wol(struct
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static u16 mvneta_select_queue(struct net_device *dev, struct sk_buff *skb,
|
||||
+ void *accel_priv,
|
||||
+ select_queue_fallback_t fallback)
|
||||
+{
|
||||
+ /* XXX: hardware queue scheduling is broken,
|
||||
+ * use only one queue until it is fixed */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const struct net_device_ops mvneta_netdev_ops = {
|
||||
.ndo_open = mvneta_open,
|
||||
.ndo_stop = mvneta_stop,
|
||||
@@ -3971,6 +3980,7 @@ static const struct net_device_ops mvnet
|
||||
.ndo_fix_features = mvneta_fix_features,
|
||||
.ndo_get_stats64 = mvneta_get_stats64,
|
||||
.ndo_do_ioctl = mvneta_ioctl,
|
||||
+ .ndo_select_queue = mvneta_select_queue,
|
||||
};
|
||||
|
||||
static const struct ethtool_ops mvneta_eth_tool_ops = {
|
|
@ -0,0 +1,60 @@
|
|||
From 287b9df160b6159f8d385424904f8bac501280c1 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Sat, 9 Jul 2016 10:58:16 +0100
|
||||
Subject: pci: mvebu: time out reset on link up
|
||||
|
||||
If the port reports that the link is up while we are resetting, there's
|
||||
little point in waiting for the full duration.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/pci/host/pci-mvebu.c | 20 ++++++++++++++------
|
||||
1 file changed, 14 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/pci/host/pci-mvebu.c
|
||||
+++ b/drivers/pci/host/pci-mvebu.c
|
||||
@@ -1167,6 +1167,7 @@ static int mvebu_pcie_powerup(struct mve
|
||||
|
||||
if (port->reset_gpio) {
|
||||
u32 reset_udelay = PCI_PM_D3COLD_WAIT * 1000;
|
||||
+ unsigned int i;
|
||||
|
||||
of_property_read_u32(port->dn, "reset-delay-us",
|
||||
&reset_udelay);
|
||||
@@ -1174,7 +1175,13 @@ static int mvebu_pcie_powerup(struct mve
|
||||
udelay(100);
|
||||
|
||||
gpiod_set_value_cansleep(port->reset_gpio, 0);
|
||||
- msleep(reset_udelay / 1000);
|
||||
+ for (i = 0; i < reset_udelay; i += 1000) {
|
||||
+ if (mvebu_pcie_link_up(port))
|
||||
+ break;
|
||||
+ msleep(1);
|
||||
+ }
|
||||
+
|
||||
+ printk("%s: reset completed in %dus\n", port->name, i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1261,15 +1268,16 @@ static int mvebu_pcie_probe(struct platf
|
||||
if (!child)
|
||||
continue;
|
||||
|
||||
- ret = mvebu_pcie_powerup(port);
|
||||
- if (ret < 0)
|
||||
- continue;
|
||||
-
|
||||
port->base = mvebu_pcie_map_registers(pdev, child, port);
|
||||
if (IS_ERR(port->base)) {
|
||||
dev_err(dev, "%s: cannot map registers\n", port->name);
|
||||
port->base = NULL;
|
||||
- mvebu_pcie_powerdown(port);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ ret = mvebu_pcie_powerup(port);
|
||||
+ if (ret < 0) {
|
||||
+ port->base = NULL;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -0,0 +1,290 @@
|
|||
From e76632d118659347d9261a4470d9f60bfbe0044c Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
Date: Sun, 13 Sep 2015 01:06:31 +0100
|
||||
Subject: sfp: display SFP module information
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 253 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -247,6 +247,184 @@ static unsigned int sfp_check(void *buf,
|
||||
return check;
|
||||
}
|
||||
|
||||
+static const char *sfp_link_len(char *buf, size_t size, unsigned int length,
|
||||
+ unsigned int multiplier)
|
||||
+{
|
||||
+ if (length == 0)
|
||||
+ return "unsupported/unspecified";
|
||||
+
|
||||
+ if (length == 255) {
|
||||
+ *buf++ = '>';
|
||||
+ size -= 1;
|
||||
+ length -= 1;
|
||||
+ }
|
||||
+
|
||||
+ length *= multiplier;
|
||||
+
|
||||
+ if (length >= 1000)
|
||||
+ snprintf(buf, size, "%u.%0*ukm",
|
||||
+ length / 1000,
|
||||
+ multiplier > 100 ? 1 :
|
||||
+ multiplier > 10 ? 2 : 3,
|
||||
+ length % 1000);
|
||||
+ else
|
||||
+ snprintf(buf, size, "%um", length);
|
||||
+
|
||||
+ return buf;
|
||||
+}
|
||||
+
|
||||
+struct bitfield {
|
||||
+ unsigned int mask;
|
||||
+ unsigned int val;
|
||||
+ const char *str;
|
||||
+};
|
||||
+
|
||||
+static const struct bitfield sfp_options[] = {
|
||||
+ {
|
||||
+ .mask = SFP_OPTIONS_HIGH_POWER_LEVEL,
|
||||
+ .val = SFP_OPTIONS_HIGH_POWER_LEVEL,
|
||||
+ .str = "hpl",
|
||||
+ }, {
|
||||
+ .mask = SFP_OPTIONS_PAGING_A2,
|
||||
+ .val = SFP_OPTIONS_PAGING_A2,
|
||||
+ .str = "paginga2",
|
||||
+ }, {
|
||||
+ .mask = SFP_OPTIONS_RETIMER,
|
||||
+ .val = SFP_OPTIONS_RETIMER,
|
||||
+ .str = "retimer",
|
||||
+ }, {
|
||||
+ .mask = SFP_OPTIONS_COOLED_XCVR,
|
||||
+ .val = SFP_OPTIONS_COOLED_XCVR,
|
||||
+ .str = "cooled",
|
||||
+ }, {
|
||||
+ .mask = SFP_OPTIONS_POWER_DECL,
|
||||
+ .val = SFP_OPTIONS_POWER_DECL,
|
||||
+ .str = "powerdecl",
|
||||
+ }, {
|
||||
+ .mask = SFP_OPTIONS_RX_LINEAR_OUT,
|
||||
+ .val = SFP_OPTIONS_RX_LINEAR_OUT,
|
||||
+ .str = "rxlinear",
|
||||
+ }, {
|
||||
+ .mask = SFP_OPTIONS_RX_DECISION_THRESH,
|
||||
+ .val = SFP_OPTIONS_RX_DECISION_THRESH,
|
||||
+ .str = "rxthresh",
|
||||
+ }, {
|
||||
+ .mask = SFP_OPTIONS_TUNABLE_TX,
|
||||
+ .val = SFP_OPTIONS_TUNABLE_TX,
|
||||
+ .str = "tunabletx",
|
||||
+ }, {
|
||||
+ .mask = SFP_OPTIONS_RATE_SELECT,
|
||||
+ .val = SFP_OPTIONS_RATE_SELECT,
|
||||
+ .str = "ratesel",
|
||||
+ }, {
|
||||
+ .mask = SFP_OPTIONS_TX_DISABLE,
|
||||
+ .val = SFP_OPTIONS_TX_DISABLE,
|
||||
+ .str = "txdisable",
|
||||
+ }, {
|
||||
+ .mask = SFP_OPTIONS_TX_FAULT,
|
||||
+ .val = SFP_OPTIONS_TX_FAULT,
|
||||
+ .str = "txfault",
|
||||
+ }, {
|
||||
+ .mask = SFP_OPTIONS_LOS_INVERTED,
|
||||
+ .val = SFP_OPTIONS_LOS_INVERTED,
|
||||
+ .str = "los-",
|
||||
+ }, {
|
||||
+ .mask = SFP_OPTIONS_LOS_NORMAL,
|
||||
+ .val = SFP_OPTIONS_LOS_NORMAL,
|
||||
+ .str = "los+",
|
||||
+ }, { }
|
||||
+};
|
||||
+
|
||||
+static const struct bitfield diagmon[] = {
|
||||
+ {
|
||||
+ .mask = SFP_DIAGMON_DDM,
|
||||
+ .val = SFP_DIAGMON_DDM,
|
||||
+ .str = "ddm",
|
||||
+ }, {
|
||||
+ .mask = SFP_DIAGMON_INT_CAL,
|
||||
+ .val = SFP_DIAGMON_INT_CAL,
|
||||
+ .str = "intcal",
|
||||
+ }, {
|
||||
+ .mask = SFP_DIAGMON_EXT_CAL,
|
||||
+ .val = SFP_DIAGMON_EXT_CAL,
|
||||
+ .str = "extcal",
|
||||
+ }, {
|
||||
+ .mask = SFP_DIAGMON_RXPWR_AVG,
|
||||
+ .val = SFP_DIAGMON_RXPWR_AVG,
|
||||
+ .str = "rxpwravg",
|
||||
+ }, { }
|
||||
+};
|
||||
+
|
||||
+static const char *sfp_bitfield(char *out, size_t outsz, const struct bitfield *bits, unsigned int val)
|
||||
+{
|
||||
+ char *p = out;
|
||||
+ int n;
|
||||
+
|
||||
+ *p = '\0';
|
||||
+ while (bits->mask) {
|
||||
+ if ((val & bits->mask) == bits->val) {
|
||||
+ n = snprintf(p, outsz, "%s%s",
|
||||
+ out != p ? ", " : "",
|
||||
+ bits->str);
|
||||
+ if (n == outsz)
|
||||
+ break;
|
||||
+ p += n;
|
||||
+ outsz -= n;
|
||||
+ }
|
||||
+ bits++;
|
||||
+ }
|
||||
+
|
||||
+ return out;
|
||||
+}
|
||||
+
|
||||
+static const char *sfp_connector(unsigned int connector)
|
||||
+{
|
||||
+ switch (connector) {
|
||||
+ case SFP_CONNECTOR_UNSPEC:
|
||||
+ return "unknown/unspecified";
|
||||
+ case SFP_CONNECTOR_SC:
|
||||
+ return "SC";
|
||||
+ case SFP_CONNECTOR_FIBERJACK:
|
||||
+ return "Fiberjack";
|
||||
+ case SFP_CONNECTOR_LC:
|
||||
+ return "LC";
|
||||
+ case SFP_CONNECTOR_MT_RJ:
|
||||
+ return "MT-RJ";
|
||||
+ case SFP_CONNECTOR_MU:
|
||||
+ return "MU";
|
||||
+ case SFP_CONNECTOR_SG:
|
||||
+ return "SG";
|
||||
+ case SFP_CONNECTOR_OPTICAL_PIGTAIL:
|
||||
+ return "Optical pigtail";
|
||||
+ case SFP_CONNECTOR_HSSDC_II:
|
||||
+ return "HSSDC II";
|
||||
+ case SFP_CONNECTOR_COPPER_PIGTAIL:
|
||||
+ return "Copper pigtail";
|
||||
+ default:
|
||||
+ return "unknown";
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static const char *sfp_encoding(unsigned int encoding)
|
||||
+{
|
||||
+ switch (encoding) {
|
||||
+ case SFP_ENCODING_UNSPEC:
|
||||
+ return "unspecified";
|
||||
+ case SFP_ENCODING_8472_64B66B:
|
||||
+ return "64b66b";
|
||||
+ case SFP_ENCODING_8B10B:
|
||||
+ return "8b10b";
|
||||
+ case SFP_ENCODING_4B5B:
|
||||
+ return "4b5b";
|
||||
+ case SFP_ENCODING_NRZ:
|
||||
+ return "NRZ";
|
||||
+ case SFP_ENCODING_8472_MANCHESTER:
|
||||
+ return "MANCHESTER";
|
||||
+ default:
|
||||
+ return "unknown";
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* Helpers */
|
||||
static void sfp_module_tx_disable(struct sfp *sfp)
|
||||
{
|
||||
@@ -415,6 +593,7 @@ static int sfp_sm_mod_probe(struct sfp *
|
||||
char sn[17];
|
||||
char date[9];
|
||||
char rev[5];
|
||||
+ char options[80];
|
||||
u8 check;
|
||||
int err;
|
||||
|
||||
@@ -458,10 +637,83 @@ static int sfp_sm_mod_probe(struct sfp *
|
||||
rev[4] = '\0';
|
||||
memcpy(sn, sfp->id.ext.vendor_sn, 16);
|
||||
sn[16] = '\0';
|
||||
- memcpy(date, sfp->id.ext.datecode, 8);
|
||||
+ date[0] = sfp->id.ext.datecode[4];
|
||||
+ date[1] = sfp->id.ext.datecode[5];
|
||||
+ date[2] = '-';
|
||||
+ date[3] = sfp->id.ext.datecode[2];
|
||||
+ date[4] = sfp->id.ext.datecode[3];
|
||||
+ date[5] = '-';
|
||||
+ date[6] = sfp->id.ext.datecode[0];
|
||||
+ date[7] = sfp->id.ext.datecode[1];
|
||||
date[8] = '\0';
|
||||
|
||||
dev_info(sfp->dev, "module %s %s rev %s sn %s dc %s\n", vendor, part, rev, sn, date);
|
||||
+ dev_info(sfp->dev, " %s connector, encoding %s, nominal bitrate %u.%uGbps +%u%% -%u%%\n",
|
||||
+ sfp_connector(sfp->id.base.connector),
|
||||
+ sfp_encoding(sfp->id.base.encoding),
|
||||
+ sfp->id.base.br_nominal / 10,
|
||||
+ sfp->id.base.br_nominal % 10,
|
||||
+ sfp->id.ext.br_max, sfp->id.ext.br_min);
|
||||
+ dev_info(sfp->dev, " 1000BaseSX%c 1000BaseLX%c 1000BaseCX%c 1000BaseT%c 100BaseTLX%c 1000BaseFX%c BaseBX10%c BasePX%c\n",
|
||||
+ sfp->id.base.e1000_base_sx ? '+' : '-',
|
||||
+ sfp->id.base.e1000_base_lx ? '+' : '-',
|
||||
+ sfp->id.base.e1000_base_cx ? '+' : '-',
|
||||
+ sfp->id.base.e1000_base_t ? '+' : '-',
|
||||
+ sfp->id.base.e100_base_lx ? '+' : '-',
|
||||
+ sfp->id.base.e100_base_fx ? '+' : '-',
|
||||
+ sfp->id.base.e_base_bx10 ? '+' : '-',
|
||||
+ sfp->id.base.e_base_px ? '+' : '-');
|
||||
+ dev_info(sfp->dev, " 10GBaseSR%c 10GBaseLR%c 10GBaseLRM%c 10GBaseER%c\n",
|
||||
+ sfp->id.base.e10g_base_sr ? '+' : '-',
|
||||
+ sfp->id.base.e10g_base_lr ? '+' : '-',
|
||||
+ sfp->id.base.e10g_base_lrm ? '+' : '-',
|
||||
+ sfp->id.base.e10g_base_er ? '+' : '-');
|
||||
+
|
||||
+ if (!sfp->id.base.sfp_ct_passive && !sfp->id.base.sfp_ct_active &&
|
||||
+ !sfp->id.base.e1000_base_t) {
|
||||
+ char len_9um[16], len_om[16];
|
||||
+
|
||||
+ dev_info(sfp->dev, " Wavelength %unm, fiber lengths:\n",
|
||||
+ be16_to_cpup(&sfp->id.base.optical_wavelength));
|
||||
+
|
||||
+ if (sfp->id.base.link_len[0] == 255)
|
||||
+ strcpy(len_9um, ">254km");
|
||||
+ else if (sfp->id.base.link_len[1] && sfp->id.base.link_len[1] != 255)
|
||||
+ sprintf(len_9um, "%um",
|
||||
+ sfp->id.base.link_len[1] * 100);
|
||||
+ else if (sfp->id.base.link_len[0])
|
||||
+ sprintf(len_9um, "%ukm", sfp->id.base.link_len[0]);
|
||||
+ else if (sfp->id.base.link_len[1] == 255)
|
||||
+ strcpy(len_9um, ">25.4km");
|
||||
+ else
|
||||
+ strcpy(len_9um, "unsupported");
|
||||
+
|
||||
+ dev_info(sfp->dev, " 9µm SM : %s\n", len_9um);
|
||||
+ dev_info(sfp->dev, " 62.5µm MM OM1: %s\n",
|
||||
+ sfp_link_len(len_om, sizeof(len_om),
|
||||
+ sfp->id.base.link_len[3], 10));
|
||||
+ dev_info(sfp->dev, " 50µm MM OM2: %s\n",
|
||||
+ sfp_link_len(len_om, sizeof(len_om),
|
||||
+ sfp->id.base.link_len[2], 10));
|
||||
+ dev_info(sfp->dev, " 50µm MM OM3: %s\n",
|
||||
+ sfp_link_len(len_om, sizeof(len_om),
|
||||
+ sfp->id.base.link_len[5], 10));
|
||||
+ dev_info(sfp->dev, " 50µm MM OM4: %s\n",
|
||||
+ sfp_link_len(len_om, sizeof(len_om),
|
||||
+ sfp->id.base.link_len[4], 10));
|
||||
+ } else {
|
||||
+ char len[16];
|
||||
+ dev_info(sfp->dev, " Copper length: %s\n",
|
||||
+ sfp_link_len(len, sizeof(len),
|
||||
+ sfp->id.base.link_len[4], 1));
|
||||
+ }
|
||||
+
|
||||
+ dev_info(sfp->dev, " Options: %s\n",
|
||||
+ sfp_bitfield(options, sizeof(options), sfp_options,
|
||||
+ be16_to_cpu(sfp->id.ext.options)));
|
||||
+ dev_info(sfp->dev, " Diagnostics: %s\n",
|
||||
+ sfp_bitfield(options, sizeof(options), diagmon,
|
||||
+ sfp->id.ext.diagmon));
|
||||
|
||||
/* We only support SFP modules, not the legacy GBIC modules. */
|
||||
if (sfp->id.base.phys_id != SFP_PHYS_ID_SFP ||
|
979
patch/kernel/mvebu-next/403-net-mvneta-convert-to-phylink.patch
Normal file
979
patch/kernel/mvebu-next/403-net-mvneta-convert-to-phylink.patch
Normal file
|
@ -0,0 +1,979 @@
|
|||
From 36f29e6cf8071fed3854d9825217ed2a3c83b990 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
Date: Wed, 16 Sep 2015 21:27:10 +0100
|
||||
Subject: net: mvneta: convert to phylink
|
||||
|
||||
Convert mvneta to use phylink, which models the MAC to PHY link in
|
||||
a generic, reusable form.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
|
||||
- remove unused sync status
|
||||
---
|
||||
drivers/net/ethernet/marvell/Kconfig | 2 +-
|
||||
drivers/net/ethernet/marvell/mvneta.c | 594 ++++++++++++++++++++--------------
|
||||
2 files changed, 349 insertions(+), 247 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/marvell/Kconfig
|
||||
+++ b/drivers/net/ethernet/marvell/Kconfig
|
||||
@@ -60,7 +60,7 @@ config MVNETA
|
||||
depends on ARCH_MVEBU || COMPILE_TEST
|
||||
depends on HAS_DMA
|
||||
select MVMDIO
|
||||
- select FIXED_PHY
|
||||
+ select PHYLINK
|
||||
---help---
|
||||
This driver supports the network interface units in the
|
||||
Marvell ARMADA XP, ARMADA 370, ARMADA 38x and
|
||||
--- a/drivers/net/ethernet/marvell/mvneta.c
|
||||
+++ b/drivers/net/ethernet/marvell/mvneta.c
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/phy.h>
|
||||
-#include <linux/phy_fixed.h>
|
||||
+#include <linux/phylink.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/hwbm.h>
|
||||
@@ -189,6 +189,7 @@
|
||||
#define MVNETA_GMAC_CTRL_0 0x2c00
|
||||
#define MVNETA_GMAC_MAX_RX_SIZE_SHIFT 2
|
||||
#define MVNETA_GMAC_MAX_RX_SIZE_MASK 0x7ffc
|
||||
+#define MVNETA_GMAC0_PORT_1000BASE_X BIT(1)
|
||||
#define MVNETA_GMAC0_PORT_ENABLE BIT(0)
|
||||
#define MVNETA_GMAC_CTRL_2 0x2c08
|
||||
#define MVNETA_GMAC2_INBAND_AN_ENABLE BIT(0)
|
||||
@@ -204,13 +205,19 @@
|
||||
#define MVNETA_GMAC_TX_FLOW_CTRL_ENABLE BIT(5)
|
||||
#define MVNETA_GMAC_RX_FLOW_CTRL_ACTIVE BIT(6)
|
||||
#define MVNETA_GMAC_TX_FLOW_CTRL_ACTIVE BIT(7)
|
||||
+#define MVNETA_GMAC_AN_COMPLETE BIT(11)
|
||||
+#define MVNETA_GMAC_SYNC_OK BIT(14)
|
||||
#define MVNETA_GMAC_AUTONEG_CONFIG 0x2c0c
|
||||
#define MVNETA_GMAC_FORCE_LINK_DOWN BIT(0)
|
||||
#define MVNETA_GMAC_FORCE_LINK_PASS BIT(1)
|
||||
#define MVNETA_GMAC_INBAND_AN_ENABLE BIT(2)
|
||||
+#define MVNETA_GMAC_AN_BYPASS_ENABLE BIT(3)
|
||||
+#define MVNETA_GMAC_INBAND_RESTART_AN BIT(4)
|
||||
#define MVNETA_GMAC_CONFIG_MII_SPEED BIT(5)
|
||||
#define MVNETA_GMAC_CONFIG_GMII_SPEED BIT(6)
|
||||
#define MVNETA_GMAC_AN_SPEED_EN BIT(7)
|
||||
+#define MVNETA_GMAC_CONFIG_FLOW_CTRL BIT(8)
|
||||
+#define MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL BIT(9)
|
||||
#define MVNETA_GMAC_AN_FLOW_CTRL_EN BIT(11)
|
||||
#define MVNETA_GMAC_CONFIG_FULL_DUPLEX BIT(12)
|
||||
#define MVNETA_GMAC_AN_DUPLEX_EN BIT(13)
|
||||
@@ -237,6 +244,12 @@
|
||||
#define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2))
|
||||
#define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff
|
||||
|
||||
+#define MVNETA_LPI_CTRL_0 0x2cc0
|
||||
+#define MVNETA_LPI_CTRL_1 0x2cc4
|
||||
+#define MVNETA_LPI_REQUEST_ENABLE BIT(0)
|
||||
+#define MVNETA_LPI_CTRL_2 0x2cc8
|
||||
+#define MVNETA_LPI_STATUS 0x2ccc
|
||||
+
|
||||
#define MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK 0xff
|
||||
|
||||
/* Descriptor ring Macros */
|
||||
@@ -313,6 +326,11 @@
|
||||
#define MVNETA_RX_GET_BM_POOL_ID(rxd) \
|
||||
(((rxd)->status & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT)
|
||||
|
||||
+enum {
|
||||
+ ETHTOOL_STAT_EEE_WAKEUP,
|
||||
+ ETHTOOL_MAX_STATS,
|
||||
+};
|
||||
+
|
||||
struct mvneta_statistic {
|
||||
unsigned short offset;
|
||||
unsigned short type;
|
||||
@@ -321,6 +339,7 @@ struct mvneta_statistic {
|
||||
|
||||
#define T_REG_32 32
|
||||
#define T_REG_64 64
|
||||
+#define T_SW 1
|
||||
|
||||
static const struct mvneta_statistic mvneta_statistics[] = {
|
||||
{ 0x3000, T_REG_64, "good_octets_received", },
|
||||
@@ -355,6 +374,7 @@ static const struct mvneta_statistic mvn
|
||||
{ 0x304c, T_REG_32, "broadcast_frames_sent", },
|
||||
{ 0x3054, T_REG_32, "fc_sent", },
|
||||
{ 0x300c, T_REG_32, "internal_mac_transmit_err", },
|
||||
+ { ETHTOOL_STAT_EEE_WAKEUP, T_SW, "eee_wakeup_errors", },
|
||||
};
|
||||
|
||||
struct mvneta_pcpu_stats {
|
||||
@@ -407,20 +427,19 @@ struct mvneta_port {
|
||||
u16 tx_ring_size;
|
||||
u16 rx_ring_size;
|
||||
|
||||
- struct mii_bus *mii_bus;
|
||||
- phy_interface_t phy_interface;
|
||||
- struct device_node *phy_node;
|
||||
- unsigned int link;
|
||||
- unsigned int duplex;
|
||||
- unsigned int speed;
|
||||
+ struct device_node *dn;
|
||||
unsigned int tx_csum_limit;
|
||||
- unsigned int use_inband_status:1;
|
||||
+ struct phylink *phylink;
|
||||
|
||||
struct mvneta_bm *bm_priv;
|
||||
struct mvneta_bm_pool *pool_long;
|
||||
struct mvneta_bm_pool *pool_short;
|
||||
int bm_win_id;
|
||||
|
||||
+ bool eee_enabled;
|
||||
+ bool eee_active;
|
||||
+ bool tx_lpi_enabled;
|
||||
+
|
||||
u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
|
||||
|
||||
u32 indir[MVNETA_RSS_LU_TABLE_SIZE];
|
||||
@@ -1214,10 +1233,6 @@ static void mvneta_port_disable(struct m
|
||||
val &= ~MVNETA_GMAC0_PORT_ENABLE;
|
||||
mvreg_write(pp, MVNETA_GMAC_CTRL_0, val);
|
||||
|
||||
- pp->link = 0;
|
||||
- pp->duplex = -1;
|
||||
- pp->speed = 0;
|
||||
-
|
||||
udelay(200);
|
||||
}
|
||||
|
||||
@@ -1277,44 +1292,6 @@ static void mvneta_set_other_mcast_table
|
||||
mvreg_write(pp, MVNETA_DA_FILT_OTH_MCAST + offset, val);
|
||||
}
|
||||
|
||||
-static void mvneta_set_autoneg(struct mvneta_port *pp, int enable)
|
||||
-{
|
||||
- u32 val;
|
||||
-
|
||||
- if (enable) {
|
||||
- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
- val &= ~(MVNETA_GMAC_FORCE_LINK_PASS |
|
||||
- MVNETA_GMAC_FORCE_LINK_DOWN |
|
||||
- MVNETA_GMAC_AN_FLOW_CTRL_EN);
|
||||
- val |= MVNETA_GMAC_INBAND_AN_ENABLE |
|
||||
- MVNETA_GMAC_AN_SPEED_EN |
|
||||
- MVNETA_GMAC_AN_DUPLEX_EN;
|
||||
- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
|
||||
-
|
||||
- val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER);
|
||||
- val |= MVNETA_GMAC_1MS_CLOCK_ENABLE;
|
||||
- mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val);
|
||||
-
|
||||
- val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
|
||||
- val |= MVNETA_GMAC2_INBAND_AN_ENABLE;
|
||||
- mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
|
||||
- } else {
|
||||
- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
- val &= ~(MVNETA_GMAC_INBAND_AN_ENABLE |
|
||||
- MVNETA_GMAC_AN_SPEED_EN |
|
||||
- MVNETA_GMAC_AN_DUPLEX_EN);
|
||||
- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
|
||||
-
|
||||
- val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER);
|
||||
- val &= ~MVNETA_GMAC_1MS_CLOCK_ENABLE;
|
||||
- mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val);
|
||||
-
|
||||
- val = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
|
||||
- val &= ~MVNETA_GMAC2_INBAND_AN_ENABLE;
|
||||
- mvreg_write(pp, MVNETA_GMAC_CTRL_2, val);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
static void mvneta_percpu_unmask_interrupt(void *arg)
|
||||
{
|
||||
struct mvneta_port *pp = arg;
|
||||
@@ -1467,7 +1444,6 @@ static void mvneta_defaults_set(struct m
|
||||
val &= ~MVNETA_PHY_POLLING_ENABLE;
|
||||
mvreg_write(pp, MVNETA_UNIT_CONTROL, val);
|
||||
|
||||
- mvneta_set_autoneg(pp, pp->use_inband_status);
|
||||
mvneta_set_ucast_table(pp, -1);
|
||||
mvneta_set_special_mcast_table(pp, -1);
|
||||
mvneta_set_other_mcast_table(pp, -1);
|
||||
@@ -2692,26 +2668,11 @@ static irqreturn_t mvneta_percpu_isr(int
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
-static int mvneta_fixed_link_update(struct mvneta_port *pp,
|
||||
- struct phy_device *phy)
|
||||
+static void mvneta_link_change(struct mvneta_port *pp)
|
||||
{
|
||||
- struct fixed_phy_status status;
|
||||
- struct fixed_phy_status changed = {};
|
||||
u32 gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS);
|
||||
|
||||
- status.link = !!(gmac_stat & MVNETA_GMAC_LINK_UP);
|
||||
- if (gmac_stat & MVNETA_GMAC_SPEED_1000)
|
||||
- status.speed = SPEED_1000;
|
||||
- else if (gmac_stat & MVNETA_GMAC_SPEED_100)
|
||||
- status.speed = SPEED_100;
|
||||
- else
|
||||
- status.speed = SPEED_10;
|
||||
- status.duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX);
|
||||
- changed.link = 1;
|
||||
- changed.speed = 1;
|
||||
- changed.duplex = 1;
|
||||
- fixed_phy_update_state(phy, &status, &changed);
|
||||
- return 0;
|
||||
+ phylink_mac_change(pp->phylink, !!(gmac_stat & MVNETA_GMAC_LINK_UP));
|
||||
}
|
||||
|
||||
/* NAPI handler
|
||||
@@ -2727,7 +2688,6 @@ static int mvneta_poll(struct napi_struc
|
||||
u32 cause_rx_tx;
|
||||
int rx_queue;
|
||||
struct mvneta_port *pp = netdev_priv(napi->dev);
|
||||
- struct net_device *ndev = pp->dev;
|
||||
struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports);
|
||||
|
||||
if (!netif_running(pp->dev)) {
|
||||
@@ -2741,12 +2701,11 @@ static int mvneta_poll(struct napi_struc
|
||||
u32 cause_misc = mvreg_read(pp, MVNETA_INTR_MISC_CAUSE);
|
||||
|
||||
mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
|
||||
- if (pp->use_inband_status && (cause_misc &
|
||||
- (MVNETA_CAUSE_PHY_STATUS_CHANGE |
|
||||
- MVNETA_CAUSE_LINK_CHANGE |
|
||||
- MVNETA_CAUSE_PSC_SYNC_CHANGE))) {
|
||||
- mvneta_fixed_link_update(pp, ndev->phydev);
|
||||
- }
|
||||
+
|
||||
+ if (cause_misc & (MVNETA_CAUSE_PHY_STATUS_CHANGE |
|
||||
+ MVNETA_CAUSE_LINK_CHANGE |
|
||||
+ MVNETA_CAUSE_PSC_SYNC_CHANGE))
|
||||
+ mvneta_link_change(pp);
|
||||
}
|
||||
|
||||
/* Release Tx descriptors */
|
||||
@@ -3060,7 +3019,6 @@ static int mvneta_setup_txqs(struct mvne
|
||||
static void mvneta_start_dev(struct mvneta_port *pp)
|
||||
{
|
||||
int cpu;
|
||||
- struct net_device *ndev = pp->dev;
|
||||
|
||||
mvneta_max_rx_size_set(pp, pp->pkt_size);
|
||||
mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
|
||||
@@ -3088,16 +3046,15 @@ static void mvneta_start_dev(struct mvne
|
||||
MVNETA_CAUSE_LINK_CHANGE |
|
||||
MVNETA_CAUSE_PSC_SYNC_CHANGE);
|
||||
|
||||
- phy_start(ndev->phydev);
|
||||
+ phylink_start(pp->phylink);
|
||||
netif_tx_start_all_queues(pp->dev);
|
||||
}
|
||||
|
||||
static void mvneta_stop_dev(struct mvneta_port *pp)
|
||||
{
|
||||
unsigned int cpu;
|
||||
- struct net_device *ndev = pp->dev;
|
||||
|
||||
- phy_stop(ndev->phydev);
|
||||
+ phylink_stop(pp->phylink);
|
||||
|
||||
if (!pp->neta_armada3700) {
|
||||
for_each_online_cpu(cpu) {
|
||||
@@ -3251,103 +3208,232 @@ static int mvneta_set_mac_addr(struct ne
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void mvneta_adjust_link(struct net_device *ndev)
|
||||
+static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
|
||||
+ struct phylink_link_state *state)
|
||||
+{
|
||||
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
|
||||
+
|
||||
+ /* Allow all the expected bits */
|
||||
+ phylink_set(mask, Autoneg);
|
||||
+ phylink_set_port_modes(mask);
|
||||
+
|
||||
+ /* Asymmetric pause is unsupported */
|
||||
+ phylink_set(mask, Pause);
|
||||
+ /* Half-duplex at speeds higher than 100Mbit is unsupported */
|
||||
+ phylink_set(mask, 1000baseT_Full);
|
||||
+ phylink_set(mask, 1000baseX_Full);
|
||||
+
|
||||
+ if (state->interface != PHY_INTERFACE_MODE_1000BASEX) {
|
||||
+ /* 10M and 100M are only supported in non-802.3z mode */
|
||||
+ phylink_set(mask, 10baseT_Half);
|
||||
+ phylink_set(mask, 10baseT_Full);
|
||||
+ phylink_set(mask, 100baseT_Half);
|
||||
+ phylink_set(mask, 100baseT_Full);
|
||||
+ }
|
||||
+
|
||||
+ bitmap_and(supported, supported, mask,
|
||||
+ __ETHTOOL_LINK_MODE_MASK_NBITS);
|
||||
+ bitmap_and(state->advertising, state->advertising, mask,
|
||||
+ __ETHTOOL_LINK_MODE_MASK_NBITS);
|
||||
+}
|
||||
+
|
||||
+static int mvneta_mac_link_state(struct net_device *ndev,
|
||||
+ struct phylink_link_state *state)
|
||||
{
|
||||
struct mvneta_port *pp = netdev_priv(ndev);
|
||||
- struct phy_device *phydev = ndev->phydev;
|
||||
- int status_change = 0;
|
||||
+ u32 gmac_stat;
|
||||
|
||||
- if (phydev->link) {
|
||||
- if ((pp->speed != phydev->speed) ||
|
||||
- (pp->duplex != phydev->duplex)) {
|
||||
- u32 val;
|
||||
-
|
||||
- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
- val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED |
|
||||
- MVNETA_GMAC_CONFIG_GMII_SPEED |
|
||||
- MVNETA_GMAC_CONFIG_FULL_DUPLEX);
|
||||
-
|
||||
- if (phydev->duplex)
|
||||
- val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX;
|
||||
-
|
||||
- if (phydev->speed == SPEED_1000)
|
||||
- val |= MVNETA_GMAC_CONFIG_GMII_SPEED;
|
||||
- else if (phydev->speed == SPEED_100)
|
||||
- val |= MVNETA_GMAC_CONFIG_MII_SPEED;
|
||||
+ gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS);
|
||||
|
||||
- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
|
||||
+ if (gmac_stat & MVNETA_GMAC_SPEED_1000)
|
||||
+ state->speed = SPEED_1000;
|
||||
+ else if (gmac_stat & MVNETA_GMAC_SPEED_100)
|
||||
+ state->speed = SPEED_100;
|
||||
+ else
|
||||
+ state->speed = SPEED_10;
|
||||
|
||||
- pp->duplex = phydev->duplex;
|
||||
- pp->speed = phydev->speed;
|
||||
- }
|
||||
+ state->an_complete = !!(gmac_stat & MVNETA_GMAC_AN_COMPLETE);
|
||||
+ state->link = !!(gmac_stat & MVNETA_GMAC_LINK_UP);
|
||||
+ state->duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX);
|
||||
+
|
||||
+ state->pause = 0;
|
||||
+ if (gmac_stat & MVNETA_GMAC_RX_FLOW_CTRL_ENABLE)
|
||||
+ state->pause |= MLO_PAUSE_RX;
|
||||
+ if (gmac_stat & MVNETA_GMAC_TX_FLOW_CTRL_ENABLE)
|
||||
+ state->pause |= MLO_PAUSE_TX;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static void mvneta_mac_an_restart(struct net_device *ndev)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(ndev);
|
||||
+ u32 gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
+
|
||||
+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
|
||||
+ gmac_an | MVNETA_GMAC_INBAND_RESTART_AN);
|
||||
+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
|
||||
+ gmac_an & ~MVNETA_GMAC_INBAND_RESTART_AN);
|
||||
+}
|
||||
+
|
||||
+static void mvneta_mac_config(struct net_device *ndev, unsigned int mode,
|
||||
+ const struct phylink_link_state *state)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(ndev);
|
||||
+ u32 new_ctrl0, gmac_ctrl0 = mvreg_read(pp, MVNETA_GMAC_CTRL_0);
|
||||
+ u32 new_ctrl2, gmac_ctrl2 = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
|
||||
+ u32 new_clk, gmac_clk = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER);
|
||||
+ u32 new_an, gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
+
|
||||
+ new_ctrl0 = gmac_ctrl0 & ~MVNETA_GMAC0_PORT_1000BASE_X;
|
||||
+ new_ctrl2 = gmac_ctrl2 & ~MVNETA_GMAC2_INBAND_AN_ENABLE;
|
||||
+ new_clk = gmac_clk & ~MVNETA_GMAC_1MS_CLOCK_ENABLE;
|
||||
+ new_an = gmac_an & ~(MVNETA_GMAC_INBAND_AN_ENABLE |
|
||||
+ MVNETA_GMAC_INBAND_RESTART_AN |
|
||||
+ MVNETA_GMAC_CONFIG_MII_SPEED |
|
||||
+ MVNETA_GMAC_CONFIG_GMII_SPEED |
|
||||
+ MVNETA_GMAC_AN_SPEED_EN |
|
||||
+ MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL |
|
||||
+ MVNETA_GMAC_CONFIG_FLOW_CTRL |
|
||||
+ MVNETA_GMAC_AN_FLOW_CTRL_EN |
|
||||
+ MVNETA_GMAC_CONFIG_FULL_DUPLEX |
|
||||
+ MVNETA_GMAC_AN_DUPLEX_EN);
|
||||
+
|
||||
+ if (phylink_test(state->advertising, Pause))
|
||||
+ new_an |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL;
|
||||
+ if (state->pause & MLO_PAUSE_TXRX_MASK)
|
||||
+ new_an |= MVNETA_GMAC_CONFIG_FLOW_CTRL;
|
||||
+
|
||||
+ if (!phylink_autoneg_inband(mode)) {
|
||||
+ /* Phy or fixed speed */
|
||||
+ if (state->duplex)
|
||||
+ new_an |= MVNETA_GMAC_CONFIG_FULL_DUPLEX;
|
||||
+
|
||||
+ if (state->speed == SPEED_1000)
|
||||
+ new_an |= MVNETA_GMAC_CONFIG_GMII_SPEED;
|
||||
+ else if (state->speed == SPEED_100)
|
||||
+ new_an |= MVNETA_GMAC_CONFIG_MII_SPEED;
|
||||
+ } else if (state->interface == PHY_INTERFACE_MODE_SGMII) {
|
||||
+ /* SGMII mode receives the state from the PHY */
|
||||
+ new_ctrl2 |= MVNETA_GMAC2_INBAND_AN_ENABLE;
|
||||
+ new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE;
|
||||
+ new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN |
|
||||
+ MVNETA_GMAC_FORCE_LINK_PASS)) |
|
||||
+ MVNETA_GMAC_INBAND_AN_ENABLE |
|
||||
+ MVNETA_GMAC_AN_SPEED_EN |
|
||||
+ MVNETA_GMAC_AN_DUPLEX_EN;
|
||||
+ } else {
|
||||
+ /* 802.3z negotiation - only 1000base-X */
|
||||
+ new_ctrl0 |= MVNETA_GMAC0_PORT_1000BASE_X;
|
||||
+ new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE;
|
||||
+ new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN |
|
||||
+ MVNETA_GMAC_FORCE_LINK_PASS)) |
|
||||
+ MVNETA_GMAC_INBAND_AN_ENABLE |
|
||||
+ MVNETA_GMAC_CONFIG_GMII_SPEED |
|
||||
+ /* The MAC only supports FD mode */
|
||||
+ MVNETA_GMAC_CONFIG_FULL_DUPLEX;
|
||||
+
|
||||
+ if (state->pause & MLO_PAUSE_AN && state->an_enabled)
|
||||
+ new_an |= MVNETA_GMAC_AN_FLOW_CTRL_EN;
|
||||
+ }
|
||||
+
|
||||
+ /* Armada 370 documentation says we can only change the port mode
|
||||
+ * and in-band enable when the link is down, so force it down
|
||||
+ * while making these changes. We also do this for GMAC_CTRL2 */
|
||||
+ if ((new_ctrl0 ^ gmac_ctrl0) & MVNETA_GMAC0_PORT_1000BASE_X ||
|
||||
+ (new_ctrl2 ^ gmac_ctrl2) & MVNETA_GMAC2_INBAND_AN_ENABLE ||
|
||||
+ (new_an ^ gmac_an) & MVNETA_GMAC_INBAND_AN_ENABLE) {
|
||||
+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
|
||||
+ (gmac_an & ~MVNETA_GMAC_FORCE_LINK_PASS) |
|
||||
+ MVNETA_GMAC_FORCE_LINK_DOWN);
|
||||
+ }
|
||||
+
|
||||
+ if (new_ctrl0 != gmac_ctrl0)
|
||||
+ mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0);
|
||||
+ if (new_ctrl2 != gmac_ctrl2)
|
||||
+ mvreg_write(pp, MVNETA_GMAC_CTRL_2, new_ctrl2);
|
||||
+ if (new_clk != gmac_clk)
|
||||
+ mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, new_clk);
|
||||
+ if (new_an != gmac_an)
|
||||
+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, new_an);
|
||||
+}
|
||||
+
|
||||
+static void mvneta_set_eee(struct mvneta_port *pp, bool enable)
|
||||
+{
|
||||
+ u32 lpi_ctl1;
|
||||
+
|
||||
+ lpi_ctl1 = mvreg_read(pp, MVNETA_LPI_CTRL_1);
|
||||
+ if (enable)
|
||||
+ lpi_ctl1 |= MVNETA_LPI_REQUEST_ENABLE;
|
||||
+ else
|
||||
+ lpi_ctl1 &= ~MVNETA_LPI_REQUEST_ENABLE;
|
||||
+ mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi_ctl1);
|
||||
+}
|
||||
+
|
||||
+static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(ndev);
|
||||
+ u32 val;
|
||||
+
|
||||
+ mvneta_port_down(pp);
|
||||
+
|
||||
+ if (!phylink_autoneg_inband(mode)) {
|
||||
+ val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
+ val &= ~MVNETA_GMAC_FORCE_LINK_PASS;
|
||||
+ val |= MVNETA_GMAC_FORCE_LINK_DOWN;
|
||||
+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
|
||||
}
|
||||
|
||||
- if (phydev->link != pp->link) {
|
||||
- if (!phydev->link) {
|
||||
- pp->duplex = -1;
|
||||
- pp->speed = 0;
|
||||
- }
|
||||
+ pp->eee_active = false;
|
||||
+ mvneta_set_eee(pp, false);
|
||||
+}
|
||||
+
|
||||
+static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode,
|
||||
+ struct phy_device *phy)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(ndev);
|
||||
+ u32 val;
|
||||
|
||||
- pp->link = phydev->link;
|
||||
- status_change = 1;
|
||||
+ if (!phylink_autoneg_inband(mode)) {
|
||||
+ val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
+ val &= ~MVNETA_GMAC_FORCE_LINK_DOWN;
|
||||
+ val |= MVNETA_GMAC_FORCE_LINK_PASS;
|
||||
+ mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
|
||||
}
|
||||
|
||||
- if (status_change) {
|
||||
- if (phydev->link) {
|
||||
- if (!pp->use_inband_status) {
|
||||
- u32 val = mvreg_read(pp,
|
||||
- MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
- val &= ~MVNETA_GMAC_FORCE_LINK_DOWN;
|
||||
- val |= MVNETA_GMAC_FORCE_LINK_PASS;
|
||||
- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
|
||||
- val);
|
||||
- }
|
||||
- mvneta_port_up(pp);
|
||||
- } else {
|
||||
- if (!pp->use_inband_status) {
|
||||
- u32 val = mvreg_read(pp,
|
||||
- MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
- val &= ~MVNETA_GMAC_FORCE_LINK_PASS;
|
||||
- val |= MVNETA_GMAC_FORCE_LINK_DOWN;
|
||||
- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG,
|
||||
- val);
|
||||
- }
|
||||
- mvneta_port_down(pp);
|
||||
- }
|
||||
- phy_print_status(phydev);
|
||||
+ mvneta_port_up(pp);
|
||||
+
|
||||
+ if (phy && pp->eee_enabled) {
|
||||
+ pp->eee_active = phy_init_eee(phy, 0) >= 0;
|
||||
+ mvneta_set_eee(pp, pp->eee_active && pp->tx_lpi_enabled);
|
||||
}
|
||||
}
|
||||
|
||||
+static const struct phylink_mac_ops mvneta_phylink_ops = {
|
||||
+ .validate = mvneta_validate,
|
||||
+ .mac_link_state = mvneta_mac_link_state,
|
||||
+ .mac_an_restart = mvneta_mac_an_restart,
|
||||
+ .mac_config = mvneta_mac_config,
|
||||
+ .mac_link_down = mvneta_mac_link_down,
|
||||
+ .mac_link_up = mvneta_mac_link_up,
|
||||
+};
|
||||
+
|
||||
static int mvneta_mdio_probe(struct mvneta_port *pp)
|
||||
{
|
||||
- struct phy_device *phy_dev;
|
||||
struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
|
||||
+ int err = phylink_of_phy_connect(pp->phylink, pp->dn);
|
||||
+ if (err)
|
||||
+ netdev_err(pp->dev, "could not attach PHY\n");
|
||||
|
||||
- phy_dev = of_phy_connect(pp->dev, pp->phy_node, mvneta_adjust_link, 0,
|
||||
- pp->phy_interface);
|
||||
- if (!phy_dev) {
|
||||
- netdev_err(pp->dev, "could not find the PHY\n");
|
||||
- return -ENODEV;
|
||||
- }
|
||||
-
|
||||
- phy_ethtool_get_wol(phy_dev, &wol);
|
||||
+ phylink_ethtool_get_wol(pp->phylink, &wol);
|
||||
device_set_wakeup_capable(&pp->dev->dev, !!wol.supported);
|
||||
|
||||
- phy_dev->supported &= PHY_GBIT_FEATURES;
|
||||
- phy_dev->advertising = phy_dev->supported;
|
||||
-
|
||||
- pp->link = 0;
|
||||
- pp->duplex = 0;
|
||||
- pp->speed = 0;
|
||||
-
|
||||
- return 0;
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static void mvneta_mdio_remove(struct mvneta_port *pp)
|
||||
{
|
||||
- struct net_device *ndev = pp->dev;
|
||||
-
|
||||
- phy_disconnect(ndev->phydev);
|
||||
+ phylink_disconnect_phy(pp->phylink);
|
||||
}
|
||||
|
||||
/* Electing a CPU must be done in an atomic way: it should be done
|
||||
@@ -3626,10 +3712,9 @@ static int mvneta_stop(struct net_device
|
||||
|
||||
static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
- if (!dev->phydev)
|
||||
- return -ENOTSUPP;
|
||||
+ struct mvneta_port *pp = netdev_priv(dev);
|
||||
|
||||
- return phy_mii_ioctl(dev->phydev, ifr, cmd);
|
||||
+ return phylink_mii_ioctl(pp->phylink, ifr, cmd);
|
||||
}
|
||||
|
||||
/* Ethtool methods */
|
||||
@@ -3640,44 +3725,25 @@ mvneta_ethtool_set_link_ksettings(struct
|
||||
const struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
struct mvneta_port *pp = netdev_priv(ndev);
|
||||
- struct phy_device *phydev = ndev->phydev;
|
||||
|
||||
- if (!phydev)
|
||||
- return -ENODEV;
|
||||
-
|
||||
- if ((cmd->base.autoneg == AUTONEG_ENABLE) != pp->use_inband_status) {
|
||||
- u32 val;
|
||||
-
|
||||
- mvneta_set_autoneg(pp, cmd->base.autoneg == AUTONEG_ENABLE);
|
||||
-
|
||||
- if (cmd->base.autoneg == AUTONEG_DISABLE) {
|
||||
- val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
|
||||
- val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED |
|
||||
- MVNETA_GMAC_CONFIG_GMII_SPEED |
|
||||
- MVNETA_GMAC_CONFIG_FULL_DUPLEX);
|
||||
-
|
||||
- if (phydev->duplex)
|
||||
- val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX;
|
||||
+ return phylink_ethtool_ksettings_set(pp->phylink, cmd);
|
||||
+}
|
||||
|
||||
- if (phydev->speed == SPEED_1000)
|
||||
- val |= MVNETA_GMAC_CONFIG_GMII_SPEED;
|
||||
- else if (phydev->speed == SPEED_100)
|
||||
- val |= MVNETA_GMAC_CONFIG_MII_SPEED;
|
||||
+/* Get link ksettings for ethtools */
|
||||
+static int
|
||||
+mvneta_ethtool_get_link_ksettings(struct net_device *ndev,
|
||||
+ struct ethtool_link_ksettings *cmd)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(ndev);
|
||||
|
||||
- mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
|
||||
- }
|
||||
+ return phylink_ethtool_ksettings_get(pp->phylink, cmd);
|
||||
+}
|
||||
|
||||
- pp->use_inband_status = (cmd->base.autoneg == AUTONEG_ENABLE);
|
||||
- netdev_info(pp->dev, "autoneg status set to %i\n",
|
||||
- pp->use_inband_status);
|
||||
-
|
||||
- if (netif_running(ndev)) {
|
||||
- mvneta_port_down(pp);
|
||||
- mvneta_port_up(pp);
|
||||
- }
|
||||
- }
|
||||
+static int mvneta_ethtool_nway_reset(struct net_device *dev)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(dev);
|
||||
|
||||
- return phy_ethtool_ksettings_set(ndev->phydev, cmd);
|
||||
+ return phylink_ethtool_nway_reset(pp->phylink);
|
||||
}
|
||||
|
||||
/* Set interrupt coalescing for ethtools */
|
||||
@@ -3769,6 +3835,22 @@ static int mvneta_ethtool_set_ringparam(
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void mvneta_ethtool_get_pauseparam(struct net_device *dev,
|
||||
+ struct ethtool_pauseparam *pause)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(dev);
|
||||
+
|
||||
+ phylink_ethtool_get_pauseparam(pp->phylink, pause);
|
||||
+}
|
||||
+
|
||||
+static int mvneta_ethtool_set_pauseparam(struct net_device *dev,
|
||||
+ struct ethtool_pauseparam *pause)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(dev);
|
||||
+
|
||||
+ return phylink_ethtool_set_pauseparam(pp->phylink, pause);
|
||||
+}
|
||||
+
|
||||
static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset,
|
||||
u8 *data)
|
||||
{
|
||||
@@ -3785,26 +3867,35 @@ static void mvneta_ethtool_update_stats(
|
||||
{
|
||||
const struct mvneta_statistic *s;
|
||||
void __iomem *base = pp->base;
|
||||
- u32 high, low, val;
|
||||
- u64 val64;
|
||||
+ u32 high, low;
|
||||
+ u64 val;
|
||||
int i;
|
||||
|
||||
for (i = 0, s = mvneta_statistics;
|
||||
s < mvneta_statistics + ARRAY_SIZE(mvneta_statistics);
|
||||
s++, i++) {
|
||||
+ val = 0;
|
||||
+
|
||||
switch (s->type) {
|
||||
case T_REG_32:
|
||||
val = readl_relaxed(base + s->offset);
|
||||
- pp->ethtool_stats[i] += val;
|
||||
break;
|
||||
case T_REG_64:
|
||||
/* Docs say to read low 32-bit then high */
|
||||
low = readl_relaxed(base + s->offset);
|
||||
high = readl_relaxed(base + s->offset + 4);
|
||||
- val64 = (u64)high << 32 | low;
|
||||
- pp->ethtool_stats[i] += val64;
|
||||
+ val = (u64)high << 32 | low;
|
||||
+ break;
|
||||
+ case T_SW:
|
||||
+ switch (s->offset) {
|
||||
+ case ETHTOOL_STAT_EEE_WAKEUP:
|
||||
+ val = phylink_get_eee_err(pp->phylink);
|
||||
+ break;
|
||||
+ }
|
||||
break;
|
||||
}
|
||||
+
|
||||
+ pp->ethtool_stats[i] += val;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3939,28 +4030,65 @@ static int mvneta_ethtool_get_rxfh(struc
|
||||
static void mvneta_ethtool_get_wol(struct net_device *dev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
- wol->supported = 0;
|
||||
- wol->wolopts = 0;
|
||||
+ struct mvneta_port *pp = netdev_priv(dev);
|
||||
|
||||
- if (dev->phydev)
|
||||
- phy_ethtool_get_wol(dev->phydev, wol);
|
||||
+ phylink_ethtool_get_wol(pp->phylink, wol);
|
||||
}
|
||||
|
||||
static int mvneta_ethtool_set_wol(struct net_device *dev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
+ struct mvneta_port *pp = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
- if (!dev->phydev)
|
||||
- return -EOPNOTSUPP;
|
||||
-
|
||||
- ret = phy_ethtool_set_wol(dev->phydev, wol);
|
||||
+ ret = phylink_ethtool_set_wol(pp->phylink, wol);
|
||||
if (!ret)
|
||||
device_set_wakeup_enable(&dev->dev, !!wol->wolopts);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int mvneta_ethtool_get_eee(struct net_device *dev,
|
||||
+ struct ethtool_eee *eee)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(dev);
|
||||
+ u32 lpi_ctl0;
|
||||
+
|
||||
+ lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0);
|
||||
+
|
||||
+ eee->eee_enabled = pp->eee_enabled;
|
||||
+ eee->eee_active = pp->eee_active;
|
||||
+ eee->tx_lpi_enabled = pp->tx_lpi_enabled;
|
||||
+ eee->tx_lpi_timer = (lpi_ctl0) >> 8; // * scale;
|
||||
+
|
||||
+ return phylink_ethtool_get_eee(pp->phylink, eee);
|
||||
+}
|
||||
+
|
||||
+static int mvneta_ethtool_set_eee(struct net_device *dev,
|
||||
+ struct ethtool_eee *eee)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(dev);
|
||||
+ u32 lpi_ctl0;
|
||||
+
|
||||
+ /* The Armada 37x documents do not give limits for this other than
|
||||
+ * it being an 8-bit register. */
|
||||
+ if (eee->tx_lpi_enabled &&
|
||||
+ (eee->tx_lpi_timer < 0 || eee->tx_lpi_timer > 255))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0);
|
||||
+ lpi_ctl0 &= ~(0xff << 8);
|
||||
+ lpi_ctl0 |= eee->tx_lpi_timer << 8;
|
||||
+ mvreg_write(pp, MVNETA_LPI_CTRL_0, lpi_ctl0);
|
||||
+
|
||||
+ pp->eee_enabled = eee->eee_enabled;
|
||||
+ pp->tx_lpi_enabled = eee->tx_lpi_enabled;
|
||||
+
|
||||
+ mvneta_set_eee(pp, eee->tx_lpi_enabled && eee->eee_enabled);
|
||||
+
|
||||
+ return phylink_ethtool_set_eee(pp->phylink, eee);
|
||||
+}
|
||||
+
|
||||
static u16 mvneta_select_queue(struct net_device *dev, struct sk_buff *skb,
|
||||
void *accel_priv,
|
||||
select_queue_fallback_t fallback)
|
||||
@@ -3984,13 +4112,15 @@ static const struct net_device_ops mvnet
|
||||
};
|
||||
|
||||
static const struct ethtool_ops mvneta_eth_tool_ops = {
|
||||
- .nway_reset = phy_ethtool_nway_reset,
|
||||
+ .nway_reset = mvneta_ethtool_nway_reset,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.set_coalesce = mvneta_ethtool_set_coalesce,
|
||||
.get_coalesce = mvneta_ethtool_get_coalesce,
|
||||
.get_drvinfo = mvneta_ethtool_get_drvinfo,
|
||||
.get_ringparam = mvneta_ethtool_get_ringparam,
|
||||
.set_ringparam = mvneta_ethtool_set_ringparam,
|
||||
+ .get_pauseparam = mvneta_ethtool_get_pauseparam,
|
||||
+ .set_pauseparam = mvneta_ethtool_set_pauseparam,
|
||||
.get_strings = mvneta_ethtool_get_strings,
|
||||
.get_ethtool_stats = mvneta_ethtool_get_stats,
|
||||
.get_sset_count = mvneta_ethtool_get_sset_count,
|
||||
@@ -3998,10 +4128,12 @@ static const struct ethtool_ops mvneta_e
|
||||
.get_rxnfc = mvneta_ethtool_get_rxnfc,
|
||||
.get_rxfh = mvneta_ethtool_get_rxfh,
|
||||
.set_rxfh = mvneta_ethtool_set_rxfh,
|
||||
- .get_link_ksettings = phy_ethtool_get_link_ksettings,
|
||||
+ .get_link_ksettings = mvneta_ethtool_get_link_ksettings,
|
||||
.set_link_ksettings = mvneta_ethtool_set_link_ksettings,
|
||||
.get_wol = mvneta_ethtool_get_wol,
|
||||
.set_wol = mvneta_ethtool_set_wol,
|
||||
+ .get_eee = mvneta_ethtool_get_eee,
|
||||
+ .set_eee = mvneta_ethtool_set_eee,
|
||||
};
|
||||
|
||||
/* Initialize hw */
|
||||
@@ -4146,14 +4278,13 @@ static int mvneta_probe(struct platform_
|
||||
{
|
||||
struct resource *res;
|
||||
struct device_node *dn = pdev->dev.of_node;
|
||||
- struct device_node *phy_node;
|
||||
struct device_node *bm_node;
|
||||
struct mvneta_port *pp;
|
||||
struct net_device *dev;
|
||||
+ struct phylink *phylink;
|
||||
const char *dt_mac_addr;
|
||||
char hw_mac_addr[ETH_ALEN];
|
||||
const char *mac_from;
|
||||
- const char *managed;
|
||||
int tx_csum_limit;
|
||||
int phy_mode;
|
||||
int err;
|
||||
@@ -4169,31 +4300,11 @@ static int mvneta_probe(struct platform_
|
||||
goto err_free_netdev;
|
||||
}
|
||||
|
||||
- phy_node = of_parse_phandle(dn, "phy", 0);
|
||||
- if (!phy_node) {
|
||||
- if (!of_phy_is_fixed_link(dn)) {
|
||||
- dev_err(&pdev->dev, "no PHY specified\n");
|
||||
- err = -ENODEV;
|
||||
- goto err_free_irq;
|
||||
- }
|
||||
-
|
||||
- err = of_phy_register_fixed_link(dn);
|
||||
- if (err < 0) {
|
||||
- dev_err(&pdev->dev, "cannot register fixed PHY\n");
|
||||
- goto err_free_irq;
|
||||
- }
|
||||
-
|
||||
- /* In the case of a fixed PHY, the DT node associated
|
||||
- * to the PHY is the Ethernet MAC DT node.
|
||||
- */
|
||||
- phy_node = of_node_get(dn);
|
||||
- }
|
||||
-
|
||||
phy_mode = of_get_phy_mode(dn);
|
||||
if (phy_mode < 0) {
|
||||
dev_err(&pdev->dev, "incorrect phy-mode\n");
|
||||
err = -EINVAL;
|
||||
- goto err_put_phy_node;
|
||||
+ goto err_free_irq;
|
||||
}
|
||||
|
||||
dev->tx_queue_len = MVNETA_MAX_TXD;
|
||||
@@ -4204,12 +4315,7 @@ static int mvneta_probe(struct platform_
|
||||
|
||||
pp = netdev_priv(dev);
|
||||
spin_lock_init(&pp->lock);
|
||||
- pp->phy_node = phy_node;
|
||||
- pp->phy_interface = phy_mode;
|
||||
-
|
||||
- err = of_property_read_string(dn, "managed", &managed);
|
||||
- pp->use_inband_status = (err == 0 &&
|
||||
- strcmp(managed, "in-band-status") == 0);
|
||||
+ pp->dn = dn;
|
||||
|
||||
pp->rxq_def = rxq_def;
|
||||
|
||||
@@ -4231,7 +4337,7 @@ static int mvneta_probe(struct platform_
|
||||
pp->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(pp->clk)) {
|
||||
err = PTR_ERR(pp->clk);
|
||||
- goto err_put_phy_node;
|
||||
+ goto err_free_irq;
|
||||
}
|
||||
|
||||
clk_prepare_enable(pp->clk);
|
||||
@@ -4357,6 +4463,14 @@ static int mvneta_probe(struct platform_
|
||||
/* 9676 == 9700 - 20 and rounding to 8 */
|
||||
dev->max_mtu = 9676;
|
||||
|
||||
+ phylink = phylink_create(dev, dn, phy_mode, &mvneta_phylink_ops);
|
||||
+ if (IS_ERR(phylink)) {
|
||||
+ err = PTR_ERR(phylink);
|
||||
+ goto err_free_stats;
|
||||
+ }
|
||||
+
|
||||
+ pp->phylink = phylink;
|
||||
+
|
||||
err = register_netdev(dev);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to register\n");
|
||||
@@ -4368,14 +4482,6 @@ static int mvneta_probe(struct platform_
|
||||
|
||||
platform_set_drvdata(pdev, pp->dev);
|
||||
|
||||
- if (pp->use_inband_status) {
|
||||
- struct phy_device *phy = of_phy_find_device(dn);
|
||||
-
|
||||
- mvneta_fixed_link_update(pp, phy);
|
||||
-
|
||||
- put_device(&phy->mdio.dev);
|
||||
- }
|
||||
-
|
||||
return 0;
|
||||
|
||||
err_netdev:
|
||||
@@ -4386,16 +4492,14 @@ err_netdev:
|
||||
1 << pp->id);
|
||||
}
|
||||
err_free_stats:
|
||||
+ if (pp->phylink)
|
||||
+ phylink_destroy(pp->phylink);
|
||||
free_percpu(pp->stats);
|
||||
err_free_ports:
|
||||
free_percpu(pp->ports);
|
||||
err_clk:
|
||||
clk_disable_unprepare(pp->clk_bus);
|
||||
clk_disable_unprepare(pp->clk);
|
||||
-err_put_phy_node:
|
||||
- of_node_put(phy_node);
|
||||
- if (of_phy_is_fixed_link(dn))
|
||||
- of_phy_deregister_fixed_link(dn);
|
||||
err_free_irq:
|
||||
irq_dispose_mapping(dev->irq);
|
||||
err_free_netdev:
|
||||
@@ -4407,7 +4511,6 @@ err_free_netdev:
|
||||
static int mvneta_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct net_device *dev = platform_get_drvdata(pdev);
|
||||
- struct device_node *dn = pdev->dev.of_node;
|
||||
struct mvneta_port *pp = netdev_priv(dev);
|
||||
|
||||
unregister_netdev(dev);
|
||||
@@ -4415,10 +4518,8 @@ static int mvneta_remove(struct platform
|
||||
clk_disable_unprepare(pp->clk);
|
||||
free_percpu(pp->ports);
|
||||
free_percpu(pp->stats);
|
||||
- if (of_phy_is_fixed_link(dn))
|
||||
- of_phy_deregister_fixed_link(dn);
|
||||
irq_dispose_mapping(dev->irq);
|
||||
- of_node_put(pp->phy_node);
|
||||
+ phylink_destroy(pp->phylink);
|
||||
free_netdev(dev);
|
||||
|
||||
if (pp->bm_priv) {
|
||||
@@ -4470,9 +4571,6 @@ static int mvneta_resume(struct device *
|
||||
return err;
|
||||
}
|
||||
|
||||
- if (pp->use_inband_status)
|
||||
- mvneta_fixed_link_update(pp, dev->phydev);
|
||||
-
|
||||
netif_device_attach(dev);
|
||||
if (netif_running(dev)) {
|
||||
mvneta_open(dev);
|
|
@ -0,0 +1,28 @@
|
|||
From acdfcc7ef78c46baca1439a1cac5b73008abc672 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 16 May 2017 11:55:58 +0100
|
||||
Subject: net: mvneta: hack fix phy_interface
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/ethernet/marvell/mvneta.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/net/ethernet/marvell/mvneta.c
|
||||
+++ b/drivers/net/ethernet/marvell/mvneta.c
|
||||
@@ -427,6 +427,7 @@ struct mvneta_port {
|
||||
u16 tx_ring_size;
|
||||
u16 rx_ring_size;
|
||||
|
||||
+ phy_interface_t phy_interface;
|
||||
struct device_node *dn;
|
||||
unsigned int tx_csum_limit;
|
||||
struct phylink *phylink;
|
||||
@@ -4315,6 +4316,7 @@ static int mvneta_probe(struct platform_
|
||||
|
||||
pp = netdev_priv(dev);
|
||||
spin_lock_init(&pp->lock);
|
||||
+ pp->phy_interface = phy_mode;
|
||||
pp->dn = dn;
|
||||
|
||||
pp->rxq_def = rxq_def;
|
|
@ -0,0 +1,56 @@
|
|||
From fde9e742a47606110232b7464608b6f9c0510938 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Sat, 24 Dec 2016 10:27:08 +0000
|
||||
Subject: net: mvneta: disable MVNETA_CAUSE_PSC_SYNC_CHANGE interrupt
|
||||
|
||||
The PSC sync change interrupt can fire multiple times while the link is
|
||||
down. As this isn't information we make use of, it's pointless having
|
||||
the interrupt enabled, so let's disable this interrupt.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/ethernet/marvell/mvneta.c | 12 ++++--------
|
||||
1 file changed, 4 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/marvell/mvneta.c
|
||||
+++ b/drivers/net/ethernet/marvell/mvneta.c
|
||||
@@ -2704,8 +2704,7 @@ static int mvneta_poll(struct napi_struc
|
||||
mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
|
||||
|
||||
if (cause_misc & (MVNETA_CAUSE_PHY_STATUS_CHANGE |
|
||||
- MVNETA_CAUSE_LINK_CHANGE |
|
||||
- MVNETA_CAUSE_PSC_SYNC_CHANGE))
|
||||
+ MVNETA_CAUSE_LINK_CHANGE))
|
||||
mvneta_link_change(pp);
|
||||
}
|
||||
|
||||
@@ -3044,8 +3043,7 @@ static void mvneta_start_dev(struct mvne
|
||||
|
||||
mvreg_write(pp, MVNETA_INTR_MISC_MASK,
|
||||
MVNETA_CAUSE_PHY_STATUS_CHANGE |
|
||||
- MVNETA_CAUSE_LINK_CHANGE |
|
||||
- MVNETA_CAUSE_PSC_SYNC_CHANGE);
|
||||
+ MVNETA_CAUSE_LINK_CHANGE);
|
||||
|
||||
phylink_start(pp->phylink);
|
||||
netif_tx_start_all_queues(pp->dev);
|
||||
@@ -3542,8 +3540,7 @@ static int mvneta_cpu_online(unsigned in
|
||||
on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true);
|
||||
mvreg_write(pp, MVNETA_INTR_MISC_MASK,
|
||||
MVNETA_CAUSE_PHY_STATUS_CHANGE |
|
||||
- MVNETA_CAUSE_LINK_CHANGE |
|
||||
- MVNETA_CAUSE_PSC_SYNC_CHANGE);
|
||||
+ MVNETA_CAUSE_LINK_CHANGE);
|
||||
netif_tx_start_all_queues(pp->dev);
|
||||
spin_unlock(&pp->lock);
|
||||
return 0;
|
||||
@@ -3584,8 +3581,7 @@ static int mvneta_cpu_dead(unsigned int
|
||||
on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true);
|
||||
mvreg_write(pp, MVNETA_INTR_MISC_MASK,
|
||||
MVNETA_CAUSE_PHY_STATUS_CHANGE |
|
||||
- MVNETA_CAUSE_LINK_CHANGE |
|
||||
- MVNETA_CAUSE_PSC_SYNC_CHANGE);
|
||||
+ MVNETA_CAUSE_LINK_CHANGE);
|
||||
netif_tx_start_all_queues(pp->dev);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
From 2ff039aa4462c2104c210b7cf39691c612de8214 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
Date: Thu, 1 Oct 2015 23:32:39 +0100
|
||||
Subject: net: mvneta: add module EEPROM reading support
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
---
|
||||
drivers/net/ethernet/marvell/mvneta.c | 18 ++++++++++++++++++
|
||||
1 file changed, 18 insertions(+)
|
||||
|
||||
--- a/drivers/net/ethernet/marvell/mvneta.c
|
||||
+++ b/drivers/net/ethernet/marvell/mvneta.c
|
||||
@@ -4045,6 +4045,22 @@ static int mvneta_ethtool_set_wol(struct
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int mvneta_ethtool_get_module_info(struct net_device *dev,
|
||||
+ struct ethtool_modinfo *modinfo)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(dev);
|
||||
+
|
||||
+ return phylink_ethtool_get_module_info(pp->phylink, modinfo);
|
||||
+}
|
||||
+
|
||||
+static int mvneta_ethtool_get_module_eeprom(struct net_device *dev,
|
||||
+ struct ethtool_eeprom *ee, u8 *buf)
|
||||
+{
|
||||
+ struct mvneta_port *pp = netdev_priv(dev);
|
||||
+
|
||||
+ return phylink_ethtool_get_module_eeprom(pp->phylink, ee, buf);
|
||||
+}
|
||||
+
|
||||
static int mvneta_ethtool_get_eee(struct net_device *dev,
|
||||
struct ethtool_eee *eee)
|
||||
{
|
||||
@@ -4129,6 +4145,8 @@ static const struct ethtool_ops mvneta_e
|
||||
.set_link_ksettings = mvneta_ethtool_set_link_ksettings,
|
||||
.get_wol = mvneta_ethtool_get_wol,
|
||||
.set_wol = mvneta_ethtool_set_wol,
|
||||
+ .get_module_info = mvneta_ethtool_get_module_info,
|
||||
+ .get_module_eeprom = mvneta_ethtool_get_module_eeprom,
|
||||
.get_eee = mvneta_ethtool_get_eee,
|
||||
.set_eee = mvneta_ethtool_set_eee,
|
||||
};
|
|
@ -0,0 +1,80 @@
|
|||
From 774ce2eda0a929f79ee398ba6d2d13fd406f31c4 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
Date: Fri, 2 Oct 2015 22:46:54 +0100
|
||||
Subject: phy: fixed-phy: remove fixed_phy_update_state()
|
||||
|
||||
mvneta is the only user of fixed_phy_update_state(), which has been
|
||||
converted to use phylink instead. Remove fixed_phy_update_state().
|
||||
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
---
|
||||
drivers/net/phy/fixed_phy.c | 31 -------------------------------
|
||||
include/linux/phy_fixed.h | 9 ---------
|
||||
2 files changed, 40 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/fixed_phy.c
|
||||
+++ b/drivers/net/phy/fixed_phy.c
|
||||
@@ -115,37 +115,6 @@ int fixed_phy_set_link_update(struct phy
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fixed_phy_set_link_update);
|
||||
|
||||
-int fixed_phy_update_state(struct phy_device *phydev,
|
||||
- const struct fixed_phy_status *status,
|
||||
- const struct fixed_phy_status *changed)
|
||||
-{
|
||||
- struct fixed_mdio_bus *fmb = &platform_fmb;
|
||||
- struct fixed_phy *fp;
|
||||
-
|
||||
- if (!phydev || phydev->mdio.bus != fmb->mii_bus)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- list_for_each_entry(fp, &fmb->phys, node) {
|
||||
- if (fp->addr == phydev->mdio.addr) {
|
||||
- write_seqcount_begin(&fp->seqcount);
|
||||
-#define _UPD(x) if (changed->x) \
|
||||
- fp->status.x = status->x
|
||||
- _UPD(link);
|
||||
- _UPD(speed);
|
||||
- _UPD(duplex);
|
||||
- _UPD(pause);
|
||||
- _UPD(asym_pause);
|
||||
-#undef _UPD
|
||||
- fixed_phy_update(fp);
|
||||
- write_seqcount_end(&fp->seqcount);
|
||||
- return 0;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return -ENOENT;
|
||||
-}
|
||||
-EXPORT_SYMBOL(fixed_phy_update_state);
|
||||
-
|
||||
int fixed_phy_add(unsigned int irq, int phy_addr,
|
||||
struct fixed_phy_status *status,
|
||||
int link_gpio)
|
||||
--- a/include/linux/phy_fixed.h
|
||||
+++ b/include/linux/phy_fixed.h
|
||||
@@ -24,9 +24,6 @@ extern void fixed_phy_unregister(struct
|
||||
extern int fixed_phy_set_link_update(struct phy_device *phydev,
|
||||
int (*link_update)(struct net_device *,
|
||||
struct fixed_phy_status *));
|
||||
-extern int fixed_phy_update_state(struct phy_device *phydev,
|
||||
- const struct fixed_phy_status *status,
|
||||
- const struct fixed_phy_status *changed);
|
||||
#else
|
||||
static inline int fixed_phy_add(unsigned int irq, int phy_id,
|
||||
struct fixed_phy_status *status,
|
||||
@@ -50,12 +47,6 @@ static inline int fixed_phy_set_link_upd
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
-static inline int fixed_phy_update_state(struct phy_device *phydev,
|
||||
- const struct fixed_phy_status *status,
|
||||
- const struct fixed_phy_status *changed)
|
||||
-{
|
||||
- return -ENODEV;
|
||||
-}
|
||||
#endif /* CONFIG_FIXED_PHY */
|
||||
|
||||
#endif /* __PHY_FIXED_H */
|
|
@ -0,0 +1,181 @@
|
|||
From c47beb7e3f8575dfd7d58240a72c4e4e66ce5449 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 14 Apr 2017 15:26:32 +0100
|
||||
Subject: sfp: move module eeprom ethtool access into netdev core ethtool
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/ethernet/marvell/mvneta.c | 18 ------------------
|
||||
drivers/net/phy/phylink.c | 28 ----------------------------
|
||||
drivers/net/phy/sfp-bus.c | 6 ++----
|
||||
include/linux/netdevice.h | 2 ++
|
||||
include/linux/phylink.h | 3 ---
|
||||
net/core/ethtool.c | 7 +++++++
|
||||
6 files changed, 11 insertions(+), 53 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/marvell/mvneta.c
|
||||
+++ b/drivers/net/ethernet/marvell/mvneta.c
|
||||
@@ -4045,22 +4045,6 @@ static int mvneta_ethtool_set_wol(struct
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int mvneta_ethtool_get_module_info(struct net_device *dev,
|
||||
- struct ethtool_modinfo *modinfo)
|
||||
-{
|
||||
- struct mvneta_port *pp = netdev_priv(dev);
|
||||
-
|
||||
- return phylink_ethtool_get_module_info(pp->phylink, modinfo);
|
||||
-}
|
||||
-
|
||||
-static int mvneta_ethtool_get_module_eeprom(struct net_device *dev,
|
||||
- struct ethtool_eeprom *ee, u8 *buf)
|
||||
-{
|
||||
- struct mvneta_port *pp = netdev_priv(dev);
|
||||
-
|
||||
- return phylink_ethtool_get_module_eeprom(pp->phylink, ee, buf);
|
||||
-}
|
||||
-
|
||||
static int mvneta_ethtool_get_eee(struct net_device *dev,
|
||||
struct ethtool_eee *eee)
|
||||
{
|
||||
@@ -4145,8 +4129,6 @@ static const struct ethtool_ops mvneta_e
|
||||
.set_link_ksettings = mvneta_ethtool_set_link_ksettings,
|
||||
.get_wol = mvneta_ethtool_get_wol,
|
||||
.set_wol = mvneta_ethtool_set_wol,
|
||||
- .get_module_info = mvneta_ethtool_get_module_info,
|
||||
- .get_module_eeprom = mvneta_ethtool_get_module_eeprom,
|
||||
.get_eee = mvneta_ethtool_get_eee,
|
||||
.set_eee = mvneta_ethtool_set_eee,
|
||||
};
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1040,34 +1040,6 @@ int phylink_ethtool_set_pauseparam(struc
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phylink_ethtool_set_pauseparam);
|
||||
|
||||
-int phylink_ethtool_get_module_info(struct phylink *pl,
|
||||
- struct ethtool_modinfo *modinfo)
|
||||
-{
|
||||
- int ret = -EOPNOTSUPP;
|
||||
-
|
||||
- WARN_ON(!lockdep_rtnl_is_held());
|
||||
-
|
||||
- if (pl->sfp_bus)
|
||||
- ret = sfp_get_module_info(pl->sfp_bus, modinfo);
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-EXPORT_SYMBOL_GPL(phylink_ethtool_get_module_info);
|
||||
-
|
||||
-int phylink_ethtool_get_module_eeprom(struct phylink *pl,
|
||||
- struct ethtool_eeprom *ee, u8 *buf)
|
||||
-{
|
||||
- int ret = -EOPNOTSUPP;
|
||||
-
|
||||
- WARN_ON(!lockdep_rtnl_is_held());
|
||||
-
|
||||
- if (pl->sfp_bus)
|
||||
- ret = sfp_get_module_eeprom(pl->sfp_bus, ee, buf);
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-EXPORT_SYMBOL_GPL(phylink_ethtool_get_module_eeprom);
|
||||
-
|
||||
int phylink_init_eee(struct phylink *pl, bool clk_stop_enable)
|
||||
{
|
||||
int ret = -EPROTONOSUPPORT;
|
||||
--- a/drivers/net/phy/sfp-bus.c
|
||||
+++ b/drivers/net/phy/sfp-bus.c
|
||||
@@ -278,6 +278,7 @@ static int sfp_register_bus(struct sfp_b
|
||||
}
|
||||
if (bus->started)
|
||||
bus->socket_ops->start(bus->sfp);
|
||||
+ bus->netdev->sfp_bus = bus;
|
||||
bus->registered = true;
|
||||
return 0;
|
||||
}
|
||||
@@ -292,14 +293,13 @@ static void sfp_unregister_bus(struct sf
|
||||
if (bus->phydev && ops && ops->disconnect_phy)
|
||||
ops->disconnect_phy(bus->upstream);
|
||||
}
|
||||
+ bus->netdev->sfp_bus = NULL;
|
||||
bus->registered = false;
|
||||
}
|
||||
|
||||
|
||||
int sfp_get_module_info(struct sfp_bus *bus, struct ethtool_modinfo *modinfo)
|
||||
{
|
||||
- if (!bus->registered)
|
||||
- return -ENOIOCTLCMD;
|
||||
return bus->socket_ops->module_info(bus->sfp, modinfo);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sfp_get_module_info);
|
||||
@@ -307,8 +307,6 @@ EXPORT_SYMBOL_GPL(sfp_get_module_info);
|
||||
int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee,
|
||||
u8 *data)
|
||||
{
|
||||
- if (!bus->registered)
|
||||
- return -ENOIOCTLCMD;
|
||||
return bus->socket_ops->module_eeprom(bus->sfp, ee, data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sfp_get_module_eeprom);
|
||||
--- a/include/linux/netdevice.h
|
||||
+++ b/include/linux/netdevice.h
|
||||
@@ -57,6 +57,7 @@ struct device;
|
||||
struct phy_device;
|
||||
struct dsa_switch_tree;
|
||||
|
||||
+struct sfp_bus;
|
||||
/* 802.11 specific */
|
||||
struct wireless_dev;
|
||||
/* 802.15.4 specific */
|
||||
@@ -1932,6 +1933,7 @@ struct net_device {
|
||||
struct netprio_map __rcu *priomap;
|
||||
#endif
|
||||
struct phy_device *phydev;
|
||||
+ struct sfp_bus *sfp_bus;
|
||||
struct lock_class_key *qdisc_tx_busylock;
|
||||
struct lock_class_key *qdisc_running_key;
|
||||
bool proto_down;
|
||||
--- a/include/linux/phylink.h
|
||||
+++ b/include/linux/phylink.h
|
||||
@@ -125,9 +125,6 @@ void phylink_ethtool_get_pauseparam(stru
|
||||
struct ethtool_pauseparam *);
|
||||
int phylink_ethtool_set_pauseparam(struct phylink *,
|
||||
struct ethtool_pauseparam *);
|
||||
-int phylink_ethtool_get_module_info(struct phylink *, struct ethtool_modinfo *);
|
||||
-int phylink_ethtool_get_module_eeprom(struct phylink *,
|
||||
- struct ethtool_eeprom *, u8 *);
|
||||
int phylink_init_eee(struct phylink *, bool);
|
||||
int phylink_get_eee_err(struct phylink *);
|
||||
int phylink_ethtool_get_eee(struct phylink *, struct ethtool_eee *);
|
||||
--- a/net/core/ethtool.c
|
||||
+++ b/net/core/ethtool.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/vmalloc.h>
|
||||
+#include <linux/sfp.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/sched/signal.h>
|
||||
@@ -2190,6 +2191,9 @@ static int __ethtool_get_module_info(str
|
||||
const struct ethtool_ops *ops = dev->ethtool_ops;
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
|
||||
+ if (dev->sfp_bus)
|
||||
+ return sfp_get_module_info(dev->sfp_bus, modinfo);
|
||||
+
|
||||
if (phydev && phydev->drv && phydev->drv->module_info)
|
||||
return phydev->drv->module_info(phydev, modinfo);
|
||||
|
||||
@@ -2224,6 +2228,9 @@ static int __ethtool_get_module_eeprom(s
|
||||
const struct ethtool_ops *ops = dev->ethtool_ops;
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
|
||||
+ if (dev->sfp_bus)
|
||||
+ return sfp_get_module_eeprom(dev->sfp_bus, ee, data);
|
||||
+
|
||||
if (phydev && phydev->drv && phydev->drv->module_eeprom)
|
||||
return phydev->drv->module_eeprom(phydev, ee, data);
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
From 883dc66755313e133a787eba4dfde313fe33525b Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 14 Apr 2017 16:41:55 +0100
|
||||
Subject: sfp: use netdev sfp_bus for start/stop
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -755,8 +755,8 @@ void phylink_start(struct phylink *pl)
|
||||
clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
|
||||
phylink_run_resolve(pl);
|
||||
|
||||
- if (pl->sfp_bus)
|
||||
- sfp_upstream_start(pl->sfp_bus);
|
||||
+ if (pl->netdev->sfp_bus)
|
||||
+ sfp_upstream_start(pl->netdev->sfp_bus);
|
||||
if (pl->phydev)
|
||||
phy_start(pl->phydev);
|
||||
}
|
||||
@@ -768,8 +768,8 @@ void phylink_stop(struct phylink *pl)
|
||||
|
||||
if (pl->phydev)
|
||||
phy_stop(pl->phydev);
|
||||
- if (pl->sfp_bus)
|
||||
- sfp_upstream_stop(pl->sfp_bus);
|
||||
+ if (pl->netdev->sfp_bus)
|
||||
+ sfp_upstream_stop(pl->netdev->sfp_bus);
|
||||
|
||||
set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
|
||||
queue_work(system_power_efficient_wq, &pl->resolve);
|
|
@ -0,0 +1,131 @@
|
|||
From 4a4aca08b11501cb1b2c509113bbb65eb66a1f45 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 14 Apr 2017 14:21:25 +0100
|
||||
Subject: sfp: hack: allow marvell 10G phy support to use SFP
|
||||
|
||||
Allow the Marvell 10G PHY to register with the SFP bus, so that SFP+
|
||||
cages can work. This bypasses phylink, meaning that socket status
|
||||
is not taken into account for the link state. Also, the tx-disable
|
||||
signal must be commented out in DT for this to work...
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/marvell10g.c | 54 +++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 53 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/phy/marvell10g.c
|
||||
+++ b/drivers/net/phy/marvell10g.c
|
||||
@@ -15,8 +15,10 @@
|
||||
* If both the fiber and copper ports are connected, the first to gain
|
||||
* link takes priority and the other port is completely locked out.
|
||||
*/
|
||||
+#include <linux/of.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/marvell_phy.h>
|
||||
+#include <linux/sfp.h>
|
||||
|
||||
enum {
|
||||
MV_PCS_BASE_T = 0x0000,
|
||||
@@ -38,6 +40,11 @@ enum {
|
||||
MV_AN_RESULT_SPD_10000 = BIT(15),
|
||||
};
|
||||
|
||||
+struct mv3310_priv {
|
||||
+ struct device_node *sfp_node;
|
||||
+ struct sfp_bus *sfp_bus;
|
||||
+};
|
||||
+
|
||||
static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
|
||||
u16 mask, u16 bits)
|
||||
{
|
||||
@@ -56,17 +63,52 @@ static int mv3310_modify(struct phy_devi
|
||||
return ret < 0 ? ret : 1;
|
||||
}
|
||||
|
||||
+static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
|
||||
+{
|
||||
+ struct phy_device *phydev = upstream;
|
||||
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
|
||||
+
|
||||
+ if (sfp_parse_interface(priv->sfp_bus, id) != PHY_INTERFACE_MODE_10GKR) {
|
||||
+ dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct sfp_upstream_ops mv3310_sfp_ops = {
|
||||
+ .module_insert = mv3310_sfp_insert,
|
||||
+};
|
||||
+
|
||||
static int mv3310_probe(struct phy_device *phydev)
|
||||
{
|
||||
+ struct mv3310_priv *priv;
|
||||
u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
|
||||
|
||||
if (!phydev->is_c45 ||
|
||||
(phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
|
||||
return -ENODEV;
|
||||
|
||||
+ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ dev_set_drvdata(&phydev->mdio.dev, priv);
|
||||
+
|
||||
+ if (phydev->mdio.dev.of_node)
|
||||
+ priv->sfp_node = of_parse_phandle(phydev->mdio.dev.of_node,
|
||||
+ "sfp", 0);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void mv3310_remove(struct phy_device *phydev)
|
||||
+{
|
||||
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
|
||||
+
|
||||
+ if (priv->sfp_bus)
|
||||
+ sfp_unregister_upstream(priv->sfp_bus);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Resetting the MV88X3310 causes it to become non-responsive. Avoid
|
||||
* setting the reset bit(s).
|
||||
@@ -78,6 +120,7 @@ static int mv3310_soft_reset(struct phy_
|
||||
|
||||
static int mv3310_config_init(struct phy_device *phydev)
|
||||
{
|
||||
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
|
||||
u32 mask;
|
||||
int val;
|
||||
@@ -166,6 +209,14 @@ static int mv3310_config_init(struct phy
|
||||
phydev->supported &= mask;
|
||||
phydev->advertising &= phydev->supported;
|
||||
|
||||
+ /* Would be nice to do this in the probe function, but unfortunately,
|
||||
+ * phylib doesn't have phydev->attached_dev set there.
|
||||
+ */
|
||||
+ if (priv->sfp_node && !priv->sfp_bus)
|
||||
+ priv->sfp_bus = sfp_register_upstream(priv->sfp_node,
|
||||
+ phydev->attached_dev,
|
||||
+ phydev, &mv3310_sfp_ops);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -349,12 +400,13 @@ static struct phy_driver mv3310_drivers[
|
||||
SUPPORTED_FIBRE |
|
||||
SUPPORTED_10000baseT_Full |
|
||||
SUPPORTED_Backplane,
|
||||
- .probe = mv3310_probe,
|
||||
.soft_reset = mv3310_soft_reset,
|
||||
.config_init = mv3310_config_init,
|
||||
+ .probe = mv3310_probe,
|
||||
.config_aneg = mv3310_config_aneg,
|
||||
.aneg_done = mv3310_aneg_done,
|
||||
.read_status = mv3310_read_status,
|
||||
+ .remove = mv3310_remove,
|
||||
},
|
||||
};
|
||||
|
24
patch/kernel/mvebu-next/411-sfp-add-sfp-compatible.patch
Normal file
24
patch/kernel/mvebu-next/411-sfp-add-sfp-compatible.patch
Normal file
|
@ -0,0 +1,24 @@
|
|||
From 3344f73509a34d2124b716efc79cd9787773018b Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 14 Apr 2017 20:17:13 +0100
|
||||
Subject: sfp: add sfp+ compatible
|
||||
|
||||
Add a compatible for SFP+ cages. SFP+ cages are backwards compatible,
|
||||
but the ethernet device behind them may not support the slower speeds
|
||||
of SFP modules.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -1136,6 +1136,7 @@ static int sfp_remove(struct platform_de
|
||||
|
||||
static const struct of_device_id sfp_of_match[] = {
|
||||
{ .compatible = "sff,sfp", },
|
||||
+ { .compatible = "sff,sfp+", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sfp_of_match);
|
|
@ -0,0 +1,87 @@
|
|||
From 8137da20701c776ad3481115305a5e8e410871ba Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 29 Nov 2016 10:15:45 +0000
|
||||
Subject: ARM: dts: armada388-clearfog: emmc on clearfog base
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
arch/arm/boot/dts/armada-388-clearfog-base.dts | 1 +
|
||||
.../dts/armada-38x-solidrun-microsom-emmc.dtsi | 62 ++++++++++++++++++++++
|
||||
2 files changed, 63 insertions(+)
|
||||
create mode 100644 arch/arm/boot/dts/armada-38x-solidrun-microsom-emmc.dtsi
|
||||
|
||||
--- a/arch/arm/boot/dts/armada-388-clearfog-base.dts
|
||||
+++ b/arch/arm/boot/dts/armada-388-clearfog-base.dts
|
||||
@@ -48,6 +48,7 @@
|
||||
|
||||
/dts-v1/;
|
||||
#include "armada-388-clearfog.dtsi"
|
||||
+#include "armada-38x-solidrun-microsom-emmc.dtsi"
|
||||
|
||||
/ {
|
||||
model = "SolidRun Clearfog Base A1";
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/boot/dts/armada-38x-solidrun-microsom-emmc.dtsi
|
||||
@@ -0,0 +1,62 @@
|
||||
+/*
|
||||
+ * Device Tree file for SolidRun Armada 38x Microsom add-on for eMMC
|
||||
+ *
|
||||
+ * Copyright (C) 2015 Russell King
|
||||
+ *
|
||||
+ * This board is in development; the contents of this file work with
|
||||
+ * the A1 rev 2.0 of the board, which does not represent final
|
||||
+ * production board. Things will change, don't expect this file to
|
||||
+ * remain compatible info the future.
|
||||
+ *
|
||||
+ * This file is dual-licensed: you can use it either under the terms
|
||||
+ * of the GPL or the X11 license, at your option. Note that this dual
|
||||
+ * licensing only applies to this file, and not this project as a
|
||||
+ * whole.
|
||||
+ *
|
||||
+ * a) This file is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License
|
||||
+ * version 2 as published by the Free Software Foundation.
|
||||
+ *
|
||||
+ * This file is distributed in the hope that it will be useful
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * Or, alternatively
|
||||
+ *
|
||||
+ * b) Permission is hereby granted, free of charge, to any person
|
||||
+ * obtaining a copy of this software and associated documentation
|
||||
+ * files (the "Software"), to deal in the Software without
|
||||
+ * restriction, including without limitation the rights to use
|
||||
+ * copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
+ * sell copies of the Software, and to permit persons to whom the
|
||||
+ * Software is furnished to do so, subject to the following
|
||||
+ * conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be
|
||||
+ * included in all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
|
||||
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
|
||||
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
+ * OTHER DEALINGS IN THE SOFTWARE.
|
||||
+ */
|
||||
+/ {
|
||||
+ soc {
|
||||
+ internal-regs {
|
||||
+ sdhci@d8000 {
|
||||
+ bus-width = <4>;
|
||||
+ no-1-8-v;
|
||||
+ non-removable;
|
||||
+ pinctrl-0 = <µsom_sdhci_pins>;
|
||||
+ pinctrl-names = "default";
|
||||
+ status = "okay";
|
||||
+ wp-inverted;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+};
|
|
@ -0,0 +1,42 @@
|
|||
From 6e127081e669cf163a818dc04d590790e4ed9527 Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 29 Nov 2016 20:06:44 +0000
|
||||
Subject: ARM: dts: armada388-clearfog: increase speed of i2c0 to 400kHz
|
||||
|
||||
All the devices on I2C0 support fast mode, so increase the bus speed
|
||||
to match. The Armada 388 is known to have a timing issue when in
|
||||
standard mode, which we believe causes the ficticious device at 0x64
|
||||
to appear.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
---
|
||||
arch/arm/boot/dts/armada-388-clearfog.dtsi | 7 ++-----
|
||||
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/arch/arm/boot/dts/armada-388-clearfog.dtsi
|
||||
+++ b/arch/arm/boot/dts/armada-388-clearfog.dtsi
|
||||
@@ -143,8 +143,7 @@
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
- /* Is there anything on this? */
|
||||
- clock-frequency = <100000>;
|
||||
+ clock-frequency = <400000>;
|
||||
pinctrl-0 = <&i2c0_pins>;
|
||||
pinctrl-names = "default";
|
||||
status = "okay";
|
||||
@@ -239,13 +238,11 @@
|
||||
};
|
||||
};
|
||||
|
||||
- /* The MCP3021 is 100kHz clock only */
|
||||
+ /* The MCP3021 supports standard and fast modes */
|
||||
mikrobus_adc: mcp3021@4c {
|
||||
compatible = "microchip,mcp3021";
|
||||
reg = <0x4c>;
|
||||
};
|
||||
-
|
||||
- /* Also something at 0x64 */
|
||||
};
|
||||
|
||||
&i2c1 {
|
|
@ -0,0 +1,124 @@
|
|||
From 09a0122c74ec076e08512f1b00b7ccb8a450282f Mon Sep 17 00:00:00 2001
|
||||
From: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
Date: Tue, 29 Nov 2016 10:15:43 +0000
|
||||
Subject: ARM: dts: armada388-clearfog: document MPP usage
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
---
|
||||
arch/arm/boot/dts/armada-388-clearfog-base.dts | 51 ++++++++++++++++++++++++++
|
||||
arch/arm/boot/dts/armada-388-clearfog.dts | 50 +++++++++++++++++++++++++
|
||||
2 files changed, 101 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/armada-388-clearfog-base.dts
|
||||
+++ b/arch/arm/boot/dts/armada-388-clearfog-base.dts
|
||||
@@ -108,3 +108,54 @@
|
||||
marvell,function = "gpio";
|
||||
};
|
||||
};
|
||||
+
|
||||
+/*
|
||||
+MPP
|
||||
+18: pu gpio pca9655 int
|
||||
+19: gpio phy reset
|
||||
+20: pu gpio sd0 detect
|
||||
+21: sd0:cmd
|
||||
+22: pd gpio mikro int
|
||||
+23:
|
||||
+
|
||||
+24: ua1:rxd mikro rx
|
||||
+25: ua1:txd mikro tx
|
||||
+26: pu i2c1:sck
|
||||
+27: pu i2c1:sda
|
||||
+28: sd0:clk
|
||||
+29: pd gpio mikro rst
|
||||
+30:
|
||||
+31:
|
||||
+
|
||||
+32:
|
||||
+33:
|
||||
+34:
|
||||
+35:
|
||||
+36:
|
||||
+37: sd0:d3
|
||||
+38: sd0:d0
|
||||
+39: sd0:d1
|
||||
+
|
||||
+40: sd0:d2
|
||||
+41:
|
||||
+42:
|
||||
+43: spi1:cs2 mikro cs
|
||||
+44: gpio rear button sw3
|
||||
+45: ref:clk_out0 phy#0 clock
|
||||
+46: ref:clk_out1 phy#1 clock
|
||||
+47:
|
||||
+
|
||||
+48: gpio J18 spare gpio
|
||||
+49: gpio U10 I2C_IRQ(GNSS)
|
||||
+50: gpio board id?
|
||||
+51:
|
||||
+52:
|
||||
+53:
|
||||
+54: gpio mikro pwm
|
||||
+55:
|
||||
+
|
||||
+56: pu spi1:mosi mikro mosi
|
||||
+57: pd spi1:sck mikro sck
|
||||
+58: spi1:miso mikro miso
|
||||
+59:
|
||||
+*/
|
||||
--- a/arch/arm/boot/dts/armada-388-clearfog.dts
|
||||
+++ b/arch/arm/boot/dts/armada-388-clearfog.dts
|
||||
@@ -290,3 +290,53 @@
|
||||
*/
|
||||
pinctrl-0 = <&spi1_pins &clearfog_spi1_cs_pins &mikro_spi_pins>;
|
||||
};
|
||||
+/*
|
||||
++#define A38x_CUSTOMER_BOARD_1_MPP16_23 0x00400011
|
||||
+MPP18: gpio ? (pca9655 int?)
|
||||
+MPP19: gpio ? (clkreq?)
|
||||
+MPP20: gpio ? (sd0 detect)
|
||||
+MPP21: sd0:cmd x sd0
|
||||
+MPP22: gpio x mikro int
|
||||
+MPP23: gpio x switch irq
|
||||
++#define A38x_CUSTOMER_BOARD_1_MPP24_31 0x22043333
|
||||
+MPP24: ua1:rxd x mikro rx
|
||||
+MPP25: ua1:txd x mikro tx
|
||||
+MPP26: i2c1:sck x mikro sck
|
||||
+MPP27: i2c1:sda x mikro sda
|
||||
+MPP28: sd0:clk x sd0
|
||||
+MPP29: gpio x mikro rst
|
||||
+MPP30: ge1:txd2 ? (config)
|
||||
+MPP31: ge1:txd3 ? (config)
|
||||
++#define A38x_CUSTOMER_BOARD_1_MPP32_39 0x44400002
|
||||
+MPP32: ge1:txctl ? (unused)
|
||||
+MPP33: gpio ? (pic_com0)
|
||||
+MPP34: gpio x rear button (pic_com1)
|
||||
+MPP35: gpio ? (pic_com2)
|
||||
+MPP36: gpio ? (unused)
|
||||
+MPP37: sd0:d3 x sd0
|
||||
+MPP38: sd0:d0 x sd0
|
||||
+MPP39: sd0:d1 x sd0
|
||||
++#define A38x_CUSTOMER_BOARD_1_MPP40_47 0x41144004
|
||||
+MPP40: sd0:d2 x sd0
|
||||
+MPP41: gpio x switch reset
|
||||
+MPP42: gpio ? sw1-1
|
||||
+MPP43: spi1:cs2 x mikro cs
|
||||
+MPP44: sata3:prsnt ? (unused)
|
||||
+MPP45: ref:clk_out0 ?
|
||||
+MPP46: ref:clk_out1 x switch clk
|
||||
+MPP47: 4 ? (unused)
|
||||
++#define A38x_CUSTOMER_BOARD_1_MPP48_55 0x40333333
|
||||
+MPP48: tdm:pclk
|
||||
+MPP49: tdm:fsync
|
||||
+MPP50: tdm:drx
|
||||
+MPP51: tdm:dtx
|
||||
+MPP52: tdm:int
|
||||
+MPP53: tdm:rst
|
||||
+MPP54: gpio ? (pwm)
|
||||
+MPP55: spi1:cs1 x slic
|
||||
++#define A38x_CUSTOMER_BOARD_1_MPP56_63 0x00004444
|
||||
+MPP56: spi1:mosi x mikro mosi
|
||||
+MPP57: spi1:sck x mikro sck
|
||||
+MPP58: spi1:miso x mikro miso
|
||||
+MPP59: spi1:cs0 x w25q32
|
||||
+*/
|
143
patch/kernel/mvebu-next/420-rtc-trimming-support.patch
Normal file
143
patch/kernel/mvebu-next/420-rtc-trimming-support.patch
Normal file
|
@ -0,0 +1,143 @@
|
|||
commit f94ffbc2c2a4128c4412bb483d0807722dfb682b
|
||||
Author: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri Sep 29 11:23:31 2017 +0100
|
||||
|
||||
rtc: armada38x: add support for trimming the RTC
|
||||
|
||||
Add support for trimming the RTC using the offset mechanism. This RTC
|
||||
supports two modes: low update mode and high update mode. Low update
|
||||
mode has finer precision than high update mode, so we use the low mode
|
||||
where possible.
|
||||
|
||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
||||
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
|
||||
|
||||
--- a/drivers/rtc/rtc-armada38x.c
|
||||
+++ b/drivers/rtc/rtc-armada38x.c
|
||||
@@ -28,6 +28,8 @@
|
||||
#define RTC_IRQ_AL_EN BIT(0)
|
||||
#define RTC_IRQ_FREQ_EN BIT(1)
|
||||
#define RTC_IRQ_FREQ_1HZ BIT(2)
|
||||
+#define RTC_CCR 0x18
|
||||
+#define RTC_CCR_MODE BIT(15)
|
||||
|
||||
#define RTC_TIME 0xC
|
||||
#define RTC_ALARM1 0x10
|
||||
@@ -343,18 +345,117 @@ static irqreturn_t armada38x_rtc_alarm_i
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * The information given in the Armada 388 functional spec is complex.
|
||||
+ * They give two different formulas for calculating the offset value,
|
||||
+ * but when considering "Offset" as an 8-bit signed integer, they both
|
||||
+ * reduce down to (we shall rename "Offset" as "val" here):
|
||||
+ *
|
||||
+ * val = (f_ideal / f_measured - 1) / resolution where f_ideal = 32768
|
||||
+ *
|
||||
+ * Converting to time, f = 1/t:
|
||||
+ * val = (t_measured / t_ideal - 1) / resolution where t_ideal = 1/32768
|
||||
+ *
|
||||
+ * => t_measured / t_ideal = val * resolution + 1
|
||||
+ *
|
||||
+ * "offset" in the RTC interface is defined as:
|
||||
+ * t = t0 * (1 + offset * 1e-9)
|
||||
+ * where t is the desired period, t0 is the measured period with a zero
|
||||
+ * offset, which is t_measured above. With t0 = t_measured and t = t_ideal,
|
||||
+ * offset = (t_ideal / t_measured - 1) / 1e-9
|
||||
+ *
|
||||
+ * => t_ideal / t_measured = offset * 1e-9 + 1
|
||||
+ *
|
||||
+ * so:
|
||||
+ *
|
||||
+ * offset * 1e-9 + 1 = 1 / (val * resolution + 1)
|
||||
+ *
|
||||
+ * We want "resolution" to be an integer, so resolution = R * 1e-9, giving
|
||||
+ * offset = 1e18 / (val * R + 1e9) - 1e9
|
||||
+ * val = (1e18 / (offset + 1e9) - 1e9) / R
|
||||
+ * with a common transformation:
|
||||
+ * f(x) = 1e18 / (x + 1e9) - 1e9
|
||||
+ * offset = f(val * R)
|
||||
+ * val = f(offset) / R
|
||||
+ *
|
||||
+ * Armada 38x supports two modes, fine mode (954ppb) and coarse mode (3815ppb).
|
||||
+ */
|
||||
+static long armada38x_ppb_convert(long ppb)
|
||||
+{
|
||||
+ long div = ppb + 1000000000L;
|
||||
+
|
||||
+ return div_s64(1000000000000000000LL + div / 2, div) - 1000000000L;
|
||||
+}
|
||||
+
|
||||
+static int armada38x_rtc_read_offset(struct device *dev, long *offset)
|
||||
+{
|
||||
+ struct armada38x_rtc *rtc = dev_get_drvdata(dev);
|
||||
+ unsigned long ccr, flags;
|
||||
+ long ppb_cor;
|
||||
+
|
||||
+ spin_lock_irqsave(&rtc->lock, flags);
|
||||
+ ccr = rtc->data->read_rtc_reg(rtc, RTC_CCR);
|
||||
+ spin_unlock_irqrestore(&rtc->lock, flags);
|
||||
+
|
||||
+ ppb_cor = (ccr & RTC_CCR_MODE ? 3815 : 954) * (s8)ccr;
|
||||
+ /* ppb_cor + 1000000000L can never be zero */
|
||||
+ *offset = armada38x_ppb_convert(ppb_cor);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int armada38x_rtc_set_offset(struct device *dev, long offset)
|
||||
+{
|
||||
+ struct armada38x_rtc *rtc = dev_get_drvdata(dev);
|
||||
+ unsigned long ccr = 0;
|
||||
+ long ppb_cor, off;
|
||||
+
|
||||
+ /*
|
||||
+ * The maximum ppb_cor is -128 * 3815 .. 127 * 3815, but we
|
||||
+ * need to clamp the input. This equates to -484270 .. 488558.
|
||||
+ * Not only is this to stop out of range "off" but also to
|
||||
+ * avoid the division by zero in armada38x_ppb_convert().
|
||||
+ */
|
||||
+ offset = clamp(offset, -484270L, 488558L);
|
||||
+
|
||||
+ ppb_cor = armada38x_ppb_convert(offset);
|
||||
+
|
||||
+ /*
|
||||
+ * Use low update mode where possible, which gives a better
|
||||
+ * resolution of correction.
|
||||
+ */
|
||||
+ off = DIV_ROUND_CLOSEST(ppb_cor, 954);
|
||||
+ if (off > 127 || off < -128) {
|
||||
+ ccr = RTC_CCR_MODE;
|
||||
+ off = DIV_ROUND_CLOSEST(ppb_cor, 3815);
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Armada 388 requires a bit pattern in bits 14..8 depending on
|
||||
+ * the sign bit: { 0, ~S, S, S, S, S, S }
|
||||
+ */
|
||||
+ ccr |= (off & 0x3fff) ^ 0x2000;
|
||||
+ rtc_delayed_write(ccr, rtc, RTC_CCR);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const struct rtc_class_ops armada38x_rtc_ops = {
|
||||
.read_time = armada38x_rtc_read_time,
|
||||
.set_time = armada38x_rtc_set_time,
|
||||
.read_alarm = armada38x_rtc_read_alarm,
|
||||
.set_alarm = armada38x_rtc_set_alarm,
|
||||
.alarm_irq_enable = armada38x_rtc_alarm_irq_enable,
|
||||
+ .read_offset = armada38x_rtc_read_offset,
|
||||
+ .set_offset = armada38x_rtc_set_offset,
|
||||
};
|
||||
|
||||
static const struct rtc_class_ops armada38x_rtc_ops_noirq = {
|
||||
.read_time = armada38x_rtc_read_time,
|
||||
.set_time = armada38x_rtc_set_time,
|
||||
.read_alarm = armada38x_rtc_read_alarm,
|
||||
+ .read_offset = armada38x_rtc_read_offset,
|
||||
+ .set_offset = armada38x_rtc_set_offset,
|
||||
};
|
||||
|
||||
static const struct armada38x_rtc_data armada38x_data = {
|
74
patch/kernel/mvebu-next/421-rtc-initialize.patch
Normal file
74
patch/kernel/mvebu-next/421-rtc-initialize.patch
Normal file
|
@ -0,0 +1,74 @@
|
|||
Some boards like the Turris Omnia have an RTC chip that does not get
|
||||
initialized. Initializing the RTC at the driver level helps get rid of
|
||||
bootloader hacks that write special register values.
|
||||
|
||||
--- a/drivers/rtc/rtc-armada38x.c
|
||||
+++ b/drivers/rtc/rtc-armada38x.c
|
||||
@@ -30,6 +30,9 @@
|
||||
#define RTC_IRQ_FREQ_1HZ BIT(2)
|
||||
#define RTC_CCR 0x18
|
||||
#define RTC_CCR_MODE BIT(15)
|
||||
+#define RTC_CCR_NORMAL_PPB 0x2000
|
||||
+#define RTC_TEST_CONF 0x1c
|
||||
+#define RTC_TEST_CONF_MASK 0xff
|
||||
|
||||
#define RTC_TIME 0xC
|
||||
#define RTC_ALARM1 0x10
|
||||
@@ -91,6 +94,7 @@ struct armada38x_rtc_data {
|
||||
void (*clear_isr)(struct armada38x_rtc *rtc);
|
||||
void (*unmask_interrupt)(struct armada38x_rtc *rtc);
|
||||
u32 alarm;
|
||||
+ void (*init_rtc)(struct armada38x_rtc *rtc);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -202,6 +206,23 @@ static void armada38x_unmask_interrupt(s
|
||||
writel(val | SOC_RTC_ALARM1_MASK, rtc->regs_soc + SOC_RTC_INTERRUPT);
|
||||
}
|
||||
|
||||
+static void armada38x_rtc_init(struct armada38x_rtc *rtc)
|
||||
+{
|
||||
+ u32 reg;
|
||||
+
|
||||
+ /* Test RTC test configuration register bits [7:0] */
|
||||
+ reg = readl(rtc->regs + RTC_TEST_CONF);
|
||||
+ /* If bits [7:0] are non-zero, assume RTC was uninitialized */
|
||||
+ if (reg & RTC_TEST_CONF_MASK) {
|
||||
+ rtc_delayed_write(0, rtc, RTC_TEST_CONF);
|
||||
+ rtc_delayed_write(0, rtc, RTC_TIME);
|
||||
+ rtc_delayed_write((RTC_STATUS_ALARM1 | RTC_STATUS_ALARM2),
|
||||
+ rtc, RTC_STATUS);
|
||||
+ rtc_delayed_write(RTC_CCR_NORMAL_PPB, rtc, RTC_CCR);
|
||||
+ }
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
static void armada8k_clear_isr(struct armada38x_rtc *rtc)
|
||||
{
|
||||
writel(RTC_8K_ALARM2, rtc->regs_soc + RTC_8K_ISR);
|
||||
@@ -464,6 +485,7 @@ static const struct armada38x_rtc_data a
|
||||
.clear_isr = armada38x_clear_isr,
|
||||
.unmask_interrupt = armada38x_unmask_interrupt,
|
||||
.alarm = ALARM1,
|
||||
+ .init_rtc = armada38x_rtc_init,
|
||||
};
|
||||
|
||||
static const struct armada38x_rtc_data armada8k_data = {
|
||||
@@ -558,6 +580,17 @@ static __init int armada38x_rtc_probe(st
|
||||
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+ /*
|
||||
+ * Try to detect if RTC is in uninitialized state.
|
||||
+ * It is not definitive to know if the RTC is in an uninialized state or not,
|
||||
+ * but the following call will read some bits in the RTC unit and guess if
|
||||
+ * if it's in that state, and accordingly set it to sane default values.
|
||||
+ */
|
||||
+ if (rtc->data->init_rtc) {
|
||||
+ rtc->data->init_rtc(rtc);
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
From e1cac198fea08c31ec204bed84c279ab05d20389 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sat, 17 Mar 2018 15:22:25 +0100
|
||||
Subject: ARM: dts: armada-385-linksys: Disable internal RTC
|
||||
|
||||
The internal RTC does not work correctly on these Linksys boards based
|
||||
on Marvell SoCs. For me it only shows Wed Dec 31 23:59:59 1969 and for
|
||||
others it is off by 3 minutes in 10 minutes running, this was reported
|
||||
by multiple users. On the Linksys Mamba device the device tree comment
|
||||
says that no crystal is connected to the internal RTC, this is probably
|
||||
also true for the other devices.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
---
|
||||
arch/arm/boot/dts/armada-385-linksys.dtsi | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
--- a/arch/arm/boot/dts/armada-385-linksys.dtsi
|
||||
+++ b/arch/arm/boot/dts/armada-385-linksys.dtsi
|
||||
@@ -304,3 +304,8 @@
|
||||
status = "okay";
|
||||
usb-phy = <&usb3_1_phy>;
|
||||
};
|
||||
+
|
||||
+&rtc {
|
||||
+ /* No crystal connected to the internal RTC */
|
||||
+ status = "disabled";
|
||||
+};
|
94
patch/kernel/mvebu-next/450-reprobe_sfp_phy.patch
Normal file
94
patch/kernel/mvebu-next/450-reprobe_sfp_phy.patch
Normal file
|
@ -0,0 +1,94 @@
|
|||
From 28baa5e2635285b178326b301f534ed95c65dd01 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
Date: Thu, 29 Sep 2016 11:44:39 +0200
|
||||
Subject: [PATCH] sfp: retry phy probe if unsuccessful
|
||||
|
||||
Some phys seem to take longer than 50 ms to come out of reset, so retry
|
||||
until we find a phy.
|
||||
|
||||
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
|
||||
---
|
||||
drivers/net/phy/sfp.c | 38 +++++++++++++++++++++++++-------------
|
||||
1 file changed, 25 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/sfp.c
|
||||
+++ b/drivers/net/phy/sfp.c
|
||||
@@ -488,7 +488,7 @@ static void sfp_sm_phy_detach(struct sfp
|
||||
sfp->mod_phy = NULL;
|
||||
}
|
||||
|
||||
-static void sfp_sm_probe_phy(struct sfp *sfp)
|
||||
+static int sfp_sm_probe_phy(struct sfp *sfp)
|
||||
{
|
||||
struct phy_device *phy;
|
||||
int err;
|
||||
@@ -498,11 +498,11 @@ static void sfp_sm_probe_phy(struct sfp
|
||||
phy = mdiobus_scan(sfp->i2c_mii, SFP_PHY_ADDR);
|
||||
if (phy == ERR_PTR(-ENODEV)) {
|
||||
dev_info(sfp->dev, "no PHY detected\n");
|
||||
- return;
|
||||
+ return -EAGAIN;
|
||||
}
|
||||
if (IS_ERR(phy)) {
|
||||
dev_err(sfp->dev, "mdiobus scan returned %ld\n", PTR_ERR(phy));
|
||||
- return;
|
||||
+ return PTR_ERR(phy);
|
||||
}
|
||||
|
||||
err = sfp_add_phy(sfp->sfp_bus, phy);
|
||||
@@ -510,11 +510,13 @@ static void sfp_sm_probe_phy(struct sfp
|
||||
phy_device_remove(phy);
|
||||
phy_device_free(phy);
|
||||
dev_err(sfp->dev, "sfp_add_phy failed: %d\n", err);
|
||||
- return;
|
||||
+ return err;
|
||||
}
|
||||
|
||||
sfp->mod_phy = phy;
|
||||
phy_start(phy);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static void sfp_sm_link_up(struct sfp *sfp)
|
||||
@@ -560,14 +562,9 @@ static void sfp_sm_fault(struct sfp *sfp
|
||||
|
||||
static void sfp_sm_mod_init(struct sfp *sfp)
|
||||
{
|
||||
- sfp_module_tx_enable(sfp);
|
||||
+ int ret = 0;
|
||||
|
||||
- /* Wait t_init before indicating that the link is up, provided the
|
||||
- * current state indicates no TX_FAULT. If TX_FAULT clears before
|
||||
- * this time, that's fine too.
|
||||
- */
|
||||
- sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES);
|
||||
- sfp->sm_retries = 5;
|
||||
+ sfp_module_tx_enable(sfp);
|
||||
|
||||
/* Setting the serdes link mode is guesswork: there's no
|
||||
* field in the EEPROM which indicates what mode should
|
||||
@@ -581,7 +578,22 @@ static void sfp_sm_mod_init(struct sfp *
|
||||
if (sfp->id.base.e1000_base_t ||
|
||||
sfp->id.base.e100_base_lx ||
|
||||
sfp->id.base.e100_base_fx)
|
||||
- sfp_sm_probe_phy(sfp);
|
||||
+ ret = sfp_sm_probe_phy(sfp);
|
||||
+
|
||||
+ if (!ret) {
|
||||
+ /* Wait t_init before indicating that the link is up, provided
|
||||
+ * the current state indicates no TX_FAULT. If TX_FAULT clears
|
||||
+ * this time, that's fine too.
|
||||
+ */
|
||||
+ sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES);
|
||||
+ sfp->sm_retries = 5;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (ret == -EAGAIN)
|
||||
+ sfp_sm_set_timer(sfp, T_PROBE_RETRY);
|
||||
+ else
|
||||
+ sfp_sm_next(sfp, SFP_S_TX_DISABLE, 0);
|
||||
}
|
||||
|
||||
static int sfp_sm_mod_probe(struct sfp *sfp)
|
|
@ -1,18 +0,0 @@
|
|||
diff --git a/drivers/clk/mvebu/armada-38x.c b/drivers/clk/mvebu/armada-38x.c
|
||||
index 394aa6f0..3a5910b3 100644
|
||||
--- a/drivers/clk/mvebu/armada-38x.c
|
||||
+++ b/drivers/clk/mvebu/armada-38x.c
|
||||
@@ -47,10 +47,11 @@ static u32 __init armada_38x_get_tclk_freq(void __iomem *sar)
|
||||
|
||||
static const u32 armada_38x_cpu_frequencies[] __initconst = {
|
||||
0, 0, 0, 0,
|
||||
- 1066 * 1000 * 1000, 0, 0, 0,
|
||||
+ 666 * 1000 * 1000, 0, 800 * 1000 * 1000, 0,
|
||||
+ 1066 * 1000 * 1000, 0, 1200 * 1000 * 1000, 0,
|
||||
1332 * 1000 * 1000, 0, 0, 0,
|
||||
1600 * 1000 * 1000, 0, 0, 0,
|
||||
- 1866 * 1000 * 1000,
|
||||
+ 1866 * 1000 * 1000, 0, 0, 2000 * 1000 * 1000,
|
||||
};
|
||||
|
||||
static u32 __init armada_38x_get_cpu_freq(void __iomem *sar)
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue