Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: 1) Missing list head init in bluetooth hidp session creation, from Tedd Ho-Jeong An. 2) Don't leak SKB in bridge netfilter error paths, from Florian Westphal. 3) ipv6 netdevice private leak in netfilter bridging, fixed by Julien Grall. 4) Fix regression in IP over hamradio bpq encapsulation, from Ralf Baechle. 5) Fix race between rhashtable resize events and table walks, from Phil Sutter. 6) Missing validation of IFLA_VF_INFO netlink attributes, fix from Daniel Borkmann. 7) Missing security layer socket state initialization in tipc code, from Stephen Smalley. 8) Fix shared IRQ handling in boomerang 3c59x interrupt handler, from Denys Vlasenko. 9) Missing minor_idr destroy on module unload on macvtap driver, from Johannes Thumshirn. 10) Various pktgen kernel thread races, from Oleg Nesterov. 11) Fix races that can cause packets to be processed in the backlog even after a device attached to that SKB has been fully unregistered. From Julian Anastasov. 12) bcmgenet driver doesn't account packet drops vs. errors properly, fix from Petri Gynther. 13) Array index validation and off by one fix in DSA layer from Florian Fainelli * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (66 commits) can: replace timestamp as unique skb attribute ARM: dts: dra7x-evm: Prevent glitch on DCAN1 pinmux can: c_can: Fix default pinmux glitch at init can: rcar_can: unify error messages can: rcar_can: print request_irq() error code can: rcar_can: fix typo in error message can: rcar_can: print signed IRQ # can: rcar_can: fix IRQ check net: dsa: Fix off-by-one in switch address parsing net: dsa: Test array index before use net: switchdev: don't abort unsupported operations net: bcmgenet: fix accounting of packet drops vs errors cdc_ncm: update specs URL Doc: z8530book: Fix typo in API-z8530-sync-txdma-open.html net: inet_diag: always export IPV6_V6ONLY sockopt for listening sockets bridge: mdb: allow the user to delete mdb entry if there's a querier net: call rcu_read_lock early in process_backlog net: do not process device backlog during unregistration bridge: fix potential crash in __netdev_pick_tx() net: axienet: Fix devm_ioremap_resource return value check ...
This commit is contained in:
commit
f760b87f8f
|
@ -7019,6 +7019,7 @@ F: include/uapi/linux/netfilter/
|
||||||
F: net/*/netfilter.c
|
F: net/*/netfilter.c
|
||||||
F: net/*/netfilter/
|
F: net/*/netfilter/
|
||||||
F: net/netfilter/
|
F: net/netfilter/
|
||||||
|
F: net/bridge/br_netfilter*.c
|
||||||
|
|
||||||
NETLABEL
|
NETLABEL
|
||||||
M: Paul Moore <paul@paul-moore.com>
|
M: Paul Moore <paul@paul-moore.com>
|
||||||
|
|
|
@ -686,7 +686,8 @@
|
||||||
|
|
||||||
&dcan1 {
|
&dcan1 {
|
||||||
status = "ok";
|
status = "ok";
|
||||||
pinctrl-names = "default", "sleep";
|
pinctrl-names = "default", "sleep", "active";
|
||||||
pinctrl-0 = <&dcan1_pins_default>;
|
pinctrl-0 = <&dcan1_pins_sleep>;
|
||||||
pinctrl-1 = <&dcan1_pins_sleep>;
|
pinctrl-1 = <&dcan1_pins_sleep>;
|
||||||
|
pinctrl-2 = <&dcan1_pins_default>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -587,9 +587,10 @@
|
||||||
|
|
||||||
&dcan1 {
|
&dcan1 {
|
||||||
status = "ok";
|
status = "ok";
|
||||||
pinctrl-names = "default", "sleep";
|
pinctrl-names = "default", "sleep", "active";
|
||||||
pinctrl-0 = <&dcan1_pins_default>;
|
pinctrl-0 = <&dcan1_pins_sleep>;
|
||||||
pinctrl-1 = <&dcan1_pins_sleep>;
|
pinctrl-1 = <&dcan1_pins_sleep>;
|
||||||
|
pinctrl-2 = <&dcan1_pins_default>;
|
||||||
};
|
};
|
||||||
|
|
||||||
&qspi {
|
&qspi {
|
||||||
|
|
|
@ -689,40 +689,57 @@ out:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bond_should_change_active(struct bonding *bond)
|
static struct slave *bond_choose_primary_or_current(struct bonding *bond)
|
||||||
{
|
{
|
||||||
struct slave *prim = rtnl_dereference(bond->primary_slave);
|
struct slave *prim = rtnl_dereference(bond->primary_slave);
|
||||||
struct slave *curr = rtnl_dereference(bond->curr_active_slave);
|
struct slave *curr = rtnl_dereference(bond->curr_active_slave);
|
||||||
|
|
||||||
if (!prim || !curr || curr->link != BOND_LINK_UP)
|
if (!prim || prim->link != BOND_LINK_UP) {
|
||||||
return true;
|
if (!curr || curr->link != BOND_LINK_UP)
|
||||||
|
return NULL;
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
if (bond->force_primary) {
|
if (bond->force_primary) {
|
||||||
bond->force_primary = false;
|
bond->force_primary = false;
|
||||||
return true;
|
return prim;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!curr || curr->link != BOND_LINK_UP)
|
||||||
|
return prim;
|
||||||
|
|
||||||
|
/* At this point, prim and curr are both up */
|
||||||
|
switch (bond->params.primary_reselect) {
|
||||||
|
case BOND_PRI_RESELECT_ALWAYS:
|
||||||
|
return prim;
|
||||||
|
case BOND_PRI_RESELECT_BETTER:
|
||||||
|
if (prim->speed < curr->speed)
|
||||||
|
return curr;
|
||||||
|
if (prim->speed == curr->speed && prim->duplex <= curr->duplex)
|
||||||
|
return curr;
|
||||||
|
return prim;
|
||||||
|
case BOND_PRI_RESELECT_FAILURE:
|
||||||
|
return curr;
|
||||||
|
default:
|
||||||
|
netdev_err(bond->dev, "impossible primary_reselect %d\n",
|
||||||
|
bond->params.primary_reselect);
|
||||||
|
return curr;
|
||||||
}
|
}
|
||||||
if (bond->params.primary_reselect == BOND_PRI_RESELECT_BETTER &&
|
|
||||||
(prim->speed < curr->speed ||
|
|
||||||
(prim->speed == curr->speed && prim->duplex <= curr->duplex)))
|
|
||||||
return false;
|
|
||||||
if (bond->params.primary_reselect == BOND_PRI_RESELECT_FAILURE)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find_best_interface - select the best available slave to be the active one
|
* bond_find_best_slave - select the best available slave to be the active one
|
||||||
* @bond: our bonding struct
|
* @bond: our bonding struct
|
||||||
*/
|
*/
|
||||||
static struct slave *bond_find_best_slave(struct bonding *bond)
|
static struct slave *bond_find_best_slave(struct bonding *bond)
|
||||||
{
|
{
|
||||||
struct slave *slave, *bestslave = NULL, *primary;
|
struct slave *slave, *bestslave = NULL;
|
||||||
struct list_head *iter;
|
struct list_head *iter;
|
||||||
int mintime = bond->params.updelay;
|
int mintime = bond->params.updelay;
|
||||||
|
|
||||||
primary = rtnl_dereference(bond->primary_slave);
|
slave = bond_choose_primary_or_current(bond);
|
||||||
if (primary && primary->link == BOND_LINK_UP &&
|
if (slave)
|
||||||
bond_should_change_active(bond))
|
return slave;
|
||||||
return primary;
|
|
||||||
|
|
||||||
bond_for_each_slave(bond, slave, iter) {
|
bond_for_each_slave(bond, slave, iter) {
|
||||||
if (slave->link == BOND_LINK_UP)
|
if (slave->link == BOND_LINK_UP)
|
||||||
|
|
|
@ -592,6 +592,7 @@ static int c_can_start(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct c_can_priv *priv = netdev_priv(dev);
|
struct c_can_priv *priv = netdev_priv(dev);
|
||||||
int err;
|
int err;
|
||||||
|
struct pinctrl *p;
|
||||||
|
|
||||||
/* basic c_can configuration */
|
/* basic c_can configuration */
|
||||||
err = c_can_chip_config(dev);
|
err = c_can_chip_config(dev);
|
||||||
|
@ -604,8 +605,13 @@ static int c_can_start(struct net_device *dev)
|
||||||
|
|
||||||
priv->can.state = CAN_STATE_ERROR_ACTIVE;
|
priv->can.state = CAN_STATE_ERROR_ACTIVE;
|
||||||
|
|
||||||
/* activate pins */
|
/* Attempt to use "active" if available else use "default" */
|
||||||
pinctrl_pm_select_default_state(dev->dev.parent);
|
p = pinctrl_get_select(priv->device, "active");
|
||||||
|
if (!IS_ERR(p))
|
||||||
|
pinctrl_put(p);
|
||||||
|
else
|
||||||
|
pinctrl_pm_select_default_state(priv->device);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -440,9 +440,6 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
|
||||||
struct can_frame *cf = (struct can_frame *)skb->data;
|
struct can_frame *cf = (struct can_frame *)skb->data;
|
||||||
u8 dlc = cf->can_dlc;
|
u8 dlc = cf->can_dlc;
|
||||||
|
|
||||||
if (!(skb->tstamp.tv64))
|
|
||||||
__net_timestamp(skb);
|
|
||||||
|
|
||||||
netif_rx(priv->echo_skb[idx]);
|
netif_rx(priv->echo_skb[idx]);
|
||||||
priv->echo_skb[idx] = NULL;
|
priv->echo_skb[idx] = NULL;
|
||||||
|
|
||||||
|
@ -578,7 +575,6 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
|
||||||
if (unlikely(!skb))
|
if (unlikely(!skb))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
__net_timestamp(skb);
|
|
||||||
skb->protocol = htons(ETH_P_CAN);
|
skb->protocol = htons(ETH_P_CAN);
|
||||||
skb->pkt_type = PACKET_BROADCAST;
|
skb->pkt_type = PACKET_BROADCAST;
|
||||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||||
|
@ -589,6 +585,7 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
|
||||||
|
|
||||||
can_skb_reserve(skb);
|
can_skb_reserve(skb);
|
||||||
can_skb_prv(skb)->ifindex = dev->ifindex;
|
can_skb_prv(skb)->ifindex = dev->ifindex;
|
||||||
|
can_skb_prv(skb)->skbcnt = 0;
|
||||||
|
|
||||||
*cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
|
*cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
|
||||||
memset(*cf, 0, sizeof(struct can_frame));
|
memset(*cf, 0, sizeof(struct can_frame));
|
||||||
|
@ -607,7 +604,6 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
|
||||||
if (unlikely(!skb))
|
if (unlikely(!skb))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
__net_timestamp(skb);
|
|
||||||
skb->protocol = htons(ETH_P_CANFD);
|
skb->protocol = htons(ETH_P_CANFD);
|
||||||
skb->pkt_type = PACKET_BROADCAST;
|
skb->pkt_type = PACKET_BROADCAST;
|
||||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||||
|
@ -618,6 +614,7 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
|
||||||
|
|
||||||
can_skb_reserve(skb);
|
can_skb_reserve(skb);
|
||||||
can_skb_prv(skb)->ifindex = dev->ifindex;
|
can_skb_prv(skb)->ifindex = dev->ifindex;
|
||||||
|
can_skb_prv(skb)->skbcnt = 0;
|
||||||
|
|
||||||
*cfd = (struct canfd_frame *)skb_put(skb, sizeof(struct canfd_frame));
|
*cfd = (struct canfd_frame *)skb_put(skb, sizeof(struct canfd_frame));
|
||||||
memset(*cfd, 0, sizeof(struct canfd_frame));
|
memset(*cfd, 0, sizeof(struct canfd_frame));
|
||||||
|
|
|
@ -508,7 +508,8 @@ static int rcar_can_open(struct net_device *ndev)
|
||||||
|
|
||||||
err = clk_prepare_enable(priv->clk);
|
err = clk_prepare_enable(priv->clk);
|
||||||
if (err) {
|
if (err) {
|
||||||
netdev_err(ndev, "failed to enable periperal clock, error %d\n",
|
netdev_err(ndev,
|
||||||
|
"failed to enable peripheral clock, error %d\n",
|
||||||
err);
|
err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -526,7 +527,8 @@ static int rcar_can_open(struct net_device *ndev)
|
||||||
napi_enable(&priv->napi);
|
napi_enable(&priv->napi);
|
||||||
err = request_irq(ndev->irq, rcar_can_interrupt, 0, ndev->name, ndev);
|
err = request_irq(ndev->irq, rcar_can_interrupt, 0, ndev->name, ndev);
|
||||||
if (err) {
|
if (err) {
|
||||||
netdev_err(ndev, "error requesting interrupt %x\n", ndev->irq);
|
netdev_err(ndev, "request_irq(%d) failed, error %d\n",
|
||||||
|
ndev->irq, err);
|
||||||
goto out_close;
|
goto out_close;
|
||||||
}
|
}
|
||||||
can_led_event(ndev, CAN_LED_EVENT_OPEN);
|
can_led_event(ndev, CAN_LED_EVENT_OPEN);
|
||||||
|
@ -758,8 +760,9 @@ static int rcar_can_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (!irq) {
|
if (irq < 0) {
|
||||||
dev_err(&pdev->dev, "No IRQ resource\n");
|
dev_err(&pdev->dev, "No IRQ resource\n");
|
||||||
|
err = irq;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,7 +785,8 @@ static int rcar_can_probe(struct platform_device *pdev)
|
||||||
priv->clk = devm_clk_get(&pdev->dev, "clkp1");
|
priv->clk = devm_clk_get(&pdev->dev, "clkp1");
|
||||||
if (IS_ERR(priv->clk)) {
|
if (IS_ERR(priv->clk)) {
|
||||||
err = PTR_ERR(priv->clk);
|
err = PTR_ERR(priv->clk);
|
||||||
dev_err(&pdev->dev, "cannot get peripheral clock: %d\n", err);
|
dev_err(&pdev->dev, "cannot get peripheral clock, error %d\n",
|
||||||
|
err);
|
||||||
goto fail_clk;
|
goto fail_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,7 +798,7 @@ static int rcar_can_probe(struct platform_device *pdev)
|
||||||
priv->can_clk = devm_clk_get(&pdev->dev, clock_names[clock_select]);
|
priv->can_clk = devm_clk_get(&pdev->dev, clock_names[clock_select]);
|
||||||
if (IS_ERR(priv->can_clk)) {
|
if (IS_ERR(priv->can_clk)) {
|
||||||
err = PTR_ERR(priv->can_clk);
|
err = PTR_ERR(priv->can_clk);
|
||||||
dev_err(&pdev->dev, "cannot get CAN clock: %d\n", err);
|
dev_err(&pdev->dev, "cannot get CAN clock, error %d\n", err);
|
||||||
goto fail_clk;
|
goto fail_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -823,7 +827,7 @@ static int rcar_can_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
devm_can_led_init(ndev);
|
devm_can_led_init(ndev);
|
||||||
|
|
||||||
dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%u)\n",
|
dev_info(&pdev->dev, "device registered (regs @ %p, IRQ%d)\n",
|
||||||
priv->regs, ndev->irq);
|
priv->regs, ndev->irq);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -207,7 +207,6 @@ static void slc_bump(struct slcan *sl)
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
__net_timestamp(skb);
|
|
||||||
skb->dev = sl->dev;
|
skb->dev = sl->dev;
|
||||||
skb->protocol = htons(ETH_P_CAN);
|
skb->protocol = htons(ETH_P_CAN);
|
||||||
skb->pkt_type = PACKET_BROADCAST;
|
skb->pkt_type = PACKET_BROADCAST;
|
||||||
|
@ -215,6 +214,7 @@ static void slc_bump(struct slcan *sl)
|
||||||
|
|
||||||
can_skb_reserve(skb);
|
can_skb_reserve(skb);
|
||||||
can_skb_prv(skb)->ifindex = sl->dev->ifindex;
|
can_skb_prv(skb)->ifindex = sl->dev->ifindex;
|
||||||
|
can_skb_prv(skb)->skbcnt = 0;
|
||||||
|
|
||||||
memcpy(skb_put(skb, sizeof(struct can_frame)),
|
memcpy(skb_put(skb, sizeof(struct can_frame)),
|
||||||
&cf, sizeof(struct can_frame));
|
&cf, sizeof(struct can_frame));
|
||||||
|
|
|
@ -78,9 +78,6 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
|
||||||
skb->dev = dev;
|
skb->dev = dev;
|
||||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||||
|
|
||||||
if (!(skb->tstamp.tv64))
|
|
||||||
__net_timestamp(skb);
|
|
||||||
|
|
||||||
netif_rx_ni(skb);
|
netif_rx_ni(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2382,6 +2382,7 @@ boomerang_interrupt(int irq, void *dev_id)
|
||||||
void __iomem *ioaddr;
|
void __iomem *ioaddr;
|
||||||
int status;
|
int status;
|
||||||
int work_done = max_interrupt_work;
|
int work_done = max_interrupt_work;
|
||||||
|
int handled = 0;
|
||||||
|
|
||||||
ioaddr = vp->ioaddr;
|
ioaddr = vp->ioaddr;
|
||||||
|
|
||||||
|
@ -2400,6 +2401,7 @@ boomerang_interrupt(int irq, void *dev_id)
|
||||||
|
|
||||||
if ((status & IntLatch) == 0)
|
if ((status & IntLatch) == 0)
|
||||||
goto handler_exit; /* No interrupt: shared IRQs can cause this */
|
goto handler_exit; /* No interrupt: shared IRQs can cause this */
|
||||||
|
handled = 1;
|
||||||
|
|
||||||
if (status == 0xffff) { /* h/w no longer present (hotplug)? */
|
if (status == 0xffff) { /* h/w no longer present (hotplug)? */
|
||||||
if (vortex_debug > 1)
|
if (vortex_debug > 1)
|
||||||
|
@ -2501,7 +2503,7 @@ boomerang_interrupt(int irq, void *dev_id)
|
||||||
handler_exit:
|
handler_exit:
|
||||||
vp->handling_irq = 0;
|
vp->handling_irq = 0;
|
||||||
spin_unlock(&vp->lock);
|
spin_unlock(&vp->lock);
|
||||||
return IRQ_HANDLED;
|
return IRQ_RETVAL(handled);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vortex_rx(struct net_device *dev)
|
static int vortex_rx(struct net_device *dev)
|
||||||
|
|
|
@ -303,7 +303,8 @@ static void xgbe_set_buffer_data(struct xgbe_buffer_data *bd,
|
||||||
get_page(pa->pages);
|
get_page(pa->pages);
|
||||||
bd->pa = *pa;
|
bd->pa = *pa;
|
||||||
|
|
||||||
bd->dma = pa->pages_dma + pa->pages_offset;
|
bd->dma_base = pa->pages_dma;
|
||||||
|
bd->dma_off = pa->pages_offset;
|
||||||
bd->dma_len = len;
|
bd->dma_len = len;
|
||||||
|
|
||||||
pa->pages_offset += len;
|
pa->pages_offset += len;
|
||||||
|
|
|
@ -1110,6 +1110,7 @@ static void xgbe_rx_desc_reset(struct xgbe_prv_data *pdata,
|
||||||
unsigned int rx_usecs = pdata->rx_usecs;
|
unsigned int rx_usecs = pdata->rx_usecs;
|
||||||
unsigned int rx_frames = pdata->rx_frames;
|
unsigned int rx_frames = pdata->rx_frames;
|
||||||
unsigned int inte;
|
unsigned int inte;
|
||||||
|
dma_addr_t hdr_dma, buf_dma;
|
||||||
|
|
||||||
if (!rx_usecs && !rx_frames) {
|
if (!rx_usecs && !rx_frames) {
|
||||||
/* No coalescing, interrupt for every descriptor */
|
/* No coalescing, interrupt for every descriptor */
|
||||||
|
@ -1129,10 +1130,12 @@ static void xgbe_rx_desc_reset(struct xgbe_prv_data *pdata,
|
||||||
* Set buffer 2 (hi) address to buffer dma address (hi) and
|
* Set buffer 2 (hi) address to buffer dma address (hi) and
|
||||||
* set control bits OWN and INTE
|
* set control bits OWN and INTE
|
||||||
*/
|
*/
|
||||||
rdesc->desc0 = cpu_to_le32(lower_32_bits(rdata->rx.hdr.dma));
|
hdr_dma = rdata->rx.hdr.dma_base + rdata->rx.hdr.dma_off;
|
||||||
rdesc->desc1 = cpu_to_le32(upper_32_bits(rdata->rx.hdr.dma));
|
buf_dma = rdata->rx.buf.dma_base + rdata->rx.buf.dma_off;
|
||||||
rdesc->desc2 = cpu_to_le32(lower_32_bits(rdata->rx.buf.dma));
|
rdesc->desc0 = cpu_to_le32(lower_32_bits(hdr_dma));
|
||||||
rdesc->desc3 = cpu_to_le32(upper_32_bits(rdata->rx.buf.dma));
|
rdesc->desc1 = cpu_to_le32(upper_32_bits(hdr_dma));
|
||||||
|
rdesc->desc2 = cpu_to_le32(lower_32_bits(buf_dma));
|
||||||
|
rdesc->desc3 = cpu_to_le32(upper_32_bits(buf_dma));
|
||||||
|
|
||||||
XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, inte);
|
XGMAC_SET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, INTE, inte);
|
||||||
|
|
||||||
|
|
|
@ -1765,8 +1765,9 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata,
|
||||||
/* Start with the header buffer which may contain just the header
|
/* Start with the header buffer which may contain just the header
|
||||||
* or the header plus data
|
* or the header plus data
|
||||||
*/
|
*/
|
||||||
dma_sync_single_for_cpu(pdata->dev, rdata->rx.hdr.dma,
|
dma_sync_single_range_for_cpu(pdata->dev, rdata->rx.hdr.dma_base,
|
||||||
rdata->rx.hdr.dma_len, DMA_FROM_DEVICE);
|
rdata->rx.hdr.dma_off,
|
||||||
|
rdata->rx.hdr.dma_len, DMA_FROM_DEVICE);
|
||||||
|
|
||||||
packet = page_address(rdata->rx.hdr.pa.pages) +
|
packet = page_address(rdata->rx.hdr.pa.pages) +
|
||||||
rdata->rx.hdr.pa.pages_offset;
|
rdata->rx.hdr.pa.pages_offset;
|
||||||
|
@ -1778,8 +1779,11 @@ static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata,
|
||||||
len -= copy_len;
|
len -= copy_len;
|
||||||
if (len) {
|
if (len) {
|
||||||
/* Add the remaining data as a frag */
|
/* Add the remaining data as a frag */
|
||||||
dma_sync_single_for_cpu(pdata->dev, rdata->rx.buf.dma,
|
dma_sync_single_range_for_cpu(pdata->dev,
|
||||||
rdata->rx.buf.dma_len, DMA_FROM_DEVICE);
|
rdata->rx.buf.dma_base,
|
||||||
|
rdata->rx.buf.dma_off,
|
||||||
|
rdata->rx.buf.dma_len,
|
||||||
|
DMA_FROM_DEVICE);
|
||||||
|
|
||||||
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
|
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
|
||||||
rdata->rx.buf.pa.pages,
|
rdata->rx.buf.pa.pages,
|
||||||
|
@ -1945,8 +1949,9 @@ read_again:
|
||||||
if (!skb)
|
if (!skb)
|
||||||
error = 1;
|
error = 1;
|
||||||
} else if (rdesc_len) {
|
} else if (rdesc_len) {
|
||||||
dma_sync_single_for_cpu(pdata->dev,
|
dma_sync_single_range_for_cpu(pdata->dev,
|
||||||
rdata->rx.buf.dma,
|
rdata->rx.buf.dma_base,
|
||||||
|
rdata->rx.buf.dma_off,
|
||||||
rdata->rx.buf.dma_len,
|
rdata->rx.buf.dma_len,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
|
|
||||||
|
|
|
@ -337,7 +337,8 @@ struct xgbe_buffer_data {
|
||||||
struct xgbe_page_alloc pa;
|
struct xgbe_page_alloc pa;
|
||||||
struct xgbe_page_alloc pa_unmap;
|
struct xgbe_page_alloc pa_unmap;
|
||||||
|
|
||||||
dma_addr_t dma;
|
dma_addr_t dma_base;
|
||||||
|
unsigned long dma_off;
|
||||||
unsigned int dma_len;
|
unsigned int dma_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1793,7 +1793,7 @@ static int bcm_sysport_probe(struct platform_device *pdev)
|
||||||
macaddr = of_get_mac_address(dn);
|
macaddr = of_get_mac_address(dn);
|
||||||
if (!macaddr || !is_valid_ether_addr(macaddr)) {
|
if (!macaddr || !is_valid_ether_addr(macaddr)) {
|
||||||
dev_warn(&pdev->dev, "using random Ethernet MAC\n");
|
dev_warn(&pdev->dev, "using random Ethernet MAC\n");
|
||||||
random_ether_addr(dev->dev_addr);
|
eth_hw_addr_random(dev);
|
||||||
} else {
|
} else {
|
||||||
ether_addr_copy(dev->dev_addr, macaddr);
|
ether_addr_copy(dev->dev_addr, macaddr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1230,7 +1230,6 @@ static struct sk_buff *bcmgenet_put_tx_csum(struct net_device *dev,
|
||||||
new_skb = skb_realloc_headroom(skb, sizeof(*status));
|
new_skb = skb_realloc_headroom(skb, sizeof(*status));
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
if (!new_skb) {
|
if (!new_skb) {
|
||||||
dev->stats.tx_errors++;
|
|
||||||
dev->stats.tx_dropped++;
|
dev->stats.tx_dropped++;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1465,7 +1464,6 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
|
||||||
|
|
||||||
if (unlikely(!skb)) {
|
if (unlikely(!skb)) {
|
||||||
dev->stats.rx_dropped++;
|
dev->stats.rx_dropped++;
|
||||||
dev->stats.rx_errors++;
|
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1493,7 +1491,6 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
|
||||||
if (unlikely(!(dma_flag & DMA_EOP) || !(dma_flag & DMA_SOP))) {
|
if (unlikely(!(dma_flag & DMA_EOP) || !(dma_flag & DMA_SOP))) {
|
||||||
netif_err(priv, rx_status, dev,
|
netif_err(priv, rx_status, dev,
|
||||||
"dropping fragmented packet!\n");
|
"dropping fragmented packet!\n");
|
||||||
dev->stats.rx_dropped++;
|
|
||||||
dev->stats.rx_errors++;
|
dev->stats.rx_errors++;
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
goto next;
|
goto next;
|
||||||
|
@ -1515,7 +1512,6 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
|
||||||
dev->stats.rx_frame_errors++;
|
dev->stats.rx_frame_errors++;
|
||||||
if (dma_flag & DMA_RX_LG)
|
if (dma_flag & DMA_RX_LG)
|
||||||
dev->stats.rx_length_errors++;
|
dev->stats.rx_length_errors++;
|
||||||
dev->stats.rx_dropped++;
|
|
||||||
dev->stats.rx_errors++;
|
dev->stats.rx_errors++;
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
goto next;
|
goto next;
|
||||||
|
|
|
@ -952,16 +952,23 @@ static int devlog_show(struct seq_file *seq, void *v)
|
||||||
* eventually have to put a format interpreter in here ...
|
* eventually have to put a format interpreter in here ...
|
||||||
*/
|
*/
|
||||||
seq_printf(seq, "%10d %15llu %8s %8s ",
|
seq_printf(seq, "%10d %15llu %8s %8s ",
|
||||||
e->seqno, e->timestamp,
|
be32_to_cpu(e->seqno),
|
||||||
|
be64_to_cpu(e->timestamp),
|
||||||
(e->level < ARRAY_SIZE(devlog_level_strings)
|
(e->level < ARRAY_SIZE(devlog_level_strings)
|
||||||
? devlog_level_strings[e->level]
|
? devlog_level_strings[e->level]
|
||||||
: "UNKNOWN"),
|
: "UNKNOWN"),
|
||||||
(e->facility < ARRAY_SIZE(devlog_facility_strings)
|
(e->facility < ARRAY_SIZE(devlog_facility_strings)
|
||||||
? devlog_facility_strings[e->facility]
|
? devlog_facility_strings[e->facility]
|
||||||
: "UNKNOWN"));
|
: "UNKNOWN"));
|
||||||
seq_printf(seq, e->fmt, e->params[0], e->params[1],
|
seq_printf(seq, e->fmt,
|
||||||
e->params[2], e->params[3], e->params[4],
|
be32_to_cpu(e->params[0]),
|
||||||
e->params[5], e->params[6], e->params[7]);
|
be32_to_cpu(e->params[1]),
|
||||||
|
be32_to_cpu(e->params[2]),
|
||||||
|
be32_to_cpu(e->params[3]),
|
||||||
|
be32_to_cpu(e->params[4]),
|
||||||
|
be32_to_cpu(e->params[5]),
|
||||||
|
be32_to_cpu(e->params[6]),
|
||||||
|
be32_to_cpu(e->params[7]));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1043,23 +1050,17 @@ static int devlog_open(struct inode *inode, struct file *file)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Translate log multi-byte integral elements into host native format
|
/* Find the earliest (lowest Sequence Number) log entry in the
|
||||||
* and determine where the first entry in the log is.
|
* circular Device Log.
|
||||||
*/
|
*/
|
||||||
for (fseqno = ~((u32)0), index = 0; index < dinfo->nentries; index++) {
|
for (fseqno = ~((u32)0), index = 0; index < dinfo->nentries; index++) {
|
||||||
struct fw_devlog_e *e = &dinfo->log[index];
|
struct fw_devlog_e *e = &dinfo->log[index];
|
||||||
int i;
|
|
||||||
__u32 seqno;
|
__u32 seqno;
|
||||||
|
|
||||||
if (e->timestamp == 0)
|
if (e->timestamp == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
e->timestamp = (__force __be64)be64_to_cpu(e->timestamp);
|
|
||||||
seqno = be32_to_cpu(e->seqno);
|
seqno = be32_to_cpu(e->seqno);
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
e->params[i] =
|
|
||||||
(__force __be32)be32_to_cpu(e->params[i]);
|
|
||||||
|
|
||||||
if (seqno < fseqno) {
|
if (seqno < fseqno) {
|
||||||
fseqno = seqno;
|
fseqno = seqno;
|
||||||
dinfo->first = index;
|
dinfo->first = index;
|
||||||
|
|
|
@ -1170,7 +1170,7 @@ static int enic_poll(struct napi_struct *napi, int budget)
|
||||||
wq_work_done,
|
wq_work_done,
|
||||||
0 /* dont unmask intr */,
|
0 /* dont unmask intr */,
|
||||||
0 /* dont reset intr timer */);
|
0 /* dont reset intr timer */);
|
||||||
return rq_work_done;
|
return budget;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (budget > 0)
|
if (budget > 0)
|
||||||
|
@ -1191,6 +1191,7 @@ static int enic_poll(struct napi_struct *napi, int budget)
|
||||||
0 /* don't reset intr timer */);
|
0 /* don't reset intr timer */);
|
||||||
|
|
||||||
err = vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
|
err = vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
|
||||||
|
enic_poll_unlock_napi(&enic->rq[cq_rq], napi);
|
||||||
|
|
||||||
/* Buffer allocation failed. Stay in polling
|
/* Buffer allocation failed. Stay in polling
|
||||||
* mode so we can try to fill the ring again.
|
* mode so we can try to fill the ring again.
|
||||||
|
@ -1208,7 +1209,6 @@ static int enic_poll(struct napi_struct *napi, int budget)
|
||||||
napi_complete(napi);
|
napi_complete(napi);
|
||||||
vnic_intr_unmask(&enic->intr[intr]);
|
vnic_intr_unmask(&enic->intr[intr]);
|
||||||
}
|
}
|
||||||
enic_poll_unlock_napi(&enic->rq[cq_rq], napi);
|
|
||||||
|
|
||||||
return rq_work_done;
|
return rq_work_done;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
|
@ -77,6 +78,7 @@ static void fec_enet_itr_coal_init(struct net_device *ndev);
|
||||||
#define FEC_ENET_RAEM_V 0x8
|
#define FEC_ENET_RAEM_V 0x8
|
||||||
#define FEC_ENET_RAFL_V 0x8
|
#define FEC_ENET_RAFL_V 0x8
|
||||||
#define FEC_ENET_OPD_V 0xFFF0
|
#define FEC_ENET_OPD_V 0xFFF0
|
||||||
|
#define FEC_MDIO_PM_TIMEOUT 100 /* ms */
|
||||||
|
|
||||||
static struct platform_device_id fec_devtype[] = {
|
static struct platform_device_id fec_devtype[] = {
|
||||||
{
|
{
|
||||||
|
@ -1767,7 +1769,13 @@ static void fec_enet_adjust_link(struct net_device *ndev)
|
||||||
static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
|
static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
|
||||||
{
|
{
|
||||||
struct fec_enet_private *fep = bus->priv;
|
struct fec_enet_private *fep = bus->priv;
|
||||||
|
struct device *dev = &fep->pdev->dev;
|
||||||
unsigned long time_left;
|
unsigned long time_left;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = pm_runtime_get_sync(dev);
|
||||||
|
if (IS_ERR_VALUE(ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
fep->mii_timeout = 0;
|
fep->mii_timeout = 0;
|
||||||
init_completion(&fep->mdio_done);
|
init_completion(&fep->mdio_done);
|
||||||
|
@ -1783,18 +1791,30 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
|
||||||
if (time_left == 0) {
|
if (time_left == 0) {
|
||||||
fep->mii_timeout = 1;
|
fep->mii_timeout = 1;
|
||||||
netdev_err(fep->netdev, "MDIO read timeout\n");
|
netdev_err(fep->netdev, "MDIO read timeout\n");
|
||||||
return -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return value */
|
ret = FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA));
|
||||||
return FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA));
|
|
||||||
|
out:
|
||||||
|
pm_runtime_mark_last_busy(dev);
|
||||||
|
pm_runtime_put_autosuspend(dev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
|
static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
|
||||||
u16 value)
|
u16 value)
|
||||||
{
|
{
|
||||||
struct fec_enet_private *fep = bus->priv;
|
struct fec_enet_private *fep = bus->priv;
|
||||||
|
struct device *dev = &fep->pdev->dev;
|
||||||
unsigned long time_left;
|
unsigned long time_left;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = pm_runtime_get_sync(dev);
|
||||||
|
if (IS_ERR_VALUE(ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
fep->mii_timeout = 0;
|
fep->mii_timeout = 0;
|
||||||
init_completion(&fep->mdio_done);
|
init_completion(&fep->mdio_done);
|
||||||
|
@ -1811,10 +1831,13 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
|
||||||
if (time_left == 0) {
|
if (time_left == 0) {
|
||||||
fep->mii_timeout = 1;
|
fep->mii_timeout = 1;
|
||||||
netdev_err(fep->netdev, "MDIO write timeout\n");
|
netdev_err(fep->netdev, "MDIO write timeout\n");
|
||||||
return -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
pm_runtime_mark_last_busy(dev);
|
||||||
|
pm_runtime_put_autosuspend(dev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
|
static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
|
||||||
|
@ -1826,9 +1849,6 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
|
||||||
ret = clk_prepare_enable(fep->clk_ahb);
|
ret = clk_prepare_enable(fep->clk_ahb);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
ret = clk_prepare_enable(fep->clk_ipg);
|
|
||||||
if (ret)
|
|
||||||
goto failed_clk_ipg;
|
|
||||||
if (fep->clk_enet_out) {
|
if (fep->clk_enet_out) {
|
||||||
ret = clk_prepare_enable(fep->clk_enet_out);
|
ret = clk_prepare_enable(fep->clk_enet_out);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -1852,7 +1872,6 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
clk_disable_unprepare(fep->clk_ahb);
|
clk_disable_unprepare(fep->clk_ahb);
|
||||||
clk_disable_unprepare(fep->clk_ipg);
|
|
||||||
if (fep->clk_enet_out)
|
if (fep->clk_enet_out)
|
||||||
clk_disable_unprepare(fep->clk_enet_out);
|
clk_disable_unprepare(fep->clk_enet_out);
|
||||||
if (fep->clk_ptp) {
|
if (fep->clk_ptp) {
|
||||||
|
@ -1874,8 +1893,6 @@ failed_clk_ptp:
|
||||||
if (fep->clk_enet_out)
|
if (fep->clk_enet_out)
|
||||||
clk_disable_unprepare(fep->clk_enet_out);
|
clk_disable_unprepare(fep->clk_enet_out);
|
||||||
failed_clk_enet_out:
|
failed_clk_enet_out:
|
||||||
clk_disable_unprepare(fep->clk_ipg);
|
|
||||||
failed_clk_ipg:
|
|
||||||
clk_disable_unprepare(fep->clk_ahb);
|
clk_disable_unprepare(fep->clk_ahb);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2847,10 +2864,14 @@ fec_enet_open(struct net_device *ndev)
|
||||||
struct fec_enet_private *fep = netdev_priv(ndev);
|
struct fec_enet_private *fep = netdev_priv(ndev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
ret = pm_runtime_get_sync(&fep->pdev->dev);
|
||||||
|
if (IS_ERR_VALUE(ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
pinctrl_pm_select_default_state(&fep->pdev->dev);
|
pinctrl_pm_select_default_state(&fep->pdev->dev);
|
||||||
ret = fec_enet_clk_enable(ndev, true);
|
ret = fec_enet_clk_enable(ndev, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto clk_enable;
|
||||||
|
|
||||||
/* I should reset the ring buffers here, but I don't yet know
|
/* I should reset the ring buffers here, but I don't yet know
|
||||||
* a simple way to do that.
|
* a simple way to do that.
|
||||||
|
@ -2881,6 +2902,9 @@ err_enet_mii_probe:
|
||||||
fec_enet_free_buffers(ndev);
|
fec_enet_free_buffers(ndev);
|
||||||
err_enet_alloc:
|
err_enet_alloc:
|
||||||
fec_enet_clk_enable(ndev, false);
|
fec_enet_clk_enable(ndev, false);
|
||||||
|
clk_enable:
|
||||||
|
pm_runtime_mark_last_busy(&fep->pdev->dev);
|
||||||
|
pm_runtime_put_autosuspend(&fep->pdev->dev);
|
||||||
pinctrl_pm_select_sleep_state(&fep->pdev->dev);
|
pinctrl_pm_select_sleep_state(&fep->pdev->dev);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2903,6 +2927,9 @@ fec_enet_close(struct net_device *ndev)
|
||||||
|
|
||||||
fec_enet_clk_enable(ndev, false);
|
fec_enet_clk_enable(ndev, false);
|
||||||
pinctrl_pm_select_sleep_state(&fep->pdev->dev);
|
pinctrl_pm_select_sleep_state(&fep->pdev->dev);
|
||||||
|
pm_runtime_mark_last_busy(&fep->pdev->dev);
|
||||||
|
pm_runtime_put_autosuspend(&fep->pdev->dev);
|
||||||
|
|
||||||
fec_enet_free_buffers(ndev);
|
fec_enet_free_buffers(ndev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3388,6 +3415,10 @@ fec_probe(struct platform_device *pdev)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto failed_clk;
|
goto failed_clk;
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(fep->clk_ipg);
|
||||||
|
if (ret)
|
||||||
|
goto failed_clk_ipg;
|
||||||
|
|
||||||
fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
|
fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
|
||||||
if (!IS_ERR(fep->reg_phy)) {
|
if (!IS_ERR(fep->reg_phy)) {
|
||||||
ret = regulator_enable(fep->reg_phy);
|
ret = regulator_enable(fep->reg_phy);
|
||||||
|
@ -3434,6 +3465,8 @@ fec_probe(struct platform_device *pdev)
|
||||||
netif_carrier_off(ndev);
|
netif_carrier_off(ndev);
|
||||||
fec_enet_clk_enable(ndev, false);
|
fec_enet_clk_enable(ndev, false);
|
||||||
pinctrl_pm_select_sleep_state(&pdev->dev);
|
pinctrl_pm_select_sleep_state(&pdev->dev);
|
||||||
|
pm_runtime_set_active(&pdev->dev);
|
||||||
|
pm_runtime_enable(&pdev->dev);
|
||||||
|
|
||||||
ret = register_netdev(ndev);
|
ret = register_netdev(ndev);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -3447,6 +3480,12 @@ fec_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
fep->rx_copybreak = COPYBREAK_DEFAULT;
|
fep->rx_copybreak = COPYBREAK_DEFAULT;
|
||||||
INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work);
|
INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work);
|
||||||
|
|
||||||
|
pm_runtime_set_autosuspend_delay(&pdev->dev, FEC_MDIO_PM_TIMEOUT);
|
||||||
|
pm_runtime_use_autosuspend(&pdev->dev);
|
||||||
|
pm_runtime_mark_last_busy(&pdev->dev);
|
||||||
|
pm_runtime_put_autosuspend(&pdev->dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed_register:
|
failed_register:
|
||||||
|
@ -3457,6 +3496,8 @@ failed_init:
|
||||||
if (fep->reg_phy)
|
if (fep->reg_phy)
|
||||||
regulator_disable(fep->reg_phy);
|
regulator_disable(fep->reg_phy);
|
||||||
failed_regulator:
|
failed_regulator:
|
||||||
|
clk_disable_unprepare(fep->clk_ipg);
|
||||||
|
failed_clk_ipg:
|
||||||
fec_enet_clk_enable(ndev, false);
|
fec_enet_clk_enable(ndev, false);
|
||||||
failed_clk:
|
failed_clk:
|
||||||
failed_phy:
|
failed_phy:
|
||||||
|
@ -3568,7 +3609,28 @@ failed_clk:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SIMPLE_DEV_PM_OPS(fec_pm_ops, fec_suspend, fec_resume);
|
static int __maybe_unused fec_runtime_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct net_device *ndev = dev_get_drvdata(dev);
|
||||||
|
struct fec_enet_private *fep = netdev_priv(ndev);
|
||||||
|
|
||||||
|
clk_disable_unprepare(fep->clk_ipg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __maybe_unused fec_runtime_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct net_device *ndev = dev_get_drvdata(dev);
|
||||||
|
struct fec_enet_private *fep = netdev_priv(ndev);
|
||||||
|
|
||||||
|
return clk_prepare_enable(fep->clk_ipg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dev_pm_ops fec_pm_ops = {
|
||||||
|
SET_SYSTEM_SLEEP_PM_OPS(fec_suspend, fec_resume)
|
||||||
|
SET_RUNTIME_PM_OPS(fec_runtime_suspend, fec_runtime_resume, NULL)
|
||||||
|
};
|
||||||
|
|
||||||
static struct platform_driver fec_driver = {
|
static struct platform_driver fec_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
|
|
|
@ -101,6 +101,11 @@ static unsigned int efx_ef10_mem_map_size(struct efx_nic *efx)
|
||||||
return resource_size(&efx->pci_dev->resource[bar]);
|
return resource_size(&efx->pci_dev->resource[bar]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool efx_ef10_is_vf(struct efx_nic *efx)
|
||||||
|
{
|
||||||
|
return efx->type->is_vf;
|
||||||
|
}
|
||||||
|
|
||||||
static int efx_ef10_get_pf_index(struct efx_nic *efx)
|
static int efx_ef10_get_pf_index(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_FUNCTION_INFO_OUT_LEN);
|
MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_FUNCTION_INFO_OUT_LEN);
|
||||||
|
@ -677,6 +682,48 @@ static int efx_ef10_probe_pf(struct efx_nic *efx)
|
||||||
return efx_ef10_probe(efx);
|
return efx_ef10_probe(efx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id)
|
||||||
|
{
|
||||||
|
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_ALLOC_IN_LEN);
|
||||||
|
|
||||||
|
MCDI_SET_DWORD(inbuf, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
|
||||||
|
return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_ALLOC, inbuf, sizeof(inbuf),
|
||||||
|
NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id)
|
||||||
|
{
|
||||||
|
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_FREE_IN_LEN);
|
||||||
|
|
||||||
|
MCDI_SET_DWORD(inbuf, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
|
||||||
|
return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_FREE, inbuf, sizeof(inbuf),
|
||||||
|
NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int efx_ef10_vport_add_mac(struct efx_nic *efx,
|
||||||
|
unsigned int port_id, u8 *mac)
|
||||||
|
{
|
||||||
|
MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN);
|
||||||
|
|
||||||
|
MCDI_SET_DWORD(inbuf, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, port_id);
|
||||||
|
ether_addr_copy(MCDI_PTR(inbuf, VPORT_ADD_MAC_ADDRESS_IN_MACADDR), mac);
|
||||||
|
|
||||||
|
return efx_mcdi_rpc(efx, MC_CMD_VPORT_ADD_MAC_ADDRESS, inbuf,
|
||||||
|
sizeof(inbuf), NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int efx_ef10_vport_del_mac(struct efx_nic *efx,
|
||||||
|
unsigned int port_id, u8 *mac)
|
||||||
|
{
|
||||||
|
MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN);
|
||||||
|
|
||||||
|
MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id);
|
||||||
|
ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac);
|
||||||
|
|
||||||
|
return efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf,
|
||||||
|
sizeof(inbuf), NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SFC_SRIOV
|
#ifdef CONFIG_SFC_SRIOV
|
||||||
static int efx_ef10_probe_vf(struct efx_nic *efx)
|
static int efx_ef10_probe_vf(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
|
@ -3804,6 +3851,72 @@ static void efx_ef10_filter_sync_rx_mode(struct efx_nic *efx)
|
||||||
WARN_ON(remove_failed);
|
WARN_ON(remove_failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)
|
||||||
|
{
|
||||||
|
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
||||||
|
u8 mac_old[ETH_ALEN];
|
||||||
|
int rc, rc2;
|
||||||
|
|
||||||
|
/* Only reconfigure a PF-created vport */
|
||||||
|
if (is_zero_ether_addr(nic_data->vport_mac))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
efx_device_detach_sync(efx);
|
||||||
|
efx_net_stop(efx->net_dev);
|
||||||
|
down_write(&efx->filter_sem);
|
||||||
|
efx_ef10_filter_table_remove(efx);
|
||||||
|
up_write(&efx->filter_sem);
|
||||||
|
|
||||||
|
rc = efx_ef10_vadaptor_free(efx, nic_data->vport_id);
|
||||||
|
if (rc)
|
||||||
|
goto restore_filters;
|
||||||
|
|
||||||
|
ether_addr_copy(mac_old, nic_data->vport_mac);
|
||||||
|
rc = efx_ef10_vport_del_mac(efx, nic_data->vport_id,
|
||||||
|
nic_data->vport_mac);
|
||||||
|
if (rc)
|
||||||
|
goto restore_vadaptor;
|
||||||
|
|
||||||
|
rc = efx_ef10_vport_add_mac(efx, nic_data->vport_id,
|
||||||
|
efx->net_dev->dev_addr);
|
||||||
|
if (!rc) {
|
||||||
|
ether_addr_copy(nic_data->vport_mac, efx->net_dev->dev_addr);
|
||||||
|
} else {
|
||||||
|
rc2 = efx_ef10_vport_add_mac(efx, nic_data->vport_id, mac_old);
|
||||||
|
if (rc2) {
|
||||||
|
/* Failed to add original MAC, so clear vport_mac */
|
||||||
|
eth_zero_addr(nic_data->vport_mac);
|
||||||
|
goto reset_nic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_vadaptor:
|
||||||
|
rc2 = efx_ef10_vadaptor_alloc(efx, nic_data->vport_id);
|
||||||
|
if (rc2)
|
||||||
|
goto reset_nic;
|
||||||
|
restore_filters:
|
||||||
|
down_write(&efx->filter_sem);
|
||||||
|
rc2 = efx_ef10_filter_table_probe(efx);
|
||||||
|
up_write(&efx->filter_sem);
|
||||||
|
if (rc2)
|
||||||
|
goto reset_nic;
|
||||||
|
|
||||||
|
rc2 = efx_net_open(efx->net_dev);
|
||||||
|
if (rc2)
|
||||||
|
goto reset_nic;
|
||||||
|
|
||||||
|
netif_device_attach(efx->net_dev);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
reset_nic:
|
||||||
|
netif_err(efx, drv, efx->net_dev,
|
||||||
|
"Failed to restore when changing MAC address - scheduling reset\n");
|
||||||
|
efx_schedule_reset(efx, RESET_TYPE_DATAPATH);
|
||||||
|
|
||||||
|
return rc ? rc : rc2;
|
||||||
|
}
|
||||||
|
|
||||||
static int efx_ef10_set_mac_address(struct efx_nic *efx)
|
static int efx_ef10_set_mac_address(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_SET_MAC_IN_LEN);
|
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_SET_MAC_IN_LEN);
|
||||||
|
@ -3820,8 +3933,8 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
|
||||||
efx->net_dev->dev_addr);
|
efx->net_dev->dev_addr);
|
||||||
MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID,
|
MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID,
|
||||||
nic_data->vport_id);
|
nic_data->vport_id);
|
||||||
rc = efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf,
|
rc = efx_mcdi_rpc_quiet(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf,
|
||||||
sizeof(inbuf), NULL, 0, NULL);
|
sizeof(inbuf), NULL, 0, NULL);
|
||||||
|
|
||||||
efx_ef10_filter_table_probe(efx);
|
efx_ef10_filter_table_probe(efx);
|
||||||
up_write(&efx->filter_sem);
|
up_write(&efx->filter_sem);
|
||||||
|
@ -3829,38 +3942,27 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
|
||||||
efx_net_open(efx->net_dev);
|
efx_net_open(efx->net_dev);
|
||||||
netif_device_attach(efx->net_dev);
|
netif_device_attach(efx->net_dev);
|
||||||
|
|
||||||
#if !defined(CONFIG_SFC_SRIOV)
|
#ifdef CONFIG_SFC_SRIOV
|
||||||
if (rc == -EPERM)
|
if (efx->pci_dev->is_virtfn && efx->pci_dev->physfn) {
|
||||||
netif_err(efx, drv, efx->net_dev,
|
|
||||||
"Cannot change MAC address; use sfboot to enable mac-spoofing"
|
|
||||||
" on this interface\n");
|
|
||||||
#else
|
|
||||||
if (rc == -EPERM) {
|
|
||||||
struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;
|
struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;
|
||||||
|
|
||||||
/* Switch to PF and change MAC address on vport */
|
if (rc == -EPERM) {
|
||||||
if (efx->pci_dev->is_virtfn && pci_dev_pf) {
|
struct efx_nic *efx_pf;
|
||||||
struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
|
|
||||||
|
|
||||||
if (!efx_ef10_sriov_set_vf_mac(efx_pf,
|
/* Switch to PF and change MAC address on vport */
|
||||||
|
efx_pf = pci_get_drvdata(pci_dev_pf);
|
||||||
|
|
||||||
|
rc = efx_ef10_sriov_set_vf_mac(efx_pf,
|
||||||
nic_data->vf_index,
|
nic_data->vf_index,
|
||||||
efx->net_dev->dev_addr))
|
efx->net_dev->dev_addr);
|
||||||
return 0;
|
} else if (!rc) {
|
||||||
}
|
|
||||||
netif_err(efx, drv, efx->net_dev,
|
|
||||||
"Cannot change MAC address; use sfboot to enable mac-spoofing"
|
|
||||||
" on this interface\n");
|
|
||||||
} else if (efx->pci_dev->is_virtfn) {
|
|
||||||
/* Successfully changed by VF (with MAC spoofing), so update the
|
|
||||||
* parent PF if possible.
|
|
||||||
*/
|
|
||||||
struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;
|
|
||||||
|
|
||||||
if (pci_dev_pf) {
|
|
||||||
struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
|
struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
|
||||||
struct efx_ef10_nic_data *nic_data = efx_pf->nic_data;
|
struct efx_ef10_nic_data *nic_data = efx_pf->nic_data;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
/* MAC address successfully changed by VF (with MAC
|
||||||
|
* spoofing) so update the parent PF if possible.
|
||||||
|
*/
|
||||||
for (i = 0; i < efx_pf->vf_count; ++i) {
|
for (i = 0; i < efx_pf->vf_count; ++i) {
|
||||||
struct ef10_vf *vf = nic_data->vf + i;
|
struct ef10_vf *vf = nic_data->vf + i;
|
||||||
|
|
||||||
|
@ -3871,8 +3973,24 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
if (rc == -EPERM) {
|
||||||
|
netif_err(efx, drv, efx->net_dev,
|
||||||
|
"Cannot change MAC address; use sfboot to enable"
|
||||||
|
" mac-spoofing on this interface\n");
|
||||||
|
} else if (rc == -ENOSYS && !efx_ef10_is_vf(efx)) {
|
||||||
|
/* If the active MCFW does not support MC_CMD_VADAPTOR_SET_MAC
|
||||||
|
* fall-back to the method of changing the MAC address on the
|
||||||
|
* vport. This only applies to PFs because such versions of
|
||||||
|
* MCFW do not support VFs.
|
||||||
|
*/
|
||||||
|
rc = efx_ef10_vport_set_mac_address(efx);
|
||||||
|
} else {
|
||||||
|
efx_mcdi_display_error(efx, MC_CMD_VADAPTOR_SET_MAC,
|
||||||
|
sizeof(inbuf), NULL, 0, rc);
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,30 +29,6 @@ static int efx_ef10_evb_port_assign(struct efx_nic *efx, unsigned int port_id,
|
||||||
NULL, 0, NULL);
|
NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efx_ef10_vport_add_mac(struct efx_nic *efx,
|
|
||||||
unsigned int port_id, u8 *mac)
|
|
||||||
{
|
|
||||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN);
|
|
||||||
|
|
||||||
MCDI_SET_DWORD(inbuf, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, port_id);
|
|
||||||
ether_addr_copy(MCDI_PTR(inbuf, VPORT_ADD_MAC_ADDRESS_IN_MACADDR), mac);
|
|
||||||
|
|
||||||
return efx_mcdi_rpc(efx, MC_CMD_VPORT_ADD_MAC_ADDRESS, inbuf,
|
|
||||||
sizeof(inbuf), NULL, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int efx_ef10_vport_del_mac(struct efx_nic *efx,
|
|
||||||
unsigned int port_id, u8 *mac)
|
|
||||||
{
|
|
||||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN);
|
|
||||||
|
|
||||||
MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id);
|
|
||||||
ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac);
|
|
||||||
|
|
||||||
return efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf,
|
|
||||||
sizeof(inbuf), NULL, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int efx_ef10_vswitch_alloc(struct efx_nic *efx, unsigned int port_id,
|
static int efx_ef10_vswitch_alloc(struct efx_nic *efx, unsigned int port_id,
|
||||||
unsigned int vswitch_type)
|
unsigned int vswitch_type)
|
||||||
{
|
{
|
||||||
|
@ -136,24 +112,6 @@ static int efx_ef10_vport_free(struct efx_nic *efx, unsigned int port_id)
|
||||||
NULL, 0, NULL);
|
NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id)
|
|
||||||
{
|
|
||||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_ALLOC_IN_LEN);
|
|
||||||
|
|
||||||
MCDI_SET_DWORD(inbuf, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
|
|
||||||
return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_ALLOC, inbuf, sizeof(inbuf),
|
|
||||||
NULL, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id)
|
|
||||||
{
|
|
||||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_FREE_IN_LEN);
|
|
||||||
|
|
||||||
MCDI_SET_DWORD(inbuf, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
|
|
||||||
return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_FREE, inbuf, sizeof(inbuf),
|
|
||||||
NULL, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void efx_ef10_sriov_free_vf_vports(struct efx_nic *efx)
|
static void efx_ef10_sriov_free_vf_vports(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
||||||
|
@ -640,21 +598,21 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan,
|
||||||
MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL,
|
MC_CMD_VPORT_ALLOC_IN_VPORT_TYPE_NORMAL,
|
||||||
vf->vlan, &vf->vport_id);
|
vf->vlan, &vf->vport_id);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto reset_nic;
|
goto reset_nic_up_write;
|
||||||
|
|
||||||
restore_mac:
|
restore_mac:
|
||||||
if (!is_zero_ether_addr(vf->mac)) {
|
if (!is_zero_ether_addr(vf->mac)) {
|
||||||
rc2 = efx_ef10_vport_add_mac(efx, vf->vport_id, vf->mac);
|
rc2 = efx_ef10_vport_add_mac(efx, vf->vport_id, vf->mac);
|
||||||
if (rc2) {
|
if (rc2) {
|
||||||
eth_zero_addr(vf->mac);
|
eth_zero_addr(vf->mac);
|
||||||
goto reset_nic;
|
goto reset_nic_up_write;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
restore_evb_port:
|
restore_evb_port:
|
||||||
rc2 = efx_ef10_evb_port_assign(efx, vf->vport_id, vf_i);
|
rc2 = efx_ef10_evb_port_assign(efx, vf->vport_id, vf_i);
|
||||||
if (rc2)
|
if (rc2)
|
||||||
goto reset_nic;
|
goto reset_nic_up_write;
|
||||||
else
|
else
|
||||||
vf->vport_assigned = 1;
|
vf->vport_assigned = 1;
|
||||||
|
|
||||||
|
@ -662,14 +620,16 @@ restore_vadaptor:
|
||||||
if (vf->efx) {
|
if (vf->efx) {
|
||||||
rc2 = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED);
|
rc2 = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED);
|
||||||
if (rc2)
|
if (rc2)
|
||||||
goto reset_nic;
|
goto reset_nic_up_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
restore_filters:
|
restore_filters:
|
||||||
if (vf->efx) {
|
if (vf->efx) {
|
||||||
rc2 = vf->efx->type->filter_table_probe(vf->efx);
|
rc2 = vf->efx->type->filter_table_probe(vf->efx);
|
||||||
if (rc2)
|
if (rc2)
|
||||||
goto reset_nic;
|
goto reset_nic_up_write;
|
||||||
|
|
||||||
|
up_write(&vf->efx->filter_sem);
|
||||||
|
|
||||||
up_write(&vf->efx->filter_sem);
|
up_write(&vf->efx->filter_sem);
|
||||||
|
|
||||||
|
@ -681,9 +641,12 @@ restore_filters:
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
reset_nic_up_write:
|
||||||
|
if (vf->efx)
|
||||||
|
up_write(&vf->efx->filter_sem);
|
||||||
|
|
||||||
reset_nic:
|
reset_nic:
|
||||||
if (vf->efx) {
|
if (vf->efx) {
|
||||||
up_write(&vf->efx->filter_sem);
|
|
||||||
netif_err(efx, drv, efx->net_dev,
|
netif_err(efx, drv, efx->net_dev,
|
||||||
"Failed to restore VF - scheduling reset.\n");
|
"Failed to restore VF - scheduling reset.\n");
|
||||||
efx_schedule_reset(vf->efx, RESET_TYPE_DATAPATH);
|
efx_schedule_reset(vf->efx, RESET_TYPE_DATAPATH);
|
||||||
|
|
|
@ -65,5 +65,11 @@ int efx_ef10_vswitching_restore_pf(struct efx_nic *efx);
|
||||||
int efx_ef10_vswitching_restore_vf(struct efx_nic *efx);
|
int efx_ef10_vswitching_restore_vf(struct efx_nic *efx);
|
||||||
void efx_ef10_vswitching_remove_pf(struct efx_nic *efx);
|
void efx_ef10_vswitching_remove_pf(struct efx_nic *efx);
|
||||||
void efx_ef10_vswitching_remove_vf(struct efx_nic *efx);
|
void efx_ef10_vswitching_remove_vf(struct efx_nic *efx);
|
||||||
|
int efx_ef10_vport_add_mac(struct efx_nic *efx,
|
||||||
|
unsigned int port_id, u8 *mac);
|
||||||
|
int efx_ef10_vport_del_mac(struct efx_nic *efx,
|
||||||
|
unsigned int port_id, u8 *mac);
|
||||||
|
int efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id);
|
||||||
|
int efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id);
|
||||||
|
|
||||||
#endif /* EF10_SRIOV_H */
|
#endif /* EF10_SRIOV_H */
|
||||||
|
|
|
@ -245,11 +245,17 @@ static int efx_check_disabled(struct efx_nic *efx)
|
||||||
*/
|
*/
|
||||||
static int efx_process_channel(struct efx_channel *channel, int budget)
|
static int efx_process_channel(struct efx_channel *channel, int budget)
|
||||||
{
|
{
|
||||||
|
struct efx_tx_queue *tx_queue;
|
||||||
int spent;
|
int spent;
|
||||||
|
|
||||||
if (unlikely(!channel->enabled))
|
if (unlikely(!channel->enabled))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
efx_for_each_channel_tx_queue(tx_queue, channel) {
|
||||||
|
tx_queue->pkts_compl = 0;
|
||||||
|
tx_queue->bytes_compl = 0;
|
||||||
|
}
|
||||||
|
|
||||||
spent = efx_nic_process_eventq(channel, budget);
|
spent = efx_nic_process_eventq(channel, budget);
|
||||||
if (spent && efx_channel_has_rx_queue(channel)) {
|
if (spent && efx_channel_has_rx_queue(channel)) {
|
||||||
struct efx_rx_queue *rx_queue =
|
struct efx_rx_queue *rx_queue =
|
||||||
|
@ -259,6 +265,14 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
|
||||||
efx_fast_push_rx_descriptors(rx_queue, true);
|
efx_fast_push_rx_descriptors(rx_queue, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update BQL */
|
||||||
|
efx_for_each_channel_tx_queue(tx_queue, channel) {
|
||||||
|
if (tx_queue->bytes_compl) {
|
||||||
|
netdev_tx_completed_queue(tx_queue->core_txq,
|
||||||
|
tx_queue->pkts_compl, tx_queue->bytes_compl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return spent;
|
return spent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -241,6 +241,8 @@ struct efx_tx_queue {
|
||||||
unsigned int read_count ____cacheline_aligned_in_smp;
|
unsigned int read_count ____cacheline_aligned_in_smp;
|
||||||
unsigned int old_write_count;
|
unsigned int old_write_count;
|
||||||
unsigned int merge_events;
|
unsigned int merge_events;
|
||||||
|
unsigned int bytes_compl;
|
||||||
|
unsigned int pkts_compl;
|
||||||
|
|
||||||
/* Members used only on the xmit path */
|
/* Members used only on the xmit path */
|
||||||
unsigned int insert_count ____cacheline_aligned_in_smp;
|
unsigned int insert_count ____cacheline_aligned_in_smp;
|
||||||
|
|
|
@ -617,7 +617,8 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
|
||||||
EFX_BUG_ON_PARANOID(index > tx_queue->ptr_mask);
|
EFX_BUG_ON_PARANOID(index > tx_queue->ptr_mask);
|
||||||
|
|
||||||
efx_dequeue_buffers(tx_queue, index, &pkts_compl, &bytes_compl);
|
efx_dequeue_buffers(tx_queue, index, &pkts_compl, &bytes_compl);
|
||||||
netdev_tx_completed_queue(tx_queue->core_txq, pkts_compl, bytes_compl);
|
tx_queue->pkts_compl += pkts_compl;
|
||||||
|
tx_queue->bytes_compl += bytes_compl;
|
||||||
|
|
||||||
if (pkts_compl > 1)
|
if (pkts_compl > 1)
|
||||||
++tx_queue->merge_events;
|
++tx_queue->merge_events;
|
||||||
|
|
|
@ -138,19 +138,6 @@ do { \
|
||||||
#define CPSW_CMINTMAX_INTVL (1000 / CPSW_CMINTMIN_CNT)
|
#define CPSW_CMINTMAX_INTVL (1000 / CPSW_CMINTMIN_CNT)
|
||||||
#define CPSW_CMINTMIN_INTVL ((1000 / CPSW_CMINTMAX_CNT) + 1)
|
#define CPSW_CMINTMIN_INTVL ((1000 / CPSW_CMINTMAX_CNT) + 1)
|
||||||
|
|
||||||
#define cpsw_enable_irq(priv) \
|
|
||||||
do { \
|
|
||||||
u32 i; \
|
|
||||||
for (i = 0; i < priv->num_irqs; i++) \
|
|
||||||
enable_irq(priv->irqs_table[i]); \
|
|
||||||
} while (0)
|
|
||||||
#define cpsw_disable_irq(priv) \
|
|
||||||
do { \
|
|
||||||
u32 i; \
|
|
||||||
for (i = 0; i < priv->num_irqs; i++) \
|
|
||||||
disable_irq_nosync(priv->irqs_table[i]); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define cpsw_slave_index(priv) \
|
#define cpsw_slave_index(priv) \
|
||||||
((priv->data.dual_emac) ? priv->emac_port : \
|
((priv->data.dual_emac) ? priv->emac_port : \
|
||||||
priv->data.active_slave)
|
priv->data.active_slave)
|
||||||
|
@ -509,9 +496,11 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = {
|
||||||
(func)(slave++, ##arg); \
|
(func)(slave++, ##arg); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define cpsw_get_slave_ndev(priv, __slave_no__) \
|
#define cpsw_get_slave_ndev(priv, __slave_no__) \
|
||||||
(priv->slaves[__slave_no__].ndev)
|
((__slave_no__ < priv->data.slaves) ? \
|
||||||
|
priv->slaves[__slave_no__].ndev : NULL)
|
||||||
#define cpsw_get_slave_priv(priv, __slave_no__) \
|
#define cpsw_get_slave_priv(priv, __slave_no__) \
|
||||||
((priv->slaves[__slave_no__].ndev) ? \
|
(((__slave_no__ < priv->data.slaves) && \
|
||||||
|
(priv->slaves[__slave_no__].ndev)) ? \
|
||||||
netdev_priv(priv->slaves[__slave_no__].ndev) : NULL) \
|
netdev_priv(priv->slaves[__slave_no__].ndev) : NULL) \
|
||||||
|
|
||||||
#define cpsw_dual_emac_src_port_detect(status, priv, ndev, skb) \
|
#define cpsw_dual_emac_src_port_detect(status, priv, ndev, skb) \
|
||||||
|
@ -781,7 +770,7 @@ static irqreturn_t cpsw_rx_interrupt(int irq, void *dev_id)
|
||||||
|
|
||||||
cpsw_intr_disable(priv);
|
cpsw_intr_disable(priv);
|
||||||
if (priv->irq_enabled == true) {
|
if (priv->irq_enabled == true) {
|
||||||
cpsw_disable_irq(priv);
|
disable_irq_nosync(priv->irqs_table[0]);
|
||||||
priv->irq_enabled = false;
|
priv->irq_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -817,7 +806,7 @@ static int cpsw_poll(struct napi_struct *napi, int budget)
|
||||||
prim_cpsw = cpsw_get_slave_priv(priv, 0);
|
prim_cpsw = cpsw_get_slave_priv(priv, 0);
|
||||||
if (prim_cpsw->irq_enabled == false) {
|
if (prim_cpsw->irq_enabled == false) {
|
||||||
prim_cpsw->irq_enabled = true;
|
prim_cpsw->irq_enabled = true;
|
||||||
cpsw_enable_irq(priv);
|
enable_irq(priv->irqs_table[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1333,7 +1322,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
|
||||||
if (prim_cpsw->irq_enabled == false) {
|
if (prim_cpsw->irq_enabled == false) {
|
||||||
if ((priv == prim_cpsw) || !netif_running(prim_cpsw->ndev)) {
|
if ((priv == prim_cpsw) || !netif_running(prim_cpsw->ndev)) {
|
||||||
prim_cpsw->irq_enabled = true;
|
prim_cpsw->irq_enabled = true;
|
||||||
cpsw_enable_irq(prim_cpsw);
|
enable_irq(prim_cpsw->irqs_table[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1530,9 +1530,9 @@ static int axienet_probe(struct platform_device *pdev)
|
||||||
/* Map device registers */
|
/* Map device registers */
|
||||||
ethres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
ethres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
lp->regs = devm_ioremap_resource(&pdev->dev, ethres);
|
lp->regs = devm_ioremap_resource(&pdev->dev, ethres);
|
||||||
if (!lp->regs) {
|
if (IS_ERR(lp->regs)) {
|
||||||
dev_err(&pdev->dev, "could not map Axi Ethernet regs.\n");
|
dev_err(&pdev->dev, "could not map Axi Ethernet regs.\n");
|
||||||
ret = -ENOMEM;
|
ret = PTR_ERR(lp->regs);
|
||||||
goto free_netdev;
|
goto free_netdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1599,9 +1599,9 @@ static int axienet_probe(struct platform_device *pdev)
|
||||||
goto free_netdev;
|
goto free_netdev;
|
||||||
}
|
}
|
||||||
lp->dma_regs = devm_ioremap_resource(&pdev->dev, &dmares);
|
lp->dma_regs = devm_ioremap_resource(&pdev->dev, &dmares);
|
||||||
if (!lp->dma_regs) {
|
if (IS_ERR(lp->dma_regs)) {
|
||||||
dev_err(&pdev->dev, "could not map DMA regs\n");
|
dev_err(&pdev->dev, "could not map DMA regs\n");
|
||||||
ret = -ENOMEM;
|
ret = PTR_ERR(lp->dma_regs);
|
||||||
goto free_netdev;
|
goto free_netdev;
|
||||||
}
|
}
|
||||||
lp->rx_irq = irq_of_parse_and_map(np, 1);
|
lp->rx_irq = irq_of_parse_and_map(np, 1);
|
||||||
|
|
|
@ -482,6 +482,7 @@ static void bpq_setup(struct net_device *dev)
|
||||||
memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
|
memcpy(dev->dev_addr, &ax25_defaddr, AX25_ADDR_LEN);
|
||||||
|
|
||||||
dev->flags = 0;
|
dev->flags = 0;
|
||||||
|
dev->features = NETIF_F_LLTX; /* Allow recursion */
|
||||||
|
|
||||||
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
|
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
|
||||||
dev->header_ops = &ax25_header_ops;
|
dev->header_ops = &ax25_header_ops;
|
||||||
|
|
|
@ -1355,6 +1355,7 @@ static void macvtap_exit(void)
|
||||||
class_unregister(macvtap_class);
|
class_unregister(macvtap_class);
|
||||||
cdev_del(&macvtap_cdev);
|
cdev_del(&macvtap_cdev);
|
||||||
unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
|
unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
|
||||||
|
idr_destroy(&minor_idr);
|
||||||
}
|
}
|
||||||
module_exit(macvtap_exit);
|
module_exit(macvtap_exit);
|
||||||
|
|
||||||
|
|
|
@ -191,7 +191,7 @@ config MDIO_BUS_MUX_GPIO
|
||||||
|
|
||||||
config MDIO_BUS_MUX_MMIOREG
|
config MDIO_BUS_MUX_MMIOREG
|
||||||
tristate "Support for MMIO device-controlled MDIO bus multiplexers"
|
tristate "Support for MMIO device-controlled MDIO bus multiplexers"
|
||||||
depends on OF_MDIO
|
depends on OF_MDIO && HAS_IOMEM
|
||||||
select MDIO_BUS_MUX
|
select MDIO_BUS_MUX
|
||||||
help
|
help
|
||||||
This module provides a driver for MDIO bus multiplexers that
|
This module provides a driver for MDIO bus multiplexers that
|
||||||
|
|
|
@ -523,6 +523,7 @@ static const struct driver_info wwan_info = {
|
||||||
#define REALTEK_VENDOR_ID 0x0bda
|
#define REALTEK_VENDOR_ID 0x0bda
|
||||||
#define SAMSUNG_VENDOR_ID 0x04e8
|
#define SAMSUNG_VENDOR_ID 0x04e8
|
||||||
#define LENOVO_VENDOR_ID 0x17ef
|
#define LENOVO_VENDOR_ID 0x17ef
|
||||||
|
#define NVIDIA_VENDOR_ID 0x0955
|
||||||
|
|
||||||
static const struct usb_device_id products[] = {
|
static const struct usb_device_id products[] = {
|
||||||
/* BLACKLIST !!
|
/* BLACKLIST !!
|
||||||
|
@ -710,6 +711,13 @@ static const struct usb_device_id products[] = {
|
||||||
.driver_info = 0,
|
.driver_info = 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/* NVIDIA Tegra USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
|
||||||
|
{
|
||||||
|
USB_DEVICE_AND_INTERFACE_INFO(NVIDIA_VENDOR_ID, 0x09ff, USB_CLASS_COMM,
|
||||||
|
USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||||
|
.driver_info = 0,
|
||||||
|
},
|
||||||
|
|
||||||
/* WHITELIST!!!
|
/* WHITELIST!!!
|
||||||
*
|
*
|
||||||
* CDC Ether uses two interfaces, not necessarily consecutive.
|
* CDC Ether uses two interfaces, not necessarily consecutive.
|
||||||
|
|
|
@ -158,7 +158,7 @@ static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||||
if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
|
if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
ret = cdc_ncm_bind_common(dev, intf, data_altsetting);
|
ret = cdc_ncm_bind_common(dev, intf, data_altsetting, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* Original author: Hans Petter Selasky <hans.petter.selasky@stericsson.com>
|
* Original author: Hans Petter Selasky <hans.petter.selasky@stericsson.com>
|
||||||
*
|
*
|
||||||
* USB Host Driver for Network Control Model (NCM)
|
* USB Host Driver for Network Control Model (NCM)
|
||||||
* http://www.usb.org/developers/devclass_docs/NCM10.zip
|
* http://www.usb.org/developers/docs/devclass_docs/NCM10_012011.zip
|
||||||
*
|
*
|
||||||
* The NCM encoding, decoding and initialization logic
|
* The NCM encoding, decoding and initialization logic
|
||||||
* derives from FreeBSD 8.x. if_cdce.c and if_cdcereg.h
|
* derives from FreeBSD 8.x. if_cdce.c and if_cdcereg.h
|
||||||
|
@ -684,10 +684,12 @@ static void cdc_ncm_free(struct cdc_ncm_ctx *ctx)
|
||||||
ctx->tx_curr_skb = NULL;
|
ctx->tx_curr_skb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kfree(ctx->delayed_ndp16);
|
||||||
|
|
||||||
kfree(ctx);
|
kfree(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting)
|
int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting, int drvflags)
|
||||||
{
|
{
|
||||||
const struct usb_cdc_union_desc *union_desc = NULL;
|
const struct usb_cdc_union_desc *union_desc = NULL;
|
||||||
struct cdc_ncm_ctx *ctx;
|
struct cdc_ncm_ctx *ctx;
|
||||||
|
@ -855,6 +857,17 @@ advance:
|
||||||
/* finish setting up the device specific data */
|
/* finish setting up the device specific data */
|
||||||
cdc_ncm_setup(dev);
|
cdc_ncm_setup(dev);
|
||||||
|
|
||||||
|
/* Device-specific flags */
|
||||||
|
ctx->drvflags = drvflags;
|
||||||
|
|
||||||
|
/* Allocate the delayed NDP if needed. */
|
||||||
|
if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
|
||||||
|
ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL);
|
||||||
|
if (!ctx->delayed_ndp16)
|
||||||
|
goto error2;
|
||||||
|
dev_info(&intf->dev, "NDP will be placed at end of frame for this device.");
|
||||||
|
}
|
||||||
|
|
||||||
/* override ethtool_ops */
|
/* override ethtool_ops */
|
||||||
dev->net->ethtool_ops = &cdc_ncm_ethtool_ops;
|
dev->net->ethtool_ops = &cdc_ncm_ethtool_ops;
|
||||||
|
|
||||||
|
@ -954,8 +967,11 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||||
if (cdc_ncm_select_altsetting(intf) != CDC_NCM_COMM_ALTSETTING_NCM)
|
if (cdc_ncm_select_altsetting(intf) != CDC_NCM_COMM_ALTSETTING_NCM)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* The NCM data altsetting is fixed */
|
/* The NCM data altsetting is fixed, so we hard-coded it.
|
||||||
ret = cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM);
|
* Additionally, generic NCM devices are assumed to accept arbitrarily
|
||||||
|
* placed NDP.
|
||||||
|
*/
|
||||||
|
ret = cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We should get an event when network connection is "connected" or
|
* We should get an event when network connection is "connected" or
|
||||||
|
@ -986,6 +1002,14 @@ static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_
|
||||||
struct usb_cdc_ncm_nth16 *nth16 = (void *)skb->data;
|
struct usb_cdc_ncm_nth16 *nth16 = (void *)skb->data;
|
||||||
size_t ndpoffset = le16_to_cpu(nth16->wNdpIndex);
|
size_t ndpoffset = le16_to_cpu(nth16->wNdpIndex);
|
||||||
|
|
||||||
|
/* If NDP should be moved to the end of the NCM package, we can't follow the
|
||||||
|
* NTH16 header as we would normally do. NDP isn't written to the SKB yet, and
|
||||||
|
* the wNdpIndex field in the header is actually not consistent with reality. It will be later.
|
||||||
|
*/
|
||||||
|
if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)
|
||||||
|
if (ctx->delayed_ndp16->dwSignature == sign)
|
||||||
|
return ctx->delayed_ndp16;
|
||||||
|
|
||||||
/* follow the chain of NDPs, looking for a match */
|
/* follow the chain of NDPs, looking for a match */
|
||||||
while (ndpoffset) {
|
while (ndpoffset) {
|
||||||
ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset);
|
ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset);
|
||||||
|
@ -995,7 +1019,8 @@ static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_
|
||||||
}
|
}
|
||||||
|
|
||||||
/* align new NDP */
|
/* align new NDP */
|
||||||
cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_max);
|
if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END))
|
||||||
|
cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_max);
|
||||||
|
|
||||||
/* verify that there is room for the NDP and the datagram (reserve) */
|
/* verify that there is room for the NDP and the datagram (reserve) */
|
||||||
if ((ctx->tx_max - skb->len - reserve) < ctx->max_ndp_size)
|
if ((ctx->tx_max - skb->len - reserve) < ctx->max_ndp_size)
|
||||||
|
@ -1008,7 +1033,11 @@ static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_
|
||||||
nth16->wNdpIndex = cpu_to_le16(skb->len);
|
nth16->wNdpIndex = cpu_to_le16(skb->len);
|
||||||
|
|
||||||
/* push a new empty NDP */
|
/* push a new empty NDP */
|
||||||
ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, ctx->max_ndp_size), 0, ctx->max_ndp_size);
|
if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END))
|
||||||
|
ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, ctx->max_ndp_size), 0, ctx->max_ndp_size);
|
||||||
|
else
|
||||||
|
ndp16 = ctx->delayed_ndp16;
|
||||||
|
|
||||||
ndp16->dwSignature = sign;
|
ndp16->dwSignature = sign;
|
||||||
ndp16->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16));
|
ndp16->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16));
|
||||||
return ndp16;
|
return ndp16;
|
||||||
|
@ -1023,6 +1052,15 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
|
||||||
struct sk_buff *skb_out;
|
struct sk_buff *skb_out;
|
||||||
u16 n = 0, index, ndplen;
|
u16 n = 0, index, ndplen;
|
||||||
u8 ready2send = 0;
|
u8 ready2send = 0;
|
||||||
|
u32 delayed_ndp_size;
|
||||||
|
|
||||||
|
/* When our NDP gets written in cdc_ncm_ndp(), then skb_out->len gets updated
|
||||||
|
* accordingly. Otherwise, we should check here.
|
||||||
|
*/
|
||||||
|
if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)
|
||||||
|
delayed_ndp_size = ctx->max_ndp_size;
|
||||||
|
else
|
||||||
|
delayed_ndp_size = 0;
|
||||||
|
|
||||||
/* if there is a remaining skb, it gets priority */
|
/* if there is a remaining skb, it gets priority */
|
||||||
if (skb != NULL) {
|
if (skb != NULL) {
|
||||||
|
@ -1077,7 +1115,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
|
||||||
cdc_ncm_align_tail(skb_out, ctx->tx_modulus, ctx->tx_remainder, ctx->tx_max);
|
cdc_ncm_align_tail(skb_out, ctx->tx_modulus, ctx->tx_remainder, ctx->tx_max);
|
||||||
|
|
||||||
/* check if we had enough room left for both NDP and frame */
|
/* check if we had enough room left for both NDP and frame */
|
||||||
if (!ndp16 || skb_out->len + skb->len > ctx->tx_max) {
|
if (!ndp16 || skb_out->len + skb->len + delayed_ndp_size > ctx->tx_max) {
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
/* won't fit, MTU problem? */
|
/* won't fit, MTU problem? */
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
|
@ -1150,6 +1188,17 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
|
||||||
/* variables will be reset at next call */
|
/* variables will be reset at next call */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If requested, put NDP at end of frame. */
|
||||||
|
if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
|
||||||
|
nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
|
||||||
|
cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_max);
|
||||||
|
nth16->wNdpIndex = cpu_to_le16(skb_out->len);
|
||||||
|
memcpy(skb_put(skb_out, ctx->max_ndp_size), ctx->delayed_ndp16, ctx->max_ndp_size);
|
||||||
|
|
||||||
|
/* Zero out delayed NDP - signature checking will naturally fail. */
|
||||||
|
ndp16 = memset(ctx->delayed_ndp16, 0, ctx->max_ndp_size);
|
||||||
|
}
|
||||||
|
|
||||||
/* If collected data size is less or equal ctx->min_tx_pkt
|
/* If collected data size is less or equal ctx->min_tx_pkt
|
||||||
* bytes, we send buffers as it is. If we get more data, it
|
* bytes, we send buffers as it is. If we get more data, it
|
||||||
* would be more efficient for USB HS mobile device with DMA
|
* would be more efficient for USB HS mobile device with DMA
|
||||||
|
|
|
@ -73,11 +73,14 @@ static int huawei_cdc_ncm_bind(struct usbnet *usbnet_dev,
|
||||||
struct usb_driver *subdriver = ERR_PTR(-ENODEV);
|
struct usb_driver *subdriver = ERR_PTR(-ENODEV);
|
||||||
int ret = -ENODEV;
|
int ret = -ENODEV;
|
||||||
struct huawei_cdc_ncm_state *drvstate = (void *)&usbnet_dev->data;
|
struct huawei_cdc_ncm_state *drvstate = (void *)&usbnet_dev->data;
|
||||||
|
int drvflags = 0;
|
||||||
|
|
||||||
/* altsetting should always be 1 for NCM devices - so we hard-coded
|
/* altsetting should always be 1 for NCM devices - so we hard-coded
|
||||||
* it here
|
* it here. Some huawei devices will need the NDP part of the NCM package to
|
||||||
|
* be at the end of the frame.
|
||||||
*/
|
*/
|
||||||
ret = cdc_ncm_bind_common(usbnet_dev, intf, 1);
|
drvflags |= CDC_NCM_FLAG_NDP_TO_END;
|
||||||
|
ret = cdc_ncm_bind_common(usbnet_dev, intf, 1, drvflags);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
|
|
@ -494,6 +494,7 @@ enum rtl8152_flags {
|
||||||
#define VENDOR_ID_REALTEK 0x0bda
|
#define VENDOR_ID_REALTEK 0x0bda
|
||||||
#define VENDOR_ID_SAMSUNG 0x04e8
|
#define VENDOR_ID_SAMSUNG 0x04e8
|
||||||
#define VENDOR_ID_LENOVO 0x17ef
|
#define VENDOR_ID_LENOVO 0x17ef
|
||||||
|
#define VENDOR_ID_NVIDIA 0x0955
|
||||||
|
|
||||||
#define MCU_TYPE_PLA 0x0100
|
#define MCU_TYPE_PLA 0x0100
|
||||||
#define MCU_TYPE_USB 0x0000
|
#define MCU_TYPE_USB 0x0000
|
||||||
|
@ -4117,6 +4118,7 @@ static struct usb_device_id rtl8152_table[] = {
|
||||||
{REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)},
|
{REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)},
|
||||||
{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)},
|
{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)},
|
||||||
{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)},
|
{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)},
|
||||||
|
{REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1216,7 +1216,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
|
||||||
static const u32 rxprod_reg[2] = {
|
static const u32 rxprod_reg[2] = {
|
||||||
VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2
|
VMXNET3_REG_RXPROD, VMXNET3_REG_RXPROD2
|
||||||
};
|
};
|
||||||
u32 num_rxd = 0;
|
u32 num_pkts = 0;
|
||||||
bool skip_page_frags = false;
|
bool skip_page_frags = false;
|
||||||
struct Vmxnet3_RxCompDesc *rcd;
|
struct Vmxnet3_RxCompDesc *rcd;
|
||||||
struct vmxnet3_rx_ctx *ctx = &rq->rx_ctx;
|
struct vmxnet3_rx_ctx *ctx = &rq->rx_ctx;
|
||||||
|
@ -1235,13 +1235,12 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
|
||||||
struct Vmxnet3_RxDesc *rxd;
|
struct Vmxnet3_RxDesc *rxd;
|
||||||
u32 idx, ring_idx;
|
u32 idx, ring_idx;
|
||||||
struct vmxnet3_cmd_ring *ring = NULL;
|
struct vmxnet3_cmd_ring *ring = NULL;
|
||||||
if (num_rxd >= quota) {
|
if (num_pkts >= quota) {
|
||||||
/* we may stop even before we see the EOP desc of
|
/* we may stop even before we see the EOP desc of
|
||||||
* the current pkt
|
* the current pkt
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
num_rxd++;
|
|
||||||
BUG_ON(rcd->rqID != rq->qid && rcd->rqID != rq->qid2);
|
BUG_ON(rcd->rqID != rq->qid && rcd->rqID != rq->qid2);
|
||||||
idx = rcd->rxdIdx;
|
idx = rcd->rxdIdx;
|
||||||
ring_idx = rcd->rqID < adapter->num_rx_queues ? 0 : 1;
|
ring_idx = rcd->rqID < adapter->num_rx_queues ? 0 : 1;
|
||||||
|
@ -1413,6 +1412,7 @@ not_lro:
|
||||||
napi_gro_receive(&rq->napi, skb);
|
napi_gro_receive(&rq->napi, skb);
|
||||||
|
|
||||||
ctx->skb = NULL;
|
ctx->skb = NULL;
|
||||||
|
num_pkts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcd_done:
|
rcd_done:
|
||||||
|
@ -1443,7 +1443,7 @@ rcd_done:
|
||||||
&rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp);
|
&rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return num_rxd;
|
return num_pkts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1044,7 +1044,7 @@ EXPORT_SYMBOL(z8530_sync_dma_close);
|
||||||
* @dev: The network device to attach
|
* @dev: The network device to attach
|
||||||
* @c: The Z8530 channel to configure in sync DMA mode.
|
* @c: The Z8530 channel to configure in sync DMA mode.
|
||||||
*
|
*
|
||||||
* Set up a Z85x30 device for synchronous DMA tranmission. One
|
* Set up a Z85x30 device for synchronous DMA transmission. One
|
||||||
* ISA DMA channel must be available for this to work. The receive
|
* ISA DMA channel must be available for this to work. The receive
|
||||||
* side is run in PIO mode, but then it has the bigger FIFO.
|
* side is run in PIO mode, but then it has the bigger FIFO.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,10 +27,12 @@
|
||||||
/**
|
/**
|
||||||
* struct can_skb_priv - private additional data inside CAN sk_buffs
|
* struct can_skb_priv - private additional data inside CAN sk_buffs
|
||||||
* @ifindex: ifindex of the first interface the CAN frame appeared on
|
* @ifindex: ifindex of the first interface the CAN frame appeared on
|
||||||
|
* @skbcnt: atomic counter to have an unique id together with skb pointer
|
||||||
* @cf: align to the following CAN frame at skb->data
|
* @cf: align to the following CAN frame at skb->data
|
||||||
*/
|
*/
|
||||||
struct can_skb_priv {
|
struct can_skb_priv {
|
||||||
int ifindex;
|
int ifindex;
|
||||||
|
int skbcnt;
|
||||||
struct can_frame cf[0];
|
struct can_frame cf[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,9 @@
|
||||||
#define CDC_NCM_TIMER_INTERVAL_MIN 5UL
|
#define CDC_NCM_TIMER_INTERVAL_MIN 5UL
|
||||||
#define CDC_NCM_TIMER_INTERVAL_MAX (U32_MAX / NSEC_PER_USEC)
|
#define CDC_NCM_TIMER_INTERVAL_MAX (U32_MAX / NSEC_PER_USEC)
|
||||||
|
|
||||||
|
/* Driver flags */
|
||||||
|
#define CDC_NCM_FLAG_NDP_TO_END 0x02 /* NDP is placed at end of frame */
|
||||||
|
|
||||||
#define cdc_ncm_comm_intf_is_mbim(x) ((x)->desc.bInterfaceSubClass == USB_CDC_SUBCLASS_MBIM && \
|
#define cdc_ncm_comm_intf_is_mbim(x) ((x)->desc.bInterfaceSubClass == USB_CDC_SUBCLASS_MBIM && \
|
||||||
(x)->desc.bInterfaceProtocol == USB_CDC_PROTO_NONE)
|
(x)->desc.bInterfaceProtocol == USB_CDC_PROTO_NONE)
|
||||||
#define cdc_ncm_data_intf_is_mbim(x) ((x)->desc.bInterfaceProtocol == USB_CDC_MBIM_PROTO_NTB)
|
#define cdc_ncm_data_intf_is_mbim(x) ((x)->desc.bInterfaceProtocol == USB_CDC_MBIM_PROTO_NTB)
|
||||||
|
@ -103,9 +106,11 @@ struct cdc_ncm_ctx {
|
||||||
|
|
||||||
spinlock_t mtx;
|
spinlock_t mtx;
|
||||||
atomic_t stop;
|
atomic_t stop;
|
||||||
|
int drvflags;
|
||||||
|
|
||||||
u32 timer_interval;
|
u32 timer_interval;
|
||||||
u32 max_ndp_size;
|
u32 max_ndp_size;
|
||||||
|
struct usb_cdc_ncm_ndp16 *delayed_ndp16;
|
||||||
|
|
||||||
u32 tx_timer_pending;
|
u32 tx_timer_pending;
|
||||||
u32 tx_curr_frame_num;
|
u32 tx_curr_frame_num;
|
||||||
|
@ -133,7 +138,7 @@ struct cdc_ncm_ctx {
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 cdc_ncm_select_altsetting(struct usb_interface *intf);
|
u8 cdc_ncm_select_altsetting(struct usb_interface *intf);
|
||||||
int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting);
|
int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting, int drvflags);
|
||||||
void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf);
|
void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf);
|
||||||
struct sk_buff *cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign);
|
struct sk_buff *cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign);
|
||||||
int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in);
|
int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in);
|
||||||
|
|
|
@ -15,6 +15,7 @@ enum {
|
||||||
NETCONFA_RP_FILTER,
|
NETCONFA_RP_FILTER,
|
||||||
NETCONFA_MC_FORWARDING,
|
NETCONFA_MC_FORWARDING,
|
||||||
NETCONFA_PROXY_NEIGH,
|
NETCONFA_PROXY_NEIGH,
|
||||||
|
NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
|
||||||
__NETCONFA_MAX
|
__NETCONFA_MAX
|
||||||
};
|
};
|
||||||
#define NETCONFA_MAX (__NETCONFA_MAX - 1)
|
#define NETCONFA_MAX (__NETCONFA_MAX - 1)
|
||||||
|
|
|
@ -610,6 +610,8 @@ next:
|
||||||
iter->skip = 0;
|
iter->skip = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iter->p = NULL;
|
||||||
|
|
||||||
/* Ensure we see any new tables. */
|
/* Ensure we see any new tables. */
|
||||||
smp_rmb();
|
smp_rmb();
|
||||||
|
|
||||||
|
@ -620,8 +622,6 @@ next:
|
||||||
return ERR_PTR(-EAGAIN);
|
return ERR_PTR(-EAGAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
iter->p = NULL;
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rhashtable_walk_next);
|
EXPORT_SYMBOL_GPL(rhashtable_walk_next);
|
||||||
|
|
|
@ -42,6 +42,7 @@ int br_dev_queue_push_xmit(struct sock *sk, struct sk_buff *skb)
|
||||||
} else {
|
} else {
|
||||||
skb_push(skb, ETH_HLEN);
|
skb_push(skb, ETH_HLEN);
|
||||||
br_drop_fake_rtable(skb);
|
br_drop_fake_rtable(skb);
|
||||||
|
skb_sender_cpu_clear(skb);
|
||||||
dev_queue_xmit(skb);
|
dev_queue_xmit(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -323,6 +323,7 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
|
||||||
struct net_bridge_port_group *p;
|
struct net_bridge_port_group *p;
|
||||||
struct net_bridge_port_group __rcu **pp;
|
struct net_bridge_port_group __rcu **pp;
|
||||||
struct net_bridge_mdb_htable *mdb;
|
struct net_bridge_mdb_htable *mdb;
|
||||||
|
unsigned long now = jiffies;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
mdb = mlock_dereference(br->mdb, br);
|
mdb = mlock_dereference(br->mdb, br);
|
||||||
|
@ -347,6 +348,8 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
|
||||||
if (unlikely(!p))
|
if (unlikely(!p))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
rcu_assign_pointer(*pp, p);
|
rcu_assign_pointer(*pp, p);
|
||||||
|
if (state == MDB_TEMPORARY)
|
||||||
|
mod_timer(&p->timer, now + br->multicast_membership_interval);
|
||||||
|
|
||||||
br_mdb_notify(br->dev, port, group, RTM_NEWMDB);
|
br_mdb_notify(br->dev, port, group, RTM_NEWMDB);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -371,6 +374,7 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br,
|
||||||
if (!p || p->br != br || p->state == BR_STATE_DISABLED)
|
if (!p || p->br != br || p->state == BR_STATE_DISABLED)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
memset(&ip, 0, sizeof(ip));
|
||||||
ip.proto = entry->addr.proto;
|
ip.proto = entry->addr.proto;
|
||||||
if (ip.proto == htons(ETH_P_IP))
|
if (ip.proto == htons(ETH_P_IP))
|
||||||
ip.u.ip4 = entry->addr.u.ip4;
|
ip.u.ip4 = entry->addr.u.ip4;
|
||||||
|
@ -417,20 +421,14 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
|
||||||
if (!netif_running(br->dev) || br->multicast_disabled)
|
if (!netif_running(br->dev) || br->multicast_disabled)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
memset(&ip, 0, sizeof(ip));
|
||||||
ip.proto = entry->addr.proto;
|
ip.proto = entry->addr.proto;
|
||||||
if (ip.proto == htons(ETH_P_IP)) {
|
if (ip.proto == htons(ETH_P_IP))
|
||||||
if (timer_pending(&br->ip4_other_query.timer))
|
|
||||||
return -EBUSY;
|
|
||||||
|
|
||||||
ip.u.ip4 = entry->addr.u.ip4;
|
ip.u.ip4 = entry->addr.u.ip4;
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
} else {
|
else
|
||||||
if (timer_pending(&br->ip6_other_query.timer))
|
|
||||||
return -EBUSY;
|
|
||||||
|
|
||||||
ip.u.ip6 = entry->addr.u.ip6;
|
ip.u.ip6 = entry->addr.u.ip6;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_bh(&br->multicast_lock);
|
spin_lock_bh(&br->multicast_lock);
|
||||||
mdb = mlock_dereference(br->mdb, br);
|
mdb = mlock_dereference(br->mdb, br);
|
||||||
|
|
|
@ -111,7 +111,7 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb)
|
||||||
/* largest possible L2 header, see br_nf_dev_queue_xmit() */
|
/* largest possible L2 header, see br_nf_dev_queue_xmit() */
|
||||||
#define NF_BRIDGE_MAX_MAC_HEADER_LENGTH (PPPOE_SES_HLEN + ETH_HLEN)
|
#define NF_BRIDGE_MAX_MAC_HEADER_LENGTH (PPPOE_SES_HLEN + ETH_HLEN)
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4)
|
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4) || IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
|
||||||
struct brnf_frag_data {
|
struct brnf_frag_data {
|
||||||
char mac[NF_BRIDGE_MAX_MAC_HEADER_LENGTH];
|
char mac[NF_BRIDGE_MAX_MAC_HEADER_LENGTH];
|
||||||
u8 encap_size;
|
u8 encap_size;
|
||||||
|
@ -694,6 +694,7 @@ static int br_nf_push_frag_xmit(struct sock *sk, struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4)
|
||||||
static int br_nf_ip_fragment(struct sock *sk, struct sk_buff *skb,
|
static int br_nf_ip_fragment(struct sock *sk, struct sk_buff *skb,
|
||||||
int (*output)(struct sock *, struct sk_buff *))
|
int (*output)(struct sock *, struct sk_buff *))
|
||||||
{
|
{
|
||||||
|
@ -712,6 +713,7 @@ static int br_nf_ip_fragment(struct sock *sk, struct sk_buff *skb,
|
||||||
|
|
||||||
return ip_do_fragment(sk, skb, output);
|
return ip_do_fragment(sk, skb, output);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
|
static unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
@ -742,7 +744,7 @@ static int br_nf_dev_queue_xmit(struct sock *sk, struct sk_buff *skb)
|
||||||
struct brnf_frag_data *data;
|
struct brnf_frag_data *data;
|
||||||
|
|
||||||
if (br_validate_ipv4(skb))
|
if (br_validate_ipv4(skb))
|
||||||
return NF_DROP;
|
goto drop;
|
||||||
|
|
||||||
IPCB(skb)->frag_max_size = nf_bridge->frag_max_size;
|
IPCB(skb)->frag_max_size = nf_bridge->frag_max_size;
|
||||||
|
|
||||||
|
@ -767,7 +769,7 @@ static int br_nf_dev_queue_xmit(struct sock *sk, struct sk_buff *skb)
|
||||||
struct brnf_frag_data *data;
|
struct brnf_frag_data *data;
|
||||||
|
|
||||||
if (br_validate_ipv6(skb))
|
if (br_validate_ipv6(skb))
|
||||||
return NF_DROP;
|
goto drop;
|
||||||
|
|
||||||
IP6CB(skb)->frag_max_size = nf_bridge->frag_max_size;
|
IP6CB(skb)->frag_max_size = nf_bridge->frag_max_size;
|
||||||
|
|
||||||
|
@ -782,12 +784,16 @@ static int br_nf_dev_queue_xmit(struct sock *sk, struct sk_buff *skb)
|
||||||
|
|
||||||
if (v6ops)
|
if (v6ops)
|
||||||
return v6ops->fragment(sk, skb, br_nf_push_frag_xmit);
|
return v6ops->fragment(sk, skb, br_nf_push_frag_xmit);
|
||||||
else
|
|
||||||
return -EMSGSIZE;
|
kfree_skb(skb);
|
||||||
|
return -EMSGSIZE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
nf_bridge_info_free(skb);
|
nf_bridge_info_free(skb);
|
||||||
return br_dev_queue_push_xmit(sk, skb);
|
return br_dev_queue_push_xmit(sk, skb);
|
||||||
|
drop:
|
||||||
|
kfree_skb(skb);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PF_BRIDGE/POST_ROUTING ********************************************/
|
/* PF_BRIDGE/POST_ROUTING ********************************************/
|
||||||
|
|
|
@ -104,7 +104,7 @@ int br_validate_ipv6(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
const struct ipv6hdr *hdr;
|
const struct ipv6hdr *hdr;
|
||||||
struct net_device *dev = skb->dev;
|
struct net_device *dev = skb->dev;
|
||||||
struct inet6_dev *idev = in6_dev_get(skb->dev);
|
struct inet6_dev *idev = __in6_dev_get(skb->dev);
|
||||||
u32 pkt_len;
|
u32 pkt_len;
|
||||||
u8 ip6h_len = sizeof(struct ipv6hdr);
|
u8 ip6h_len = sizeof(struct ipv6hdr);
|
||||||
|
|
||||||
|
|
|
@ -457,6 +457,8 @@ static int br_afspec(struct net_bridge *br,
|
||||||
if (nla_len(attr) != sizeof(struct bridge_vlan_info))
|
if (nla_len(attr) != sizeof(struct bridge_vlan_info))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
vinfo = nla_data(attr);
|
vinfo = nla_data(attr);
|
||||||
|
if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
|
||||||
|
return -EINVAL;
|
||||||
if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
|
if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
|
||||||
if (vinfo_start)
|
if (vinfo_start)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -89,6 +89,8 @@ struct timer_list can_stattimer; /* timer for statistics update */
|
||||||
struct s_stats can_stats; /* packet statistics */
|
struct s_stats can_stats; /* packet statistics */
|
||||||
struct s_pstats can_pstats; /* receive list statistics */
|
struct s_pstats can_pstats; /* receive list statistics */
|
||||||
|
|
||||||
|
static atomic_t skbcounter = ATOMIC_INIT(0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* af_can socket functions
|
* af_can socket functions
|
||||||
*/
|
*/
|
||||||
|
@ -310,12 +312,8 @@ int can_send(struct sk_buff *skb, int loop)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newskb) {
|
if (newskb)
|
||||||
if (!(newskb->tstamp.tv64))
|
|
||||||
__net_timestamp(newskb);
|
|
||||||
|
|
||||||
netif_rx_ni(newskb);
|
netif_rx_ni(newskb);
|
||||||
}
|
|
||||||
|
|
||||||
/* update statistics */
|
/* update statistics */
|
||||||
can_stats.tx_frames++;
|
can_stats.tx_frames++;
|
||||||
|
@ -683,6 +681,10 @@ static void can_receive(struct sk_buff *skb, struct net_device *dev)
|
||||||
can_stats.rx_frames++;
|
can_stats.rx_frames++;
|
||||||
can_stats.rx_frames_delta++;
|
can_stats.rx_frames_delta++;
|
||||||
|
|
||||||
|
/* create non-zero unique skb identifier together with *skb */
|
||||||
|
while (!(can_skb_prv(skb)->skbcnt))
|
||||||
|
can_skb_prv(skb)->skbcnt = atomic_inc_return(&skbcounter);
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
||||||
/* deliver the packet to sockets listening on all devices */
|
/* deliver the packet to sockets listening on all devices */
|
||||||
|
|
|
@ -261,6 +261,7 @@ static void bcm_can_tx(struct bcm_op *op)
|
||||||
|
|
||||||
can_skb_reserve(skb);
|
can_skb_reserve(skb);
|
||||||
can_skb_prv(skb)->ifindex = dev->ifindex;
|
can_skb_prv(skb)->ifindex = dev->ifindex;
|
||||||
|
can_skb_prv(skb)->skbcnt = 0;
|
||||||
|
|
||||||
memcpy(skb_put(skb, CFSIZ), cf, CFSIZ);
|
memcpy(skb_put(skb, CFSIZ), cf, CFSIZ);
|
||||||
|
|
||||||
|
@ -1217,6 +1218,7 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk)
|
||||||
}
|
}
|
||||||
|
|
||||||
can_skb_prv(skb)->ifindex = dev->ifindex;
|
can_skb_prv(skb)->ifindex = dev->ifindex;
|
||||||
|
can_skb_prv(skb)->skbcnt = 0;
|
||||||
skb->dev = dev;
|
skb->dev = dev;
|
||||||
can_skb_set_owner(skb, sk);
|
can_skb_set_owner(skb, sk);
|
||||||
err = can_send(skb, 1); /* send with loopback */
|
err = can_send(skb, 1); /* send with loopback */
|
||||||
|
|
|
@ -75,7 +75,7 @@ MODULE_ALIAS("can-proto-1");
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct uniqframe {
|
struct uniqframe {
|
||||||
ktime_t tstamp;
|
int skbcnt;
|
||||||
const struct sk_buff *skb;
|
const struct sk_buff *skb;
|
||||||
unsigned int join_rx_count;
|
unsigned int join_rx_count;
|
||||||
};
|
};
|
||||||
|
@ -133,7 +133,7 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
|
||||||
|
|
||||||
/* eliminate multiple filter matches for the same skb */
|
/* eliminate multiple filter matches for the same skb */
|
||||||
if (this_cpu_ptr(ro->uniq)->skb == oskb &&
|
if (this_cpu_ptr(ro->uniq)->skb == oskb &&
|
||||||
ktime_equal(this_cpu_ptr(ro->uniq)->tstamp, oskb->tstamp)) {
|
this_cpu_ptr(ro->uniq)->skbcnt == can_skb_prv(oskb)->skbcnt) {
|
||||||
if (ro->join_filters) {
|
if (ro->join_filters) {
|
||||||
this_cpu_inc(ro->uniq->join_rx_count);
|
this_cpu_inc(ro->uniq->join_rx_count);
|
||||||
/* drop frame until all enabled filters matched */
|
/* drop frame until all enabled filters matched */
|
||||||
|
@ -144,7 +144,7 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this_cpu_ptr(ro->uniq)->skb = oskb;
|
this_cpu_ptr(ro->uniq)->skb = oskb;
|
||||||
this_cpu_ptr(ro->uniq)->tstamp = oskb->tstamp;
|
this_cpu_ptr(ro->uniq)->skbcnt = can_skb_prv(oskb)->skbcnt;
|
||||||
this_cpu_ptr(ro->uniq)->join_rx_count = 1;
|
this_cpu_ptr(ro->uniq)->join_rx_count = 1;
|
||||||
/* drop first frame to check all enabled filters? */
|
/* drop first frame to check all enabled filters? */
|
||||||
if (ro->join_filters && ro->count > 1)
|
if (ro->join_filters && ro->count > 1)
|
||||||
|
@ -749,6 +749,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
||||||
|
|
||||||
can_skb_reserve(skb);
|
can_skb_reserve(skb);
|
||||||
can_skb_prv(skb)->ifindex = dev->ifindex;
|
can_skb_prv(skb)->ifindex = dev->ifindex;
|
||||||
|
can_skb_prv(skb)->skbcnt = 0;
|
||||||
|
|
||||||
err = memcpy_from_msg(skb_put(skb, size), msg, size);
|
err = memcpy_from_msg(skb_put(skb, size), msg, size);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
|
@ -677,10 +677,6 @@ int dev_get_iflink(const struct net_device *dev)
|
||||||
if (dev->netdev_ops && dev->netdev_ops->ndo_get_iflink)
|
if (dev->netdev_ops && dev->netdev_ops->ndo_get_iflink)
|
||||||
return dev->netdev_ops->ndo_get_iflink(dev);
|
return dev->netdev_ops->ndo_get_iflink(dev);
|
||||||
|
|
||||||
/* If dev->rtnl_link_ops is set, it's a virtual interface. */
|
|
||||||
if (dev->rtnl_link_ops)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return dev->ifindex;
|
return dev->ifindex;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dev_get_iflink);
|
EXPORT_SYMBOL(dev_get_iflink);
|
||||||
|
@ -3452,6 +3448,8 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu,
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
|
|
||||||
rps_lock(sd);
|
rps_lock(sd);
|
||||||
|
if (!netif_running(skb->dev))
|
||||||
|
goto drop;
|
||||||
qlen = skb_queue_len(&sd->input_pkt_queue);
|
qlen = skb_queue_len(&sd->input_pkt_queue);
|
||||||
if (qlen <= netdev_max_backlog && !skb_flow_limit(skb, qlen)) {
|
if (qlen <= netdev_max_backlog && !skb_flow_limit(skb, qlen)) {
|
||||||
if (qlen) {
|
if (qlen) {
|
||||||
|
@ -3473,6 +3471,7 @@ enqueue:
|
||||||
goto enqueue;
|
goto enqueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drop:
|
||||||
sd->dropped++;
|
sd->dropped++;
|
||||||
rps_unlock(sd);
|
rps_unlock(sd);
|
||||||
|
|
||||||
|
@ -3775,8 +3774,6 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
|
||||||
|
|
||||||
pt_prev = NULL;
|
pt_prev = NULL;
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
|
|
||||||
another_round:
|
another_round:
|
||||||
skb->skb_iif = skb->dev->ifindex;
|
skb->skb_iif = skb->dev->ifindex;
|
||||||
|
|
||||||
|
@ -3786,7 +3783,7 @@ another_round:
|
||||||
skb->protocol == cpu_to_be16(ETH_P_8021AD)) {
|
skb->protocol == cpu_to_be16(ETH_P_8021AD)) {
|
||||||
skb = skb_vlan_untag(skb);
|
skb = skb_vlan_untag(skb);
|
||||||
if (unlikely(!skb))
|
if (unlikely(!skb))
|
||||||
goto unlock;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_NET_CLS_ACT
|
#ifdef CONFIG_NET_CLS_ACT
|
||||||
|
@ -3816,10 +3813,10 @@ skip_taps:
|
||||||
if (static_key_false(&ingress_needed)) {
|
if (static_key_false(&ingress_needed)) {
|
||||||
skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
|
skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
goto unlock;
|
goto out;
|
||||||
|
|
||||||
if (nf_ingress(skb, &pt_prev, &ret, orig_dev) < 0)
|
if (nf_ingress(skb, &pt_prev, &ret, orig_dev) < 0)
|
||||||
goto unlock;
|
goto out;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_NET_CLS_ACT
|
#ifdef CONFIG_NET_CLS_ACT
|
||||||
|
@ -3837,7 +3834,7 @@ ncls:
|
||||||
if (vlan_do_receive(&skb))
|
if (vlan_do_receive(&skb))
|
||||||
goto another_round;
|
goto another_round;
|
||||||
else if (unlikely(!skb))
|
else if (unlikely(!skb))
|
||||||
goto unlock;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rx_handler = rcu_dereference(skb->dev->rx_handler);
|
rx_handler = rcu_dereference(skb->dev->rx_handler);
|
||||||
|
@ -3849,7 +3846,7 @@ ncls:
|
||||||
switch (rx_handler(&skb)) {
|
switch (rx_handler(&skb)) {
|
||||||
case RX_HANDLER_CONSUMED:
|
case RX_HANDLER_CONSUMED:
|
||||||
ret = NET_RX_SUCCESS;
|
ret = NET_RX_SUCCESS;
|
||||||
goto unlock;
|
goto out;
|
||||||
case RX_HANDLER_ANOTHER:
|
case RX_HANDLER_ANOTHER:
|
||||||
goto another_round;
|
goto another_round;
|
||||||
case RX_HANDLER_EXACT:
|
case RX_HANDLER_EXACT:
|
||||||
|
@ -3903,8 +3900,7 @@ drop:
|
||||||
ret = NET_RX_DROP;
|
ret = NET_RX_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock:
|
out:
|
||||||
rcu_read_unlock();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3935,29 +3931,30 @@ static int __netif_receive_skb(struct sk_buff *skb)
|
||||||
|
|
||||||
static int netif_receive_skb_internal(struct sk_buff *skb)
|
static int netif_receive_skb_internal(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
net_timestamp_check(netdev_tstamp_prequeue, skb);
|
net_timestamp_check(netdev_tstamp_prequeue, skb);
|
||||||
|
|
||||||
if (skb_defer_rx_timestamp(skb))
|
if (skb_defer_rx_timestamp(skb))
|
||||||
return NET_RX_SUCCESS;
|
return NET_RX_SUCCESS;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
#ifdef CONFIG_RPS
|
#ifdef CONFIG_RPS
|
||||||
if (static_key_false(&rps_needed)) {
|
if (static_key_false(&rps_needed)) {
|
||||||
struct rps_dev_flow voidflow, *rflow = &voidflow;
|
struct rps_dev_flow voidflow, *rflow = &voidflow;
|
||||||
int cpu, ret;
|
int cpu = get_rps_cpu(skb->dev, skb, &rflow);
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
|
|
||||||
cpu = get_rps_cpu(skb->dev, skb, &rflow);
|
|
||||||
|
|
||||||
if (cpu >= 0) {
|
if (cpu >= 0) {
|
||||||
ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail);
|
ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return __netif_receive_skb(skb);
|
ret = __netif_receive_skb(skb);
|
||||||
|
rcu_read_unlock();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4502,8 +4499,10 @@ static int process_backlog(struct napi_struct *napi, int quota)
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
|
||||||
while ((skb = __skb_dequeue(&sd->process_queue))) {
|
while ((skb = __skb_dequeue(&sd->process_queue))) {
|
||||||
|
rcu_read_lock();
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
__netif_receive_skb(skb);
|
__netif_receive_skb(skb);
|
||||||
|
rcu_read_unlock();
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
input_queue_head_incr(sd);
|
input_queue_head_incr(sd);
|
||||||
if (++work >= quota) {
|
if (++work >= quota) {
|
||||||
|
@ -6139,6 +6138,7 @@ static void rollback_registered_many(struct list_head *head)
|
||||||
unlist_netdevice(dev);
|
unlist_netdevice(dev);
|
||||||
|
|
||||||
dev->reg_state = NETREG_UNREGISTERING;
|
dev->reg_state = NETREG_UNREGISTERING;
|
||||||
|
on_each_cpu(flush_backlog, dev, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronize_net();
|
synchronize_net();
|
||||||
|
@ -6409,7 +6409,8 @@ static int netif_alloc_netdev_queues(struct net_device *dev)
|
||||||
struct netdev_queue *tx;
|
struct netdev_queue *tx;
|
||||||
size_t sz = count * sizeof(*tx);
|
size_t sz = count * sizeof(*tx);
|
||||||
|
|
||||||
BUG_ON(count < 1 || count > 0xffff);
|
if (count < 1 || count > 0xffff)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
tx = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
|
tx = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
|
||||||
if (!tx) {
|
if (!tx) {
|
||||||
|
@ -6773,8 +6774,6 @@ void netdev_run_todo(void)
|
||||||
|
|
||||||
dev->reg_state = NETREG_UNREGISTERED;
|
dev->reg_state = NETREG_UNREGISTERED;
|
||||||
|
|
||||||
on_each_cpu(flush_backlog, dev, 1);
|
|
||||||
|
|
||||||
netdev_wait_allrefs(dev);
|
netdev_wait_allrefs(dev);
|
||||||
|
|
||||||
/* paranoia */
|
/* paranoia */
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
|
|
||||||
NOTES.
|
NOTES.
|
||||||
|
|
||||||
* avbps is scaled by 2^5, avpps is scaled by 2^10.
|
* avbps and avpps are scaled by 2^5.
|
||||||
* both values are reported as 32 bit unsigned values. bps can
|
* both values are reported as 32 bit unsigned values. bps can
|
||||||
overflow for fast links : max speed being 34360Mbit/sec
|
overflow for fast links : max speed being 34360Mbit/sec
|
||||||
* Minimal interval is HZ/4=250msec (it is the greatest common divisor
|
* Minimal interval is HZ/4=250msec (it is the greatest common divisor
|
||||||
|
@ -85,10 +85,10 @@ struct gen_estimator
|
||||||
struct gnet_stats_rate_est64 *rate_est;
|
struct gnet_stats_rate_est64 *rate_est;
|
||||||
spinlock_t *stats_lock;
|
spinlock_t *stats_lock;
|
||||||
int ewma_log;
|
int ewma_log;
|
||||||
|
u32 last_packets;
|
||||||
|
unsigned long avpps;
|
||||||
u64 last_bytes;
|
u64 last_bytes;
|
||||||
u64 avbps;
|
u64 avbps;
|
||||||
u32 last_packets;
|
|
||||||
u32 avpps;
|
|
||||||
struct rcu_head e_rcu;
|
struct rcu_head e_rcu;
|
||||||
struct rb_node node;
|
struct rb_node node;
|
||||||
struct gnet_stats_basic_cpu __percpu *cpu_bstats;
|
struct gnet_stats_basic_cpu __percpu *cpu_bstats;
|
||||||
|
@ -118,8 +118,8 @@ static void est_timer(unsigned long arg)
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
list_for_each_entry_rcu(e, &elist[idx].list, list) {
|
list_for_each_entry_rcu(e, &elist[idx].list, list) {
|
||||||
struct gnet_stats_basic_packed b = {0};
|
struct gnet_stats_basic_packed b = {0};
|
||||||
|
unsigned long rate;
|
||||||
u64 brate;
|
u64 brate;
|
||||||
u32 rate;
|
|
||||||
|
|
||||||
spin_lock(e->stats_lock);
|
spin_lock(e->stats_lock);
|
||||||
read_lock(&est_lock);
|
read_lock(&est_lock);
|
||||||
|
@ -133,10 +133,11 @@ static void est_timer(unsigned long arg)
|
||||||
e->avbps += (brate >> e->ewma_log) - (e->avbps >> e->ewma_log);
|
e->avbps += (brate >> e->ewma_log) - (e->avbps >> e->ewma_log);
|
||||||
e->rate_est->bps = (e->avbps+0xF)>>5;
|
e->rate_est->bps = (e->avbps+0xF)>>5;
|
||||||
|
|
||||||
rate = (b.packets - e->last_packets)<<(12 - idx);
|
rate = b.packets - e->last_packets;
|
||||||
|
rate <<= (7 - idx);
|
||||||
e->last_packets = b.packets;
|
e->last_packets = b.packets;
|
||||||
e->avpps += (rate >> e->ewma_log) - (e->avpps >> e->ewma_log);
|
e->avpps += (rate >> e->ewma_log) - (e->avpps >> e->ewma_log);
|
||||||
e->rate_est->pps = (e->avpps+0x1FF)>>10;
|
e->rate_est->pps = (e->avpps + 0xF) >> 5;
|
||||||
skip:
|
skip:
|
||||||
read_unlock(&est_lock);
|
read_unlock(&est_lock);
|
||||||
spin_unlock(e->stats_lock);
|
spin_unlock(e->stats_lock);
|
||||||
|
|
|
@ -3571,13 +3571,6 @@ static int pktgen_thread_worker(void *arg)
|
||||||
pr_debug("%s removing thread\n", t->tsk->comm);
|
pr_debug("%s removing thread\n", t->tsk->comm);
|
||||||
pktgen_rem_thread(t);
|
pktgen_rem_thread(t);
|
||||||
|
|
||||||
/* Wait for kthread_stop */
|
|
||||||
while (!kthread_should_stop()) {
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
|
||||||
schedule();
|
|
||||||
}
|
|
||||||
__set_current_state(TASK_RUNNING);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3769,6 +3762,7 @@ static int __net_init pktgen_create_thread(int cpu, struct pktgen_net *pn)
|
||||||
}
|
}
|
||||||
|
|
||||||
t->net = pn;
|
t->net = pn;
|
||||||
|
get_task_struct(p);
|
||||||
wake_up_process(p);
|
wake_up_process(p);
|
||||||
wait_for_completion(&t->start_done);
|
wait_for_completion(&t->start_done);
|
||||||
|
|
||||||
|
@ -3891,6 +3885,7 @@ static void __net_exit pg_net_exit(struct net *net)
|
||||||
t = list_entry(q, struct pktgen_thread, th_list);
|
t = list_entry(q, struct pktgen_thread, th_list);
|
||||||
list_del(&t->th_list);
|
list_del(&t->th_list);
|
||||||
kthread_stop(t->tsk);
|
kthread_stop(t->tsk);
|
||||||
|
put_task_struct(t->tsk);
|
||||||
kfree(t);
|
kfree(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1328,10 +1328,6 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
|
||||||
[IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED },
|
[IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = {
|
|
||||||
[IFLA_VF_INFO] = { .type = NLA_NESTED },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
|
static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
|
||||||
[IFLA_VF_MAC] = { .len = sizeof(struct ifla_vf_mac) },
|
[IFLA_VF_MAC] = { .len = sizeof(struct ifla_vf_mac) },
|
||||||
[IFLA_VF_VLAN] = { .len = sizeof(struct ifla_vf_vlan) },
|
[IFLA_VF_VLAN] = { .len = sizeof(struct ifla_vf_vlan) },
|
||||||
|
@ -1488,96 +1484,98 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
|
static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)
|
||||||
{
|
{
|
||||||
int rem, err = -EINVAL;
|
|
||||||
struct nlattr *vf;
|
|
||||||
const struct net_device_ops *ops = dev->netdev_ops;
|
const struct net_device_ops *ops = dev->netdev_ops;
|
||||||
|
int err = -EINVAL;
|
||||||
|
|
||||||
nla_for_each_nested(vf, attr, rem) {
|
if (tb[IFLA_VF_MAC]) {
|
||||||
switch (nla_type(vf)) {
|
struct ifla_vf_mac *ivm = nla_data(tb[IFLA_VF_MAC]);
|
||||||
case IFLA_VF_MAC: {
|
|
||||||
struct ifla_vf_mac *ivm;
|
|
||||||
ivm = nla_data(vf);
|
|
||||||
err = -EOPNOTSUPP;
|
|
||||||
if (ops->ndo_set_vf_mac)
|
|
||||||
err = ops->ndo_set_vf_mac(dev, ivm->vf,
|
|
||||||
ivm->mac);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IFLA_VF_VLAN: {
|
|
||||||
struct ifla_vf_vlan *ivv;
|
|
||||||
ivv = nla_data(vf);
|
|
||||||
err = -EOPNOTSUPP;
|
|
||||||
if (ops->ndo_set_vf_vlan)
|
|
||||||
err = ops->ndo_set_vf_vlan(dev, ivv->vf,
|
|
||||||
ivv->vlan,
|
|
||||||
ivv->qos);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IFLA_VF_TX_RATE: {
|
|
||||||
struct ifla_vf_tx_rate *ivt;
|
|
||||||
struct ifla_vf_info ivf;
|
|
||||||
ivt = nla_data(vf);
|
|
||||||
err = -EOPNOTSUPP;
|
|
||||||
if (ops->ndo_get_vf_config)
|
|
||||||
err = ops->ndo_get_vf_config(dev, ivt->vf,
|
|
||||||
&ivf);
|
|
||||||
if (err)
|
|
||||||
break;
|
|
||||||
err = -EOPNOTSUPP;
|
|
||||||
if (ops->ndo_set_vf_rate)
|
|
||||||
err = ops->ndo_set_vf_rate(dev, ivt->vf,
|
|
||||||
ivf.min_tx_rate,
|
|
||||||
ivt->rate);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IFLA_VF_RATE: {
|
|
||||||
struct ifla_vf_rate *ivt;
|
|
||||||
ivt = nla_data(vf);
|
|
||||||
err = -EOPNOTSUPP;
|
|
||||||
if (ops->ndo_set_vf_rate)
|
|
||||||
err = ops->ndo_set_vf_rate(dev, ivt->vf,
|
|
||||||
ivt->min_tx_rate,
|
|
||||||
ivt->max_tx_rate);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IFLA_VF_SPOOFCHK: {
|
|
||||||
struct ifla_vf_spoofchk *ivs;
|
|
||||||
ivs = nla_data(vf);
|
|
||||||
err = -EOPNOTSUPP;
|
|
||||||
if (ops->ndo_set_vf_spoofchk)
|
|
||||||
err = ops->ndo_set_vf_spoofchk(dev, ivs->vf,
|
|
||||||
ivs->setting);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IFLA_VF_LINK_STATE: {
|
|
||||||
struct ifla_vf_link_state *ivl;
|
|
||||||
ivl = nla_data(vf);
|
|
||||||
err = -EOPNOTSUPP;
|
|
||||||
if (ops->ndo_set_vf_link_state)
|
|
||||||
err = ops->ndo_set_vf_link_state(dev, ivl->vf,
|
|
||||||
ivl->link_state);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IFLA_VF_RSS_QUERY_EN: {
|
|
||||||
struct ifla_vf_rss_query_en *ivrssq_en;
|
|
||||||
|
|
||||||
ivrssq_en = nla_data(vf);
|
err = -EOPNOTSUPP;
|
||||||
err = -EOPNOTSUPP;
|
if (ops->ndo_set_vf_mac)
|
||||||
if (ops->ndo_set_vf_rss_query_en)
|
err = ops->ndo_set_vf_mac(dev, ivm->vf,
|
||||||
err = ops->ndo_set_vf_rss_query_en(dev,
|
ivm->mac);
|
||||||
ivrssq_en->vf,
|
if (err < 0)
|
||||||
ivrssq_en->setting);
|
return err;
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
err = -EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (err)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tb[IFLA_VF_VLAN]) {
|
||||||
|
struct ifla_vf_vlan *ivv = nla_data(tb[IFLA_VF_VLAN]);
|
||||||
|
|
||||||
|
err = -EOPNOTSUPP;
|
||||||
|
if (ops->ndo_set_vf_vlan)
|
||||||
|
err = ops->ndo_set_vf_vlan(dev, ivv->vf, ivv->vlan,
|
||||||
|
ivv->qos);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[IFLA_VF_TX_RATE]) {
|
||||||
|
struct ifla_vf_tx_rate *ivt = nla_data(tb[IFLA_VF_TX_RATE]);
|
||||||
|
struct ifla_vf_info ivf;
|
||||||
|
|
||||||
|
err = -EOPNOTSUPP;
|
||||||
|
if (ops->ndo_get_vf_config)
|
||||||
|
err = ops->ndo_get_vf_config(dev, ivt->vf, &ivf);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = -EOPNOTSUPP;
|
||||||
|
if (ops->ndo_set_vf_rate)
|
||||||
|
err = ops->ndo_set_vf_rate(dev, ivt->vf,
|
||||||
|
ivf.min_tx_rate,
|
||||||
|
ivt->rate);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[IFLA_VF_RATE]) {
|
||||||
|
struct ifla_vf_rate *ivt = nla_data(tb[IFLA_VF_RATE]);
|
||||||
|
|
||||||
|
err = -EOPNOTSUPP;
|
||||||
|
if (ops->ndo_set_vf_rate)
|
||||||
|
err = ops->ndo_set_vf_rate(dev, ivt->vf,
|
||||||
|
ivt->min_tx_rate,
|
||||||
|
ivt->max_tx_rate);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[IFLA_VF_SPOOFCHK]) {
|
||||||
|
struct ifla_vf_spoofchk *ivs = nla_data(tb[IFLA_VF_SPOOFCHK]);
|
||||||
|
|
||||||
|
err = -EOPNOTSUPP;
|
||||||
|
if (ops->ndo_set_vf_spoofchk)
|
||||||
|
err = ops->ndo_set_vf_spoofchk(dev, ivs->vf,
|
||||||
|
ivs->setting);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[IFLA_VF_LINK_STATE]) {
|
||||||
|
struct ifla_vf_link_state *ivl = nla_data(tb[IFLA_VF_LINK_STATE]);
|
||||||
|
|
||||||
|
err = -EOPNOTSUPP;
|
||||||
|
if (ops->ndo_set_vf_link_state)
|
||||||
|
err = ops->ndo_set_vf_link_state(dev, ivl->vf,
|
||||||
|
ivl->link_state);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tb[IFLA_VF_RSS_QUERY_EN]) {
|
||||||
|
struct ifla_vf_rss_query_en *ivrssq_en;
|
||||||
|
|
||||||
|
err = -EOPNOTSUPP;
|
||||||
|
ivrssq_en = nla_data(tb[IFLA_VF_RSS_QUERY_EN]);
|
||||||
|
if (ops->ndo_set_vf_rss_query_en)
|
||||||
|
err = ops->ndo_set_vf_rss_query_en(dev, ivrssq_en->vf,
|
||||||
|
ivrssq_en->setting);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1773,14 +1771,21 @@ static int do_setlink(const struct sk_buff *skb,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tb[IFLA_VFINFO_LIST]) {
|
if (tb[IFLA_VFINFO_LIST]) {
|
||||||
|
struct nlattr *vfinfo[IFLA_VF_MAX + 1];
|
||||||
struct nlattr *attr;
|
struct nlattr *attr;
|
||||||
int rem;
|
int rem;
|
||||||
|
|
||||||
nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) {
|
nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) {
|
||||||
if (nla_type(attr) != IFLA_VF_INFO) {
|
if (nla_type(attr) != IFLA_VF_INFO ||
|
||||||
|
nla_len(attr) < NLA_HDRLEN) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
err = do_setvfinfo(dev, attr);
|
err = nla_parse_nested(vfinfo, IFLA_VF_MAX, attr,
|
||||||
|
ifla_vf_policy);
|
||||||
|
if (err < 0)
|
||||||
|
goto errout;
|
||||||
|
err = do_setvfinfo(dev, vfinfo);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto errout;
|
goto errout;
|
||||||
status |= DO_SETLINK_NOTIFY;
|
status |= DO_SETLINK_NOTIFY;
|
||||||
|
|
|
@ -630,7 +630,7 @@ static int dsa_of_probe(struct device *dev)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cd->sw_addr = be32_to_cpup(sw_addr);
|
cd->sw_addr = be32_to_cpup(sw_addr);
|
||||||
if (cd->sw_addr > PHY_MAX_ADDR)
|
if (cd->sw_addr >= PHY_MAX_ADDR)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!of_property_read_u32(child, "eeprom-length", &eeprom_len))
|
if (!of_property_read_u32(child, "eeprom-length", &eeprom_len))
|
||||||
|
@ -642,6 +642,8 @@ static int dsa_of_probe(struct device *dev)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
port_index = be32_to_cpup(port_reg);
|
port_index = be32_to_cpup(port_reg);
|
||||||
|
if (port_index >= DSA_MAX_PORTS)
|
||||||
|
break;
|
||||||
|
|
||||||
port_name = of_get_property(port, "label", NULL);
|
port_name = of_get_property(port, "label", NULL);
|
||||||
if (!port_name)
|
if (!port_name)
|
||||||
|
@ -666,8 +668,6 @@ static int dsa_of_probe(struct device *dev)
|
||||||
goto out_free_chip;
|
goto out_free_chip;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port_index == DSA_MAX_PORTS)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1740,6 +1740,8 @@ static int inet_netconf_msgsize_devconf(int type)
|
||||||
size += nla_total_size(4);
|
size += nla_total_size(4);
|
||||||
if (type == -1 || type == NETCONFA_PROXY_NEIGH)
|
if (type == -1 || type == NETCONFA_PROXY_NEIGH)
|
||||||
size += nla_total_size(4);
|
size += nla_total_size(4);
|
||||||
|
if (type == -1 || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN)
|
||||||
|
size += nla_total_size(4);
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
@ -1780,6 +1782,10 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
|
||||||
nla_put_s32(skb, NETCONFA_PROXY_NEIGH,
|
nla_put_s32(skb, NETCONFA_PROXY_NEIGH,
|
||||||
IPV4_DEVCONF(*devconf, PROXY_ARP)) < 0)
|
IPV4_DEVCONF(*devconf, PROXY_ARP)) < 0)
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
if ((type == -1 || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN) &&
|
||||||
|
nla_put_s32(skb, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
|
||||||
|
IPV4_DEVCONF(*devconf, IGNORE_ROUTES_WITH_LINKDOWN)) < 0)
|
||||||
|
goto nla_put_failure;
|
||||||
|
|
||||||
nlmsg_end(skb, nlh);
|
nlmsg_end(skb, nlh);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1819,6 +1825,7 @@ static const struct nla_policy devconf_ipv4_policy[NETCONFA_MAX+1] = {
|
||||||
[NETCONFA_FORWARDING] = { .len = sizeof(int) },
|
[NETCONFA_FORWARDING] = { .len = sizeof(int) },
|
||||||
[NETCONFA_RP_FILTER] = { .len = sizeof(int) },
|
[NETCONFA_RP_FILTER] = { .len = sizeof(int) },
|
||||||
[NETCONFA_PROXY_NEIGH] = { .len = sizeof(int) },
|
[NETCONFA_PROXY_NEIGH] = { .len = sizeof(int) },
|
||||||
|
[NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN] = { .len = sizeof(int) },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int inet_netconf_get_devconf(struct sk_buff *in_skb,
|
static int inet_netconf_get_devconf(struct sk_buff *in_skb,
|
||||||
|
@ -2048,6 +2055,12 @@ static int devinet_conf_proc(struct ctl_table *ctl, int write,
|
||||||
inet_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
|
inet_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
|
||||||
ifindex, cnf);
|
ifindex, cnf);
|
||||||
}
|
}
|
||||||
|
if (i == IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN - 1 &&
|
||||||
|
new_value != old_value) {
|
||||||
|
ifindex = devinet_conf_ifindex(net, cnf);
|
||||||
|
inet_netconf_notify_devconf(net, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
|
||||||
|
ifindex, cnf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -152,8 +152,8 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
|
||||||
inet6_sk(sk)->tclass) < 0)
|
inet6_sk(sk)->tclass) < 0)
|
||||||
goto errout;
|
goto errout;
|
||||||
|
|
||||||
if (ipv6_only_sock(sk) &&
|
if (((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) &&
|
||||||
nla_put_u8(skb, INET_DIAG_SKV6ONLY, 1))
|
nla_put_u8(skb, INET_DIAG_SKV6ONLY, ipv6_only_sock(sk)))
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -586,7 +586,8 @@ int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
|
||||||
EXPORT_SYMBOL(ip_tunnel_encap);
|
EXPORT_SYMBOL(ip_tunnel_encap);
|
||||||
|
|
||||||
static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
|
static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
|
||||||
struct rtable *rt, __be16 df)
|
struct rtable *rt, __be16 df,
|
||||||
|
const struct iphdr *inner_iph)
|
||||||
{
|
{
|
||||||
struct ip_tunnel *tunnel = netdev_priv(dev);
|
struct ip_tunnel *tunnel = netdev_priv(dev);
|
||||||
int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len;
|
int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len;
|
||||||
|
@ -603,7 +604,8 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
|
||||||
|
|
||||||
if (skb->protocol == htons(ETH_P_IP)) {
|
if (skb->protocol == htons(ETH_P_IP)) {
|
||||||
if (!skb_is_gso(skb) &&
|
if (!skb_is_gso(skb) &&
|
||||||
(df & htons(IP_DF)) && mtu < pkt_size) {
|
(inner_iph->frag_off & htons(IP_DF)) &&
|
||||||
|
mtu < pkt_size) {
|
||||||
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
|
memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
|
||||||
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
|
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
|
@ -737,7 +739,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||||
goto tx_error;
|
goto tx_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off)) {
|
if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off, inner_iph)) {
|
||||||
ip_rt_put(rt);
|
ip_rt_put(rt);
|
||||||
goto tx_error;
|
goto tx_error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,9 +254,10 @@ unsigned int arpt_do_table(struct sk_buff *skb,
|
||||||
static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
|
static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
|
||||||
unsigned int verdict = NF_DROP;
|
unsigned int verdict = NF_DROP;
|
||||||
const struct arphdr *arp;
|
const struct arphdr *arp;
|
||||||
struct arpt_entry *e, *back;
|
struct arpt_entry *e, **jumpstack;
|
||||||
const char *indev, *outdev;
|
const char *indev, *outdev;
|
||||||
const void *table_base;
|
const void *table_base;
|
||||||
|
unsigned int cpu, stackidx = 0;
|
||||||
const struct xt_table_info *private;
|
const struct xt_table_info *private;
|
||||||
struct xt_action_param acpar;
|
struct xt_action_param acpar;
|
||||||
unsigned int addend;
|
unsigned int addend;
|
||||||
|
@ -270,15 +271,16 @@ unsigned int arpt_do_table(struct sk_buff *skb,
|
||||||
local_bh_disable();
|
local_bh_disable();
|
||||||
addend = xt_write_recseq_begin();
|
addend = xt_write_recseq_begin();
|
||||||
private = table->private;
|
private = table->private;
|
||||||
|
cpu = smp_processor_id();
|
||||||
/*
|
/*
|
||||||
* Ensure we load private-> members after we've fetched the base
|
* Ensure we load private-> members after we've fetched the base
|
||||||
* pointer.
|
* pointer.
|
||||||
*/
|
*/
|
||||||
smp_read_barrier_depends();
|
smp_read_barrier_depends();
|
||||||
table_base = private->entries;
|
table_base = private->entries;
|
||||||
|
jumpstack = (struct arpt_entry **)private->jumpstack[cpu];
|
||||||
|
|
||||||
e = get_entry(table_base, private->hook_entry[hook]);
|
e = get_entry(table_base, private->hook_entry[hook]);
|
||||||
back = get_entry(table_base, private->underflow[hook]);
|
|
||||||
|
|
||||||
acpar.in = state->in;
|
acpar.in = state->in;
|
||||||
acpar.out = state->out;
|
acpar.out = state->out;
|
||||||
|
@ -312,18 +314,23 @@ unsigned int arpt_do_table(struct sk_buff *skb,
|
||||||
verdict = (unsigned int)(-v) - 1;
|
verdict = (unsigned int)(-v) - 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
e = back;
|
if (stackidx == 0) {
|
||||||
back = get_entry(table_base, back->comefrom);
|
e = get_entry(table_base,
|
||||||
|
private->underflow[hook]);
|
||||||
|
} else {
|
||||||
|
e = jumpstack[--stackidx];
|
||||||
|
e = arpt_next_entry(e);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (table_base + v
|
if (table_base + v
|
||||||
!= arpt_next_entry(e)) {
|
!= arpt_next_entry(e)) {
|
||||||
/* Save old back ptr in next entry */
|
|
||||||
struct arpt_entry *next = arpt_next_entry(e);
|
|
||||||
next->comefrom = (void *)back - table_base;
|
|
||||||
|
|
||||||
/* set back pointer to next entry */
|
if (stackidx >= private->stacksize) {
|
||||||
back = next;
|
verdict = NF_DROP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
jumpstack[stackidx++] = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = get_entry(table_base, v);
|
e = get_entry(table_base, v);
|
||||||
|
|
|
@ -331,10 +331,10 @@ int ip6_mc_input(struct sk_buff *skb)
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!ipv6_is_mld(skb, nexthdr, offset))
|
if (ipv6_is_mld(skb, nexthdr, offset))
|
||||||
goto out;
|
deliver = true;
|
||||||
|
|
||||||
deliver = true;
|
goto out;
|
||||||
}
|
}
|
||||||
/* unknown RA - process it normally */
|
/* unknown RA - process it normally */
|
||||||
}
|
}
|
||||||
|
|
|
@ -369,10 +369,7 @@ static void ip6_dst_destroy(struct dst_entry *dst)
|
||||||
struct inet6_dev *idev;
|
struct inet6_dev *idev;
|
||||||
|
|
||||||
dst_destroy_metrics_generic(dst);
|
dst_destroy_metrics_generic(dst);
|
||||||
|
free_percpu(rt->rt6i_pcpu);
|
||||||
if (rt->rt6i_pcpu)
|
|
||||||
free_percpu(rt->rt6i_pcpu);
|
|
||||||
|
|
||||||
rt6_uncached_list_del(rt);
|
rt6_uncached_list_del(rt);
|
||||||
|
|
||||||
idev = rt->rt6i_idev;
|
idev = rt->rt6i_idev;
|
||||||
|
|
|
@ -213,7 +213,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
|
||||||
|
|
||||||
if (verdict == NF_ACCEPT) {
|
if (verdict == NF_ACCEPT) {
|
||||||
next_hook:
|
next_hook:
|
||||||
verdict = nf_iterate(&nf_hooks[entry->state.pf][entry->state.hook],
|
verdict = nf_iterate(entry->state.hook_list,
|
||||||
skb, &entry->state, &elem);
|
skb, &entry->state, &elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -269,6 +269,12 @@ static void nfnl_err_deliver(struct list_head *err_list, struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NFNL_BATCH_FAILURE = (1 << 0),
|
||||||
|
NFNL_BATCH_DONE = (1 << 1),
|
||||||
|
NFNL_BATCH_REPLAY = (1 << 2),
|
||||||
|
};
|
||||||
|
|
||||||
static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
|
static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||||
u_int16_t subsys_id)
|
u_int16_t subsys_id)
|
||||||
{
|
{
|
||||||
|
@ -276,13 +282,15 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||||
struct net *net = sock_net(skb->sk);
|
struct net *net = sock_net(skb->sk);
|
||||||
const struct nfnetlink_subsystem *ss;
|
const struct nfnetlink_subsystem *ss;
|
||||||
const struct nfnl_callback *nc;
|
const struct nfnl_callback *nc;
|
||||||
bool success = true, done = false;
|
|
||||||
static LIST_HEAD(err_list);
|
static LIST_HEAD(err_list);
|
||||||
|
u32 status;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (subsys_id >= NFNL_SUBSYS_COUNT)
|
if (subsys_id >= NFNL_SUBSYS_COUNT)
|
||||||
return netlink_ack(skb, nlh, -EINVAL);
|
return netlink_ack(skb, nlh, -EINVAL);
|
||||||
replay:
|
replay:
|
||||||
|
status = 0;
|
||||||
|
|
||||||
skb = netlink_skb_clone(oskb, GFP_KERNEL);
|
skb = netlink_skb_clone(oskb, GFP_KERNEL);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return netlink_ack(oskb, nlh, -ENOMEM);
|
return netlink_ack(oskb, nlh, -ENOMEM);
|
||||||
|
@ -336,10 +344,10 @@ replay:
|
||||||
if (type == NFNL_MSG_BATCH_BEGIN) {
|
if (type == NFNL_MSG_BATCH_BEGIN) {
|
||||||
/* Malformed: Batch begin twice */
|
/* Malformed: Batch begin twice */
|
||||||
nfnl_err_reset(&err_list);
|
nfnl_err_reset(&err_list);
|
||||||
success = false;
|
status |= NFNL_BATCH_FAILURE;
|
||||||
goto done;
|
goto done;
|
||||||
} else if (type == NFNL_MSG_BATCH_END) {
|
} else if (type == NFNL_MSG_BATCH_END) {
|
||||||
done = true;
|
status |= NFNL_BATCH_DONE;
|
||||||
goto done;
|
goto done;
|
||||||
} else if (type < NLMSG_MIN_TYPE) {
|
} else if (type < NLMSG_MIN_TYPE) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
|
@ -382,11 +390,8 @@ replay:
|
||||||
* original skb.
|
* original skb.
|
||||||
*/
|
*/
|
||||||
if (err == -EAGAIN) {
|
if (err == -EAGAIN) {
|
||||||
nfnl_err_reset(&err_list);
|
status |= NFNL_BATCH_REPLAY;
|
||||||
ss->abort(oskb);
|
goto next;
|
||||||
nfnl_unlock(subsys_id);
|
|
||||||
kfree_skb(skb);
|
|
||||||
goto replay;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ack:
|
ack:
|
||||||
|
@ -402,7 +407,7 @@ ack:
|
||||||
*/
|
*/
|
||||||
nfnl_err_reset(&err_list);
|
nfnl_err_reset(&err_list);
|
||||||
netlink_ack(skb, nlmsg_hdr(oskb), -ENOMEM);
|
netlink_ack(skb, nlmsg_hdr(oskb), -ENOMEM);
|
||||||
success = false;
|
status |= NFNL_BATCH_FAILURE;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* We don't stop processing the batch on errors, thus,
|
/* We don't stop processing the batch on errors, thus,
|
||||||
|
@ -410,19 +415,26 @@ ack:
|
||||||
* triggers.
|
* triggers.
|
||||||
*/
|
*/
|
||||||
if (err)
|
if (err)
|
||||||
success = false;
|
status |= NFNL_BATCH_FAILURE;
|
||||||
}
|
}
|
||||||
|
next:
|
||||||
msglen = NLMSG_ALIGN(nlh->nlmsg_len);
|
msglen = NLMSG_ALIGN(nlh->nlmsg_len);
|
||||||
if (msglen > skb->len)
|
if (msglen > skb->len)
|
||||||
msglen = skb->len;
|
msglen = skb->len;
|
||||||
skb_pull(skb, msglen);
|
skb_pull(skb, msglen);
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
if (success && done)
|
if (status & NFNL_BATCH_REPLAY) {
|
||||||
ss->commit(oskb);
|
|
||||||
else
|
|
||||||
ss->abort(oskb);
|
ss->abort(oskb);
|
||||||
|
nfnl_err_reset(&err_list);
|
||||||
|
nfnl_unlock(subsys_id);
|
||||||
|
kfree_skb(skb);
|
||||||
|
goto replay;
|
||||||
|
} else if (status == NFNL_BATCH_DONE) {
|
||||||
|
ss->commit(oskb);
|
||||||
|
} else {
|
||||||
|
ss->abort(oskb);
|
||||||
|
}
|
||||||
|
|
||||||
nfnl_err_deliver(&err_list, oskb);
|
nfnl_err_deliver(&err_list, oskb);
|
||||||
nfnl_unlock(subsys_id);
|
nfnl_unlock(subsys_id);
|
||||||
|
|
|
@ -158,7 +158,7 @@ static int __netlink_remove_tap(struct netlink_tap *nt)
|
||||||
out:
|
out:
|
||||||
spin_unlock(&netlink_tap_lock);
|
spin_unlock(&netlink_tap_lock);
|
||||||
|
|
||||||
if (found && nt->module)
|
if (found)
|
||||||
module_put(nt->module);
|
module_put(nt->module);
|
||||||
|
|
||||||
return found ? 0 : -ENODEV;
|
return found ? 0 : -ENODEV;
|
||||||
|
|
|
@ -73,7 +73,7 @@ EXPORT_SYMBOL_GPL(rds_trans_unregister);
|
||||||
|
|
||||||
void rds_trans_put(struct rds_transport *trans)
|
void rds_trans_put(struct rds_transport *trans)
|
||||||
{
|
{
|
||||||
if (trans && trans->t_owner)
|
if (trans)
|
||||||
module_put(trans->t_owner);
|
module_put(trans->t_owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,8 +171,10 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr)
|
||||||
* released.
|
* released.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
attr->trans = SWITCHDEV_TRANS_ABORT;
|
if (err != -EOPNOTSUPP) {
|
||||||
__switchdev_port_attr_set(dev, attr);
|
attr->trans = SWITCHDEV_TRANS_ABORT;
|
||||||
|
__switchdev_port_attr_set(dev, attr);
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -249,8 +251,10 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj)
|
||||||
* released.
|
* released.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
obj->trans = SWITCHDEV_TRANS_ABORT;
|
if (err != -EOPNOTSUPP) {
|
||||||
__switchdev_port_obj_add(dev, obj);
|
obj->trans = SWITCHDEV_TRANS_ABORT;
|
||||||
|
__switchdev_port_obj_add(dev, obj);
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2007,6 +2007,7 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags)
|
||||||
res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 1);
|
res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 1);
|
||||||
if (res)
|
if (res)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
security_sk_clone(sock->sk, new_sock->sk);
|
||||||
|
|
||||||
new_sk = new_sock->sk;
|
new_sk = new_sock->sk;
|
||||||
new_tsock = tipc_sk(new_sk);
|
new_tsock = tipc_sk(new_sk);
|
||||||
|
|
Loading…
Reference in New Issue