Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Browse files Browse the repository at this point in the history
Pull networking fixes from David Miller:

 1) If the timing is wrong we can indefinitely stop generating new ipv6
    temporary addresses, from Marcus Huewe.

 2) Don't double free per-cpu stats in ipv6 SIT tunnel driver, from Cong
    Wang.

 3) Put protections in place so that AF_PACKET is not able to submit
    packets which don't even have a link level header to drivers. From
    Willem de Bruijn.

 4) Fix memory leaks in ipv4 and ipv6 multicast code, from Hangbin Liu.

 5) Don't use udp_ioctl() in l2tp code, UDP version expects a UDP socket
    and that doesn't go over very well when it is passed an L2TP one.
    Fix from Eric Dumazet.

 6) Don't crash on NULL pointer in phy_attach_direct(), from Florian
    Fainelli.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
  l2tp: do not use udp_ioctl()
  xen-netfront: Delete rx_refill_timer in xennet_disconnect_backend()
  NET: mkiss: Fix panic
  net: hns: Fix the device being used for dma mapping during TX
  net: phy: Initialize mdio clock at probe function
  igmp, mld: Fix memory leak in igmpv3/mld_del_delrec()
  xen-netfront: Improve error handling during initialization
  sierra_net: Skip validating irrelevant fields for IDLE LSIs
  sierra_net: Add support for IPv6 and Dual-Stack Link Sense Indications
  kcm: fix 0-length case for kcm_sendmsg()
  xen-netfront: Rework the fix for Rx stall during OOM and network stress
  net: phy: Fix PHY module checks and NULL deref in phy_attach_direct()
  net: thunderx: Fix PHY autoneg for SGMII QLM mode
  net: dsa: Do not destroy invalid network devices
  ping: fix a null pointer dereference
  packet: round up linear to header len
  net: introduce device min_header_len
  sit: fix a double free on error path
  lwtunnel: valid encap attr check should return 0 when lwtunnel is disabled
  ipv6: addrconf: fix generation of new temporary addresses
  • Loading branch information
Linus Torvalds committed Feb 10, 2017
2 parents a9dbf5c + 72fb96e commit 1ee1832
Show file tree
Hide file tree
Showing 23 changed files with 297 additions and 113 deletions.
108 changes: 96 additions & 12 deletions drivers/net/ethernet/cavium/thunder/thunder_bgx.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ struct lmac {
u8 lmac_type;
u8 lane_to_sds;
bool use_training;
bool autoneg;
bool link_up;
int lmacid; /* ID within BGX */
int lmacid_bd; /* ID on board */
Expand Down Expand Up @@ -461,7 +462,17 @@ static int bgx_lmac_sgmii_init(struct bgx *bgx, struct lmac *lmac)
/* power down, reset autoneg, autoneg enable */
cfg = bgx_reg_read(bgx, lmacid, BGX_GMP_PCS_MRX_CTL);
cfg &= ~PCS_MRX_CTL_PWR_DN;
cfg |= (PCS_MRX_CTL_RST_AN | PCS_MRX_CTL_AN_EN);
cfg |= PCS_MRX_CTL_RST_AN;
if (lmac->phydev) {
cfg |= PCS_MRX_CTL_AN_EN;
} else {
/* In scenarios where PHY driver is not present or it's a
* non-standard PHY, FW sets AN_EN to inform Linux driver
* to do auto-neg and link polling or not.
*/
if (cfg & PCS_MRX_CTL_AN_EN)
lmac->autoneg = true;
}
bgx_reg_write(bgx, lmacid, BGX_GMP_PCS_MRX_CTL, cfg);

if (lmac->lmac_type == BGX_MODE_QSGMII) {
Expand All @@ -472,7 +483,7 @@ static int bgx_lmac_sgmii_init(struct bgx *bgx, struct lmac *lmac)
return 0;
}

if (lmac->lmac_type == BGX_MODE_SGMII) {
if ((lmac->lmac_type == BGX_MODE_SGMII) && lmac->phydev) {
if (bgx_poll_reg(bgx, lmacid, BGX_GMP_PCS_MRX_STATUS,
PCS_MRX_STATUS_AN_CPT, false)) {
dev_err(&bgx->pdev->dev, "BGX AN_CPT not completed\n");
Expand Down Expand Up @@ -678,12 +689,71 @@ static int bgx_xaui_check_link(struct lmac *lmac)
return -1;
}

static void bgx_poll_for_sgmii_link(struct lmac *lmac)
{
u64 pcs_link, an_result;
u8 speed;

pcs_link = bgx_reg_read(lmac->bgx, lmac->lmacid,
BGX_GMP_PCS_MRX_STATUS);

/*Link state bit is sticky, read it again*/
if (!(pcs_link & PCS_MRX_STATUS_LINK))
pcs_link = bgx_reg_read(lmac->bgx, lmac->lmacid,
BGX_GMP_PCS_MRX_STATUS);

if (bgx_poll_reg(lmac->bgx, lmac->lmacid, BGX_GMP_PCS_MRX_STATUS,
PCS_MRX_STATUS_AN_CPT, false)) {
lmac->link_up = false;
lmac->last_speed = SPEED_UNKNOWN;
lmac->last_duplex = DUPLEX_UNKNOWN;
goto next_poll;
}

lmac->link_up = ((pcs_link & PCS_MRX_STATUS_LINK) != 0) ? true : false;
an_result = bgx_reg_read(lmac->bgx, lmac->lmacid,
BGX_GMP_PCS_ANX_AN_RESULTS);

speed = (an_result >> 3) & 0x3;
lmac->last_duplex = (an_result >> 1) & 0x1;
switch (speed) {
case 0:
lmac->last_speed = 10;
break;
case 1:
lmac->last_speed = 100;
break;
case 2:
lmac->last_speed = 1000;
break;
default:
lmac->link_up = false;
lmac->last_speed = SPEED_UNKNOWN;
lmac->last_duplex = DUPLEX_UNKNOWN;
break;
}

next_poll:

if (lmac->last_link != lmac->link_up) {
if (lmac->link_up)
bgx_sgmii_change_link_state(lmac);
lmac->last_link = lmac->link_up;
}

queue_delayed_work(lmac->check_link, &lmac->dwork, HZ * 3);
}

static void bgx_poll_for_link(struct work_struct *work)
{
struct lmac *lmac;
u64 spu_link, smu_link;

lmac = container_of(work, struct lmac, dwork.work);
if (lmac->is_sgmii) {
bgx_poll_for_sgmii_link(lmac);
return;
}

/* Receive link is latching low. Force it high and verify it */
bgx_reg_modify(lmac->bgx, lmac->lmacid,
Expand Down Expand Up @@ -775,9 +845,21 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
(lmac->lmac_type != BGX_MODE_XLAUI) &&
(lmac->lmac_type != BGX_MODE_40G_KR) &&
(lmac->lmac_type != BGX_MODE_10G_KR)) {
if (!lmac->phydev)
return -ENODEV;

if (!lmac->phydev) {
if (lmac->autoneg) {
bgx_reg_write(bgx, lmacid,
BGX_GMP_PCS_LINKX_TIMER,
PCS_LINKX_TIMER_COUNT);
goto poll;
} else {
/* Default to below link speed and duplex */
lmac->link_up = true;
lmac->last_speed = 1000;
lmac->last_duplex = 1;
bgx_sgmii_change_link_state(lmac);
return 0;
}
}
lmac->phydev->dev_flags = 0;

if (phy_connect_direct(&lmac->netdev, lmac->phydev,
Expand All @@ -786,15 +868,17 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
return -ENODEV;

phy_start_aneg(lmac->phydev);
} else {
lmac->check_link = alloc_workqueue("check_link", WQ_UNBOUND |
WQ_MEM_RECLAIM, 1);
if (!lmac->check_link)
return -ENOMEM;
INIT_DELAYED_WORK(&lmac->dwork, bgx_poll_for_link);
queue_delayed_work(lmac->check_link, &lmac->dwork, 0);
return 0;
}

poll:
lmac->check_link = alloc_workqueue("check_link", WQ_UNBOUND |
WQ_MEM_RECLAIM, 1);
if (!lmac->check_link)
return -ENOMEM;
INIT_DELAYED_WORK(&lmac->dwork, bgx_poll_for_link);
queue_delayed_work(lmac->check_link, &lmac->dwork, 0);

return 0;
}

Expand Down
5 changes: 5 additions & 0 deletions drivers/net/ethernet/cavium/thunder/thunder_bgx.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,15 @@
#define PCS_MRX_CTL_LOOPBACK1 BIT_ULL(14)
#define PCS_MRX_CTL_RESET BIT_ULL(15)
#define BGX_GMP_PCS_MRX_STATUS 0x30008
#define PCS_MRX_STATUS_LINK BIT_ULL(2)
#define PCS_MRX_STATUS_AN_CPT BIT_ULL(5)
#define BGX_GMP_PCS_ANX_ADV 0x30010
#define BGX_GMP_PCS_ANX_AN_RESULTS 0x30020
#define BGX_GMP_PCS_LINKX_TIMER 0x30040
#define PCS_LINKX_TIMER_COUNT 0x1E84
#define BGX_GMP_PCS_SGM_AN_ADV 0x30068
#define BGX_GMP_PCS_MISCX_CTL 0x30078
#define PCS_MISC_CTL_MODE BIT_ULL(8)
#define PCS_MISC_CTL_DISP_EN BIT_ULL(13)
#define PCS_MISC_CTL_GMX_ENO BIT_ULL(11)
#define PCS_MISC_CTL_SAMP_PT_MASK 0x7Full
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/hisilicon/hns/hns_enet.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,8 @@ int hns_nic_net_xmit_hw(struct net_device *ndev,
struct hns_nic_ring_data *ring_data)
{
struct hns_nic_priv *priv = netdev_priv(ndev);
struct device *dev = priv->dev;
struct hnae_ring *ring = ring_data->ring;
struct device *dev = ring_to_dev(ring);
struct netdev_queue *dev_queue;
struct skb_frag_struct *frag;
int buf_num;
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/hamradio/mkiss.c
Original file line number Diff line number Diff line change
Expand Up @@ -648,8 +648,8 @@ static void ax_setup(struct net_device *dev)
{
/* Finish setting up the DEVICE info. */
dev->mtu = AX_MTU;
dev->hard_header_len = 0;
dev->addr_len = 0;
dev->hard_header_len = AX25_MAX_HEADER_LEN;
dev->addr_len = AX25_ADDR_LEN;
dev->type = ARPHRD_AX25;
dev->tx_queue_len = 10;
dev->header_ops = &ax25_header_ops;
Expand Down
1 change: 1 addition & 0 deletions drivers/net/loopback.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ static void loopback_setup(struct net_device *dev)
{
dev->mtu = 64 * 1024;
dev->hard_header_len = ETH_HLEN; /* 14 */
dev->min_header_len = ETH_HLEN; /* 14 */
dev->addr_len = ETH_ALEN; /* 6 */
dev->type = ARPHRD_LOOPBACK; /* 0x0001*/
dev->flags = IFF_LOOPBACK;
Expand Down
6 changes: 2 additions & 4 deletions drivers/net/phy/mdio-bcm-iproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ static int iproc_mdio_read(struct mii_bus *bus, int phy_id, int reg)
if (rc)
return rc;

iproc_mdio_config_clk(priv->base);

/* Prepare the read operation */
cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) |
(reg << MII_DATA_RA_SHIFT) |
Expand Down Expand Up @@ -112,8 +110,6 @@ static int iproc_mdio_write(struct mii_bus *bus, int phy_id,
if (rc)
return rc;

iproc_mdio_config_clk(priv->base);

/* Prepare the write operation */
cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) |
(reg << MII_DATA_RA_SHIFT) |
Expand Down Expand Up @@ -163,6 +159,8 @@ static int iproc_mdio_probe(struct platform_device *pdev)
bus->read = iproc_mdio_read;
bus->write = iproc_mdio_write;

iproc_mdio_config_clk(priv->base);

rc = of_mdiobus_register(bus, pdev->dev.of_node);
if (rc) {
dev_err(&pdev->dev, "MDIO bus registration failed\n");
Expand Down
28 changes: 20 additions & 8 deletions drivers/net/phy/phy_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
struct module *ndev_owner = dev->dev.parent->driver->owner;
struct mii_bus *bus = phydev->mdio.bus;
struct device *d = &phydev->mdio.dev;
bool using_genphy = false;
int err;

/* For Ethernet device drivers that register their own MDIO bus, we
Expand All @@ -920,11 +921,6 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
return -EIO;
}

if (!try_module_get(d->driver->owner)) {
dev_err(&dev->dev, "failed to get the device driver module\n");
return -EIO;
}

get_device(d);

/* Assume that if there is no driver, that it doesn't
Expand All @@ -938,12 +934,22 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
d->driver =
&genphy_driver[GENPHY_DRV_1G].mdiodrv.driver;

using_genphy = true;
}

if (!try_module_get(d->driver->owner)) {
dev_err(&dev->dev, "failed to get the device driver module\n");
err = -EIO;
goto error_put_device;
}

if (using_genphy) {
err = d->driver->probe(d);
if (err >= 0)
err = device_bind_driver(d);

if (err)
goto error;
goto error_module_put;
}

if (phydev->attached_dev) {
Expand Down Expand Up @@ -980,9 +986,14 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
return err;

error:
/* phy_detach() does all of the cleanup below */
phy_detach(phydev);
put_device(d);
return err;

error_module_put:
module_put(d->driver->owner);
error_put_device:
put_device(d);
if (ndev_owner != bus->owner)
module_put(bus->owner);
return err;
Expand Down Expand Up @@ -1045,6 +1056,8 @@ void phy_detach(struct phy_device *phydev)

phy_led_triggers_unregister(phydev);

module_put(phydev->mdio.dev.driver->owner);

/* If the device had no specific driver before (i.e. - it
* was using the generic driver), we unbind the device
* from the generic driver so that there's a chance a
Expand All @@ -1065,7 +1078,6 @@ void phy_detach(struct phy_device *phydev)
bus = phydev->mdio.bus;

put_device(&phydev->mdio.dev);
module_put(phydev->mdio.dev.driver->owner);
if (ndev_owner != bus->owner)
module_put(bus->owner);
}
Expand Down
Loading

0 comments on commit 1ee1832

Please sign in to comment.