* [PATCH net 1/2] net: stmmac: Rework coalesce timer and fix multi-queue races
From: Jose Abreu @ 2018-09-17 8:22 UTC (permalink / raw)
To: netdev
Cc: Jose Abreu, Florian Fainelli, Neil Armstrong, Jerome Brunet,
Martin Blumenstingl, David S. Miller, Joao Pinto,
Giuseppe Cavallaro, Alexandre Torgue
In-Reply-To: <cover.1537171752.git.joabreu@synopsys.com>
This follows David Miller advice and tries to fix coalesce timer in
multi-queue scenarios.
We are now using per-queue coalesce values and per-queue TX timer.
Coalesce timer default values was changed to 1ms and the coalesce frames
to 25.
Tested in B2B setup between XGMAC2 and GMAC5.
Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Fixes: ce736788e8a ("net: stmmac: adding multiple buffers for TX")
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Neil Armstrong <narmstrong@baylibre.com>
Cc: Jerome Brunet <jbrunet@baylibre.com>
Cc: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Joao Pinto <jpinto@synopsys.com>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 4 +-
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 14 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 233 ++++++++++++----------
include/linux/stmmac.h | 1 +
4 files changed, 146 insertions(+), 106 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 1854f270ad66..b1b305f8f414 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -258,10 +258,10 @@ struct stmmac_safety_stats {
#define MAX_DMA_RIWT 0xff
#define MIN_DMA_RIWT 0x20
/* Tx coalesce parameters */
-#define STMMAC_COAL_TX_TIMER 40000
+#define STMMAC_COAL_TX_TIMER 1000
#define STMMAC_MAX_COAL_TX_TICK 100000
#define STMMAC_TX_MAX_FRAMES 256
-#define STMMAC_TX_FRAMES 64
+#define STMMAC_TX_FRAMES 25
/* Packets types */
enum packets_types {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index c0a855b7ab3b..63e1064b27a2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -48,6 +48,8 @@ struct stmmac_tx_info {
/* Frequently used values are kept adjacent for cache effect */
struct stmmac_tx_queue {
+ u32 tx_count_frames;
+ struct timer_list txtimer;
u32 queue_index;
struct stmmac_priv *priv_data;
struct dma_extended_desc *dma_etx ____cacheline_aligned_in_smp;
@@ -73,7 +75,14 @@ struct stmmac_rx_queue {
u32 rx_zeroc_thresh;
dma_addr_t dma_rx_phy;
u32 rx_tail_addr;
+};
+
+struct stmmac_channel {
struct napi_struct napi ____cacheline_aligned_in_smp;
+ struct stmmac_priv *priv_data;
+ u32 index;
+ int has_rx;
+ int has_tx;
};
struct stmmac_tc_entry {
@@ -109,14 +118,12 @@ struct stmmac_pps_cfg {
struct stmmac_priv {
/* Frequently used values are kept adjacent for cache effect */
- u32 tx_count_frames;
u32 tx_coal_frames;
u32 tx_coal_timer;
int tx_coalesce;
int hwts_tx_en;
bool tx_path_in_lpi_mode;
- struct timer_list txtimer;
bool tso;
unsigned int dma_buf_sz;
@@ -137,6 +144,9 @@ struct stmmac_priv {
/* TX Queue */
struct stmmac_tx_queue tx_queue[MTL_MAX_TX_QUEUES];
+ /* Generic channel for NAPI */
+ struct stmmac_channel channel[STMMAC_CH_MAX];
+
bool oldlink;
int speed;
int oldduplex;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 9f458bb16f2a..ab9cc0143ff2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -148,12 +148,14 @@ static void stmmac_verify_args(void)
static void stmmac_disable_all_queues(struct stmmac_priv *priv)
{
u32 rx_queues_cnt = priv->plat->rx_queues_to_use;
+ u32 tx_queues_cnt = priv->plat->tx_queues_to_use;
+ u32 maxq = max(rx_queues_cnt, tx_queues_cnt);
u32 queue;
- for (queue = 0; queue < rx_queues_cnt; queue++) {
- struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+ for (queue = 0; queue < maxq; queue++) {
+ struct stmmac_channel *ch = &priv->channel[queue];
- napi_disable(&rx_q->napi);
+ napi_disable(&ch->napi);
}
}
@@ -164,12 +166,14 @@ static void stmmac_disable_all_queues(struct stmmac_priv *priv)
static void stmmac_enable_all_queues(struct stmmac_priv *priv)
{
u32 rx_queues_cnt = priv->plat->rx_queues_to_use;
+ u32 tx_queues_cnt = priv->plat->tx_queues_to_use;
+ u32 maxq = max(rx_queues_cnt, tx_queues_cnt);
u32 queue;
- for (queue = 0; queue < rx_queues_cnt; queue++) {
- struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+ for (queue = 0; queue < maxq; queue++) {
+ struct stmmac_channel *ch = &priv->channel[queue];
- napi_enable(&rx_q->napi);
+ napi_enable(&ch->napi);
}
}
@@ -1843,18 +1847,18 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
* @queue: TX queue index
* Description: it reclaims the transmit resources after transmission completes.
*/
-static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)
+static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue)
{
struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
unsigned int bytes_compl = 0, pkts_compl = 0;
- unsigned int entry;
+ unsigned int entry, count = 0;
- netif_tx_lock(priv->dev);
+ __netif_tx_lock_bh(netdev_get_tx_queue(priv->dev, queue));
priv->xstats.tx_clean++;
entry = tx_q->dirty_tx;
- while (entry != tx_q->cur_tx) {
+ while ((entry != tx_q->cur_tx) && (count < budget)) {
struct sk_buff *skb = tx_q->tx_skbuff[entry];
struct dma_desc *p;
int status;
@@ -1870,6 +1874,8 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)
if (unlikely(status & tx_dma_own))
break;
+ count++;
+
/* Make sure descriptor fields are read after reading
* the own bit.
*/
@@ -1937,7 +1943,10 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)
stmmac_enable_eee_mode(priv);
mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
}
- netif_tx_unlock(priv->dev);
+
+ __netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue));
+
+ return count;
}
/**
@@ -2020,6 +2029,33 @@ static bool stmmac_safety_feat_interrupt(struct stmmac_priv *priv)
return false;
}
+static int stmmac_napi_check(struct stmmac_priv *priv, u32 chan)
+{
+ int status = stmmac_dma_interrupt_status(priv, priv->ioaddr,
+ &priv->xstats, chan);
+ struct stmmac_channel *ch = &priv->channel[chan];
+ bool needs_work = false;
+
+ if ((status & handle_rx) && ch->has_rx) {
+ needs_work = true;
+ } else {
+ status &= ~handle_rx;
+ }
+
+ if ((status & handle_tx) && ch->has_tx) {
+ needs_work = true;
+ } else {
+ status &= ~handle_tx;
+ }
+
+ if (needs_work && napi_schedule_prep(&ch->napi)) {
+ stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
+ __napi_schedule(&ch->napi);
+ }
+
+ return status;
+}
+
/**
* stmmac_dma_interrupt - DMA ISR
* @priv: driver private structure
@@ -2034,57 +2070,14 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
u32 channels_to_check = tx_channel_count > rx_channel_count ?
tx_channel_count : rx_channel_count;
u32 chan;
- bool poll_scheduled = false;
int status[max_t(u32, MTL_MAX_TX_QUEUES, MTL_MAX_RX_QUEUES)];
/* Make sure we never check beyond our status buffer. */
if (WARN_ON_ONCE(channels_to_check > ARRAY_SIZE(status)))
channels_to_check = ARRAY_SIZE(status);
- /* Each DMA channel can be used for rx and tx simultaneously, yet
- * napi_struct is embedded in struct stmmac_rx_queue rather than in a
- * stmmac_channel struct.
- * Because of this, stmmac_poll currently checks (and possibly wakes)
- * all tx queues rather than just a single tx queue.
- */
for (chan = 0; chan < channels_to_check; chan++)
- status[chan] = stmmac_dma_interrupt_status(priv, priv->ioaddr,
- &priv->xstats, chan);
-
- for (chan = 0; chan < rx_channel_count; chan++) {
- if (likely(status[chan] & handle_rx)) {
- struct stmmac_rx_queue *rx_q = &priv->rx_queue[chan];
-
- if (likely(napi_schedule_prep(&rx_q->napi))) {
- stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
- __napi_schedule(&rx_q->napi);
- poll_scheduled = true;
- }
- }
- }
-
- /* If we scheduled poll, we already know that tx queues will be checked.
- * If we didn't schedule poll, see if any DMA channel (used by tx) has a
- * completed transmission, if so, call stmmac_poll (once).
- */
- if (!poll_scheduled) {
- for (chan = 0; chan < tx_channel_count; chan++) {
- if (status[chan] & handle_tx) {
- /* It doesn't matter what rx queue we choose
- * here. We use 0 since it always exists.
- */
- struct stmmac_rx_queue *rx_q =
- &priv->rx_queue[0];
-
- if (likely(napi_schedule_prep(&rx_q->napi))) {
- stmmac_disable_dma_irq(priv,
- priv->ioaddr, chan);
- __napi_schedule(&rx_q->napi);
- }
- break;
- }
- }
- }
+ status[chan] = stmmac_napi_check(priv, chan);
for (chan = 0; chan < tx_channel_count; chan++) {
if (unlikely(status[chan] & tx_hard_error_bump_tc)) {
@@ -2233,6 +2226,13 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
return ret;
}
+static void stmmac_tx_timer_arm(struct stmmac_priv *priv, u32 queue)
+{
+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
+
+ mod_timer(&tx_q->txtimer, STMMAC_COAL_TIMER(priv->tx_coal_timer));
+}
+
/**
* stmmac_tx_timer - mitigation sw timer for tx.
* @data: data pointer
@@ -2241,13 +2241,14 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
*/
static void stmmac_tx_timer(struct timer_list *t)
{
- struct stmmac_priv *priv = from_timer(priv, t, txtimer);
- u32 tx_queues_count = priv->plat->tx_queues_to_use;
- u32 queue;
+ struct stmmac_tx_queue *tx_q = from_timer(tx_q, t, txtimer);
+ struct stmmac_priv *priv = tx_q->priv_data;
+ struct stmmac_channel *ch;
+
+ ch = &priv->channel[tx_q->queue_index];
- /* let's scan all the tx queues */
- for (queue = 0; queue < tx_queues_count; queue++)
- stmmac_tx_clean(priv, queue);
+ if (likely(napi_schedule_prep(&ch->napi)))
+ __napi_schedule(&ch->napi);
}
/**
@@ -2260,11 +2261,17 @@ static void stmmac_tx_timer(struct timer_list *t)
*/
static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
{
+ u32 tx_channel_count = priv->plat->tx_queues_to_use;
+ u32 chan;
+
priv->tx_coal_frames = STMMAC_TX_FRAMES;
priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
- timer_setup(&priv->txtimer, stmmac_tx_timer, 0);
- priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
- add_timer(&priv->txtimer);
+
+ for (chan = 0; chan < tx_channel_count; chan++) {
+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[chan];
+
+ timer_setup(&tx_q->txtimer, stmmac_tx_timer, 0);
+ }
}
static void stmmac_set_rings_length(struct stmmac_priv *priv)
@@ -2592,6 +2599,7 @@ static void stmmac_hw_teardown(struct net_device *dev)
static int stmmac_open(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
+ u32 chan;
int ret;
stmmac_check_ether_addr(priv);
@@ -2688,7 +2696,9 @@ static int stmmac_open(struct net_device *dev)
if (dev->phydev)
phy_stop(dev->phydev);
- del_timer_sync(&priv->txtimer);
+ for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
+ del_timer_sync(&priv->tx_queue[chan].txtimer);
+
stmmac_hw_teardown(dev);
init_error:
free_dma_desc_resources(priv);
@@ -2708,6 +2718,7 @@ static int stmmac_open(struct net_device *dev)
static int stmmac_release(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
+ u32 chan;
if (priv->eee_enabled)
del_timer_sync(&priv->eee_ctrl_timer);
@@ -2722,7 +2733,8 @@ static int stmmac_release(struct net_device *dev)
stmmac_disable_all_queues(priv);
- del_timer_sync(&priv->txtimer);
+ for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
+ del_timer_sync(&priv->tx_queue[chan].txtimer);
/* Free the IRQ lines */
free_irq(dev->irq, dev);
@@ -2936,14 +2948,13 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
priv->xstats.tx_tso_nfrags += nfrags;
/* Manage tx mitigation */
- priv->tx_count_frames += nfrags + 1;
- if (likely(priv->tx_coal_frames > priv->tx_count_frames)) {
- mod_timer(&priv->txtimer,
- STMMAC_COAL_TIMER(priv->tx_coal_timer));
- } else {
- priv->tx_count_frames = 0;
+ tx_q->tx_count_frames += nfrags + 1;
+ if (priv->tx_coal_frames <= tx_q->tx_count_frames) {
stmmac_set_tx_ic(priv, desc);
priv->xstats.tx_set_ic_bit++;
+ tx_q->tx_count_frames = 0;
+ } else {
+ stmmac_tx_timer_arm(priv, queue);
}
skb_tx_timestamp(skb);
@@ -3146,14 +3157,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
* This approach takes care about the fragments: desc is the first
* element in case of no SG.
*/
- priv->tx_count_frames += nfrags + 1;
- if (likely(priv->tx_coal_frames > priv->tx_count_frames)) {
- mod_timer(&priv->txtimer,
- STMMAC_COAL_TIMER(priv->tx_coal_timer));
- } else {
- priv->tx_count_frames = 0;
+ tx_q->tx_count_frames += nfrags + 1;
+ if (priv->tx_coal_frames <= tx_q->tx_count_frames) {
stmmac_set_tx_ic(priv, desc);
priv->xstats.tx_set_ic_bit++;
+ tx_q->tx_count_frames = 0;
+ } else {
+ stmmac_tx_timer_arm(priv, queue);
}
skb_tx_timestamp(skb);
@@ -3199,6 +3209,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
stmmac_enable_dma_transmission(priv, priv->ioaddr);
+
stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
return NETDEV_TX_OK;
@@ -3319,6 +3330,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
{
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+ struct stmmac_channel *ch = &priv->channel[queue];
unsigned int entry = rx_q->cur_rx;
int coe = priv->hw->rx_csum;
unsigned int next_entry;
@@ -3491,7 +3503,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
else
skb->ip_summed = CHECKSUM_UNNECESSARY;
- napi_gro_receive(&rx_q->napi, skb);
+ napi_gro_receive(&ch->napi, skb);
priv->dev->stats.rx_packets++;
priv->dev->stats.rx_bytes += frame_len;
@@ -3514,27 +3526,33 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
* Description :
* To look at the incoming frames and clear the tx resources.
*/
-static int stmmac_poll(struct napi_struct *napi, int budget)
+static int stmmac_napi_poll(struct napi_struct *napi, int budget)
{
- struct stmmac_rx_queue *rx_q =
- container_of(napi, struct stmmac_rx_queue, napi);
- struct stmmac_priv *priv = rx_q->priv_data;
- u32 tx_count = priv->plat->tx_queues_to_use;
- u32 chan = rx_q->queue_index;
- int work_done = 0;
- u32 queue;
+ struct stmmac_channel *ch =
+ container_of(napi, struct stmmac_channel, napi);
+ struct stmmac_priv *priv = ch->priv_data;
+ int work_done = 0, work_rem = budget;
+ u32 chan = ch->index;
priv->xstats.napi_poll++;
- /* check all the queues */
- for (queue = 0; queue < tx_count; queue++)
- stmmac_tx_clean(priv, queue);
+ if (ch->has_tx) {
+ int done = stmmac_tx_clean(priv, work_rem, chan);
- work_done = stmmac_rx(priv, budget, rx_q->queue_index);
- if (work_done < budget) {
- napi_complete_done(napi, work_done);
- stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
+ work_done += done;
+ work_rem -= done;
+ }
+
+ if (ch->has_rx) {
+ int done = stmmac_rx(priv, work_rem, chan);
+
+ work_done += done;
+ work_rem -= done;
}
+
+ if (work_done < budget && napi_complete_done(napi, work_done))
+ stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
+
return work_done;
}
@@ -4198,8 +4216,8 @@ int stmmac_dvr_probe(struct device *device,
{
struct net_device *ndev = NULL;
struct stmmac_priv *priv;
+ u32 queue, maxq;
int ret = 0;
- u32 queue;
ndev = alloc_etherdev_mqs(sizeof(struct stmmac_priv),
MTL_MAX_TX_QUEUES,
@@ -4322,11 +4340,22 @@ int stmmac_dvr_probe(struct device *device,
"Enable RX Mitigation via HW Watchdog Timer\n");
}
- for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) {
- struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+ /* Setup channels NAPI */
+ maxq = max(priv->plat->rx_queues_to_use, priv->plat->tx_queues_to_use);
- netif_napi_add(ndev, &rx_q->napi, stmmac_poll,
- (8 * priv->plat->rx_queues_to_use));
+ for (queue = 0; queue < maxq; queue++) {
+ struct stmmac_channel *ch = &priv->channel[queue];
+
+ ch->priv_data = priv;
+ ch->index = queue;
+
+ if (queue < priv->plat->rx_queues_to_use)
+ ch->has_rx = true;
+ if (queue < priv->plat->tx_queues_to_use)
+ ch->has_tx = true;
+
+ netif_napi_add(ndev, &ch->napi, stmmac_napi_poll,
+ NAPI_POLL_WEIGHT);
}
mutex_init(&priv->lock);
@@ -4372,10 +4401,10 @@ int stmmac_dvr_probe(struct device *device,
priv->hw->pcs != STMMAC_PCS_RTBI)
stmmac_mdio_unregister(ndev);
error_mdio_register:
- for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) {
- struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+ for (queue = 0; queue < maxq; queue++) {
+ struct stmmac_channel *ch = &priv->channel[queue];
- netif_napi_del(&rx_q->napi);
+ netif_napi_del(&ch->napi);
}
error_hw_init:
destroy_workqueue(priv->wq);
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index c43e9a01b892..7ddfc65586b0 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -30,6 +30,7 @@
#define MTL_MAX_RX_QUEUES 8
#define MTL_MAX_TX_QUEUES 8
+#define STMMAC_CH_MAX 8
#define STMMAC_RX_COE_NONE 0
#define STMMAC_RX_COE_TYPE1 1
--
2.7.4
^ permalink raw reply related
* [PATCH net 2/2] net: stmmac: Fixup the tail addr setting in xmit path
From: Jose Abreu @ 2018-09-17 8:22 UTC (permalink / raw)
To: netdev
Cc: Jose Abreu, David S. Miller, Joao Pinto, Giuseppe Cavallaro,
Alexandre Torgue
In-Reply-To: <cover.1537171752.git.joabreu@synopsys.com>
Currently we are always setting the tail address of descriptor list to
the end of the pre-allocated list.
According to databook this is not correct. Tail address should point to
the last available descriptor + 1, which means we have to update the
tail address everytime we call the xmit function.
This should make no impact in older versions of MAC but in newer
versions there are some DMA features which allows the IP to fetch
descriptors in advance and in a non sequential order so its critical
that we set the tail address correctly.
Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Fixes: f748be531d70 ("stmmac: support new GMAC4")
Cc: David S. Miller <davem@davemloft.net>
Cc: Joao Pinto <jpinto@synopsys.com>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ab9cc0143ff2..75896d6ba6e2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2213,8 +2213,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
stmmac_init_tx_chan(priv, priv->ioaddr, priv->plat->dma_cfg,
tx_q->dma_tx_phy, chan);
- tx_q->tx_tail_addr = tx_q->dma_tx_phy +
- (DMA_TX_SIZE * sizeof(struct dma_desc));
+ tx_q->tx_tail_addr = tx_q->dma_tx_phy;
stmmac_set_tx_tail_ptr(priv, priv->ioaddr,
tx_q->tx_tail_addr, chan);
}
@@ -3003,6 +3002,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
+ tx_q->tx_tail_addr = tx_q->dma_tx_phy + (tx_q->cur_tx * sizeof(*desc));
stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
return NETDEV_TX_OK;
@@ -3210,6 +3210,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
stmmac_enable_dma_transmission(priv, priv->ioaddr);
+ tx_q->tx_tail_addr = tx_q->dma_tx_phy + (tx_q->cur_tx * sizeof(*desc));
stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
return NETDEV_TX_OK;
--
2.7.4
^ permalink raw reply related
* iproute2: Debian 9 No ELF support
From: Bo YU @ 2018-09-17 8:23 UTC (permalink / raw)
To: netdev, yuzibode
Hello,
I have followed the instructions from:
https://cilium.readthedocs.io/en/latest/bpf/#bpftool
to test xdp program.
But i can not enable elf support.
./configure --prefix=/usr
```output
TC schedulers
ATM no
libc has setns: yes
SELinux support: no
ELF support: no
libmnl support: yes
Berkeley DB: yes
need for strlcpy: yes
libcap support: yes
```
And i have installed libelf-dev :
```output
sudo apt show libelf-dev
Package: libelf-dev
Version: 0.168-1
Priority: optional
Section: libdevel
Source: elfutils
Maintainer: Kurt Roeckx <kurt@roeckx.be>
Installed-Size: 353 kB
Depends: libelf1 (= 0.168-1)
Conflicts: libelfg0-dev
Homepage: https://sourceware.org/elfutils/
Tag: devel::library, role::devel-lib
```
And gcc version:
gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)
uname -a:
Linux debian 4.18.0-rc1+ #2 SMP Sun Jun 24 16:53:57 HKT 2018 x86_64 GNU/Linux
Any help is appreciate.
^ permalink raw reply
* [PATCH 0/2] NFC fixes for 4.19-final
From: Greg Kroah-Hartman @ 2018-09-17 13:51 UTC (permalink / raw)
To: sameo, davem, netdev
Cc: allen.pais, keescook, surenb, linux-wireless, linux-kernel,
Greg Kroah-Hartman
For some reason, these two NFC patches fell through the cracks. It
looks like sometimes NFC patches go through the wireless tree, and
other times, through the networking tree directly.
I don't care which way they go, but they should get merged through some
way, or, I can take them in my device tree, but that feels a bit odd to
me.
thanks,
greg k-h
Suren Baghdasaryan (2):
NFC: Fix possible memory corruption when handling SHDLC I-Frame
commands
NFC: Fix the number of pipes
include/net/nfc/hci.h | 2 +-
net/nfc/hci/core.c | 10 ++++++++++
2 files changed, 11 insertions(+), 1 deletion(-)
--
2.19.0
^ permalink raw reply
* [PATCH 1/2] NFC: Fix possible memory corruption when handling SHDLC I-Frame commands
From: Greg Kroah-Hartman @ 2018-09-17 13:51 UTC (permalink / raw)
To: sameo, davem, netdev
Cc: allen.pais, keescook, surenb, linux-wireless, linux-kernel,
stable, Greg Kroah-Hartman
In-Reply-To: <20180917135141.28328-1-gregkh@linuxfoundation.org>
From: Suren Baghdasaryan <surenb@google.com>
When handling SHDLC I-Frame commands "pipe" field used for indexing
into an array should be checked before usage. If left unchecked it
might access memory outside of the array of size NFC_HCI_MAX_PIPES(127).
Malformed NFC HCI frames could be injected by a malicious NFC device
communicating with the device being attacked (remote attack vector),
or even by an attacker with physical access to the I2C bus such that
they could influence the data transfers on that bus (local attack vector).
skb->data is controlled by the attacker and has only been sanitized in
the most trivial ways (CRC check), therefore we can consider the
create_info struct and all of its members to tainted. 'create_info->pipe'
with max value of 255 (uint8) is used to take an offset of the
hdev->pipes array of 127 elements which can lead to OOB write.
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Allen Pais <allen.pais@oracle.com>
Cc: "David S. Miller" <davem@davemloft.net>
Suggested-by: Kevin Deus <kdeus@google.com>
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
Acked-by: Kees Cook <keescook@chromium.org>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/nfc/hci/core.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index ac8030c4bcf8..19cb2e473ea6 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -209,6 +209,11 @@ void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
}
create_info = (struct hci_create_pipe_resp *)skb->data;
+ if (create_info->pipe >= NFC_HCI_MAX_PIPES) {
+ status = NFC_HCI_ANY_E_NOK;
+ goto exit;
+ }
+
/* Save the new created pipe and bind with local gate,
* the description for skb->data[3] is destination gate id
* but since we received this cmd from host controller, we
@@ -232,6 +237,11 @@ void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
}
delete_info = (struct hci_delete_pipe_noti *)skb->data;
+ if (delete_info->pipe >= NFC_HCI_MAX_PIPES) {
+ status = NFC_HCI_ANY_E_NOK;
+ goto exit;
+ }
+
hdev->pipes[delete_info->pipe].gate = NFC_HCI_INVALID_GATE;
hdev->pipes[delete_info->pipe].dest_host = NFC_HCI_INVALID_HOST;
break;
--
2.19.0
^ permalink raw reply related
* [PATCH 2/2] NFC: Fix the number of pipes
From: Greg Kroah-Hartman @ 2018-09-17 13:51 UTC (permalink / raw)
To: sameo, davem, netdev
Cc: allen.pais, keescook, surenb, linux-wireless, linux-kernel,
stable, Greg Kroah-Hartman
In-Reply-To: <20180917135141.28328-1-gregkh@linuxfoundation.org>
From: Suren Baghdasaryan <surenb@google.com>
According to ETSI TS 102 622 specification chapter 4.4 pipe identifier
is 7 bits long which allows for 128 unique pipe IDs. Because
NFC_HCI_MAX_PIPES is used as the number of pipes supported and not
as the max pipe ID, its value should be 128 instead of 127.
nfc_hci_recv_from_llc extracts pipe ID from packet header using
NFC_HCI_FRAGMENT(0x7F) mask which allows for pipe ID value of 127.
Same happens when NCI_HCP_MSG_GET_PIPE() is being used. With
pipes array having only 127 elements and pipe ID of 127 the OOB memory
access will result.
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Allen Pais <allen.pais@oracle.com>
Cc: "David S. Miller" <davem@davemloft.net>
Suggested-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/net/nfc/hci.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index 316694dafa5b..008f466d1da7 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -87,7 +87,7 @@ struct nfc_hci_pipe {
* According to specification 102 622 chapter 4.4 Pipes,
* the pipe identifier is 7 bits long.
*/
-#define NFC_HCI_MAX_PIPES 127
+#define NFC_HCI_MAX_PIPES 128
struct nfc_hci_init_data {
u8 gate_count;
struct nfc_hci_gate gates[NFC_HCI_MAX_CUSTOM_GATES];
--
2.19.0
^ permalink raw reply related
* Re: [PATCH net] netfilter: bridge: Don't sabotage nf_hook calls from an l3mdev
From: Pablo Neira Ayuso @ 2018-09-17 8:29 UTC (permalink / raw)
To: David Ahern; +Cc: dsahern, netdev, fw, ndsouza, idosch
In-Reply-To: <8aab23ef-094a-8a7d-d905-21a2055e9073@gmail.com>
On Sun, Sep 16, 2018 at 09:14:42PM -0700, David Ahern wrote:
> Pablo:
>
> DaveM has this marked as waiting for upstream. Any comment on this patch?
Please, resend a Cc netfilter-devel@vger.kernel.org
Thanks David.
^ permalink raw reply
* Re: [PATCH net-next] net/smc: cast sizeof to int for comparison
From: Ursula Braun @ 2018-09-17 8:49 UTC (permalink / raw)
To: YueHaibing; +Cc: davem, linux-kernel, netdev, linux-s390
In-Reply-To: <20180915100036.20100-1-yuehaibing@huawei.com>
On 09/15/2018 12:00 PM, YueHaibing wrote:
> Comparing an int to a size, which is unsigned, causes the int to become
> unsigned, giving the wrong result. kernel_sendmsg can return a negative
> error code.
>
Thanks for reporting this issue!
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
> ---
> net/smc/smc_clc.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c
> index 83aba9a..fd0f5ce 100644
> --- a/net/smc/smc_clc.c
> +++ b/net/smc/smc_clc.c
> @@ -446,7 +446,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
> vec[i++].iov_len = sizeof(trl);
> /* due to the few bytes needed for clc-handshake this cannot block */
> len = kernel_sendmsg(smc->clcsock, &msg, vec, i, plen);
> - if (len < sizeof(pclc)) {
> + if (len < (int)sizeof(pclc)) {
> if (len >= 0) {
> reason_code = -ENETUNREACH;
> smc->sk.sk_err = -reason_code;
>
Your fix helps, but I would like to follow the hint of Andreas Schwab, and split
the return value check like this:
---
net/smc/smc_clc.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
--- a/net/smc/smc_clc.c
+++ b/net/smc/smc_clc.c
@@ -446,14 +446,12 @@ int smc_clc_send_proposal(struct smc_soc
vec[i++].iov_len = sizeof(trl);
/* due to the few bytes needed for clc-handshake this cannot block */
len = kernel_sendmsg(smc->clcsock, &msg, vec, i, plen);
- if (len < sizeof(pclc)) {
- if (len >= 0) {
- reason_code = -ENETUNREACH;
- smc->sk.sk_err = -reason_code;
- } else {
- smc->sk.sk_err = smc->clcsock->sk->sk_err;
- reason_code = -smc->sk.sk_err;
- }
+ if (len < 0) {
+ smc->sk.sk_err = smc->clcsock->sk->sk_err;
+ reason_code = -smc->sk.sk_err;
+ } else if (len < (int)sizeof(pclc)) {
+ reason_code = -ENETUNREACH;
+ smc->sk.sk_err = -reason_code;
}
return reason_code;
Agreed?
Regards, Ursula
^ permalink raw reply
* [PATCH v2 1/4] net: qcom/emac: split phy_config to mdio bus create and get phy device
From: Wang Dongsheng @ 2018-09-17 8:53 UTC (permalink / raw)
To: timur, andrew; +Cc: davem, Wang Dongsheng, yu.zheng, netdev
In-Reply-To: <1537174411-34510-1-git-send-email-dongsheng.wang@hxt-semitech.com>
This patch separate emac_mdio_bus_create and emac_get_phydev from
emac_phy_config, and do some codes clean.
Signed-off-by: Wang Dongsheng <dongsheng.wang@hxt-semitech.com>
---
drivers/net/ethernet/qualcomm/emac/emac-phy.c | 99 +++++++++++--------
1 file changed, 57 insertions(+), 42 deletions(-)
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-phy.c b/drivers/net/ethernet/qualcomm/emac/emac-phy.c
index 53dbf1e163a8..2d16c6b9ef49 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-phy.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-phy.c
@@ -96,15 +96,14 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
return 0;
}
-/* Configure the MDIO bus and connect the external PHY */
-int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)
+static int emac_mdio_bus_create(struct platform_device *pdev,
+ struct emac_adapter *adpt)
{
struct device_node *np = pdev->dev.of_node;
struct mii_bus *mii_bus;
int ret;
- /* Create the mii_bus object for talking to the MDIO bus */
- adpt->mii_bus = mii_bus = devm_mdiobus_alloc(&pdev->dev);
+ mii_bus = devm_mdiobus_alloc(&pdev->dev);
if (!mii_bus)
return -ENOMEM;
@@ -115,50 +114,66 @@ int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)
mii_bus->parent = &pdev->dev;
mii_bus->priv = adpt;
- if (has_acpi_companion(&pdev->dev)) {
- u32 phy_addr;
-
- ret = mdiobus_register(mii_bus);
- if (ret) {
- dev_err(&pdev->dev, "could not register mdio bus\n");
- return ret;
- }
- ret = device_property_read_u32(&pdev->dev, "phy-channel",
- &phy_addr);
- if (ret)
- /* If we can't read a valid phy address, then assume
- * that there is only one phy on this mdio bus.
- */
- adpt->phydev = phy_find_first(mii_bus);
- else
- adpt->phydev = mdiobus_get_phy(mii_bus, phy_addr);
-
- /* of_phy_find_device() claims a reference to the phydev,
- * so we do that here manually as well. When the driver
- * later unloads, it can unilaterally drop the reference
- * without worrying about ACPI vs DT.
- */
- if (adpt->phydev)
- get_device(&adpt->phydev->mdio.dev);
- } else {
- struct device_node *phy_np;
+ ret = of_mdiobus_register(mii_bus, has_acpi_companion(&pdev->dev) ?
+ NULL : np);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register mdio bus\n");
+ return ret;
+ }
- ret = of_mdiobus_register(mii_bus, np);
- if (ret) {
- dev_err(&pdev->dev, "could not register mdio bus\n");
- return ret;
- }
+ adpt->mii_bus = mii_bus;
+ return 0;
+}
+static void emac_get_phydev(struct platform_device *pdev,
+ struct emac_adapter *adpt)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct mii_bus *bus = adpt->mii_bus;
+ struct device_node *phy_np;
+ u32 phy_addr;
+ int ret;
+
+ if (!has_acpi_companion(&pdev->dev)) {
phy_np = of_parse_phandle(np, "phy-handle", 0);
adpt->phydev = of_phy_find_device(phy_np);
of_node_put(phy_np);
+ return;
}
- if (!adpt->phydev) {
- dev_err(&pdev->dev, "could not find external phy\n");
- mdiobus_unregister(mii_bus);
- return -ENODEV;
- }
+ ret = device_property_read_u32(&pdev->dev, "phy-channel",
+ &phy_addr);
+ if (ret)
+ /* If we can't read a valid phy address, then assume
+ * that there is only one phy on this mdio bus.
+ */
+ adpt->phydev = phy_find_first(bus);
+ else
+ adpt->phydev = mdiobus_get_phy(bus, phy_addr);
+
+ /* of_phy_find_device() claims a reference to the phydev,
+ * so we do that here manually as well. When the driver
+ * later unloads, it can unilaterally drop the reference
+ * without worrying about ACPI vs DT.
+ */
+ if (adpt->phydev)
+ get_device(&adpt->phydev->mdio.dev);
+}
- return 0;
+/* Configure the MDIO bus and connect the external PHY */
+int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)
+{
+ int ret;
+
+ ret = emac_mdio_bus_create(pdev, adpt);
+ if (ret)
+ return ret;
+
+ emac_get_phydev(pdev, adpt);
+ if (adpt->phydev)
+ return 0;
+
+ dev_err(&pdev->dev, "Could not find external phy\n");
+ mdiobus_unregister(adpt->mii_bus);
+ return -ENODEV;
}
--
2.18.0
^ permalink raw reply related
* [PATCH v2 2/4] dt-bindings: net: qcom: Add binding for shared mdio bus
From: Wang Dongsheng @ 2018-09-17 8:53 UTC (permalink / raw)
To: timur, andrew; +Cc: davem, Wang Dongsheng, yu.zheng, netdev, devicetree
In-Reply-To: <1537174411-34510-1-git-send-email-dongsheng.wang@hxt-semitech.com>
This property copy from "ibm,emac.txt" to describe a shared MIDO bus.
Since emac include MDIO, so If the motherboard has more than one PHY
connected to an MDIO bus, this property will point to the MAC device
that has the MDIO bus.
Signed-off-by: Wang Dongsheng <dongsheng.wang@hxt-semitech.com>
---
V2: s/Since QDF2400 emac/Since emac/
---
Documentation/devicetree/bindings/net/qcom-emac.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/qcom-emac.txt b/Documentation/devicetree/bindings/net/qcom-emac.txt
index 346e6c7f47b7..50db71771358 100644
--- a/Documentation/devicetree/bindings/net/qcom-emac.txt
+++ b/Documentation/devicetree/bindings/net/qcom-emac.txt
@@ -24,6 +24,9 @@ Internal PHY node:
The external phy child node:
- reg : The phy address
+Optional properties:
+- mdio-device : Shared MIDO bus.
+
Example:
FSM9900:
@@ -86,6 +89,7 @@ soc {
reg = <0x0 0x38800000 0x0 0x10000>,
<0x0 0x38816000 0x0 0x1000>;
interrupts = <0 256 4>;
+ mdio-device = <&emac1>;
clocks = <&gcc 0>, <&gcc 1>, <&gcc 3>, <&gcc 4>, <&gcc 5>,
<&gcc 6>, <&gcc 7>;
--
2.18.0
^ permalink raw reply related
* [PATCH v2 0/4] net: qcom/emac: add shared mdio bus support
From: Wang Dongsheng @ 2018-09-17 8:53 UTC (permalink / raw)
To: timur, andrew; +Cc: davem, Wang Dongsheng, yu.zheng, netdev, devicetree
The emac include MDIO controller, and the motherboard has more than one
PHY connected to an MDIO bus. So share the shared mii_bus for others MAC
device that not has MDIO bus connected.
Tested: QDF2400 (ACPI), buildin/insmod/rmmod
V2:
- Separate patch.
- bindings: s/Since QDF2400 emac/Since emac/
Wang Dongsheng (4):
net: qcom/emac: split phy_config to mdio bus create and get phy device
dt-bindings: net: qcom: Add binding for shared mdio bus
net: qcom/emac: add of shared mdio bus support
net: qcom/emac: add acpi shared mdio bus support
.../devicetree/bindings/net/qcom-emac.txt | 4 +
drivers/net/ethernet/qualcomm/emac/emac-phy.c | 207 ++++++++++++++----
drivers/net/ethernet/qualcomm/emac/emac.c | 8 +-
3 files changed, 175 insertions(+), 44 deletions(-)
--
2.18.0
^ permalink raw reply
* [PATCH v2 4/4] net: qcom/emac: add acpi shared mdio bus support
From: Wang Dongsheng @ 2018-09-17 8:55 UTC (permalink / raw)
To: timur, andrew; +Cc: davem, Wang Dongsheng, yu.zheng, netdev
In-Reply-To: <1537174546-34642-1-git-send-email-dongsheng.wang@hxt-semitech.com>
Parsing _DSD package "mdio-device".
Signed-off-by: Wang Dongsheng <dongsheng.wang@hxt-semitech.com>
---
drivers/net/ethernet/qualcomm/emac/emac-phy.c | 51 +++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-phy.c b/drivers/net/ethernet/qualcomm/emac/emac-phy.c
index 4f98f9a0ed54..7a96bcf15d3f 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-phy.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-phy.c
@@ -97,6 +97,51 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
return 0;
}
+static int acpi_device_match(struct device *dev, void *fwnode)
+{
+ return dev->fwnode == fwnode;
+}
+
+static int emac_acpi_get_shared_bus(struct platform_device *pdev,
+ struct mii_bus **bus)
+{
+ struct fwnode_reference_args args;
+ struct fwnode_handle *fw_node;
+
+ struct device *shared_dev;
+ struct net_device *shared_netdev;
+ struct emac_adapter *shared_adpt;
+ int ret;
+
+ if (!has_acpi_companion(&pdev->dev))
+ return -ENODEV;
+
+ fw_node = acpi_fwnode_handle(ACPI_COMPANION(&pdev->dev));
+ ret = acpi_node_get_property_reference(fw_node, "mdio-device", 0,
+ &args);
+ if (ACPI_FAILURE(ret) || !is_acpi_device_node(args.fwnode)) {
+ dev_err(&pdev->dev, "Missing mdio-device property\n");
+ return -ENODEV;
+ }
+
+ shared_dev = bus_find_device(&platform_bus_type, NULL,
+ args.fwnode,
+ acpi_device_match);
+ if (!shared_dev)
+ return -EPROBE_DEFER;
+
+ shared_netdev = dev_get_drvdata(shared_dev);
+ if (!shared_netdev)
+ return -EPROBE_DEFER;
+
+ shared_adpt = netdev_priv(shared_netdev);
+ if (!shared_adpt->mii_bus)
+ return -EPROBE_DEFER;
+
+ *bus = shared_adpt->mii_bus;
+ return 0;
+}
+
static int emac_of_get_shared_bus(struct platform_device *pdev,
struct mii_bus **bus)
{
@@ -137,6 +182,12 @@ static int emac_of_get_shared_bus(struct platform_device *pdev,
static int __do_get_emac_mido_shared_bus(struct platform_device *pdev,
struct emac_adapter *adpt)
{
+ int ret;
+
+ ret = emac_acpi_get_shared_bus(pdev, &adpt->mii_bus);
+ if (adpt->mii_bus || ret == -EPROBE_DEFER)
+ return ret;
+
return emac_of_get_shared_bus(pdev, &adpt->mii_bus);
}
--
2.18.0
^ permalink raw reply related
* [PATCH v2 3/4] net: qcom/emac: add of shared mdio bus support
From: Wang Dongsheng @ 2018-09-17 8:55 UTC (permalink / raw)
To: timur, andrew; +Cc: davem, Wang Dongsheng, yu.zheng, netdev
Share the mii_bus for others MAC device because EMAC include MDIO,
and the motherboard has more than one PHY connected to an MDIO bus.
Signed-off-by: Wang Dongsheng <dongsheng.wang@hxt-semitech.com>
---
drivers/net/ethernet/qualcomm/emac/emac-phy.c | 63 ++++++++++++++++++-
drivers/net/ethernet/qualcomm/emac/emac.c | 8 ++-
2 files changed, 66 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-phy.c b/drivers/net/ethernet/qualcomm/emac/emac-phy.c
index 2d16c6b9ef49..4f98f9a0ed54 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-phy.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-phy.c
@@ -13,6 +13,7 @@
/* Qualcomm Technologies, Inc. EMAC PHY Controller driver.
*/
+#include <linux/of_platform.h>
#include <linux/of_mdio.h>
#include <linux/phy.h>
#include <linux/iopoll.h>
@@ -96,8 +97,51 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
return 0;
}
-static int emac_mdio_bus_create(struct platform_device *pdev,
- struct emac_adapter *adpt)
+static int emac_of_get_shared_bus(struct platform_device *pdev,
+ struct mii_bus **bus)
+{
+ struct device_node *shared_node;
+ struct platform_device *shared_pdev;
+ struct net_device *shared_netdev;
+ struct emac_adapter *shared_adpt;
+ struct device_node *np = pdev->dev.of_node;
+
+ const phandle *prop;
+
+ prop = of_get_property(np, "mdio-device", NULL);
+ if (!prop) {
+ dev_err(&pdev->dev, "Missing mdio-device property\n");
+ return -ENODEV;
+ }
+
+ shared_node = of_find_node_by_phandle(*prop);
+ if (!shared_node)
+ return -ENODEV;
+
+ shared_pdev = of_find_device_by_node(shared_node);
+ if (!shared_pdev)
+ return -ENODEV;
+
+ shared_netdev = dev_get_drvdata(&shared_pdev->dev);
+ if (!shared_netdev)
+ return -EPROBE_DEFER;
+
+ shared_adpt = netdev_priv(shared_netdev);
+ if (!shared_adpt->mii_bus)
+ return -EPROBE_DEFER;
+
+ *bus = shared_adpt->mii_bus;
+ return 0;
+}
+
+static int __do_get_emac_mido_shared_bus(struct platform_device *pdev,
+ struct emac_adapter *adpt)
+{
+ return emac_of_get_shared_bus(pdev, &adpt->mii_bus);
+}
+
+static int __do_emac_mido_bus_create(struct platform_device *pdev,
+ struct emac_adapter *adpt)
{
struct device_node *np = pdev->dev.of_node;
struct mii_bus *mii_bus;
@@ -125,6 +169,17 @@ static int emac_mdio_bus_create(struct platform_device *pdev,
return 0;
}
+static int emac_mdio_bus_create(struct platform_device *pdev,
+ struct emac_adapter *adpt)
+{
+ bool shared_mdio;
+
+ shared_mdio = device_property_read_bool(&pdev->dev, "mdio-device");
+ if (shared_mdio)
+ return __do_get_emac_mido_shared_bus(pdev, adpt);
+ return __do_emac_mido_bus_create(pdev, adpt);
+}
+
static void emac_get_phydev(struct platform_device *pdev,
struct emac_adapter *adpt)
{
@@ -174,6 +229,8 @@ int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)
return 0;
dev_err(&pdev->dev, "Could not find external phy\n");
- mdiobus_unregister(adpt->mii_bus);
+ /* Only the bus creator can unregister mdio bus */
+ if (&pdev->dev == adpt->mii_bus->parent)
+ mdiobus_unregister(adpt->mii_bus);
return -ENODEV;
}
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index 2a0cbc535a2e..6e566b4c5a6b 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -727,7 +727,9 @@ static int emac_probe(struct platform_device *pdev)
netif_napi_del(&adpt->rx_q.napi);
err_undo_mdiobus:
put_device(&adpt->phydev->mdio.dev);
- mdiobus_unregister(adpt->mii_bus);
+ /* Only the bus creator can unregister mdio bus */
+ if (&pdev->dev == adpt->mii_bus->parent)
+ mdiobus_unregister(adpt->mii_bus);
err_undo_clocks:
emac_clks_teardown(adpt);
err_undo_netdev:
@@ -747,7 +749,9 @@ static int emac_remove(struct platform_device *pdev)
emac_clks_teardown(adpt);
put_device(&adpt->phydev->mdio.dev);
- mdiobus_unregister(adpt->mii_bus);
+ /* Only the bus creator can unregister mdio bus */
+ if (&pdev->dev == adpt->mii_bus->parent)
+ mdiobus_unregister(adpt->mii_bus);
free_netdev(netdev);
if (adpt->phy.digital)
--
2.18.0
^ permalink raw reply related
* Re: [PATCH net-next RFC 7/8] udp: gro behind static key
From: Steffen Klassert @ 2018-09-17 9:03 UTC (permalink / raw)
To: Willem de Bruijn; +Cc: netdev, pabeni, davem, Willem de Bruijn
In-Reply-To: <20180914175941.213950-8-willemdebruijn.kernel@gmail.com>
On Fri, Sep 14, 2018 at 01:59:40PM -0400, Willem de Bruijn wrote:
> From: Willem de Bruijn <willemb@google.com>
>
> Avoid the socket lookup cost in udp_gro_receive if no socket has a
> gro callback configured.
>
> Signed-off-by: Willem de Bruijn <willemb@google.com>
...
> diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
> index 4f6aa95a9b12..f44fe328aa0f 100644
> --- a/net/ipv4/udp_offload.c
> +++ b/net/ipv4/udp_offload.c
> @@ -405,7 +405,7 @@ static struct sk_buff *udp4_gro_receive(struct list_head *head,
> {
> struct udphdr *uh = udp_gro_udphdr(skb);
>
> - if (unlikely(!uh))
> + if (unlikely(!uh) || !static_branch_unlikely(&udp_encap_needed_key))
> goto flush;
If you use udp_encap_needed_key to enalbe UDP GRO, then a UDP
encapsulation socket will enable it too. Not sure if this is
intentional.
That said, enabling UDP GRO on a UDP encapsulation socket
(ESP in UPD etc.) will fail badly as then encrypted ESP
packets might be merged together. So we somehow should
make sure that this does not happen.
Anyway, this reminds me that we can support GRO for
UDP encapsulation. It just requires separate GRO
callbacks for the different encapsulation types.
^ permalink raw reply
* Re: [PATCH] net: ethernet: ti: add missing GENERIC_ALLOCATOR dependency
From: David Miller @ 2018-09-17 14:49 UTC (permalink / raw)
To: clabbe; +Cc: linux-kernel, netdev
In-Reply-To: <1536924007-2440-1-git-send-email-clabbe@baylibre.com>
From: Corentin Labbe <clabbe@baylibre.com>
Date: Fri, 14 Sep 2018 11:20:07 +0000
> This patch mades TI_DAVINCI_CPDMA select GENERIC_ALLOCATOR.
> without that, the following sparc64 build failure happen
>
> drivers/net/ethernet/ti/davinci_cpdma.o: In function `cpdma_check_free_tx_desc':
> (.text+0x278): undefined reference to `gen_pool_avail'
> drivers/net/ethernet/ti/davinci_cpdma.o: In function `cpdma_chan_submit':
> (.text+0x340): undefined reference to `gen_pool_alloc'
> (.text+0x5c4): undefined reference to `gen_pool_free'
> drivers/net/ethernet/ti/davinci_cpdma.o: In function `__cpdma_chan_free':
> davinci_cpdma.c:(.text+0x64c): undefined reference to `gen_pool_free'
> drivers/net/ethernet/ti/davinci_cpdma.o: In function `cpdma_desc_pool_destroy.isra.6':
> davinci_cpdma.c:(.text+0x17ac): undefined reference to `gen_pool_size'
> davinci_cpdma.c:(.text+0x17b8): undefined reference to `gen_pool_avail'
> davinci_cpdma.c:(.text+0x1824): undefined reference to `gen_pool_size'
> davinci_cpdma.c:(.text+0x1830): undefined reference to `gen_pool_avail'
> drivers/net/ethernet/ti/davinci_cpdma.o: In function `cpdma_ctlr_create':
> (.text+0x19f8): undefined reference to `devm_gen_pool_create'
> (.text+0x1a90): undefined reference to `gen_pool_add_virt'
> Makefile:1011: recipe for target 'vmlinux' failed
>
> Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next v3 02/17] zinc: introduce minimal cryptography library
From: Andy Lutomirski @ 2018-09-17 14:51 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Andy Lutomirski, David S. Miller, Andrew Lunn, Jason A. Donenfeld,
Eric Biggers, Greg KH, LKML, Network Development, Samuel Neves,
Jean-Philippe Aumasson, Linux Crypto Mailing List
In-Reply-To: <CAKv+Gu8QgRo-Oex2Sk5unET3FMq+1Cp2btAWXCB8xsALxjatHg@mail.gmail.com>
> On Sep 16, 2018, at 10:26 PM, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>
> As far as I can tell (i.e., as a user not a network dev), WireGuard is
> an excellent piece of code, and I would like to see it merged. I also
> think there is little disagreement about the quality of the proposed
> algorithm implementations and the usefulness of having a set of easy
> to use solid crypto primitives in addition to or complementing the
> current crypto API.
>
> I do have some concerns over how the code is organized though:
>
> * simd_relax() is currently not called by the crypto routines
> themselves. This means that the worst case scheduling latency is
> unbounded, which is unacceptable for the -rt kernel. The worst case
> scheduling latency should never be proportional to the input size.
> (Apologies for not spotting that earlier)
>
> * Using a cute name for the crypto library [that will end up being the
> preferred choice for casual use only] may confuse people, given that
> we have lots of code in crypto/ already. I'd much prefer using, e.g.,
> crypto/lib and crypto/api (regardless of where the arch specific
> pieces live)
>
> * I'd prefer the arch specific pieces to live under arch, but I can
> live with keeping them in a single place, as long as the arch
> maintainers have some kind of jurisdiction over them. I also think
> there should be some overlap between the maintainership
> responsibilities of the two generic pieces (api and lib).
>
> * (Nit) The GCC command line -include'd .h files contain variable and
> function definitions so they are actually .c files.
Hmm. I would suggest just getting rid of the -include magic entirely. The resulting ifdef will be more comprehensible.
> * The current organization of the code puts all available (for the
> arch) versions of all routines into a single module, which can only be
> built in once we update random.c to use Zinc's chacha20 routines. This
> bloats the core kernel (which is a huge deal for embedded systems that
> have very strict boot requirements). It also makes it impossible to
> simply blacklist a module if you, for instance, prefer to use the
> [potentially more power efficient] scalar code over the SIMD code when
> using a distro kernel.
I think the module organization needs to change. It needs to be possible to have chacha20 built in but AES or whatever as a module.
>
> [To summarize the 4 points above, I'd much rather see a more
> conventional organization where different parts are provided by
> different modules. I don't think the argument that inlining is needed
> for performance is actually valid, given that we have branch
> predictors and static keys, and the arch SIMD code is built as
> separate object files anyway]
I might have agreed before Spectre :(. Unfortunately, unless we do some magic, I think the code would look something like:
if (static_branch_likely(have_simd)) arch_chacha20();
...where arch_chacha20 is a *pointer*. And that will generate a retpoline and run very, very slowly. (I just rewrote some of the x86 entry code to eliminate one retpoline. I got a 5% speedup on some tests according to the kbuild bot.)
So, if we really wanted modules, we’d need a new dynamic patching mechanism.
I would suggest instead adding two boot (or debugfs) options:
simd=off: disables simd_get using a static branch.
crypto_chacha20_nosimd: Does what it sounds like.
^ permalink raw reply
* Re: [PATCH net-next v3 02/17] zinc: introduce minimal cryptography library
From: Andy Lutomirski @ 2018-09-17 14:53 UTC (permalink / raw)
To: Jason A. Donenfeld
Cc: Andrew Lutomirski, David Miller, Andrew Lunn, Eric Biggers,
Greg Kroah-Hartman, Ard Biesheuvel, LKML, Netdev, Samuel Neves,
Jean-Philippe Aumasson, Linux Crypto Mailing List
In-Reply-To: <CAHmME9ohGPTX-fkhP6zaWdx3SbkiqO5kWkWE-bDk=pm-nUqYvw@mail.gmail.com>
> On Sep 16, 2018, at 10:07 PM, Jason A. Donenfeld <Jason@zx2c4.com> wrote:
>
> Hey Andy,
>
> Thanks a lot for your feedback.
>
>> On Mon, Sep 17, 2018 at 6:09 AM Andy Lutomirski <luto@kernel.org> wrote:
>> 1. Zinc conflates the addition of a new API with the replacement of
>> some algorithm implementations. This is problematic. Look at the
>> recent benchmarks of ipsec before and after this series. Apparently
>> big packets get faster and small packets get slower. It would be
>> really nice to bisect the series to narrow down *where* the regression
>> came from, but, as currently structured, you can't.
>>
>> The right way to do this is to rearrange the series. First, the new
>> Zinc APIs should be added, and they should be backed with the
>> *existing* crypto code. (If the code needs to be moved or copied to a
>> new location, so be it. The patch will be messy because somehow the
>> Zinc API is going to have to dispatch to the arch-specific code, and
>> the way that the crypto API handles it is not exactly friendly to this
>> type of use. So be it.) Then another patch should switch the crypto
>> API to use the Zinc interface. That patch, *by itself*, can be
>> benchmarked. If it causes a regression for small ipsec packets, then
>> it can be tracked down relatively easily. Once this is all done, the
>> actual crypto implementation can be changed, and that changed can be
>> reviewed on its own merits.
>
> That ipsec regression was less related to the implementation and more
> related to calling kernel_fpu_begin() unnecessarily, something I've
> now fixed. So I'm not sure that's such a good example. However, I can
> try to implement Zinc over the existing assembly (Martin's and Ard's),
> first, as you've described. This will be a pretty large amount of
> work, but if you think it's worth it for the commit history, then I'll
> do it.
Ard, what do you think? I think it would
be nice, but if the authors of that assembly are convinced it should be replaced, then this step is optional IMO.
>
>> 2. The new Zinc crypto implementations look like they're brand new. I
>> realize that they have some history, some of them are derived from
>> OpenSSL, etc, but none of this is really apparent in the patches
>> themselves.
>
> The whole point of going with these is that they _aren't_ brand new,
> yet they are very fast. Eyeballs and fuzzer hours are important, and
> AndyP's seems to get the most eyeballs and fuzzer hours, generally.
>
>> it would be nice if
>> the patches made it more clear how the code differs from its origin.
>> At the very least, though, if the replacement of the crypto code were,
>> as above, a patch that just replaced the crypto code, it would be much
>> easier to review and benchmark intelligently.
>
> You seem to have replied to the v3 thread, not the v4 thread. I've
> already started to include lots of detail about the origins of the
> code and [any] important differences in v4, and I'll continue to add
> more detail for v5.
This is indeed better. Ard’s reply covers this better.
^ permalink raw reply
* Re: [PATCH net-next v3 02/17] zinc: introduce minimal cryptography library
From: Andy Lutomirski @ 2018-09-17 14:55 UTC (permalink / raw)
To: David Miller, herbert
Cc: luto, andrew, Jason, ebiggers, gregkh, ard.biesheuvel,
linux-kernel, netdev, sneves, jeanphilippe.aumasson, linux-crypto
In-Reply-To: <20180916.214549.234387075817326903.davem@davemloft.net>
> On Sep 16, 2018, at 9:45 PM, David Miller <davem@davemloft.net> wrote:
>
> From: Andy Lutomirski <luto@kernel.org>
> Date: Sun, 16 Sep 2018 21:09:11 -0700
>
>> CRYPTO API
>> M: Herbert Xu <herbert@gondor.apana.org.au>
>> M: "David S. Miller" <davem@davemloft.net>
>> L: linux-crypto@vger.kernel.org
>>
>> Herbert hasn't replied to any of these submissions. You're the other
>> maintainer :)
>
> Herbert is the primary crypto maintainer, I haven't done a serious
> review of crypto code in ages.
>
> So yes, Herbert review is what is important here.
Would you accept Ard’s (and/or Eric Biggers’, perhaps, as an alternative)? Or, if you really want Herbert’s review, can you ask him to review it? (Hi Herbert!)
^ permalink raw reply
* Re: [PATCH net] net: mvpp2: let phylink manage the carrier state
From: David Miller @ 2018-09-17 14:57 UTC (permalink / raw)
To: antoine.tenart
Cc: linux, netdev, linux-kernel, thomas.petazzoni, maxime.chevallier,
gregory.clement, miquel.raynal, nadavh, stefanc, ymarkman, mw
In-Reply-To: <20180914145635.21813-1-antoine.tenart@bootlin.com>
From: Antoine Tenart <antoine.tenart@bootlin.com>
Date: Fri, 14 Sep 2018 16:56:35 +0200
> Net drivers using phylink shouldn't mess with the link carrier
> themselves and should let phylink manage it. The mvpp2 driver wasn't
> following this best practice as the mac_config() function made calls to
> change the link carrier state. This led to wrongly reported carrier link
> state which then triggered other issues. This patch fixes this
> behaviour.
>
> But the PPv2 driver relied on this misbehaviour in two cases: for fixed
> links and when not using phylink (ACPI mode). The later was fixed by
> adding an explicit call to link_up(), which when the ACPI mode will use
> phylink should be removed.
>
> The fixed link case was relying on the mac_config() function to set the
> link up, as we found an issue in phylink_start() which assumes the
> carrier is off. If not, the link_up() function is never called. To fix
> this, a call to netif_carrier_off() is added just before phylink_start()
> so that we do not introduce a regression in the driver.
>
> Fixes: 4bb043262878 ("net: mvpp2: phylink support")
> Reported-by: Russell King <linux@armlinux.org.uk>
> Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
Applied.
^ permalink raw reply
* Re: [PATCH] ARM: dts: at91: add new compatibility string for macb on sama5d3
From: David Miller @ 2018-09-17 14:57 UTC (permalink / raw)
To: nicolas.ferre
Cc: netdev, linux-kernel, linux-arm-kernel, claudiu.beznea,
alexandre.belloni, ludovic.desroches, devicetree
In-Reply-To: <20180914154811.12090-2-nicolas.ferre@microchip.com>
From: Nicolas Ferre <nicolas.ferre@microchip.com>
Date: Fri, 14 Sep 2018 17:48:11 +0200
> We need this new compatibility string as we experienced different behavior
> for this 10/100Mbits/s macb interface on this particular SoC.
> Backward compatibility is preserved as we keep the alternative strings.
>
> Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Applied.
^ permalink raw reply
* Re: [PATCH] net: macb: disable scatter-gather for macb on sama5d3
From: David Miller @ 2018-09-17 14:58 UTC (permalink / raw)
To: nicolas.ferre
Cc: netdev, linux-kernel, linux-arm-kernel, claudiu.beznea,
alexandre.belloni, ludovic.desroches, devicetree
In-Reply-To: <20180914154811.12090-1-nicolas.ferre@microchip.com>
From: Nicolas Ferre <nicolas.ferre@microchip.com>
Date: Fri, 14 Sep 2018 17:48:10 +0200
> Create a new configuration for the sama5d3-macb new compatibility string.
> This configuration disables scatter-gather because we experienced lock down
> of the macb interface of this particular SoC under very high load.
>
> Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Applied, but are you really sure it isn't just some bug in the driver
or somesuch?
^ permalink raw reply
* Re: [PATCH] net: hp100: fix always-true check for link up state
From: David Miller @ 2018-09-17 14:58 UTC (permalink / raw)
To: colin.king; +Cc: perex, netdev, kernel-janitors, linux-kernel
In-Reply-To: <20180914163953.20734-1-colin.king@canonical.com>
From: Colin King <colin.king@canonical.com>
Date: Fri, 14 Sep 2018 17:39:53 +0100
> From: Colin Ian King <colin.king@canonical.com>
>
> The operation ~(p100_inb(VG_LAN_CFG_1) & HP100_LINK_UP) returns a value
> that is always non-zero and hence the wait for the link to drop always
> terminates prematurely. Fix this by using a logical not operator instead
> of a bitwise complement. This issue has been in the driver since
> pre-2.6.12-rc2.
>
> Detected by CoverityScan, CID#114157 ("Logical vs. bitwise operator")
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
Applied and queued up for -stable.
^ permalink raw reply
* Re: [PATCH net-next v3 02/17] zinc: introduce minimal cryptography library
From: Jason A. Donenfeld @ 2018-09-17 14:59 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Andrew Lutomirski, David Miller, Andrew Lunn, Eric Biggers,
Greg Kroah-Hartman, Ard Biesheuvel, LKML, Netdev, Samuel Neves,
Jean-Philippe Aumasson, Linux Crypto Mailing List
In-Reply-To: <8937D6B1-D21C-4C47-8A89-A466CDB6FB04@amacapital.net>
On Mon, Sep 17, 2018 at 4:54 PM Andy Lutomirski <luto@amacapital.net> wrote:
> Ard, what do you think? I think it would
> be nice, but if the authors of that assembly are convinced it should be replaced, then this step is optional IMO.
I just spent several hours reworking everything for ChaCha. That was
the easy one. Poly1305 will be much harder. Work in progress, I guess,
but erf it's rough.
^ permalink raw reply
* Re: [PATCH net-next] net: fix return type of ndo_start_xmit function
From: David Miller @ 2018-09-17 15:09 UTC (permalink / raw)
To: yuehaibing; +Cc: linux-kernel, netdev, dev
In-Reply-To: <20180915081906.23816-1-yuehaibing@huawei.com>
Please don't do this.
The hard part of fixing this is not what you are doing, changing the
return type.
The hard part is fixing each and every function to actually return
values which are members of the netdev_tx_t enumeration.
Please fix each and every function properly.
Thank you.
^ permalink raw reply
* [PATCH net] net/ipv4: defensive cipso option parsing
From: Stefan Nuernberger @ 2018-09-17 15:11 UTC (permalink / raw)
To: netdev; +Cc: aams, yujuan.qi, paul, Stefan Nuernberger, stable
commit 40413955ee26 ("Cipso: cipso_v4_optptr enter infinite loop") fixed
a possible infinite loop in the IP option parsing of CIPSO. The fix
assumes that ip_options_compile filtered out all zero length options and
that no other one-byte options beside IPOPT_END and IPOPT_NOOP exist.
While this assumption currently holds true, add explicit checks for zero
length and invalid length options to be safe for the future. Even though
ip_options_compile should have validated the options, the introduction of
new one-byte options can still confuse this code without the additional
checks.
Signed-off-by: Stefan Nuernberger <snu@amazon.com>
Reviewed-by: David Woodhouse <dwmw@amazon.co.uk>
Reviewed-by: Simon Veith <sveith@amazon.de>
Cc: stable@vger.kernel.org
---
net/ipv4/cipso_ipv4.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 82178cc69c96..f291b57b8474 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -1512,7 +1512,7 @@ static int cipso_v4_parsetag_loc(const struct cipso_v4_doi *doi_def,
*
* Description:
* Parse the packet's IP header looking for a CIPSO option. Returns a pointer
- * to the start of the CIPSO option on success, NULL if one if not found.
+ * to the start of the CIPSO option on success, NULL if one is not found.
*
*/
unsigned char *cipso_v4_optptr(const struct sk_buff *skb)
@@ -1522,9 +1522,11 @@ unsigned char *cipso_v4_optptr(const struct sk_buff *skb)
int optlen;
int taglen;
- for (optlen = iph->ihl*4 - sizeof(struct iphdr); optlen > 0; ) {
+ for (optlen = iph->ihl*4 - sizeof(struct iphdr); optlen > 1; ) {
switch (optptr[0]) {
case IPOPT_CIPSO:
+ if (!optptr[1] || optptr[1] > optlen)
+ return NULL;
return optptr;
case IPOPT_END:
return NULL;
@@ -1534,6 +1536,10 @@ unsigned char *cipso_v4_optptr(const struct sk_buff *skb)
default:
taglen = optptr[1];
}
+
+ if (!taglen || taglen > optlen)
+ break;
+
optlen -= taglen;
optptr += taglen;
}
--
2.19.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox