}
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");
goto out_err_phc;
}
req = get_mac_list_cmd.va;
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
- OPCODE_COMMON_GET_MAC_LIST, sizeof(*req),
- wrb, &get_mac_list_cmd);
-
+ OPCODE_COMMON_GET_MAC_LIST,
+ get_mac_list_cmd.size, wrb, &get_mac_list_cmd);
req->hdr.domain = domain;
req->mac_type = MAC_ADDRESS_TYPE_NETWORK;
req->perm_override = 1;
mdelay(1);
} else {
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)
break;
}
q = &rxo->q;
if (q->created) {
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_queue_free(adapter, q);
* all tx skbs are freed.
*/
be_tx_compl_clean(adapter);
+ netif_tx_disable(netdev);
be_rx_qs_destroy(adapter);
if (!status)
be_link_status_update(adapter, link_status);
+ netif_tx_start_all_queues(netdev);
be_roce_dev_open(adapter);
return 0;
err:
goto done;
}
+ pci_disable_sriov(adapter->pdev);
+
for_all_vfs(adapter, vf_cfg, vf) {
if (lancer_chip(adapter))
be_cmd_set_mac_list(adapter, NULL, 0, vf + 1);
be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1);
}
- pci_disable_sriov(adapter->pdev);
done:
kfree(adapter->vf_cfg);
adapter->num_vfs = 0;
dev_info(dev, "Device supports %d VFs and not %d\n",
adapter->dev_num_vfs, num_vfs);
adapter->num_vfs = min_t(u16, num_vfs, adapter->dev_num_vfs);
-
- status = pci_enable_sriov(adapter->pdev, num_vfs);
- if (status) {
- dev_err(dev, "SRIOV enable failed\n");
- adapter->num_vfs = 0;
+ if (!adapter->num_vfs)
return 0;
- }
}
status = be_vf_setup_init(adapter);
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;
err:
dev_err(dev, "VF setup failed\n");
be_cmd_set_flow_control(adapter, adapter->tx_fc,
adapter->rx_fc);
- if (be_physfn(adapter) && num_vfs) {
+ if (be_physfn(adapter)) {
if (adapter->dev_num_vfs)
be_vf_setup(adapter);
else
#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)
+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
* tx_bd_base always point to the base of the buffer descriptors. The
* cur_rx and cur_tx point to the currently available buffer.
/* The ring entries to be free()ed */
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;
int opened;
int hwts_rx_en;
int hwts_tx_en;
struct timer_list time_keep;
-
+ struct fec_enet_delayed_work delay_work;
};
void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev);
u32 rcntl = OPT_FRAME_SIZE | 0x04;
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. */
writel(1, fep->hwp + FEC_ECNTRL);
udelay(10);
/* Enable interrupts we wish to service */
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
ndev->stats.tx_errors++;
- fec_restart(ndev, fep->full_duplex);
- netif_wake_queue(ndev);
+ fep->delay_work.timeout = true;
+ 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
{
struct fec_enet_private *fep = netdev_priv(ndev);
struct phy_device *phy_dev = fep->phy_dev;
- unsigned long flags;
-
int status_change = 0;
- spin_lock_irqsave(&fep->hw_lock, flags);
-
/* Prevent a state halted on mii error */
if (fep->mii_timeout && phy_dev->state == PHY_HALTED) {
phy_dev->state = PHY_RESUMING;
- goto spin_unlock;
+ return;
}
if (phy_dev->link) {
}
}
-spin_unlock:
- spin_unlock_irqrestore(&fep->hw_lock, flags);
-
if (status_change)
phy_print_status(phy_dev);
}
return -ENOMEM;
memset(cbd_base, 0, PAGE_SIZE);
- spin_lock_init(&fep->hw_lock);
fep->netdev = ndev;
if (fep->bufdesc_ex && fep->ptp_clock)
netdev_info(ndev, "registered PHC device %d\n", fep->dev_id);
+ INIT_DELAYED_WORK(&(fep->delay_work.delay_work), fec_enet_work);
return 0;
failed_register:
struct fec_enet_private *fep = netdev_priv(ndev);
int i;
+ cancel_delayed_work_sync(&(fep->delay_work.delay_work));
unregister_netdev(ndev);
fec_enet_mii_remove(fep);
del_timer_sync(&fep->time_keep);
ptp->phc_clock = ptp_clock_register(&ptp->phc_clock_info,
&efx->pci_dev->dev);
- if (!ptp->phc_clock)
+ if (IS_ERR(ptp->phc_clock)) {
+ rc = PTR_ERR(ptp->phc_clock);
goto fail3;
+ }
INIT_WORK(&ptp->pps_work, efx_ptp_pps_worker);
ptp->pps_workwq = create_singlethread_workqueue("sfc_pps");
goto alloc_rx_failed;
/* Allocate rx skbs */
- if (spider_net_alloc_rx_skbs(card))
+ result = spider_net_alloc_rx_skbs(card);
+ if (result)
goto alloc_skbs_failed;
spider_net_set_multi(netdev);
{
struct bfin_sir_self *self = netdev_priv(dev);
struct bfin_sir_port *port = self->sir_port;
- int err = -ENOMEM;
+ int err;
self->newspeed = 0;
self->speed = 9600;
bfin_sir_set_speed(port, 9600);
self->irlap = irlap_open(dev, &self->qos, DRIVER_NAME);
- if (!self->irlap)
+ if (!self->irlap) {
+ err = -ENOMEM;
goto err_irlap;
+ }
INIT_WORK(&self->work, bfin_sir_send_work);
.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 */
{
USB_DEVICE_AND_INTERFACE_INFO(0x16d5, 0x650a, USB_CLASS_COMM,
USB_CDC_PROTO_NONE),
.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 */
USB_DEVICE_AND_INTERFACE_INFO(0x16d5, 0x650a,
USB_CLASS_COMM,
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 */
status = sierra_net_send_sync(dev);
if (status < 0)
/* set context index initially to 0 - prepares tx hdr template */
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 */
dev->rx_urb_size = SIERRA_NET_RX_URB_SIZE;
if (dev->udev->speed != USB_SPEED_HIGH)
kfree(priv);
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;
}
netdev_err(dev->net,
"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);
}
.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) \
{USB_DEVICE_INTERFACE_NUMBER(vend, prod, 7), \
.driver_info = (unsigned long)&sierra_net_info_direct_ip}, \
static struct usb_driver sierra_net_driver = {
.name = "sierra_net",
.id_table = products,
- .probe = usbnet_probe,
+ .probe = sierra_net_probe,
.disconnect = usbnet_disconnect,
.suspend = usbnet_suspend,
.resume = usbnet_resume,
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.
* Some link protocols batch packets, so their rx_fixup paths
* can return clones as well as just modify the original skb.
if (!(info->flags & FLAG_AVOID_UNLINK_URBS))
usbnet_terminate_urbs(dev);
- usb_kill_urb(dev->interrupt);
+ usbnet_status_stop(dev);
usbnet_purge_paused_rxq(dev);
/* start any status interrupt transfer */
if (dev->interrupt) {
- retval = usb_submit_urb (dev->interrupt, GFP_KERNEL);
+ retval = usbnet_status_start(dev, GFP_KERNEL);
if (retval < 0) {
netif_err(dev, ifup, dev->net,
"intr submit %d\n", retval);
dev->delay.data = (unsigned long) dev;
init_timer (&dev->delay);
mutex_init (&dev->phy_mutex);
+ mutex_init(&dev->interrupt_mutex);
+ dev->interrupt_count = 0;
dev->net = net;
strcpy (net->name, "usb%d");
*/
netif_device_detach (dev->net);
usbnet_terminate_urbs(dev);
- usb_kill_urb(dev->interrupt);
+ __usbnet_status_stop_force(dev);
/*
* reattach so runtime management can use and
int retval;
if (!--dev->suspend_count) {
- /* resume interrupt URBs */
- if (dev->interrupt && test_bit(EVENT_DEV_OPEN, &dev->flags))
- usb_submit_urb(dev->interrupt, GFP_NOIO);
+ /* resume interrupt URB if it was previously submitted */
+ __usbnet_status_start_force(dev, GFP_NOIO);
spin_lock_irq(&dev->txq.lock);
while ((res = usb_get_from_anchor(&dev->deferred))) {
phy = get_phy_device(mdio, addr, is_c45);
if (!phy || IS_ERR(phy)) {
- phy = phy_device_create(mdio, addr, 0, false, NULL);
- if (!phy || IS_ERR(phy)) {
- dev_err(&mdio->dev,
- "error creating PHY at address %i\n",
- addr);
- continue;
- }
+ dev_err(&mdio->dev,
+ "cannot get PHY at address %i\n",
+ addr);
+ continue;
}
/* Associate the OF node with the device structure so it
struct sk_buff_head done;
struct sk_buff_head rxq_pause;
struct urb *interrupt;
+ unsigned interrupt_count;
+ struct mutex interrupt_mutex;
struct usb_anchor deferred;
struct tasklet_struct bh;
extern int usbnet_manage_power(struct usbnet *, int);
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 */
*/
/* some useful defines for sb1000.c e cmconfig.c - fv */
-#define SIOCGCMSTATS SIOCDEVPRIVATE+0 /* get cable modem stats */
-#define SIOCGCMFIRMWARE SIOCDEVPRIVATE+1 /* get cm firmware version */
-#define SIOCGCMFREQUENCY SIOCDEVPRIVATE+2 /* get cable modem frequency */
-#define SIOCSCMFREQUENCY SIOCDEVPRIVATE+3 /* set cable modem frequency */
-#define SIOCGCMPIDS SIOCDEVPRIVATE+4 /* get cable modem PIDs */
-#define SIOCSCMPIDS SIOCDEVPRIVATE+5 /* set cable modem PIDs */
+#define SIOCGCMSTATS (SIOCDEVPRIVATE+0) /* get cable modem stats */
+#define SIOCGCMFIRMWARE (SIOCDEVPRIVATE+1) /* get cm firmware version */
+#define SIOCGCMFREQUENCY (SIOCDEVPRIVATE+2) /* get cable modem frequency */
+#define SIOCSCMFREQUENCY (SIOCDEVPRIVATE+3) /* set cable modem frequency */
+#define SIOCGCMPIDS (SIOCDEVPRIVATE+4) /* get cable modem PIDs */
+#define SIOCSCMPIDS (SIOCDEVPRIVATE+5) /* set cable modem PIDs */
#endif
__be16 type = skb->protocol;
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)) {
struct vlan_hdr *vh;
csum = false;
/* setup inner skb. */
- if (greh->protocol == htons(ETH_P_TEB)) {
- struct ethhdr *eth = (struct ethhdr *)skb_inner_mac_header(skb);
- skb->protocol = eth->h_proto;
- } else {
- skb->protocol = greh->protocol;
- }
-
+ skb->protocol = greh->protocol;
skb->encapsulation = 0;
if (unlikely(!pskb_may_pull(skb, ghl)))
struct sk_buff *segs = ERR_PTR(-EINVAL);
int mac_len = skb->mac_len;
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;
netdev_features_t enc_features;
int outer_hlen;
skb_reset_mac_header(skb);
skb_set_network_header(skb, skb_inner_network_offset(skb));
skb->mac_len = skb_inner_network_offset(skb);
- inner_eth = (struct ethhdr *)skb_mac_header(skb);
- skb->protocol = inner_eth->h_proto;
+ skb->protocol = htons(ETH_P_TEB);
/* segment inner packet. */
enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);