mirror of https://gitee.com/openkylin/linux.git
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: 1) Socket addresses returned in the error queue need to be fully initialized before being passed on to userspace, fix from Willem de Bruijn. 2) Interrupt handling fixes to davinci_emac driver from Tony Lindgren. 3) Fix races between receive packet steering and cpu hotplug, from Eric Dumazet. 4) Allowing netlink sockets to subscribe to unknown multicast groups leads to crashes, don't allow it. From Johannes Berg. 5) One to many socket races in SCTP fixed by Daniel Borkmann. 6) Put in a guard against the mis-use of ipv6 atomic fragments, from Hagen Paul Pfeifer. 7) Fix promisc mode and ethtool crashes in sh_eth driver, from Ben Hutchings. 8) NULL deref and double kfree fix in sxgbe driver from Girish K.S and Byungho An. 9) cfg80211 deadlock fix from Arik Nemtsov. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (36 commits) s2io: use snprintf() as a safety feature r8152: remove sram_read r8152: remove generic_ocp_read before writing bgmac: activate irqs only if there is nothing to poll bgmac: register napi before the device sh_eth: Fix ethtool operation crash when net device is down sh_eth: Fix promiscuous mode on chips without TSU ipv6: stop sending PTB packets for MTU < 1280 net: sctp: fix race for one-to-many sockets in sendmsg's auto associate genetlink: synchronize socket closing and family removal genetlink: disallow subscribing to unknown mcast groups genetlink: document parallel_ops net: rps: fix cpu unplug net: davinci_emac: Add support for emac on dm816x net: davinci_emac: Fix ioremap for devices with MDIO within the EMAC address space net: davinci_emac: Fix incomplete code for getting the phy from device tree net: davinci_emac: Free clock after checking the frequency net: davinci_emac: Fix runtime pm calls for davinci_emac net: davinci_emac: Fix hangs with interrupts ip: zero sockaddr returned on error queue ...
This commit is contained in:
commit
eef8f4c2ac
|
@ -4,7 +4,8 @@ This file provides information, what the device node
|
|||
for the davinci_emac interface contains.
|
||||
|
||||
Required properties:
|
||||
- compatible: "ti,davinci-dm6467-emac" or "ti,am3517-emac"
|
||||
- compatible: "ti,davinci-dm6467-emac", "ti,am3517-emac" or
|
||||
"ti,dm816-emac"
|
||||
- reg: Offset and length of the register set for the device
|
||||
- ti,davinci-ctrl-reg-offset: offset to control register
|
||||
- ti,davinci-ctrl-mod-reg-offset: offset to control module register
|
||||
|
|
|
@ -2346,7 +2346,8 @@ CAN NETWORK LAYER
|
|||
M: Oliver Hartkopp <socketcan@hartkopp.net>
|
||||
L: linux-can@vger.kernel.org
|
||||
W: http://gitorious.org/linux-can
|
||||
T: git git://gitorious.org/linux-can/linux-can-next.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git
|
||||
S: Maintained
|
||||
F: Documentation/networking/can.txt
|
||||
F: net/can/
|
||||
|
@ -2361,7 +2362,8 @@ M: Wolfgang Grandegger <wg@grandegger.com>
|
|||
M: Marc Kleine-Budde <mkl@pengutronix.de>
|
||||
L: linux-can@vger.kernel.org
|
||||
W: http://gitorious.org/linux-can
|
||||
T: git git://gitorious.org/linux-can/linux-can-next.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git
|
||||
S: Maintained
|
||||
F: drivers/net/can/
|
||||
F: include/linux/can/dev.h
|
||||
|
|
|
@ -1114,7 +1114,8 @@ static int mlx4_ib_tunnel_steer_add(struct ib_qp *qp, struct ib_flow_attr *flow_
|
|||
struct mlx4_dev *dev = to_mdev(qp->device)->dev;
|
||||
int err = 0;
|
||||
|
||||
if (dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
|
||||
if (dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN ||
|
||||
dev->caps.dmfs_high_steer_mode == MLX4_STEERING_DMFS_A0_STATIC)
|
||||
return 0; /* do nothing */
|
||||
|
||||
ib_flow = flow_attr + 1;
|
||||
|
|
|
@ -103,27 +103,34 @@ static void c_can_hw_raminit_syscon(const struct c_can_priv *priv, bool enable)
|
|||
mask = 1 << raminit->bits.start | 1 << raminit->bits.done;
|
||||
regmap_read(raminit->syscon, raminit->reg, &ctrl);
|
||||
|
||||
/* We clear the done and start bit first. The start bit is
|
||||
/* We clear the start bit first. The start bit is
|
||||
* looking at the 0 -> transition, but is not self clearing;
|
||||
* And we clear the init done bit as well.
|
||||
* NOTE: DONE must be written with 1 to clear it.
|
||||
* We can't clear the DONE bit here using regmap_update_bits()
|
||||
* as it will bypass the write if initial condition is START:0 DONE:1
|
||||
* e.g. on DRA7 which needs START pulse.
|
||||
*/
|
||||
ctrl &= ~(1 << raminit->bits.start);
|
||||
ctrl |= 1 << raminit->bits.done;
|
||||
regmap_write(raminit->syscon, raminit->reg, ctrl);
|
||||
ctrl &= ~mask; /* START = 0, DONE = 0 */
|
||||
regmap_update_bits(raminit->syscon, raminit->reg, mask, ctrl);
|
||||
|
||||
ctrl &= ~(1 << raminit->bits.done);
|
||||
c_can_hw_raminit_wait_syscon(priv, mask, ctrl);
|
||||
/* check if START bit is 0. Ignore DONE bit for now
|
||||
* as it can be either 0 or 1.
|
||||
*/
|
||||
c_can_hw_raminit_wait_syscon(priv, 1 << raminit->bits.start, ctrl);
|
||||
|
||||
if (enable) {
|
||||
/* Set start bit and wait for the done bit. */
|
||||
/* Clear DONE bit & set START bit. */
|
||||
ctrl |= 1 << raminit->bits.start;
|
||||
regmap_write(raminit->syscon, raminit->reg, ctrl);
|
||||
|
||||
/* DONE must be written with 1 to clear it */
|
||||
ctrl |= 1 << raminit->bits.done;
|
||||
regmap_update_bits(raminit->syscon, raminit->reg, mask, ctrl);
|
||||
/* prevent further clearing of DONE bit */
|
||||
ctrl &= ~(1 << raminit->bits.done);
|
||||
/* clear START bit if start pulse is needed */
|
||||
if (raminit->needs_pulse) {
|
||||
ctrl &= ~(1 << raminit->bits.start);
|
||||
regmap_write(raminit->syscon, raminit->reg, ctrl);
|
||||
regmap_update_bits(raminit->syscon, raminit->reg,
|
||||
mask, ctrl);
|
||||
}
|
||||
|
||||
ctrl |= 1 << raminit->bits.done;
|
||||
|
|
|
@ -807,10 +807,14 @@ static int can_changelink(struct net_device *dev,
|
|||
if (dev->flags & IFF_UP)
|
||||
return -EBUSY;
|
||||
cm = nla_data(data[IFLA_CAN_CTRLMODE]);
|
||||
if (cm->flags & ~priv->ctrlmode_supported)
|
||||
|
||||
/* check whether changed bits are allowed to be modified */
|
||||
if (cm->mask & ~priv->ctrlmode_supported)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* clear bits to be modified and copy the flag values */
|
||||
priv->ctrlmode &= ~cm->mask;
|
||||
priv->ctrlmode |= cm->flags;
|
||||
priv->ctrlmode |= (cm->flags & cm->mask);
|
||||
|
||||
/* CAN_CTRLMODE_FD can only be set when driver supports FD */
|
||||
if (priv->ctrlmode & CAN_CTRLMODE_FD)
|
||||
|
|
|
@ -955,6 +955,11 @@ static struct net_device *alloc_m_can_dev(void)
|
|||
priv->can.data_bittiming_const = &m_can_data_bittiming_const;
|
||||
priv->can.do_set_mode = m_can_set_mode;
|
||||
priv->can.do_get_berr_counter = m_can_get_berr_counter;
|
||||
|
||||
/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.1 */
|
||||
priv->can.ctrlmode = CAN_CTRLMODE_FD_NON_ISO;
|
||||
|
||||
/* CAN_CTRLMODE_FD_NON_ISO can not be changed with M_CAN IP v3.0.1 */
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
|
||||
CAN_CTRLMODE_LISTENONLY |
|
||||
CAN_CTRLMODE_BERR_REPORTING |
|
||||
|
|
|
@ -520,10 +520,10 @@ static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,
|
|||
skb = alloc_can_err_skb(priv->netdev, &cf);
|
||||
if (skb) {
|
||||
cf->can_id |= CAN_ERR_RESTARTED;
|
||||
netif_rx(skb);
|
||||
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += cf->can_dlc;
|
||||
netif_rx(skb);
|
||||
} else {
|
||||
netdev_err(priv->netdev,
|
||||
"No memory left for err_skb\n");
|
||||
|
@ -770,10 +770,9 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev,
|
|||
|
||||
priv->can.state = new_state;
|
||||
|
||||
netif_rx(skb);
|
||||
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += cf->can_dlc;
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
||||
static void kvaser_usb_rx_can_err(const struct kvaser_usb_net_priv *priv,
|
||||
|
@ -805,10 +804,9 @@ static void kvaser_usb_rx_can_err(const struct kvaser_usb_net_priv *priv,
|
|||
stats->rx_over_errors++;
|
||||
stats->rx_errors++;
|
||||
|
||||
netif_rx(skb);
|
||||
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += cf->can_dlc;
|
||||
netif_rx(skb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -887,10 +885,9 @@ static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
|
|||
cf->can_dlc);
|
||||
}
|
||||
|
||||
netif_rx(skb);
|
||||
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += cf->can_dlc;
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
||||
static void kvaser_usb_start_chip_reply(const struct kvaser_usb *dev,
|
||||
|
@ -1246,6 +1243,9 @@ static int kvaser_usb_close(struct net_device *netdev)
|
|||
if (err)
|
||||
netdev_warn(netdev, "Cannot stop device, error %d\n", err);
|
||||
|
||||
/* reset tx contexts */
|
||||
kvaser_usb_unlink_tx_urbs(priv);
|
||||
|
||||
priv->can.state = CAN_STATE_STOPPED;
|
||||
close_candev(priv->netdev);
|
||||
|
||||
|
@ -1294,12 +1294,14 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
|
|||
if (!urb) {
|
||||
netdev_err(netdev, "No memory left for URBs\n");
|
||||
stats->tx_dropped++;
|
||||
goto nourbmem;
|
||||
dev_kfree_skb(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
|
||||
if (!buf) {
|
||||
stats->tx_dropped++;
|
||||
dev_kfree_skb(skb);
|
||||
goto nobufmem;
|
||||
}
|
||||
|
||||
|
@ -1334,6 +1336,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
|
|||
}
|
||||
}
|
||||
|
||||
/* This should never happen; it implies a flow control bug */
|
||||
if (!context) {
|
||||
netdev_warn(netdev, "cannot find free context\n");
|
||||
ret = NETDEV_TX_BUSY;
|
||||
|
@ -1364,9 +1367,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
|
|||
if (unlikely(err)) {
|
||||
can_free_echo_skb(netdev, context->echo_index);
|
||||
|
||||
skb = NULL; /* set to NULL to avoid double free in
|
||||
* dev_kfree_skb(skb) */
|
||||
|
||||
atomic_dec(&priv->active_tx_urbs);
|
||||
usb_unanchor_urb(urb);
|
||||
|
||||
|
@ -1388,8 +1388,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
|
|||
kfree(buf);
|
||||
nobufmem:
|
||||
usb_free_urb(urb);
|
||||
nourbmem:
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1502,6 +1500,10 @@ static int kvaser_usb_init_one(struct usb_interface *intf,
|
|||
struct kvaser_usb_net_priv *priv;
|
||||
int i, err;
|
||||
|
||||
err = kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, channel);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
|
||||
if (!netdev) {
|
||||
dev_err(&intf->dev, "Cannot alloc candev\n");
|
||||
|
@ -1606,9 +1608,6 @@ static int kvaser_usb_probe(struct usb_interface *intf,
|
|||
|
||||
usb_set_intfdata(intf, dev);
|
||||
|
||||
for (i = 0; i < MAX_NET_DEVICES; i++)
|
||||
kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, i);
|
||||
|
||||
err = kvaser_usb_get_software_info(dev);
|
||||
if (err) {
|
||||
dev_err(&intf->dev,
|
||||
|
|
|
@ -1167,10 +1167,10 @@ static int bgmac_poll(struct napi_struct *napi, int weight)
|
|||
bgmac->int_status = 0;
|
||||
}
|
||||
|
||||
if (handled < weight)
|
||||
if (handled < weight) {
|
||||
napi_complete(napi);
|
||||
|
||||
bgmac_chip_intrs_on(bgmac);
|
||||
bgmac_chip_intrs_on(bgmac);
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
@ -1515,6 +1515,8 @@ static int bgmac_probe(struct bcma_device *core)
|
|||
if (core->bus->sprom.boardflags_lo & BGMAC_BFL_ENETADM)
|
||||
bgmac_warn(bgmac, "Support for ADMtek ethernet switch not implemented\n");
|
||||
|
||||
netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);
|
||||
|
||||
err = bgmac_mii_register(bgmac);
|
||||
if (err) {
|
||||
bgmac_err(bgmac, "Cannot register MDIO\n");
|
||||
|
@ -1529,8 +1531,6 @@ static int bgmac_probe(struct bcma_device *core)
|
|||
|
||||
netif_carrier_off(net_dev);
|
||||
|
||||
netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);
|
||||
|
||||
return 0;
|
||||
|
||||
err_mii_unregister:
|
||||
|
@ -1549,9 +1549,9 @@ static void bgmac_remove(struct bcma_device *core)
|
|||
{
|
||||
struct bgmac *bgmac = bcma_get_drvdata(core);
|
||||
|
||||
netif_napi_del(&bgmac->napi);
|
||||
unregister_netdev(bgmac->net_dev);
|
||||
bgmac_mii_unregister(bgmac);
|
||||
netif_napi_del(&bgmac->napi);
|
||||
bgmac_dma_free(bgmac);
|
||||
bcma_set_drvdata(core, NULL);
|
||||
free_netdev(bgmac->net_dev);
|
||||
|
|
|
@ -4383,8 +4383,9 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
|||
* distinguish various types of transports (VxLAN, GRE, NVGRE ..). So, offload
|
||||
* is expected to work across all types of IP tunnels once exported. Skyhawk
|
||||
* supports offloads for either VxLAN or NVGRE, exclusively. So we export VxLAN
|
||||
* offloads in hw_enc_features only when a VxLAN port is added. Note this only
|
||||
* ensures that other tunnels work fine while VxLAN offloads are not enabled.
|
||||
* offloads in hw_enc_features only when a VxLAN port is added. If other (non
|
||||
* VxLAN) tunnels are configured while VxLAN offloads are enabled, offloads for
|
||||
* those other tunnels are unexported on the fly through ndo_features_check().
|
||||
*
|
||||
* Skyhawk supports VxLAN offloads only for one UDP dport. So, if the stack
|
||||
* adds more than one port, disable offloads and don't re-enable them again
|
||||
|
@ -4463,7 +4464,41 @@ static netdev_features_t be_features_check(struct sk_buff *skb,
|
|||
struct net_device *dev,
|
||||
netdev_features_t features)
|
||||
{
|
||||
return vxlan_features_check(skb, features);
|
||||
struct be_adapter *adapter = netdev_priv(dev);
|
||||
u8 l4_hdr = 0;
|
||||
|
||||
/* The code below restricts offload features for some tunneled packets.
|
||||
* Offload features for normal (non tunnel) packets are unchanged.
|
||||
*/
|
||||
if (!skb->encapsulation ||
|
||||
!(adapter->flags & BE_FLAGS_VXLAN_OFFLOADS))
|
||||
return features;
|
||||
|
||||
/* It's an encapsulated packet and VxLAN offloads are enabled. We
|
||||
* should disable tunnel offload features if it's not a VxLAN packet,
|
||||
* as tunnel offloads have been enabled only for VxLAN. This is done to
|
||||
* allow other tunneled traffic like GRE work fine while VxLAN
|
||||
* offloads are configured in Skyhawk-R.
|
||||
*/
|
||||
switch (vlan_get_protocol(skb)) {
|
||||
case htons(ETH_P_IP):
|
||||
l4_hdr = ip_hdr(skb)->protocol;
|
||||
break;
|
||||
case htons(ETH_P_IPV6):
|
||||
l4_hdr = ipv6_hdr(skb)->nexthdr;
|
||||
break;
|
||||
default:
|
||||
return features;
|
||||
}
|
||||
|
||||
if (l4_hdr != IPPROTO_UDP ||
|
||||
skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
|
||||
skb->inner_protocol != htons(ETH_P_TEB) ||
|
||||
skb_inner_mac_header(skb) - skb_transport_header(skb) !=
|
||||
sizeof(struct udphdr) + sizeof(struct vxlanhdr))
|
||||
return features & ~(NETIF_F_ALL_CSUM | NETIF_F_GSO_MASK);
|
||||
|
||||
return features;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -475,7 +475,8 @@ static int mlx4_en_tunnel_steer_add(struct mlx4_en_priv *priv, unsigned char *ad
|
|||
{
|
||||
int err;
|
||||
|
||||
if (priv->mdev->dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
|
||||
if (priv->mdev->dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN ||
|
||||
priv->mdev->dev->caps.dmfs_high_steer_mode == MLX4_STEERING_DMFS_A0_STATIC)
|
||||
return 0; /* do nothing */
|
||||
|
||||
err = mlx4_tunnel_steer_add(priv->mdev->dev, addr, priv->port, qpn,
|
||||
|
|
|
@ -1744,8 +1744,7 @@ static void choose_tunnel_offload_mode(struct mlx4_dev *dev,
|
|||
struct mlx4_dev_cap *dev_cap)
|
||||
{
|
||||
if (dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED &&
|
||||
dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS &&
|
||||
dev->caps.dmfs_high_steer_mode != MLX4_STEERING_DMFS_A0_STATIC)
|
||||
dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS)
|
||||
dev->caps.tunnel_offload_mode = MLX4_TUNNEL_OFFLOAD_MODE_VXLAN;
|
||||
else
|
||||
dev->caps.tunnel_offload_mode = MLX4_TUNNEL_OFFLOAD_MODE_NONE;
|
||||
|
|
|
@ -6987,7 +6987,9 @@ static int s2io_add_isr(struct s2io_nic *sp)
|
|||
if (sp->s2io_entries[i].in_use == MSIX_FLG) {
|
||||
if (sp->s2io_entries[i].type ==
|
||||
MSIX_RING_TYPE) {
|
||||
sprintf(sp->desc[i], "%s:MSI-X-%d-RX",
|
||||
snprintf(sp->desc[i],
|
||||
sizeof(sp->desc[i]),
|
||||
"%s:MSI-X-%d-RX",
|
||||
dev->name, i);
|
||||
err = request_irq(sp->entries[i].vector,
|
||||
s2io_msix_ring_handle,
|
||||
|
@ -6996,7 +6998,9 @@ static int s2io_add_isr(struct s2io_nic *sp)
|
|||
sp->s2io_entries[i].arg);
|
||||
} else if (sp->s2io_entries[i].type ==
|
||||
MSIX_ALARM_TYPE) {
|
||||
sprintf(sp->desc[i], "%s:MSI-X-%d-TX",
|
||||
snprintf(sp->desc[i],
|
||||
sizeof(sp->desc[i]),
|
||||
"%s:MSI-X-%d-TX",
|
||||
dev->name, i);
|
||||
err = request_irq(sp->entries[i].vector,
|
||||
s2io_msix_fifo_handle,
|
||||
|
@ -8154,7 +8158,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
|
|||
"%s: UDP Fragmentation Offload(UFO) enabled\n",
|
||||
dev->name);
|
||||
/* Initialize device name */
|
||||
sprintf(sp->name, "%s Neterion %s", dev->name, sp->product_name);
|
||||
snprintf(sp->name, sizeof(sp->name), "%s Neterion %s", dev->name,
|
||||
sp->product_name);
|
||||
|
||||
if (vlan_tag_strip)
|
||||
sp->vlan_strip_flag = 1;
|
||||
|
|
|
@ -498,6 +498,8 @@ static struct sh_eth_cpu_data r8a779x_data = {
|
|||
EESR_ECI,
|
||||
.fdr_value = 0x00000f0f,
|
||||
|
||||
.trscer_err_mask = DESC_I_RINT8,
|
||||
|
||||
.apr = 1,
|
||||
.mpr = 1,
|
||||
.tpauser = 1,
|
||||
|
@ -538,8 +540,6 @@ static struct sh_eth_cpu_data sh7724_data = {
|
|||
EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE |
|
||||
EESR_ECI,
|
||||
|
||||
.trscer_err_mask = DESC_I_RINT8,
|
||||
|
||||
.apr = 1,
|
||||
.mpr = 1,
|
||||
.tpauser = 1,
|
||||
|
@ -1827,6 +1827,9 @@ static int sh_eth_get_settings(struct net_device *ndev,
|
|||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (!mdp->phydev)
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_irqsave(&mdp->lock, flags);
|
||||
ret = phy_ethtool_gset(mdp->phydev, ecmd);
|
||||
spin_unlock_irqrestore(&mdp->lock, flags);
|
||||
|
@ -1841,6 +1844,9 @@ static int sh_eth_set_settings(struct net_device *ndev,
|
|||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (!mdp->phydev)
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_irqsave(&mdp->lock, flags);
|
||||
|
||||
/* disable tx and rx */
|
||||
|
@ -1875,6 +1881,9 @@ static int sh_eth_nway_reset(struct net_device *ndev)
|
|||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (!mdp->phydev)
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_irqsave(&mdp->lock, flags);
|
||||
ret = phy_start_aneg(mdp->phydev);
|
||||
spin_unlock_irqrestore(&mdp->lock, flags);
|
||||
|
@ -2184,6 +2193,7 @@ static int sh_eth_close(struct net_device *ndev)
|
|||
if (mdp->phydev) {
|
||||
phy_stop(mdp->phydev);
|
||||
phy_disconnect(mdp->phydev);
|
||||
mdp->phydev = NULL;
|
||||
}
|
||||
|
||||
free_irq(ndev->irq, ndev);
|
||||
|
@ -2417,7 +2427,7 @@ static int sh_eth_tsu_purge_all(struct net_device *ndev)
|
|||
struct sh_eth_private *mdp = netdev_priv(ndev);
|
||||
int i, ret;
|
||||
|
||||
if (unlikely(!mdp->cd->tsu))
|
||||
if (!mdp->cd->tsu)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++) {
|
||||
|
@ -2440,7 +2450,7 @@ static void sh_eth_tsu_purge_mcast(struct net_device *ndev)
|
|||
void *reg_offset = sh_eth_tsu_get_offset(mdp, TSU_ADRH0);
|
||||
int i;
|
||||
|
||||
if (unlikely(!mdp->cd->tsu))
|
||||
if (!mdp->cd->tsu)
|
||||
return;
|
||||
|
||||
for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++, reg_offset += 8) {
|
||||
|
@ -2450,8 +2460,8 @@ static void sh_eth_tsu_purge_mcast(struct net_device *ndev)
|
|||
}
|
||||
}
|
||||
|
||||
/* Multicast reception directions set */
|
||||
static void sh_eth_set_multicast_list(struct net_device *ndev)
|
||||
/* Update promiscuous flag and multicast filter */
|
||||
static void sh_eth_set_rx_mode(struct net_device *ndev)
|
||||
{
|
||||
struct sh_eth_private *mdp = netdev_priv(ndev);
|
||||
u32 ecmr_bits;
|
||||
|
@ -2462,7 +2472,9 @@ static void sh_eth_set_multicast_list(struct net_device *ndev)
|
|||
/* Initial condition is MCT = 1, PRM = 0.
|
||||
* Depending on ndev->flags, set PRM or clear MCT
|
||||
*/
|
||||
ecmr_bits = (sh_eth_read(ndev, ECMR) & ~ECMR_PRM) | ECMR_MCT;
|
||||
ecmr_bits = sh_eth_read(ndev, ECMR) & ~ECMR_PRM;
|
||||
if (mdp->cd->tsu)
|
||||
ecmr_bits |= ECMR_MCT;
|
||||
|
||||
if (!(ndev->flags & IFF_MULTICAST)) {
|
||||
sh_eth_tsu_purge_mcast(ndev);
|
||||
|
@ -2491,9 +2503,6 @@ static void sh_eth_set_multicast_list(struct net_device *ndev)
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Normal, unicast/broadcast-only mode. */
|
||||
ecmr_bits = (ecmr_bits & ~ECMR_PRM) | ECMR_MCT;
|
||||
}
|
||||
|
||||
/* update the ethernet mode */
|
||||
|
@ -2701,6 +2710,7 @@ static const struct net_device_ops sh_eth_netdev_ops = {
|
|||
.ndo_stop = sh_eth_close,
|
||||
.ndo_start_xmit = sh_eth_start_xmit,
|
||||
.ndo_get_stats = sh_eth_get_stats,
|
||||
.ndo_set_rx_mode = sh_eth_set_rx_mode,
|
||||
.ndo_tx_timeout = sh_eth_tx_timeout,
|
||||
.ndo_do_ioctl = sh_eth_do_ioctl,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
|
@ -2713,7 +2723,7 @@ static const struct net_device_ops sh_eth_netdev_ops_tsu = {
|
|||
.ndo_stop = sh_eth_close,
|
||||
.ndo_start_xmit = sh_eth_start_xmit,
|
||||
.ndo_get_stats = sh_eth_get_stats,
|
||||
.ndo_set_rx_mode = sh_eth_set_multicast_list,
|
||||
.ndo_set_rx_mode = sh_eth_set_rx_mode,
|
||||
.ndo_vlan_rx_add_vid = sh_eth_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = sh_eth_vlan_rx_kill_vid,
|
||||
.ndo_tx_timeout = sh_eth_tx_timeout,
|
||||
|
|
|
@ -474,13 +474,19 @@ static int init_rx_ring(struct net_device *dev, u8 queue_no,
|
|||
/* allocate memory for RX skbuff array */
|
||||
rx_ring->rx_skbuff_dma = kmalloc_array(rx_rsize,
|
||||
sizeof(dma_addr_t), GFP_KERNEL);
|
||||
if (rx_ring->rx_skbuff_dma == NULL)
|
||||
goto dmamem_err;
|
||||
if (!rx_ring->rx_skbuff_dma) {
|
||||
dma_free_coherent(priv->device,
|
||||
rx_rsize * sizeof(struct sxgbe_rx_norm_desc),
|
||||
rx_ring->dma_rx, rx_ring->dma_rx_phy);
|
||||
goto error;
|
||||
}
|
||||
|
||||
rx_ring->rx_skbuff = kmalloc_array(rx_rsize,
|
||||
sizeof(struct sk_buff *), GFP_KERNEL);
|
||||
if (rx_ring->rx_skbuff == NULL)
|
||||
goto rxbuff_err;
|
||||
if (!rx_ring->rx_skbuff) {
|
||||
kfree(rx_ring->rx_skbuff_dma);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* initialise the buffers */
|
||||
for (desc_index = 0; desc_index < rx_rsize; desc_index++) {
|
||||
|
@ -502,13 +508,6 @@ static int init_rx_ring(struct net_device *dev, u8 queue_no,
|
|||
err_init_rx_buffers:
|
||||
while (--desc_index >= 0)
|
||||
free_rx_ring(priv->device, rx_ring, desc_index);
|
||||
kfree(rx_ring->rx_skbuff);
|
||||
rxbuff_err:
|
||||
kfree(rx_ring->rx_skbuff_dma);
|
||||
dmamem_err:
|
||||
dma_free_coherent(priv->device,
|
||||
rx_rsize * sizeof(struct sxgbe_rx_norm_desc),
|
||||
rx_ring->dma_rx, rx_ring->dma_rx_phy);
|
||||
error:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
|
@ -108,10 +108,6 @@ static int sxgbe_platform_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
/* Get MAC address if available (DT) */
|
||||
if (mac)
|
||||
ether_addr_copy(priv->dev->dev_addr, mac);
|
||||
|
||||
priv = sxgbe_drv_probe(&(pdev->dev), plat_dat, addr);
|
||||
if (!priv) {
|
||||
pr_err("%s: main driver probe failed\n", __func__);
|
||||
|
@ -125,6 +121,10 @@ static int sxgbe_platform_probe(struct platform_device *pdev)
|
|||
goto err_drv_remove;
|
||||
}
|
||||
|
||||
/* Get MAC address if available (DT) */
|
||||
if (mac)
|
||||
ether_addr_copy(priv->dev->dev_addr, mac);
|
||||
|
||||
/* Get the TX/RX IRQ numbers */
|
||||
for (i = 0, chan = 1; i < SXGBE_TX_QUEUES; i++) {
|
||||
priv->txq[i]->irq_no = irq_of_parse_and_map(node, chan++);
|
||||
|
|
|
@ -1634,16 +1634,24 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
|
|||
unsigned short vid)
|
||||
{
|
||||
int ret;
|
||||
int unreg_mcast_mask;
|
||||
int unreg_mcast_mask = 0;
|
||||
u32 port_mask;
|
||||
|
||||
if (priv->ndev->flags & IFF_ALLMULTI)
|
||||
unreg_mcast_mask = ALE_ALL_PORTS;
|
||||
else
|
||||
unreg_mcast_mask = ALE_PORT_1 | ALE_PORT_2;
|
||||
if (priv->data.dual_emac) {
|
||||
port_mask = (1 << (priv->emac_port + 1)) | ALE_PORT_HOST;
|
||||
|
||||
ret = cpsw_ale_add_vlan(priv->ale, vid,
|
||||
ALE_ALL_PORTS << priv->host_port,
|
||||
0, ALE_ALL_PORTS << priv->host_port,
|
||||
if (priv->ndev->flags & IFF_ALLMULTI)
|
||||
unreg_mcast_mask = port_mask;
|
||||
} else {
|
||||
port_mask = ALE_ALL_PORTS;
|
||||
|
||||
if (priv->ndev->flags & IFF_ALLMULTI)
|
||||
unreg_mcast_mask = ALE_ALL_PORTS;
|
||||
else
|
||||
unreg_mcast_mask = ALE_PORT_1 | ALE_PORT_2;
|
||||
}
|
||||
|
||||
ret = cpsw_ale_add_vlan(priv->ale, vid, port_mask, 0, port_mask,
|
||||
unreg_mcast_mask << priv->host_port);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
@ -1654,8 +1662,7 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
|
|||
goto clean_vid;
|
||||
|
||||
ret = cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
|
||||
ALE_ALL_PORTS << priv->host_port,
|
||||
ALE_VLAN, vid, 0);
|
||||
port_mask, ALE_VLAN, vid, 0);
|
||||
if (ret != 0)
|
||||
goto clean_vlan_ucast;
|
||||
return 0;
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_net.h>
|
||||
|
||||
|
@ -343,9 +344,7 @@ struct emac_priv {
|
|||
u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS];
|
||||
u32 rx_addr_type;
|
||||
const char *phy_id;
|
||||
#ifdef CONFIG_OF
|
||||
struct device_node *phy_node;
|
||||
#endif
|
||||
struct phy_device *phydev;
|
||||
spinlock_t lock;
|
||||
/*platform specific members*/
|
||||
|
@ -922,6 +921,16 @@ static void emac_int_disable(struct emac_priv *priv)
|
|||
if (priv->int_disable)
|
||||
priv->int_disable();
|
||||
|
||||
/* NOTE: Rx Threshold and Misc interrupts are not enabled */
|
||||
|
||||
/* ack rxen only then a new pulse will be generated */
|
||||
emac_write(EMAC_DM646X_MACEOIVECTOR,
|
||||
EMAC_DM646X_MAC_EOI_C0_RXEN);
|
||||
|
||||
/* ack txen- only then a new pulse will be generated */
|
||||
emac_write(EMAC_DM646X_MACEOIVECTOR,
|
||||
EMAC_DM646X_MAC_EOI_C0_TXEN);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
} else {
|
||||
|
@ -951,15 +960,6 @@ static void emac_int_enable(struct emac_priv *priv)
|
|||
* register */
|
||||
|
||||
/* NOTE: Rx Threshold and Misc interrupts are not enabled */
|
||||
|
||||
/* ack rxen only then a new pulse will be generated */
|
||||
emac_write(EMAC_DM646X_MACEOIVECTOR,
|
||||
EMAC_DM646X_MAC_EOI_C0_RXEN);
|
||||
|
||||
/* ack txen- only then a new pulse will be generated */
|
||||
emac_write(EMAC_DM646X_MACEOIVECTOR,
|
||||
EMAC_DM646X_MAC_EOI_C0_TXEN);
|
||||
|
||||
} else {
|
||||
/* Set DM644x control registers for interrupt control */
|
||||
emac_ctrl_write(EMAC_CTRL_EWCTL, 0x1);
|
||||
|
@ -1537,7 +1537,13 @@ static int emac_dev_open(struct net_device *ndev)
|
|||
int i = 0;
|
||||
struct emac_priv *priv = netdev_priv(ndev);
|
||||
|
||||
pm_runtime_get(&priv->pdev->dev);
|
||||
ret = pm_runtime_get_sync(&priv->pdev->dev);
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_noidle(&priv->pdev->dev);
|
||||
dev_err(&priv->pdev->dev, "%s: failed to get_sync(%d)\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
netif_carrier_off(ndev);
|
||||
for (cnt = 0; cnt < ETH_ALEN; cnt++)
|
||||
|
@ -1596,8 +1602,20 @@ static int emac_dev_open(struct net_device *ndev)
|
|||
cpdma_ctlr_start(priv->dma);
|
||||
|
||||
priv->phydev = NULL;
|
||||
|
||||
if (priv->phy_node) {
|
||||
priv->phydev = of_phy_connect(ndev, priv->phy_node,
|
||||
&emac_adjust_link, 0, 0);
|
||||
if (!priv->phydev) {
|
||||
dev_err(emac_dev, "could not connect to phy %s\n",
|
||||
priv->phy_node->full_name);
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* use the first phy on the bus if pdata did not give us a phy id */
|
||||
if (!priv->phy_id) {
|
||||
if (!priv->phydev && !priv->phy_id) {
|
||||
struct device *phy;
|
||||
|
||||
phy = bus_find_device(&mdio_bus_type, NULL, NULL,
|
||||
|
@ -1606,7 +1624,7 @@ static int emac_dev_open(struct net_device *ndev)
|
|||
priv->phy_id = dev_name(phy);
|
||||
}
|
||||
|
||||
if (priv->phy_id && *priv->phy_id) {
|
||||
if (!priv->phydev && priv->phy_id && *priv->phy_id) {
|
||||
priv->phydev = phy_connect(ndev, priv->phy_id,
|
||||
&emac_adjust_link,
|
||||
PHY_INTERFACE_MODE_MII);
|
||||
|
@ -1627,7 +1645,9 @@ static int emac_dev_open(struct net_device *ndev)
|
|||
"(mii_bus:phy_addr=%s, id=%x)\n",
|
||||
priv->phydev->drv->name, dev_name(&priv->phydev->dev),
|
||||
priv->phydev->phy_id);
|
||||
} else {
|
||||
}
|
||||
|
||||
if (!priv->phydev) {
|
||||
/* No PHY , fix the link, speed and duplex settings */
|
||||
dev_notice(emac_dev, "no phy, defaulting to 100/full\n");
|
||||
priv->link = 1;
|
||||
|
@ -1724,6 +1744,15 @@ static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
|
|||
struct emac_priv *priv = netdev_priv(ndev);
|
||||
u32 mac_control;
|
||||
u32 stats_clear_mask;
|
||||
int err;
|
||||
|
||||
err = pm_runtime_get_sync(&priv->pdev->dev);
|
||||
if (err < 0) {
|
||||
pm_runtime_put_noidle(&priv->pdev->dev);
|
||||
dev_err(&priv->pdev->dev, "%s: failed to get_sync(%d)\n",
|
||||
__func__, err);
|
||||
return &ndev->stats;
|
||||
}
|
||||
|
||||
/* update emac hardware stats and reset the registers*/
|
||||
|
||||
|
@ -1766,6 +1795,8 @@ static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
|
|||
ndev->stats.tx_fifo_errors += emac_read(EMAC_TXUNDERRUN);
|
||||
emac_write(EMAC_TXUNDERRUN, stats_clear_mask);
|
||||
|
||||
pm_runtime_put(&priv->pdev->dev);
|
||||
|
||||
return &ndev->stats;
|
||||
}
|
||||
|
||||
|
@ -1859,7 +1890,7 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
|
|||
static int davinci_emac_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc = 0;
|
||||
struct resource *res;
|
||||
struct resource *res, *res_ctrl;
|
||||
struct net_device *ndev;
|
||||
struct emac_priv *priv;
|
||||
unsigned long hw_ram_addr;
|
||||
|
@ -1876,6 +1907,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
|
|||
return -EBUSY;
|
||||
}
|
||||
emac_bus_frequency = clk_get_rate(emac_clk);
|
||||
devm_clk_put(&pdev->dev, emac_clk);
|
||||
|
||||
/* TODO: Probe PHY here if possible */
|
||||
|
||||
|
@ -1917,11 +1949,20 @@ static int davinci_emac_probe(struct platform_device *pdev)
|
|||
rc = PTR_ERR(priv->remap_addr);
|
||||
goto no_pdata;
|
||||
}
|
||||
|
||||
res_ctrl = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
if (res_ctrl) {
|
||||
priv->ctrl_base =
|
||||
devm_ioremap_resource(&pdev->dev, res_ctrl);
|
||||
if (IS_ERR(priv->ctrl_base))
|
||||
goto no_pdata;
|
||||
} else {
|
||||
priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset;
|
||||
}
|
||||
|
||||
priv->emac_base = priv->remap_addr + pdata->ctrl_reg_offset;
|
||||
ndev->base_addr = (unsigned long)priv->remap_addr;
|
||||
|
||||
priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset;
|
||||
|
||||
hw_ram_addr = pdata->hw_ram_addr;
|
||||
if (!hw_ram_addr)
|
||||
hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset;
|
||||
|
@ -1980,12 +2021,22 @@ static int davinci_emac_probe(struct platform_device *pdev)
|
|||
ndev->ethtool_ops = ðtool_ops;
|
||||
netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT);
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
rc = pm_runtime_get_sync(&pdev->dev);
|
||||
if (rc < 0) {
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
dev_err(&pdev->dev, "%s: failed to get_sync(%d)\n",
|
||||
__func__, rc);
|
||||
goto no_cpdma_chan;
|
||||
}
|
||||
|
||||
/* register the network device */
|
||||
SET_NETDEV_DEV(ndev, &pdev->dev);
|
||||
rc = register_netdev(ndev);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "error in register_netdev\n");
|
||||
rc = -ENODEV;
|
||||
pm_runtime_put(&pdev->dev);
|
||||
goto no_cpdma_chan;
|
||||
}
|
||||
|
||||
|
@ -1995,9 +2046,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
|
|||
"(regs: %p, irq: %d)\n",
|
||||
(void *)priv->emac_base_phys, ndev->irq);
|
||||
}
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
pm_runtime_resume(&pdev->dev);
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -2071,9 +2120,14 @@ static const struct emac_platform_data am3517_emac_data = {
|
|||
.hw_ram_addr = 0x01e20000,
|
||||
};
|
||||
|
||||
static const struct emac_platform_data dm816_emac_data = {
|
||||
.version = EMAC_VERSION_2,
|
||||
};
|
||||
|
||||
static const struct of_device_id davinci_emac_of_match[] = {
|
||||
{.compatible = "ti,davinci-dm6467-emac", },
|
||||
{.compatible = "ti,am3517-emac", .data = &am3517_emac_data, },
|
||||
{.compatible = "ti,dm816-emac", .data = &dm816_emac_data, },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, davinci_emac_of_match);
|
||||
|
|
|
@ -833,9 +833,6 @@ static void ocp_write_word(struct r8152 *tp, u16 type, u16 index, u32 data)
|
|||
index &= ~3;
|
||||
}
|
||||
|
||||
generic_ocp_read(tp, index, sizeof(tmp), &tmp, type);
|
||||
|
||||
data |= __le32_to_cpu(tmp) & ~mask;
|
||||
tmp = __cpu_to_le32(data);
|
||||
|
||||
generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
|
||||
|
@ -874,9 +871,6 @@ static void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data)
|
|||
index &= ~3;
|
||||
}
|
||||
|
||||
generic_ocp_read(tp, index, sizeof(tmp), &tmp, type);
|
||||
|
||||
data |= __le32_to_cpu(tmp) & ~mask;
|
||||
tmp = __cpu_to_le32(data);
|
||||
|
||||
generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
|
||||
|
@ -926,12 +920,6 @@ static void sram_write(struct r8152 *tp, u16 addr, u16 data)
|
|||
ocp_reg_write(tp, OCP_SRAM_DATA, data);
|
||||
}
|
||||
|
||||
static u16 sram_read(struct r8152 *tp, u16 addr)
|
||||
{
|
||||
ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
|
||||
return ocp_reg_read(tp, OCP_SRAM_DATA);
|
||||
}
|
||||
|
||||
static int read_mii_word(struct net_device *netdev, int phy_id, int reg)
|
||||
{
|
||||
struct r8152 *tp = netdev_priv(netdev);
|
||||
|
@ -2518,24 +2506,18 @@ static void r8153_hw_phy_cfg(struct r8152 *tp)
|
|||
data = ocp_reg_read(tp, OCP_POWER_CFG);
|
||||
data |= EN_10M_PLLOFF;
|
||||
ocp_reg_write(tp, OCP_POWER_CFG, data);
|
||||
data = sram_read(tp, SRAM_IMPEDANCE);
|
||||
data &= ~RX_DRIVING_MASK;
|
||||
sram_write(tp, SRAM_IMPEDANCE, data);
|
||||
sram_write(tp, SRAM_IMPEDANCE, 0x0b13);
|
||||
|
||||
ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
|
||||
ocp_data |= PFM_PWM_SWITCH;
|
||||
ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
|
||||
|
||||
data = sram_read(tp, SRAM_LPF_CFG);
|
||||
data |= LPF_AUTO_TUNE;
|
||||
sram_write(tp, SRAM_LPF_CFG, data);
|
||||
/* Enable LPF corner auto tune */
|
||||
sram_write(tp, SRAM_LPF_CFG, 0xf70f);
|
||||
|
||||
data = sram_read(tp, SRAM_10M_AMP1);
|
||||
data |= GDAC_IB_UPALL;
|
||||
sram_write(tp, SRAM_10M_AMP1, data);
|
||||
data = sram_read(tp, SRAM_10M_AMP2);
|
||||
data |= AMP_DN;
|
||||
sram_write(tp, SRAM_10M_AMP2, data);
|
||||
/* Adjust 10M Amplitude */
|
||||
sram_write(tp, SRAM_10M_AMP1, 0x00af);
|
||||
sram_write(tp, SRAM_10M_AMP2, 0x0208);
|
||||
|
||||
set_bit(PHY_RESET, &tp->flags);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,10 @@ extern void genl_unlock(void);
|
|||
extern int lockdep_genl_is_held(void);
|
||||
#endif
|
||||
|
||||
/* for synchronisation between af_netlink and genetlink */
|
||||
extern atomic_t genl_sk_destructing_cnt;
|
||||
extern wait_queue_head_t genl_sk_destructing_waitq;
|
||||
|
||||
/**
|
||||
* rcu_dereference_genl - rcu_dereference with debug checking
|
||||
* @p: The pointer to read, prior to dereferencing
|
||||
|
|
|
@ -27,13 +27,18 @@ struct genl_info;
|
|||
* @maxattr: maximum number of attributes supported
|
||||
* @netnsok: set to true if the family can handle network
|
||||
* namespaces and should be presented in all of them
|
||||
* @parallel_ops: operations can be called in parallel and aren't
|
||||
* synchronized by the core genetlink code
|
||||
* @pre_doit: called before an operation's doit callback, it may
|
||||
* do additional, common, filtering and return an error
|
||||
* @post_doit: called after an operation's doit callback, it may
|
||||
* undo operations done by pre_doit, for example release locks
|
||||
* @mcast_bind: a socket bound to the given multicast group (which
|
||||
* is given as the offset into the groups array)
|
||||
* @mcast_unbind: a socket was unbound from the given multicast group
|
||||
* @mcast_unbind: a socket was unbound from the given multicast group.
|
||||
* Note that unbind() will not be called symmetrically if the
|
||||
* generic netlink family is removed while there are still open
|
||||
* sockets.
|
||||
* @attrbuf: buffer to store parsed attributes
|
||||
* @family_list: family list
|
||||
* @mcgrps: multicast groups used by this family (private)
|
||||
|
|
|
@ -98,6 +98,7 @@ struct can_ctrlmode {
|
|||
#define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */
|
||||
#define CAN_CTRLMODE_FD 0x20 /* CAN FD mode */
|
||||
#define CAN_CTRLMODE_PRESUME_ACK 0x40 /* Ignore missing CAN ACKs */
|
||||
#define CAN_CTRLMODE_FD_NON_ISO 0x80 /* CAN FD in non-ISO mode */
|
||||
|
||||
/*
|
||||
* CAN device statistics
|
||||
|
|
|
@ -7072,10 +7072,20 @@ static int dev_cpu_callback(struct notifier_block *nfb,
|
|||
oldsd->output_queue = NULL;
|
||||
oldsd->output_queue_tailp = &oldsd->output_queue;
|
||||
}
|
||||
/* Append NAPI poll list from offline CPU. */
|
||||
if (!list_empty(&oldsd->poll_list)) {
|
||||
list_splice_init(&oldsd->poll_list, &sd->poll_list);
|
||||
raise_softirq_irqoff(NET_RX_SOFTIRQ);
|
||||
/* Append NAPI poll list from offline CPU, with one exception :
|
||||
* process_backlog() must be called by cpu owning percpu backlog.
|
||||
* We properly handle process_queue & input_pkt_queue later.
|
||||
*/
|
||||
while (!list_empty(&oldsd->poll_list)) {
|
||||
struct napi_struct *napi = list_first_entry(&oldsd->poll_list,
|
||||
struct napi_struct,
|
||||
poll_list);
|
||||
|
||||
list_del_init(&napi->poll_list);
|
||||
if (napi->poll == process_backlog)
|
||||
napi->state = 0;
|
||||
else
|
||||
____napi_schedule(sd, napi);
|
||||
}
|
||||
|
||||
raise_softirq_irqoff(NET_TX_SOFTIRQ);
|
||||
|
@ -7086,7 +7096,7 @@ static int dev_cpu_callback(struct notifier_block *nfb,
|
|||
netif_rx_internal(skb);
|
||||
input_queue_head_incr(oldsd);
|
||||
}
|
||||
while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) {
|
||||
while ((skb = skb_dequeue(&oldsd->input_pkt_queue))) {
|
||||
netif_rx_internal(skb);
|
||||
input_queue_head_incr(oldsd);
|
||||
}
|
||||
|
|
|
@ -461,17 +461,13 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
|
|||
|
||||
memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
|
||||
sin = &errhdr.offender;
|
||||
sin->sin_family = AF_UNSPEC;
|
||||
memset(sin, 0, sizeof(*sin));
|
||||
|
||||
if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
|
||||
ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) {
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
|
||||
sin->sin_port = 0;
|
||||
memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
|
||||
if (inet->cmsg_flags)
|
||||
if (inet_sk(sk)->cmsg_flags)
|
||||
ip_cmsg_recv(msg, skb);
|
||||
}
|
||||
|
||||
|
|
|
@ -393,11 +393,10 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
|
|||
|
||||
memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
|
||||
sin = &errhdr.offender;
|
||||
sin->sin6_family = AF_UNSPEC;
|
||||
memset(sin, 0, sizeof(*sin));
|
||||
|
||||
if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
|
||||
sin->sin6_family = AF_INET6;
|
||||
sin->sin6_flowinfo = 0;
|
||||
sin->sin6_port = 0;
|
||||
if (np->rxopt.all) {
|
||||
if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP &&
|
||||
serr->ee.ee_origin != SO_EE_ORIGIN_ICMP6)
|
||||
|
@ -412,12 +411,9 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
|
|||
ipv6_iface_scope_id(&sin->sin6_addr,
|
||||
IP6CB(skb)->iif);
|
||||
} else {
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
|
||||
ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr,
|
||||
&sin->sin6_addr);
|
||||
sin->sin6_scope_id = 0;
|
||||
if (inet->cmsg_flags)
|
||||
if (inet_sk(sk)->cmsg_flags)
|
||||
ip_cmsg_recv(msg, skb);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1160,12 +1160,9 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
|
|||
struct net *net = dev_net(dst->dev);
|
||||
|
||||
rt6->rt6i_flags |= RTF_MODIFIED;
|
||||
if (mtu < IPV6_MIN_MTU) {
|
||||
u32 features = dst_metric(dst, RTAX_FEATURES);
|
||||
if (mtu < IPV6_MIN_MTU)
|
||||
mtu = IPV6_MIN_MTU;
|
||||
features |= RTAX_FEATURE_ALLFRAG;
|
||||
dst_metric_set(dst, RTAX_FEATURES, features);
|
||||
}
|
||||
|
||||
dst_metric_set(dst, RTAX_MTU, mtu);
|
||||
rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires);
|
||||
}
|
||||
|
|
|
@ -1643,7 +1643,7 @@ __ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata)
|
|||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
bool ret;
|
||||
bool ret = false;
|
||||
int ac;
|
||||
|
||||
if (local->hw.queues < IEEE80211_NUM_ACS)
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include <linux/rhashtable.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/hash.h>
|
||||
#include <linux/genetlink.h>
|
||||
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/sock.h>
|
||||
|
@ -1095,6 +1096,8 @@ static void netlink_remove(struct sock *sk)
|
|||
__sk_del_bind_node(sk);
|
||||
netlink_update_listeners(sk);
|
||||
}
|
||||
if (sk->sk_protocol == NETLINK_GENERIC)
|
||||
atomic_inc(&genl_sk_destructing_cnt);
|
||||
netlink_table_ungrab();
|
||||
}
|
||||
|
||||
|
@ -1211,6 +1214,20 @@ static int netlink_release(struct socket *sock)
|
|||
* will be purged.
|
||||
*/
|
||||
|
||||
/* must not acquire netlink_table_lock in any way again before unbind
|
||||
* and notifying genetlink is done as otherwise it might deadlock
|
||||
*/
|
||||
if (nlk->netlink_unbind) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nlk->ngroups; i++)
|
||||
if (test_bit(i, nlk->groups))
|
||||
nlk->netlink_unbind(sock_net(sk), i + 1);
|
||||
}
|
||||
if (sk->sk_protocol == NETLINK_GENERIC &&
|
||||
atomic_dec_return(&genl_sk_destructing_cnt) == 0)
|
||||
wake_up(&genl_sk_destructing_waitq);
|
||||
|
||||
sock->sk = NULL;
|
||||
wake_up_interruptible_all(&nlk->wait);
|
||||
|
||||
|
@ -1246,13 +1263,6 @@ static int netlink_release(struct socket *sock)
|
|||
netlink_table_ungrab();
|
||||
}
|
||||
|
||||
if (nlk->netlink_unbind) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nlk->ngroups; i++)
|
||||
if (test_bit(i, nlk->groups))
|
||||
nlk->netlink_unbind(sock_net(sk), i + 1);
|
||||
}
|
||||
kfree(nlk->groups);
|
||||
nlk->groups = NULL;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define _AF_NETLINK_H
|
||||
|
||||
#include <linux/rhashtable.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
#define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8)
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */
|
||||
static DECLARE_RWSEM(cb_lock);
|
||||
|
||||
atomic_t genl_sk_destructing_cnt = ATOMIC_INIT(0);
|
||||
DECLARE_WAIT_QUEUE_HEAD(genl_sk_destructing_waitq);
|
||||
|
||||
void genl_lock(void)
|
||||
{
|
||||
mutex_lock(&genl_mutex);
|
||||
|
@ -435,15 +438,18 @@ int genl_unregister_family(struct genl_family *family)
|
|||
|
||||
genl_lock_all();
|
||||
|
||||
genl_unregister_mc_groups(family);
|
||||
|
||||
list_for_each_entry(rc, genl_family_chain(family->id), family_list) {
|
||||
if (family->id != rc->id || strcmp(rc->name, family->name))
|
||||
continue;
|
||||
|
||||
genl_unregister_mc_groups(family);
|
||||
|
||||
list_del(&rc->family_list);
|
||||
family->n_ops = 0;
|
||||
genl_unlock_all();
|
||||
up_write(&cb_lock);
|
||||
wait_event(genl_sk_destructing_waitq,
|
||||
atomic_read(&genl_sk_destructing_cnt) == 0);
|
||||
genl_unlock();
|
||||
|
||||
kfree(family->attrbuf);
|
||||
genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0);
|
||||
|
@ -985,7 +991,7 @@ static struct genl_multicast_group genl_ctrl_groups[] = {
|
|||
|
||||
static int genl_bind(struct net *net, int group)
|
||||
{
|
||||
int i, err = 0;
|
||||
int i, err = -ENOENT;
|
||||
|
||||
down_read(&cb_lock);
|
||||
for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
|
||||
|
@ -1014,7 +1020,6 @@ static int genl_bind(struct net *net, int group)
|
|||
static void genl_unbind(struct net *net, int group)
|
||||
{
|
||||
int i;
|
||||
bool found = false;
|
||||
|
||||
down_read(&cb_lock);
|
||||
for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
|
||||
|
@ -1027,14 +1032,11 @@ static void genl_unbind(struct net *net, int group)
|
|||
|
||||
if (f->mcast_unbind)
|
||||
f->mcast_unbind(net, fam_grp);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
up_read(&cb_lock);
|
||||
|
||||
WARN_ON(!found);
|
||||
}
|
||||
|
||||
static int __net_init genl_pernet_init(struct net *net)
|
||||
|
|
|
@ -1603,7 +1603,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
|
|||
sctp_assoc_t associd = 0;
|
||||
sctp_cmsgs_t cmsgs = { NULL };
|
||||
sctp_scope_t scope;
|
||||
bool fill_sinfo_ttl = false;
|
||||
bool fill_sinfo_ttl = false, wait_connect = false;
|
||||
struct sctp_datamsg *datamsg;
|
||||
int msg_flags = msg->msg_flags;
|
||||
__u16 sinfo_flags = 0;
|
||||
|
@ -1943,6 +1943,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
|
|||
if (err < 0)
|
||||
goto out_free;
|
||||
|
||||
wait_connect = true;
|
||||
pr_debug("%s: we associated primitively\n", __func__);
|
||||
}
|
||||
|
||||
|
@ -1980,6 +1981,11 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
|
|||
sctp_datamsg_put(datamsg);
|
||||
err = msg_len;
|
||||
|
||||
if (unlikely(wait_connect)) {
|
||||
timeo = sock_sndtimeo(sk, msg_flags & MSG_DONTWAIT);
|
||||
sctp_wait_for_connect(asoc, &timeo);
|
||||
}
|
||||
|
||||
/* If we are already past ASSOCIATE, the lower
|
||||
* layers are responsible for association cleanup.
|
||||
*/
|
||||
|
|
|
@ -1530,45 +1530,40 @@ static void reg_call_notifier(struct wiphy *wiphy,
|
|||
|
||||
static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
{
|
||||
struct ieee80211_channel *ch;
|
||||
struct cfg80211_chan_def chandef;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
bool ret = true;
|
||||
enum nl80211_iftype iftype;
|
||||
|
||||
wdev_lock(wdev);
|
||||
iftype = wdev->iftype;
|
||||
|
||||
/* make sure the interface is active */
|
||||
if (!wdev->netdev || !netif_running(wdev->netdev))
|
||||
goto out;
|
||||
goto wdev_inactive_unlock;
|
||||
|
||||
switch (wdev->iftype) {
|
||||
switch (iftype) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
if (!wdev->beacon_interval)
|
||||
goto out;
|
||||
|
||||
ret = cfg80211_reg_can_beacon(wiphy,
|
||||
&wdev->chandef, wdev->iftype);
|
||||
goto wdev_inactive_unlock;
|
||||
chandef = wdev->chandef;
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
if (!wdev->ssid_len)
|
||||
goto out;
|
||||
|
||||
ret = cfg80211_reg_can_beacon(wiphy,
|
||||
&wdev->chandef, wdev->iftype);
|
||||
goto wdev_inactive_unlock;
|
||||
chandef = wdev->chandef;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
if (!wdev->current_bss ||
|
||||
!wdev->current_bss->pub.channel)
|
||||
goto out;
|
||||
goto wdev_inactive_unlock;
|
||||
|
||||
ch = wdev->current_bss->pub.channel;
|
||||
if (rdev->ops->get_channel &&
|
||||
!rdev_get_channel(rdev, wdev, &chandef))
|
||||
ret = cfg80211_chandef_usable(wiphy, &chandef,
|
||||
IEEE80211_CHAN_DISABLED);
|
||||
else
|
||||
ret = !(ch->flags & IEEE80211_CHAN_DISABLED);
|
||||
if (!rdev->ops->get_channel ||
|
||||
rdev_get_channel(rdev, wdev, &chandef))
|
||||
cfg80211_chandef_create(&chandef,
|
||||
wdev->current_bss->pub.channel,
|
||||
NL80211_CHAN_NO_HT);
|
||||
break;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
|
@ -1581,9 +1576,26 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
|
|||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
wdev_unlock(wdev);
|
||||
return ret;
|
||||
|
||||
switch (iftype) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
return cfg80211_reg_can_beacon(wiphy, &chandef, iftype);
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
return cfg80211_chandef_usable(wiphy, &chandef,
|
||||
IEEE80211_CHAN_DISABLED);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
wdev_inactive_unlock:
|
||||
wdev_unlock(wdev);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void reg_leave_invalid_chans(struct wiphy *wiphy)
|
||||
|
|
Loading…
Reference in New Issue