Commit ea44083a authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

Pull networking update from David Miller:

 1) Propagate return error values properly in irda, spider_net, sfc, and
    bfin_mac.  From Wei Yongjun.

 2) Fix fec driver OOPS on rapid link up/down, from Frank Li.

 3) FIX VF resource allocation and chip message payload length errors in
    be2net driver, from Sathya Perla.

 4) Fix inner protocol inspection during GSO from Pravin B Shelar.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
  if_cablemodem.h: Add parenthesis around ioctl macros
  gso: Handle Trans-Ether-Bridging protocol in skb_network_protocol()
  net: fec: fix kernel oops when plug/unplug cable many times
  bfin_mac: fix error return code in bfin_mac_probe()
  sfc: fix return value check in efx_ptp_probe_channel()
  net/spider_net: fix error return code in spider_net_open()
  net/irda: fix error return code in bfin_sir_open()
  net: of_mdio: fix behavior on missing phy device
  sierra_net: keep status interrupt URB active
  usbnet: allow status interrupt URB to always be active
  qmi_wwan/cdc_ether: add device IDs for Dell 5804 (Novatel E371) WWAN card
  be2net: disable TX in be_close()
  be2net: fix EQ from getting full while cleaning RX CQ
  be2net: fix payload_len value for GET_MAC_LIST cmd req
  be2net: provision VF resources before enabling SR-IOV
parents e15e6119 4f924b2a
...@@ -1700,7 +1700,8 @@ static int bfin_mac_probe(struct platform_device *pdev) ...@@ -1700,7 +1700,8 @@ static int bfin_mac_probe(struct platform_device *pdev)
} }
bfin_mac_hwtstamp_init(ndev); bfin_mac_hwtstamp_init(ndev);
if (bfin_phc_init(ndev, &pdev->dev)) { rc = bfin_phc_init(ndev, &pdev->dev);
if (rc) {
dev_err(&pdev->dev, "Cannot register PHC device!\n"); dev_err(&pdev->dev, "Cannot register PHC device!\n");
goto out_err_phc; goto out_err_phc;
} }
......
...@@ -2640,9 +2640,8 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, ...@@ -2640,9 +2640,8 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
req = get_mac_list_cmd.va; req = get_mac_list_cmd.va;
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_GET_MAC_LIST, sizeof(*req), OPCODE_COMMON_GET_MAC_LIST,
wrb, &get_mac_list_cmd); get_mac_list_cmd.size, wrb, &get_mac_list_cmd);
req->hdr.domain = domain; req->hdr.domain = domain;
req->mac_type = MAC_ADDRESS_TYPE_NETWORK; req->mac_type = MAC_ADDRESS_TYPE_NETWORK;
req->perm_override = 1; req->perm_override = 1;
......
...@@ -1827,7 +1827,7 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo) ...@@ -1827,7 +1827,7 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo)
mdelay(1); mdelay(1);
} else { } else {
be_rx_compl_discard(rxo, rxcp); be_rx_compl_discard(rxo, rxcp);
be_cq_notify(adapter, rx_cq->id, true, 1); be_cq_notify(adapter, rx_cq->id, false, 1);
if (rxcp->num_rcvd == 0) if (rxcp->num_rcvd == 0)
break; break;
} }
...@@ -2533,11 +2533,6 @@ static void be_rx_qs_destroy(struct be_adapter *adapter) ...@@ -2533,11 +2533,6 @@ static void be_rx_qs_destroy(struct be_adapter *adapter)
q = &rxo->q; q = &rxo->q;
if (q->created) { if (q->created) {
be_cmd_rxq_destroy(adapter, q); be_cmd_rxq_destroy(adapter, q);
/* After the rxq is invalidated, wait for a grace time
* of 1ms for all dma to end and the flush compl to
* arrive
*/
mdelay(1);
be_rx_cq_clean(rxo); be_rx_cq_clean(rxo);
} }
be_queue_free(adapter, q); be_queue_free(adapter, q);
...@@ -2564,6 +2559,7 @@ static int be_close(struct net_device *netdev) ...@@ -2564,6 +2559,7 @@ static int be_close(struct net_device *netdev)
* all tx skbs are freed. * all tx skbs are freed.
*/ */
be_tx_compl_clean(adapter); be_tx_compl_clean(adapter);
netif_tx_disable(netdev);
be_rx_qs_destroy(adapter); be_rx_qs_destroy(adapter);
...@@ -2672,6 +2668,7 @@ static int be_open(struct net_device *netdev) ...@@ -2672,6 +2668,7 @@ static int be_open(struct net_device *netdev)
if (!status) if (!status)
be_link_status_update(adapter, link_status); be_link_status_update(adapter, link_status);
netif_tx_start_all_queues(netdev);
be_roce_dev_open(adapter); be_roce_dev_open(adapter);
return 0; return 0;
err: err:
...@@ -2783,6 +2780,8 @@ static void be_vf_clear(struct be_adapter *adapter) ...@@ -2783,6 +2780,8 @@ static void be_vf_clear(struct be_adapter *adapter)
goto done; goto done;
} }
pci_disable_sriov(adapter->pdev);
for_all_vfs(adapter, vf_cfg, vf) { for_all_vfs(adapter, vf_cfg, vf) {
if (lancer_chip(adapter)) if (lancer_chip(adapter))
be_cmd_set_mac_list(adapter, NULL, 0, vf + 1); be_cmd_set_mac_list(adapter, NULL, 0, vf + 1);
...@@ -2792,7 +2791,6 @@ static void be_vf_clear(struct be_adapter *adapter) ...@@ -2792,7 +2791,6 @@ static void be_vf_clear(struct be_adapter *adapter)
be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1); be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1);
} }
pci_disable_sriov(adapter->pdev);
done: done:
kfree(adapter->vf_cfg); kfree(adapter->vf_cfg);
adapter->num_vfs = 0; adapter->num_vfs = 0;
...@@ -2889,13 +2887,8 @@ static int be_vf_setup(struct be_adapter *adapter) ...@@ -2889,13 +2887,8 @@ static int be_vf_setup(struct be_adapter *adapter)
dev_info(dev, "Device supports %d VFs and not %d\n", dev_info(dev, "Device supports %d VFs and not %d\n",
adapter->dev_num_vfs, num_vfs); adapter->dev_num_vfs, num_vfs);
adapter->num_vfs = min_t(u16, num_vfs, adapter->dev_num_vfs); adapter->num_vfs = min_t(u16, num_vfs, adapter->dev_num_vfs);
if (!adapter->num_vfs)
status = pci_enable_sriov(adapter->pdev, num_vfs);
if (status) {
dev_err(dev, "SRIOV enable failed\n");
adapter->num_vfs = 0;
return 0; return 0;
}
} }
status = be_vf_setup_init(adapter); status = be_vf_setup_init(adapter);
...@@ -2944,6 +2937,15 @@ static int be_vf_setup(struct be_adapter *adapter) ...@@ -2944,6 +2937,15 @@ static int be_vf_setup(struct be_adapter *adapter)
be_cmd_enable_vf(adapter, vf + 1); be_cmd_enable_vf(adapter, vf + 1);
} }
if (!old_vfs) {
status = pci_enable_sriov(adapter->pdev, adapter->num_vfs);
if (status) {
dev_err(dev, "SRIOV enable failed\n");
adapter->num_vfs = 0;
goto err;
}
}
return 0; return 0;
err: err:
dev_err(dev, "VF setup failed\n"); dev_err(dev, "VF setup failed\n");
...@@ -3198,7 +3200,7 @@ static int be_setup(struct be_adapter *adapter) ...@@ -3198,7 +3200,7 @@ static int be_setup(struct be_adapter *adapter)
be_cmd_set_flow_control(adapter, adapter->tx_fc, be_cmd_set_flow_control(adapter, adapter->tx_fc,
adapter->rx_fc); adapter->rx_fc);
if (be_physfn(adapter) && num_vfs) { if (be_physfn(adapter)) {
if (adapter->dev_num_vfs) if (adapter->dev_num_vfs)
be_vf_setup(adapter); be_vf_setup(adapter);
else else
......
...@@ -198,6 +198,11 @@ struct bufdesc_ex { ...@@ -198,6 +198,11 @@ struct bufdesc_ex {
#define FLAG_RX_CSUM_ENABLED (BD_ENET_RX_ICE | BD_ENET_RX_PCR) #define FLAG_RX_CSUM_ENABLED (BD_ENET_RX_ICE | BD_ENET_RX_PCR)
#define FLAG_RX_CSUM_ERROR (BD_ENET_RX_ICE | BD_ENET_RX_PCR) #define FLAG_RX_CSUM_ERROR (BD_ENET_RX_ICE | BD_ENET_RX_PCR)
struct fec_enet_delayed_work {
struct delayed_work delay_work;
bool timeout;
};
/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and /* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
* tx_bd_base always point to the base of the buffer descriptors. The * tx_bd_base always point to the base of the buffer descriptors. The
* cur_rx and cur_tx point to the currently available buffer. * cur_rx and cur_tx point to the currently available buffer.
...@@ -232,9 +237,6 @@ struct fec_enet_private { ...@@ -232,9 +237,6 @@ struct fec_enet_private {
/* The ring entries to be free()ed */ /* The ring entries to be free()ed */
struct bufdesc *dirty_tx; struct bufdesc *dirty_tx;
/* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
spinlock_t hw_lock;
struct platform_device *pdev; struct platform_device *pdev;
int opened; int opened;
...@@ -269,7 +271,7 @@ struct fec_enet_private { ...@@ -269,7 +271,7 @@ struct fec_enet_private {
int hwts_rx_en; int hwts_rx_en;
int hwts_tx_en; int hwts_tx_en;
struct timer_list time_keep; struct timer_list time_keep;
struct fec_enet_delayed_work delay_work;
}; };
void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev); void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev);
......
...@@ -445,6 +445,13 @@ fec_restart(struct net_device *ndev, int duplex) ...@@ -445,6 +445,13 @@ fec_restart(struct net_device *ndev, int duplex)
u32 rcntl = OPT_FRAME_SIZE | 0x04; u32 rcntl = OPT_FRAME_SIZE | 0x04;
u32 ecntl = 0x2; /* ETHEREN */ u32 ecntl = 0x2; /* ETHEREN */
if (netif_running(ndev)) {
netif_device_detach(ndev);
napi_disable(&fep->napi);
netif_stop_queue(ndev);
netif_tx_lock(ndev);
}
/* Whack a reset. We should wait for this. */ /* Whack a reset. We should wait for this. */
writel(1, fep->hwp + FEC_ECNTRL); writel(1, fep->hwp + FEC_ECNTRL);
udelay(10); udelay(10);
...@@ -605,6 +612,13 @@ fec_restart(struct net_device *ndev, int duplex) ...@@ -605,6 +612,13 @@ fec_restart(struct net_device *ndev, int duplex)
/* Enable interrupts we wish to service */ /* Enable interrupts we wish to service */
writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
if (netif_running(ndev)) {
netif_device_attach(ndev);
napi_enable(&fep->napi);
netif_wake_queue(ndev);
netif_tx_unlock(ndev);
}
} }
static void static void
...@@ -644,8 +658,22 @@ fec_timeout(struct net_device *ndev) ...@@ -644,8 +658,22 @@ fec_timeout(struct net_device *ndev)
ndev->stats.tx_errors++; ndev->stats.tx_errors++;
fec_restart(ndev, fep->full_duplex); fep->delay_work.timeout = true;
netif_wake_queue(ndev); schedule_delayed_work(&(fep->delay_work.delay_work), 0);
}
static void fec_enet_work(struct work_struct *work)
{
struct fec_enet_private *fep =
container_of(work,
struct fec_enet_private,
delay_work.delay_work.work);
if (fep->delay_work.timeout) {
fep->delay_work.timeout = false;
fec_restart(fep->netdev, fep->full_duplex);
netif_wake_queue(fep->netdev);
}
} }
static void static void
...@@ -1024,16 +1052,12 @@ static void fec_enet_adjust_link(struct net_device *ndev) ...@@ -1024,16 +1052,12 @@ static void fec_enet_adjust_link(struct net_device *ndev)
{ {
struct fec_enet_private *fep = netdev_priv(ndev); struct fec_enet_private *fep = netdev_priv(ndev);
struct phy_device *phy_dev = fep->phy_dev; struct phy_device *phy_dev = fep->phy_dev;
unsigned long flags;
int status_change = 0; int status_change = 0;
spin_lock_irqsave(&fep->hw_lock, flags);
/* Prevent a state halted on mii error */ /* Prevent a state halted on mii error */
if (fep->mii_timeout && phy_dev->state == PHY_HALTED) { if (fep->mii_timeout && phy_dev->state == PHY_HALTED) {
phy_dev->state = PHY_RESUMING; phy_dev->state = PHY_RESUMING;
goto spin_unlock; return;
} }
if (phy_dev->link) { if (phy_dev->link) {
...@@ -1061,9 +1085,6 @@ static void fec_enet_adjust_link(struct net_device *ndev) ...@@ -1061,9 +1085,6 @@ static void fec_enet_adjust_link(struct net_device *ndev)
} }
} }
spin_unlock:
spin_unlock_irqrestore(&fep->hw_lock, flags);
if (status_change) if (status_change)
phy_print_status(phy_dev); phy_print_status(phy_dev);
} }
...@@ -1732,7 +1753,6 @@ static int fec_enet_init(struct net_device *ndev) ...@@ -1732,7 +1753,6 @@ static int fec_enet_init(struct net_device *ndev)
return -ENOMEM; return -ENOMEM;
memset(cbd_base, 0, PAGE_SIZE); memset(cbd_base, 0, PAGE_SIZE);
spin_lock_init(&fep->hw_lock);
fep->netdev = ndev; fep->netdev = ndev;
...@@ -1952,6 +1972,7 @@ fec_probe(struct platform_device *pdev) ...@@ -1952,6 +1972,7 @@ fec_probe(struct platform_device *pdev)
if (fep->bufdesc_ex && fep->ptp_clock) if (fep->bufdesc_ex && fep->ptp_clock)
netdev_info(ndev, "registered PHC device %d\n", fep->dev_id); netdev_info(ndev, "registered PHC device %d\n", fep->dev_id);
INIT_DELAYED_WORK(&(fep->delay_work.delay_work), fec_enet_work);
return 0; return 0;
failed_register: failed_register:
...@@ -1984,6 +2005,7 @@ fec_drv_remove(struct platform_device *pdev) ...@@ -1984,6 +2005,7 @@ fec_drv_remove(struct platform_device *pdev)
struct fec_enet_private *fep = netdev_priv(ndev); struct fec_enet_private *fep = netdev_priv(ndev);
int i; int i;
cancel_delayed_work_sync(&(fep->delay_work.delay_work));
unregister_netdev(ndev); unregister_netdev(ndev);
fec_enet_mii_remove(fep); fec_enet_mii_remove(fep);
del_timer_sync(&fep->time_keep); del_timer_sync(&fep->time_keep);
......
...@@ -912,8 +912,10 @@ static int efx_ptp_probe_channel(struct efx_channel *channel) ...@@ -912,8 +912,10 @@ static int efx_ptp_probe_channel(struct efx_channel *channel)
ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info, ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info,
&efx->pci_dev->dev); &efx->pci_dev->dev);
if (!ptp->phc_clock) if (IS_ERR(ptp->phc_clock)) {
rc = PTR_ERR(ptp->phc_clock);
goto fail3; goto fail3;
}
INIT_WORK(&ptp->pps_work, efx_ptp_pps_worker); INIT_WORK(&ptp->pps_work, efx_ptp_pps_worker);
ptp->pps_workwq = create_singlethread_workqueue("sfc_pps"); ptp->pps_workwq = create_singlethread_workqueue("sfc_pps");
......
...@@ -1990,7 +1990,8 @@ spider_net_open(struct net_device *netdev) ...@@ -1990,7 +1990,8 @@ spider_net_open(struct net_device *netdev)
goto alloc_rx_failed; goto alloc_rx_failed;
/* Allocate rx skbs */ /* Allocate rx skbs */
if (spider_net_alloc_rx_skbs(card)) result = spider_net_alloc_rx_skbs(card);
if (result)
goto alloc_skbs_failed; goto alloc_skbs_failed;
spider_net_set_multi(netdev); spider_net_set_multi(netdev);
......
...@@ -609,7 +609,7 @@ static int bfin_sir_open(struct net_device *dev) ...@@ -609,7 +609,7 @@ static int bfin_sir_open(struct net_device *dev)
{ {
struct bfin_sir_self *self = netdev_priv(dev); struct bfin_sir_self *self = netdev_priv(dev);
struct bfin_sir_port *port = self->sir_port; struct bfin_sir_port *port = self->sir_port;
int err = -ENOMEM; int err;
self->newspeed = 0; self->newspeed = 0;
self->speed = 9600; self->speed = 9600;
...@@ -623,8 +623,10 @@ static int bfin_sir_open(struct net_device *dev) ...@@ -623,8 +623,10 @@ static int bfin_sir_open(struct net_device *dev)
bfin_sir_set_speed(port, 9600); bfin_sir_set_speed(port, 9600);
self->irlap = irlap_open(dev, &self->qos, DRIVER_NAME); self->irlap = irlap_open(dev, &self->qos, DRIVER_NAME);
if (!self->irlap) if (!self->irlap) {
err = -ENOMEM;
goto err_irlap; goto err_irlap;
}
INIT_WORK(&self->work, bfin_sir_send_work); INIT_WORK(&self->work, bfin_sir_send_work);
......
...@@ -613,6 +613,13 @@ static const struct usb_device_id products [] = { ...@@ -613,6 +613,13 @@ static const struct usb_device_id products [] = {
.driver_info = 0, .driver_info = 0,
}, },
/* Dell Wireless 5804 (Novatel E371) - handled by qmi_wwan */
{
USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x819b, USB_CLASS_COMM,
USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
.driver_info = 0,
},
/* AnyDATA ADU960S - handled by qmi_wwan */ /* AnyDATA ADU960S - handled by qmi_wwan */
{ {
USB_DEVICE_AND_INTERFACE_INFO(0x16d5, 0x650a, USB_CLASS_COMM, USB_DEVICE_AND_INTERFACE_INFO(0x16d5, 0x650a, USB_CLASS_COMM,
......
...@@ -501,6 +501,13 @@ static const struct usb_device_id products[] = { ...@@ -501,6 +501,13 @@ static const struct usb_device_id products[] = {
USB_CDC_PROTO_NONE), USB_CDC_PROTO_NONE),
.driver_info = (unsigned long)&qmi_wwan_info, .driver_info = (unsigned long)&qmi_wwan_info,
}, },
{ /* Dell Wireless 5804 (Novatel E371) */
USB_DEVICE_AND_INTERFACE_INFO(0x413C, 0x819b,
USB_CLASS_COMM,
USB_CDC_SUBCLASS_ETHERNET,
USB_CDC_PROTO_NONE),
.driver_info = (unsigned long)&qmi_wwan_info,
},
{ /* ADU960S */ { /* ADU960S */
USB_DEVICE_AND_INTERFACE_INFO(0x16d5, 0x650a, USB_DEVICE_AND_INTERFACE_INFO(0x16d5, 0x650a,
USB_CLASS_COMM, USB_CLASS_COMM,
......
...@@ -426,6 +426,13 @@ static void sierra_net_dosync(struct usbnet *dev) ...@@ -426,6 +426,13 @@ static void sierra_net_dosync(struct usbnet *dev)
dev_dbg(&dev->udev->dev, "%s", __func__); dev_dbg(&dev->udev->dev, "%s", __func__);
/* The SIERRA_NET_HIP_MSYNC_ID command appears to request that the
* firmware restart itself. After restarting, the modem will respond
* with the SIERRA_NET_HIP_RESTART_ID indication. The driver continues
* sending MSYNC commands every few seconds until it receives the
* RESTART event from the firmware
*/
/* tell modem we are ready */ /* tell modem we are ready */
status = sierra_net_send_sync(dev); status = sierra_net_send_sync(dev);
if (status < 0) if (status < 0)
...@@ -704,6 +711,9 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) ...@@ -704,6 +711,9 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
/* set context index initially to 0 - prepares tx hdr template */ /* set context index initially to 0 - prepares tx hdr template */
sierra_net_set_ctx_index(priv, 0); sierra_net_set_ctx_index(priv, 0);
/* prepare sync message template */
memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg));
/* decrease the rx_urb_size and max_tx_size to 4k on USB 1.1 */ /* decrease the rx_urb_size and max_tx_size to 4k on USB 1.1 */
dev->rx_urb_size = SIERRA_NET_RX_URB_SIZE; dev->rx_urb_size = SIERRA_NET_RX_URB_SIZE;
if (dev->udev->speed != USB_SPEED_HIGH) if (dev->udev->speed != USB_SPEED_HIGH)
...@@ -739,11 +749,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) ...@@ -739,11 +749,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
kfree(priv); kfree(priv);
return -ENODEV; return -ENODEV;
} }
/* prepare sync message from template */
memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg));
/* initiate the sync sequence */
sierra_net_dosync(dev);
return 0; return 0;
} }
...@@ -766,8 +771,9 @@ static void sierra_net_unbind(struct usbnet *dev, struct usb_interface *intf) ...@@ -766,8 +771,9 @@ static void sierra_net_unbind(struct usbnet *dev, struct usb_interface *intf)
netdev_err(dev->net, netdev_err(dev->net,
"usb_control_msg failed, status %d\n", status); "usb_control_msg failed, status %d\n", status);
sierra_net_set_private(dev, NULL); usbnet_status_stop(dev);
sierra_net_set_private(dev, NULL);
kfree(priv); kfree(priv);
} }
...@@ -908,6 +914,24 @@ static const struct driver_info sierra_net_info_direct_ip = { ...@@ -908,6 +914,24 @@ static const struct driver_info sierra_net_info_direct_ip = {
.tx_fixup = sierra_net_tx_fixup, .tx_fixup = sierra_net_tx_fixup,
}; };
static int
sierra_net_probe(struct usb_interface *udev, const struct usb_device_id *prod)
{
int ret;
ret = usbnet_probe(udev, prod);
if (ret == 0) {
struct usbnet *dev = usb_get_intfdata(udev);
ret = usbnet_status_start(dev, GFP_KERNEL);
if (ret == 0) {
/* Interrupt URB now set up; initiate sync sequence */
sierra_net_dosync(dev);
}
}
return ret;
}
#define DIRECT_IP_DEVICE(vend, prod) \ #define DIRECT_IP_DEVICE(vend, prod) \
{USB_DEVICE_INTERFACE_NUMBER(vend, prod, 7), \ {USB_DEVICE_INTERFACE_NUMBER(vend, prod, 7), \
.driver_info = (unsigned long)&sierra_net_info_direct_ip}, \ .driver_info = (unsigned long)&sierra_net_info_direct_ip}, \
...@@ -930,7 +954,7 @@ MODULE_DEVICE_TABLE(usb, products); ...@@ -930,7 +954,7 @@ MODULE_DEVICE_TABLE(usb, products);
static struct usb_driver sierra_net_driver = { static struct usb_driver sierra_net_driver = {
.name = "sierra_net", .name = "sierra_net",
.id_table = products, .id_table = products,
.probe = usbnet_probe, .probe = sierra_net_probe,
.disconnect = usbnet_disconnect, .disconnect = usbnet_disconnect,
.suspend = usbnet_suspend, .suspend = usbnet_suspend,
.resume = usbnet_resume, .resume = usbnet_resume,
......
...@@ -252,6 +252,70 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf) ...@@ -252,6 +252,70 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
return 0; return 0;
} }
/* Submit the interrupt URB if not previously submitted, increasing refcount */
int usbnet_status_start(struct usbnet *dev, gfp_t mem_flags)
{
int ret = 0;
WARN_ON_ONCE(dev->interrupt == NULL);
if (dev->interrupt) {
mutex_lock(&dev->interrupt_mutex);
if (++dev->interrupt_count == 1)
ret = usb_submit_urb(dev->interrupt, mem_flags);
dev_dbg(&dev->udev->dev, "incremented interrupt URB count to %d\n",
dev->interrupt_count);
mutex_unlock(&dev->interrupt_mutex);
}
return ret;
}
EXPORT_SYMBOL_GPL(usbnet_status_start);
/* For resume; submit interrupt URB if previously submitted */
static int __usbnet_status_start_force(struct usbnet *dev, gfp_t mem_flags)
{
int ret = 0;
mutex_lock(&dev->interrupt_mutex);
if (dev->interrupt_count) {
ret = usb_submit_urb(dev->interrupt, mem_flags);
dev_dbg(&dev->udev->dev,
"submitted interrupt URB for resume\n");
}
mutex_unlock(&dev->interrupt_mutex);
return ret;
}
/* Kill the interrupt URB if all submitters want it killed */
void usbnet_status_stop(struct usbnet *dev)
{
if (dev->interrupt) {
mutex_lock(&dev->interrupt_mutex);
WARN_ON(dev->interrupt_count == 0);
if (dev->interrupt_count && --dev->interrupt_count == 0)
usb_kill_urb(dev->interrupt);
dev_dbg(&dev->udev->dev,
"decremented interrupt URB count to %d\n",
dev->interrupt_count);
mutex_unlock(&dev->interrupt_mutex);
}
}
EXPORT_SYMBOL_GPL(usbnet_status_stop);
/* For suspend; always kill interrupt URB */
static void __usbnet_status_stop_force(struct usbnet *dev)
{
if (dev->interrupt) {
mutex_lock(&dev->interrupt_mutex);
usb_kill_urb(dev->interrupt);
dev_dbg(&dev->udev->dev, "killed interrupt URB for suspend\n");
mutex_unlock(&dev->interrupt_mutex);
}
}
/* Passes this packet up the stack, updating its accounting. /* Passes this packet up the stack, updating its accounting.
* Some link protocols batch packets, so their rx_fixup paths * Some link protocols batch packets, so their rx_fixup paths
* can return clones as well as just modify the original skb. * can return clones as well as just modify the original skb.
...@@ -725,7 +789,7 @@ int usbnet_stop (struct net_device *net) ...@@ -725,7 +789,7 @@ int usbnet_stop (struct net_device *net)
if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) if (!(info->flags & FLAG_AVOID_UNLINK_URBS))
usbnet_terminate_urbs(dev); usbnet_terminate_urbs(dev);
usb_kill_urb(dev->interrupt); usbnet_status_stop(dev);
usbnet_purge_paused_rxq(dev); usbnet_purge_paused_rxq(dev);
...@@ -787,7 +851,7 @@ int usbnet_open (struct net_device *net) ...@@ -787,7 +851,7 @@ int usbnet_open (struct net_device *net)
/* start any status interrupt transfer */ /* start any status interrupt transfer */
if (dev->interrupt) { if (dev->interrupt) {
retval = usb_submit_urb (dev->interrupt, GFP_KERNEL); retval = usbnet_status_start(dev, GFP_KERNEL);
if (retval < 0) { if (retval < 0) {
netif_err(dev, ifup, dev->net, netif_err(dev, ifup, dev->net,
"intr submit %d\n", retval); "intr submit %d\n", retval);
...@@ -1458,6 +1522,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) ...@@ -1458,6 +1522,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
dev->delay.data = (unsigned long) dev; dev->delay.data = (unsigned long) dev;
init_timer (&dev->delay); init_timer (&dev->delay);
mutex_init (&dev->phy_mutex); mutex_init (&dev->phy_mutex);
mutex_init(&dev->interrupt_mutex);
dev->interrupt_count = 0;
dev->net = net; dev->net = net;
strcpy (net->name, "usb%d"); strcpy (net->name, "usb%d");
...@@ -1593,7 +1659,7 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message) ...@@ -1593,7 +1659,7 @@ int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
*/ */
netif_device_detach (dev->net); netif_device_detach (dev->net);
usbnet_terminate_urbs(dev); usbnet_terminate_urbs(dev);
usb_kill_urb(dev->interrupt); __usbnet_status_stop_force(dev);
/* /*
* reattach so runtime management can use and * reattach so runtime management can use and
...@@ -1613,9 +1679,8 @@ int usbnet_resume (struct usb_interface *intf) ...@@ -1613,9 +1679,8 @@ int usbnet_resume (struct usb_interface *intf)
int retval; int retval;
if (!--dev->suspend_count) { if (!--dev->suspend_count) {
/* resume interrupt URBs */ /* resume interrupt URB if it was previously submitted */
if (dev->interrupt && test_bit(EVENT_DEV_OPEN, &dev->flags)) __usbnet_status_start_force(dev, GFP_NOIO);
usb_submit_urb(dev->interrupt, GFP_NOIO);
spin_lock_irq(&dev->txq.lock); spin_lock_irq(&dev->txq.lock);
while ((res = usb_get_from_anchor(&dev->deferred))) { while ((res = usb_get_from_anchor(&dev->deferred))) {
......
...@@ -84,13 +84,10 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) ...@@ -84,13 +84,10 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
phy = get_phy_device(mdio, addr, is_c45); phy = get_phy_device(mdio, addr, is_c45);
if (!phy || IS_ERR(phy)) { if (!phy || IS_ERR(phy)) {
phy = phy_device_create(mdio, addr, 0, false, NULL); dev_err(&mdio->dev,
if (!phy || IS_ERR(phy)) { "cannot get PHY at address %i\n",
dev_err(&mdio->dev, addr);
"error creating PHY at address %i\n", continue;
addr);
continue;
}
} }
/* Associate the OF node with the device structure so it /* Associate the OF node with the device structure so it
......
...@@ -56,6 +56,8 @@ struct usbnet { ...@@ -56,6 +56,8 @@ struct usbnet {
struct sk_buff_head done; struct sk_buff_head done;
struct sk_buff_head rxq_pause; struct sk_buff_head rxq_pause;
struct urb *interrupt; struct urb *interrupt;
unsigned interrupt_count;
struct mutex interrupt_mutex;
struct usb_anchor deferred; struct usb_anchor deferred;
struct tasklet_struct bh; struct tasklet_struct bh;
...@@ -248,4 +250,7 @@ extern int usbnet_nway_reset(struct net_device *net); ...@@ -248,4 +250,7 @@ extern int usbnet_nway_reset(struct net_device *net);
extern int usbnet_manage_power(struct usbnet *, int); extern int usbnet_manage_power(struct usbnet *, int);
extern void usbnet_link_change(struct usbnet *, bool, bool); extern void usbnet_link_change(struct usbnet *, bool, bool);
extern int usbnet_status_start(struct usbnet *dev, gfp_t mem_flags);
extern void usbnet_status_stop(struct usbnet *dev);
#endif /* __LINUX_USB_USBNET_H */ #endif /* __LINUX_USB_USBNET_H */
...@@ -12,11 +12,11 @@ ...@@ -12,11 +12,11 @@
*/ */
/* some useful defines for sb1000.c e cmconfig.c - fv */ /* some useful defines for sb1000.c e cmconfig.c - fv */
#define SIOCGCMSTATS SIOCDEVPRIVATE+0 /* get cable modem stats */ #define SIOCGCMSTATS (SIOCDEVPRIVATE+0) /* get cable modem stats */
#define SIOCGCMFIRMWARE SIOCDEVPRIVATE+1 /* get cm firmware version */ #define SIOCGCMFIRMWARE (SIOCDEVPRIVATE+1) /* get cm firmware version */
#define SIOCGCMFREQUENCY SIOCDEVPRIVATE+2 /* get cable modem frequency */ #define SIOCGCMFREQUENCY (SIOCDEVPRIVATE+2) /* get cable modem frequency */
#define SIOCSCMFREQUENCY SIOCDEVPRIVATE+3 /* set cable modem frequency */ #define SIOCSCMFREQUENCY (SIOCDEVPRIVATE+3) /* set cable modem frequency */
#define SIOCGCMPIDS SIOCDEVPRIVATE+4 /* get cable modem PIDs */ #define SIOCGCMPIDS (SIOCDEVPRIVATE+4) /* get cable modem PIDs */
#define SIOCSCMPIDS SIOCDEVPRIVATE+5 /* set cable modem PIDs */ #define SIOCSCMPIDS (SIOCDEVPRIVATE+5) /* set cable modem PIDs */
#endif #endif
...@@ -2213,6 +2213,17 @@ __be16 skb_network_protocol(struct sk_buff *skb) ...@@ -2213,6 +2213,17 @@ __be16 skb_network_protocol(struct sk_buff *skb)
__be16 type = skb->protocol; __be16 type = skb->protocol;
int vlan_depth = ETH_HLEN; int vlan_depth = ETH_HLEN;
/* Tunnel gso handlers can set protocol to ethernet. */
if (type == htons(ETH_P_TEB)) {
struct ethhdr *eth;
if (unlikely(!pskb_may_pull(skb, sizeof(struct ethhdr))))
return 0;
eth = (struct ethhdr *)skb_mac_header(skb);
type = eth->h_proto;
}
while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
struct vlan_hdr *vh; struct vlan_hdr *vh;
......
...@@ -150,13 +150,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, ...@@ -150,13 +150,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
csum = false; csum = false;
/* setup inner skb. */ /* setup inner skb. */
if (greh->protocol == htons(ETH_P_TEB)) { skb->protocol = greh->protocol;
struct ethhdr *eth = (struct ethhdr *)skb_inner_mac_header(skb);
skb->protocol = eth->h_proto;
} else {
skb->protocol = greh->protocol;
}
skb->encapsulation = 0; skb->encapsulation = 0;
if (unlikely(!pskb_may_pull(skb, ghl))) if (unlikely(!pskb_may_pull(skb, ghl)))
......
...@@ -2311,7 +2311,6 @@ static struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, ...@@ -2311,7 +2311,6 @@ static struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
struct sk_buff *segs = ERR_PTR(-EINVAL); struct sk_buff *segs = ERR_PTR(-EINVAL);
int mac_len = skb->mac_len; int mac_len = skb->mac_len;
int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
struct ethhdr *inner_eth = (struct ethhdr *)skb_inner_mac_header(skb);
__be16 protocol = skb->protocol; __be16 protocol = skb->protocol;
netdev_features_t enc_features; netdev_features_t enc_features;
int outer_hlen; int outer_hlen;
...@@ -2324,8 +2323,7 @@ static struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, ...@@ -2324,8 +2323,7 @@ static struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
skb_set_network_header(skb, skb_inner_network_offset(skb)); skb_set_network_header(skb, skb_inner_network_offset(skb));
skb->mac_len = skb_inner_network_offset(skb); skb->mac_len = skb_inner_network_offset(skb);
inner_eth = (struct ethhdr *)skb_mac_header(skb); skb->protocol = htons(ETH_P_TEB);
skb->protocol = inner_eth->h_proto;
/* segment inner packet. */ /* segment inner packet. */
enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment