/* The EL3 interrupt handler. */ static irqreturn_t el3_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *) dev_id; struct el3_private *lp = netdev_priv(dev); unsigned int ioaddr; __u16 status; int i = 0, handled = 1; if (!netif_device_present(dev)) return IRQ_NONE; ioaddr = dev->base_addr; netdev_dbg(dev, "interrupt, status %4.4x.\n", inw(ioaddr + EL3_STATUS)); spin_lock(&lp->lock); while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete | StatsFull)) { if ((status & 0xe000) != 0x2000) { netdev_dbg(dev, "interrupt from dead card\n"); handled = 0; break; } if (status & RxComplete) el3_rx(dev); if (status & TxAvailable) { netdev_dbg(dev, " TX room bit was handled.\n"); /* There's room in the FIFO for a full-sized packet. */ outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); netif_wake_queue(dev); } if (status & TxComplete) pop_tx_status(dev); if (status & (AdapterFailure | RxEarly | StatsFull)) { /* Handle all uncommon interrupts. */ if (status & StatsFull) /* Empty statistics. */ update_stats(dev); if (status & RxEarly) { /* Rx early is unused. */ el3_rx(dev); outw(AckIntr | RxEarly, ioaddr + EL3_CMD); } if (status & AdapterFailure) { u16 fifo_diag; EL3WINDOW(4); fifo_diag = inw(ioaddr + 4); EL3WINDOW(1); netdev_warn(dev, "adapter failure, FIFO diagnostic register %04x.\n", fifo_diag); if (fifo_diag & 0x0400) { /* Tx overrun */ tc589_wait_for_completion(dev, TxReset); outw(TxEnable, ioaddr + EL3_CMD); } if (fifo_diag & 0x2000) { /* Rx underrun */ tc589_wait_for_completion(dev, RxReset); set_rx_mode(dev); outw(RxEnable, ioaddr + EL3_CMD); } outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); } } if (++i > 10) { netdev_err(dev, "infinite loop in interrupt, status %4.4x.\n", status); /* Clear all interrupts */ outw(AckIntr | 0xFF, ioaddr + EL3_CMD); break; } /* Acknowledge the IRQ. */ outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); } lp->last_irq = jiffies; spin_unlock(&lp->lock); netdev_dbg(dev, "exiting interrupt, status %4.4x.\n", inw(ioaddr + EL3_STATUS)); return IRQ_RETVAL(handled); }
netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) { struct usbnet *dev = netdev_priv(net); int length; struct urb *urb = NULL; struct skb_data *entry; struct driver_info *info = dev->driver_info; unsigned long flags; int retval; // some devices want funky USB-level framing, for // win32 driver (usually) and/or hardware quirks if (info->tx_fixup) { skb = info->tx_fixup (dev, skb, GFP_ATOMIC); if (!skb) { if (netif_msg_tx_err(dev)) { netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n"); goto drop; } else { /* cdc_ncm collected packet; waits for more */ goto not_drop; } } } length = skb->len; if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) { netif_dbg(dev, tx_err, dev->net, "no urb\n"); goto drop; } entry = (struct skb_data *) skb->cb; entry->urb = urb; entry->dev = dev; entry->state = tx_start; entry->length = length; usb_fill_bulk_urb (urb, dev->udev, dev->out, skb->data, skb->len, tx_complete, skb); /* don't assume the hardware handles USB_ZERO_PACKET * NOTE: strictly conforming cdc-ether devices should expect * the ZLP here, but ignore the one-byte packet. * NOTE2: CDC NCM specification is different from CDC ECM when * handling ZLP/short packets, so cdc_ncm driver will make short * packet itself if needed. */ if (length % dev->maxpacket == 0) { if (!(info->flags & FLAG_SEND_ZLP)) { if (!(info->flags & FLAG_MULTI_PACKET)) { urb->transfer_buffer_length++; if (skb_tailroom(skb)) { skb->data[skb->len] = 0; __skb_put(skb, 1); } } } else urb->transfer_flags |= URB_ZERO_PACKET; } spin_lock_irqsave(&dev->txq.lock, flags); retval = usb_autopm_get_interface_async(dev->intf); if (retval < 0) { spin_unlock_irqrestore(&dev->txq.lock, flags); goto drop; } #ifdef CONFIG_PM /* if this triggers the device is still a sleep */ if (test_bit(EVENT_DEV_ASLEEP, &dev->flags)) { /* transmission will be done in resume */ usb_anchor_urb(urb, &dev->deferred); /* no use to process more packets */ netif_stop_queue(net); spin_unlock_irqrestore(&dev->txq.lock, flags); netdev_dbg(dev->net, "Delaying transmission for resumption\n"); goto deferred; } #endif switch ((retval = usb_submit_urb (urb, GFP_ATOMIC))) { case -EPIPE: netif_stop_queue (net); usbnet_defer_kevent (dev, EVENT_TX_HALT); usb_autopm_put_interface_async(dev->intf); break; default: usb_autopm_put_interface_async(dev->intf); netif_dbg(dev, tx_err, dev->net, "tx: submit urb err %d\n", retval); break; case 0: net->trans_start = jiffies; __skb_queue_tail (&dev->txq, skb); if (dev->txq.qlen >= TX_QLEN (dev)) netif_stop_queue (net); } spin_unlock_irqrestore (&dev->txq.lock, flags); if (retval) { netif_dbg(dev, tx_err, dev->net, "drop, code %d\n", retval); drop: dev->net->stats.tx_dropped++; not_drop: if (skb) dev_kfree_skb_any (skb); usb_free_urb (urb); } else netif_dbg(dev, tx_queued, dev->net, "> tx, len %d, type 0x%x\n", length, skb->protocol); #ifdef CONFIG_PM deferred: #endif return NETDEV_TX_OK; }
/* work that cannot be done in interrupt context uses keventd. * * NOTE: with 2.5 we could do more of this using completion callbacks, * especially now that control transfers can be queued. */ static void kevent (struct work_struct *work) { struct usbnet *dev = container_of(work, struct usbnet, kevent); int status; /* usb_clear_halt() needs a thread context */ if (test_bit (EVENT_TX_HALT, &dev->flags)) { unlink_urbs (dev, &dev->txq); status = usb_autopm_get_interface(dev->intf); if (status < 0) goto fail_pipe; status = usb_clear_halt (dev->udev, dev->out); usb_autopm_put_interface(dev->intf); if (status < 0 && status != -EPIPE && status != -ESHUTDOWN) { if (netif_msg_tx_err (dev)) fail_pipe: netdev_err(dev->net, "can't clear tx halt, status %d\n", status); } else { clear_bit (EVENT_TX_HALT, &dev->flags); if (status != -ESHUTDOWN) netif_wake_queue (dev->net); } } if (test_bit (EVENT_RX_HALT, &dev->flags)) { unlink_urbs (dev, &dev->rxq); status = usb_autopm_get_interface(dev->intf); if (status < 0) goto fail_halt; status = usb_clear_halt (dev->udev, dev->in); usb_autopm_put_interface(dev->intf); if (status < 0 && status != -EPIPE && status != -ESHUTDOWN) { if (netif_msg_rx_err (dev)) fail_halt: netdev_err(dev->net, "can't clear rx halt, status %d\n", status); } else { clear_bit (EVENT_RX_HALT, &dev->flags); tasklet_schedule (&dev->bh); } } /* tasklet could resubmit itself forever if memory is tight */ if (test_bit (EVENT_RX_MEMORY, &dev->flags)) { struct urb *urb = NULL; int resched = 1; if (netif_running (dev->net)) urb = usb_alloc_urb (0, GFP_KERNEL); else clear_bit (EVENT_RX_MEMORY, &dev->flags); if (urb != NULL) { clear_bit (EVENT_RX_MEMORY, &dev->flags); status = usb_autopm_get_interface(dev->intf); if (status < 0) goto fail_lowmem; if (rx_submit (dev, urb, GFP_KERNEL) == -ENOLINK) resched = 0; usb_autopm_put_interface(dev->intf); fail_lowmem: if (resched) tasklet_schedule (&dev->bh); } } if (test_bit (EVENT_LINK_RESET, &dev->flags)) { struct driver_info *info = dev->driver_info; int retval = 0; clear_bit (EVENT_LINK_RESET, &dev->flags); status = usb_autopm_get_interface(dev->intf); if (status < 0) goto skip_reset; if(info->link_reset && (retval = info->link_reset(dev)) < 0) { usb_autopm_put_interface(dev->intf); skip_reset: netdev_info(dev->net, "link reset failed (%d) usbnet usb-%s-%s, %s\n", retval, dev->udev->bus->bus_name, dev->udev->devpath, info->description); } else { usb_autopm_put_interface(dev->intf); } } if (dev->flags) netdev_dbg(dev->net, "kevent done, flags = 0x%lx\n", dev->flags); }
static void ti_hecc_reset(struct net_device *ndev) { u32 cnt; struct ti_hecc_priv *priv = netdev_priv(ndev); netdev_dbg(ndev, "resetting hecc ...\n"); hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_SRES); /* Set change control request and wait till enabled */ hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_CCR); /* * INFO: It has been observed that at times CCE bit may not be * set and hw seems to be ok even if this bit is not set so * timing out with a timing of 1ms to respect the specs */ cnt = HECC_CCE_WAIT_COUNT; while (!hecc_get_bit(priv, HECC_CANES, HECC_CANES_CCE) && cnt != 0) { --cnt; udelay(10); } /* * Note: On HECC, BTC can be programmed only in initialization mode, so * it is expected that the can bittiming parameters are set via ip * utility before the device is opened */ ti_hecc_set_btc(priv); /* Clear CCR (and CANMC register) and wait for CCE = 0 enable */ hecc_write(priv, HECC_CANMC, 0); /* * INFO: CAN net stack handles bus off and hence disabling auto-bus-on * hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_ABO); */ /* * INFO: It has been observed that at times CCE bit may not be * set and hw seems to be ok even if this bit is not set so */ cnt = HECC_CCE_WAIT_COUNT; while (hecc_get_bit(priv, HECC_CANES, HECC_CANES_CCE) && cnt != 0) { --cnt; udelay(10); } /* Enable TX and RX I/O Control pins */ hecc_write(priv, HECC_CANTIOC, HECC_CANTIOC_EN); hecc_write(priv, HECC_CANRIOC, HECC_CANRIOC_EN); /* Clear registers for clean operation */ hecc_write(priv, HECC_CANTA, HECC_SET_REG); hecc_write(priv, HECC_CANRMP, HECC_SET_REG); hecc_write(priv, HECC_CANGIF0, HECC_SET_REG); hecc_write(priv, HECC_CANGIF1, HECC_SET_REG); hecc_write(priv, HECC_CANME, 0); hecc_write(priv, HECC_CANMD, 0); /* SCC compat mode NOT supported (and not needed too) */ hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_SCM); }
static int c_can_poll(struct napi_struct *napi, int quota) { u16 irqstatus; int lec_type = 0; int work_done = 0; struct net_device *dev = napi->dev; struct c_can_priv *priv = netdev_priv(dev); irqstatus = priv->irqstatus; if (!irqstatus) goto end; /* status events have the highest priority */ if (irqstatus == STATUS_INTERRUPT) { priv->current_status = priv->read_reg(priv, C_CAN_STS_REG); /* handle Tx/Rx events */ if (priv->current_status & STATUS_TXOK) priv->write_reg(priv, C_CAN_STS_REG, priv->current_status & ~STATUS_TXOK); if (priv->current_status & STATUS_RXOK) priv->write_reg(priv, C_CAN_STS_REG, priv->current_status & ~STATUS_RXOK); /* handle state changes */ if ((priv->current_status & STATUS_EWARN) && (!(priv->last_status & STATUS_EWARN))) { netdev_dbg(dev, "entered error warning state\n"); work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING); } if ((priv->current_status & STATUS_EPASS) && (!(priv->last_status & STATUS_EPASS))) { netdev_dbg(dev, "entered error passive state\n"); work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE); } if ((priv->current_status & STATUS_BOFF) && (!(priv->last_status & STATUS_BOFF))) { netdev_dbg(dev, "entered bus off state\n"); work_done += c_can_handle_state_change(dev, C_CAN_BUS_OFF); } /* handle bus recovery events */ if ((!(priv->current_status & STATUS_BOFF)) && (priv->last_status & STATUS_BOFF)) { netdev_dbg(dev, "left bus off state\n"); priv->can.state = CAN_STATE_ERROR_ACTIVE; } if ((!(priv->current_status & STATUS_EPASS)) && (priv->last_status & STATUS_EPASS)) { netdev_dbg(dev, "left error passive state\n"); priv->can.state = CAN_STATE_ERROR_ACTIVE; } priv->last_status = priv->current_status; /* handle lec errors on the bus */ lec_type = c_can_has_and_handle_berr(priv); if (lec_type) work_done += c_can_handle_bus_err(dev, lec_type); } else if ((irqstatus >= C_CAN_MSG_OBJ_RX_FIRST) && (irqstatus <= C_CAN_MSG_OBJ_RX_LAST)) { /* handle events corresponding to receive message objects */ work_done += c_can_do_rx_poll(dev, (quota - work_done)); } else if ((irqstatus >= C_CAN_MSG_OBJ_TX_FIRST) && (irqstatus <= C_CAN_MSG_OBJ_TX_LAST)) { /* handle events corresponding to transmit message objects */ c_can_do_tx(dev); } end: if (work_done < quota) { napi_complete(napi); /* enable all IRQs */ c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS); } return work_done; }
static struct sk_buff *rtllib_ADDBA(struct rtllib_device *ieee, u8 *Dst, struct ba_record *pBA, u16 StatusCode, u8 type) { struct sk_buff *skb = NULL; struct rtllib_hdr_3addr *BAReq = NULL; u8 *tag = NULL; u16 len = ieee->tx_headroom + 9; netdev_dbg(ieee->dev, "%s(): frame(%d) sentd to: %pM, ieee->dev:%p\n", __func__, type, Dst, ieee->dev); if (pBA == NULL) { netdev_warn(ieee->dev, "pBA is NULL\n"); return NULL; } skb = dev_alloc_skb(len + sizeof(struct rtllib_hdr_3addr)); if (skb == NULL) return NULL; memset(skb->data, 0, sizeof(struct rtllib_hdr_3addr)); skb_reserve(skb, ieee->tx_headroom); BAReq = (struct rtllib_hdr_3addr *)skb_put(skb, sizeof(struct rtllib_hdr_3addr)); ether_addr_copy(BAReq->addr1, Dst); ether_addr_copy(BAReq->addr2, ieee->dev->dev_addr); ether_addr_copy(BAReq->addr3, ieee->current_network.bssid); BAReq->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT); tag = (u8 *)skb_put(skb, 9); *tag++ = ACT_CAT_BA; *tag++ = type; *tag++ = pBA->DialogToken; if (type == ACT_ADDBARSP) { RT_TRACE(COMP_DBG, "====>to send ADDBARSP\n"); put_unaligned_le16(StatusCode, tag); tag += 2; } put_unaligned_le16(pBA->BaParamSet.shortData, tag); tag += 2; put_unaligned_le16(pBA->BaTimeoutValue, tag); tag += 2; if (type == ACT_ADDBAREQ) { memcpy(tag, (u8 *)&(pBA->BaStartSeqCtrl), 2); tag += 2; } #ifdef VERBOSE_DEBUG print_hex_dump_bytes("rtllib_ADDBA(): ", DUMP_PREFIX_NONE, skb->data, skb->len); #endif return skb; }
static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) { netdev_dbg(dev->net, "dm_write_async() reg=0x%02x length=%d\n", reg, length); dm_write_async_helper(dev, reg, 0, length, data); }
/*---------------------------------------------------------------- * p80211_rx_typedrop * * Classifies the frame, increments the appropriate counter, and * returns 0|1|2 indicating whether the driver should handle, ignore, or * drop the frame * * Arguments: * wlandev wlan device structure * fc frame control field * * Returns: * zero if the frame should be handled by the driver, * one if the frame should be ignored * anything else means we drop it. * * Side effects: * * Call context: * interrupt *---------------------------------------------------------------- */ static int p80211_rx_typedrop(struct wlandevice *wlandev, u16 fc) { u16 ftype; u16 fstype; int drop = 0; /* Classify frame, increment counter */ ftype = WLAN_GET_FC_FTYPE(fc); fstype = WLAN_GET_FC_FSTYPE(fc); #if 0 netdev_dbg(wlandev->netdev, "rx_typedrop : ftype=%d fstype=%d.\n", ftype, fstype); #endif switch (ftype) { case WLAN_FTYPE_MGMT: if ((wlandev->netdev->flags & IFF_PROMISC) || (wlandev->netdev->flags & IFF_ALLMULTI)) { drop = 1; break; } netdev_dbg(wlandev->netdev, "rx'd mgmt:\n"); wlandev->rx.mgmt++; switch (fstype) { case WLAN_FSTYPE_ASSOCREQ: /* printk("assocreq"); */ wlandev->rx.assocreq++; break; case WLAN_FSTYPE_ASSOCRESP: /* printk("assocresp"); */ wlandev->rx.assocresp++; break; case WLAN_FSTYPE_REASSOCREQ: /* printk("reassocreq"); */ wlandev->rx.reassocreq++; break; case WLAN_FSTYPE_REASSOCRESP: /* printk("reassocresp"); */ wlandev->rx.reassocresp++; break; case WLAN_FSTYPE_PROBEREQ: /* printk("probereq"); */ wlandev->rx.probereq++; break; case WLAN_FSTYPE_PROBERESP: /* printk("proberesp"); */ wlandev->rx.proberesp++; break; case WLAN_FSTYPE_BEACON: /* printk("beacon"); */ wlandev->rx.beacon++; break; case WLAN_FSTYPE_ATIM: /* printk("atim"); */ wlandev->rx.atim++; break; case WLAN_FSTYPE_DISASSOC: /* printk("disassoc"); */ wlandev->rx.disassoc++; break; case WLAN_FSTYPE_AUTHEN: /* printk("authen"); */ wlandev->rx.authen++; break; case WLAN_FSTYPE_DEAUTHEN: /* printk("deauthen"); */ wlandev->rx.deauthen++; break; default: /* printk("unknown"); */ wlandev->rx.mgmt_unknown++; break; } /* printk("\n"); */ drop = 2; break; case WLAN_FTYPE_CTL: if ((wlandev->netdev->flags & IFF_PROMISC) || (wlandev->netdev->flags & IFF_ALLMULTI)) { drop = 1; break; } netdev_dbg(wlandev->netdev, "rx'd ctl:\n"); wlandev->rx.ctl++; switch (fstype) { case WLAN_FSTYPE_PSPOLL: /* printk("pspoll"); */ wlandev->rx.pspoll++; break; case WLAN_FSTYPE_RTS: /* printk("rts"); */ wlandev->rx.rts++; break; case WLAN_FSTYPE_CTS: /* printk("cts"); */ wlandev->rx.cts++; break; case WLAN_FSTYPE_ACK: /* printk("ack"); */ wlandev->rx.ack++; break; case WLAN_FSTYPE_CFEND: /* printk("cfend"); */ wlandev->rx.cfend++; break; case WLAN_FSTYPE_CFENDCFACK: /* printk("cfendcfack"); */ wlandev->rx.cfendcfack++; break; default: /* printk("unknown"); */ wlandev->rx.ctl_unknown++; break; } /* printk("\n"); */ drop = 2; break; case WLAN_FTYPE_DATA: wlandev->rx.data++; switch (fstype) { case WLAN_FSTYPE_DATAONLY: wlandev->rx.dataonly++; break; case WLAN_FSTYPE_DATA_CFACK: wlandev->rx.data_cfack++; break; case WLAN_FSTYPE_DATA_CFPOLL: wlandev->rx.data_cfpoll++; break; case WLAN_FSTYPE_DATA_CFACK_CFPOLL: wlandev->rx.data__cfack_cfpoll++; break; case WLAN_FSTYPE_NULL: netdev_dbg(wlandev->netdev, "rx'd data:null\n"); wlandev->rx.null++; break; case WLAN_FSTYPE_CFACK: netdev_dbg(wlandev->netdev, "rx'd data:cfack\n"); wlandev->rx.cfack++; break; case WLAN_FSTYPE_CFPOLL: netdev_dbg(wlandev->netdev, "rx'd data:cfpoll\n"); wlandev->rx.cfpoll++; break; case WLAN_FSTYPE_CFACK_CFPOLL: netdev_dbg(wlandev->netdev, "rx'd data:cfack_cfpoll\n"); wlandev->rx.cfack_cfpoll++; break; default: /* printk("unknown"); */ wlandev->rx.data_unknown++; break; } break; } return drop; }
static int ibmveth_poll(struct napi_struct *napi, int budget) { struct ibmveth_adapter *adapter = container_of(napi, struct ibmveth_adapter, napi); struct net_device *netdev = adapter->netdev; int frames_processed = 0; unsigned long lpar_rc; struct iphdr *iph; u16 mss = 0; restart_poll: while (frames_processed < budget) { if (!ibmveth_rxq_pending_buffer(adapter)) break; smp_rmb(); if (!ibmveth_rxq_buffer_valid(adapter)) { wmb(); /* suggested by larson1 */ adapter->rx_invalid_buffer++; netdev_dbg(netdev, "recycling invalid buffer\n"); ibmveth_rxq_recycle_buffer(adapter); } else { struct sk_buff *skb, *new_skb; int length = ibmveth_rxq_frame_length(adapter); int offset = ibmveth_rxq_frame_offset(adapter); int csum_good = ibmveth_rxq_csum_good(adapter); int lrg_pkt = ibmveth_rxq_large_packet(adapter); skb = ibmveth_rxq_get_buffer(adapter); /* if the large packet bit is set in the rx queue * descriptor, the mss will be written by PHYP eight * bytes from the start of the rx buffer, which is * skb->data at this stage */ if (lrg_pkt) { __be64 *rxmss = (__be64 *)(skb->data + 8); mss = (u16)be64_to_cpu(*rxmss); } new_skb = NULL; if (length < rx_copybreak) new_skb = netdev_alloc_skb(netdev, length); if (new_skb) { skb_copy_to_linear_data(new_skb, skb->data + offset, length); if (rx_flush) ibmveth_flush_buffer(skb->data, length + offset); if (!ibmveth_rxq_recycle_buffer(adapter)) kfree_skb(skb); skb = new_skb; } else { ibmveth_rxq_harvest_buffer(adapter); skb_reserve(skb, offset); } skb_put(skb, length); skb->protocol = eth_type_trans(skb, netdev); if (csum_good) { skb->ip_summed = CHECKSUM_UNNECESSARY; if (be16_to_cpu(skb->protocol) == ETH_P_IP) { iph = (struct iphdr *)skb->data; /* If the IP checksum is not offloaded and if the packet * is large send, the checksum must be rebuilt. */ if (iph->check == 0xffff) { iph->check = 0; iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); } } } if (length > netdev->mtu + ETH_HLEN) { ibmveth_rx_mss_helper(skb, mss, lrg_pkt); adapter->rx_large_packets++; } napi_gro_receive(napi, skb); /* send it up */ netdev->stats.rx_packets++; netdev->stats.rx_bytes += length; frames_processed++; } } ibmveth_replenish_task(adapter); if (frames_processed < budget) { napi_complete(napi); /* We think we are done - reenable interrupts, * then check once more to make sure we are done. */ lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_ENABLE); BUG_ON(lpar_rc != H_SUCCESS); if (ibmveth_rxq_pending_buffer(adapter) && napi_reschedule(napi)) { lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); goto restart_poll; } } return frames_processed; }
static int xenvif_count_requests(struct xenvif *vif, struct xen_netif_tx_request *first, struct xen_netif_tx_request *txp, int work_to_do) { RING_IDX cons = vif->tx.req_cons; int slots = 0; int drop_err = 0; int more_data; if (!(first->flags & XEN_NETTXF_more_data)) return 0; do { struct xen_netif_tx_request dropped_tx = { 0 }; if (slots >= work_to_do) { netdev_err(vif->dev, "Asked for %d slots but exceeds this limit\n", work_to_do); xenvif_fatal_tx_err(vif); return -ENODATA; } /* This guest is really using too many slots and * considered malicious. */ if (unlikely(slots >= fatal_skb_slots)) { netdev_err(vif->dev, "Malicious frontend using %d slots, threshold %u\n", slots, fatal_skb_slots); xenvif_fatal_tx_err(vif); return -E2BIG; } /* Xen network protocol had implicit dependency on * MAX_SKB_FRAGS. XEN_NETBK_LEGACY_SLOTS_MAX is set to * the historical MAX_SKB_FRAGS value 18 to honor the * same behavior as before. Any packet using more than * 18 slots but less than fatal_skb_slots slots is * dropped */ if (!drop_err && slots >= XEN_NETBK_LEGACY_SLOTS_MAX) { if (net_ratelimit()) netdev_dbg(vif->dev, "Too many slots (%d) exceeding limit (%d), dropping packet\n", slots, XEN_NETBK_LEGACY_SLOTS_MAX); drop_err = -E2BIG; } if (drop_err) txp = &dropped_tx; memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + slots), sizeof(*txp)); /* If the guest submitted a frame >= 64 KiB then * first->size overflowed and following slots will * appear to be larger than the frame. * * This cannot be fatal error as there are buggy * frontends that do this. * * Consume all slots and drop the packet. */ if (!drop_err && txp->size > first->size) { if (net_ratelimit()) netdev_dbg(vif->dev, "Invalid tx request, slot size %u > remaining size %u\n", txp->size, first->size); drop_err = -EIO; } first->size -= txp->size; slots++; if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { netdev_err(vif->dev, "Cross page boundary, txp->offset: %x, size: %u\n", txp->offset, txp->size); xenvif_fatal_tx_err(vif); return -EINVAL; } more_data = txp->flags & XEN_NETTXF_more_data; if (!drop_err) txp++; } while (more_data); if (drop_err) { xenvif_tx_err(vif, first, cons + slots); return drop_err; } return slots; }
/*---------------------------------------------------------------- * p80211knetdev_hard_start_xmit * * Linux netdevice method for transmitting a frame. * * Arguments: * skb Linux sk_buff containing the frame. * netdev Linux netdevice. * * Side effects: * If the lower layers report that buffers are full. netdev->tbusy * will be set to prevent higher layers from sending more traffic. * * Note: If this function returns non-zero, higher layers retain * ownership of the skb. * * Returns: * zero on success, non-zero on failure. *---------------------------------------------------------------- */ static netdev_tx_t p80211knetdev_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) { int result = 0; int txresult = -1; struct wlandevice *wlandev = netdev->ml_priv; union p80211_hdr p80211_hdr; struct p80211_metawep p80211_wep; p80211_wep.data = NULL; if (!skb) return NETDEV_TX_OK; if (wlandev->state != WLAN_DEVICE_OPEN) { result = 1; goto failed; } memset(&p80211_hdr, 0, sizeof(p80211_hdr)); memset(&p80211_wep, 0, sizeof(p80211_wep)); if (netif_queue_stopped(netdev)) { netdev_dbg(netdev, "called when queue stopped.\n"); result = 1; goto failed; } netif_stop_queue(netdev); /* Check to see that a valid mode is set */ switch (wlandev->macmode) { case WLAN_MACMODE_IBSS_STA: case WLAN_MACMODE_ESS_STA: case WLAN_MACMODE_ESS_AP: break; default: /* Mode isn't set yet, just drop the frame * and return success . * TODO: we need a saner way to handle this */ if (be16_to_cpu(skb->protocol) != ETH_P_80211_RAW) { netif_start_queue(wlandev->netdev); netdev_notice(netdev, "Tx attempt prior to association, frame dropped.\n"); netdev->stats.tx_dropped++; result = 0; goto failed; } break; } /* Check for raw transmits */ if (be16_to_cpu(skb->protocol) == ETH_P_80211_RAW) { if (!capable(CAP_NET_ADMIN)) { result = 1; goto failed; } /* move the header over */ memcpy(&p80211_hdr, skb->data, sizeof(p80211_hdr)); skb_pull(skb, sizeof(p80211_hdr)); } else { if (skb_ether_to_p80211 (wlandev, wlandev->ethconv, skb, &p80211_hdr, &p80211_wep) != 0) { /* convert failed */ netdev_dbg(netdev, "ether_to_80211(%d) failed.\n", wlandev->ethconv); result = 1; goto failed; } } if (!wlandev->txframe) { result = 1; goto failed; } netif_trans_update(netdev); netdev->stats.tx_packets++; /* count only the packet payload */ netdev->stats.tx_bytes += skb->len; txresult = wlandev->txframe(wlandev, skb, &p80211_hdr, &p80211_wep); if (txresult == 0) { /* success and more buf */ /* avail, re: hw_txdata */ netif_wake_queue(wlandev->netdev); result = NETDEV_TX_OK; } else if (txresult == 1) { /* success, no more avail */ netdev_dbg(netdev, "txframe success, no more bufs\n"); /* netdev->tbusy = 1; don't set here, irqhdlr */ /* may have already cleared it */ result = NETDEV_TX_OK; } else if (txresult == 2) { /* alloc failure, drop frame */ netdev_dbg(netdev, "txframe returned alloc_fail\n"); result = NETDEV_TX_BUSY; } else { /* buffer full or queue busy, drop frame. */ netdev_dbg(netdev, "txframe returned full or busy\n"); result = NETDEV_TX_BUSY; } failed: /* Free up the WEP buffer if it's not the same as the skb */ if ((p80211_wep.data) && (p80211_wep.data != skb->data)) kzfree(p80211_wep.data); /* we always free the skb here, never in a lower level. */ if (!result) dev_kfree_skb(skb); return result; }
static int xenvif_tx_submit(struct xenvif *vif) { struct gnttab_copy *gop = vif->tx_copy_ops; struct sk_buff *skb; int work_done = 0; while ((skb = __skb_dequeue(&vif->tx_queue)) != NULL) { struct xen_netif_tx_request *txp; u16 pending_idx; unsigned data_len; pending_idx = *((u16 *)skb->data); txp = &vif->pending_tx_info[pending_idx].req; /* Check the remap error code. */ if (unlikely(xenvif_tx_check_gop(vif, skb, &gop))) { netdev_dbg(vif->dev, "netback grant failed.\n"); skb_shinfo(skb)->nr_frags = 0; kfree_skb(skb); continue; } data_len = skb->len; memcpy(skb->data, (void *)(idx_to_kaddr(vif, pending_idx)|txp->offset), data_len); if (data_len < txp->size) { /* Append the packet payload as a fragment. */ txp->offset += data_len; txp->size -= data_len; } else { /* Schedule a response immediately. */ xenvif_idx_release(vif, pending_idx, XEN_NETIF_RSP_OKAY); } if (txp->flags & XEN_NETTXF_csum_blank) skb->ip_summed = CHECKSUM_PARTIAL; else if (txp->flags & XEN_NETTXF_data_validated) skb->ip_summed = CHECKSUM_UNNECESSARY; xenvif_fill_frags(vif, skb); if (skb_is_nonlinear(skb) && skb_headlen(skb) < PKT_PROT_LEN) { int target = min_t(int, skb->len, PKT_PROT_LEN); __pskb_pull_tail(skb, target - skb_headlen(skb)); } skb->dev = vif->dev; skb->protocol = eth_type_trans(skb, skb->dev); skb_reset_network_header(skb); if (checksum_setup(vif, skb)) { netdev_dbg(vif->dev, "Can't setup checksum in net_tx_action\n"); kfree_skb(skb); continue; } skb_probe_transport_header(skb, 0); /* If the packet is GSO then we will have just set up the * transport header offset in checksum_setup so it's now * straightforward to calculate gso_segs. */ if (skb_is_gso(skb)) { int mss = skb_shinfo(skb)->gso_size; int hdrlen = skb_transport_header(skb) - skb_mac_header(skb) + tcp_hdrlen(skb); skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len - hdrlen, mss); } vif->dev->stats.rx_bytes += skb->len; vif->dev->stats.rx_packets++; work_done++; netif_receive_skb(skb); }
static unsigned xenvif_tx_build_gops(struct xenvif *vif, int budget) { struct gnttab_copy *gop = vif->tx_copy_ops, *request_gop; struct sk_buff *skb; int ret; while ((nr_pending_reqs(vif) + XEN_NETBK_LEGACY_SLOTS_MAX < MAX_PENDING_REQS) && (skb_queue_len(&vif->tx_queue) < budget)) { struct xen_netif_tx_request txreq; struct xen_netif_tx_request txfrags[XEN_NETBK_LEGACY_SLOTS_MAX]; struct page *page; struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX-1]; u16 pending_idx; RING_IDX idx; int work_to_do; unsigned int data_len; pending_ring_idx_t index; if (vif->tx.sring->req_prod - vif->tx.req_cons > XEN_NETIF_TX_RING_SIZE) { netdev_err(vif->dev, "Impossible number of requests. " "req_prod %d, req_cons %d, size %ld\n", vif->tx.sring->req_prod, vif->tx.req_cons, XEN_NETIF_TX_RING_SIZE); xenvif_fatal_tx_err(vif); continue; } work_to_do = RING_HAS_UNCONSUMED_REQUESTS(&vif->tx); if (!work_to_do) break; idx = vif->tx.req_cons; rmb(); /* Ensure that we see the request before we copy it. */ memcpy(&txreq, RING_GET_REQUEST(&vif->tx, idx), sizeof(txreq)); /* Credit-based scheduling. */ if (txreq.size > vif->remaining_credit && tx_credit_exceeded(vif, txreq.size)) break; vif->remaining_credit -= txreq.size; work_to_do--; vif->tx.req_cons = ++idx; memset(extras, 0, sizeof(extras)); if (txreq.flags & XEN_NETTXF_extra_info) { work_to_do = xenvif_get_extras(vif, extras, work_to_do); idx = vif->tx.req_cons; if (unlikely(work_to_do < 0)) break; } ret = xenvif_count_requests(vif, &txreq, txfrags, work_to_do); if (unlikely(ret < 0)) break; idx += ret; if (unlikely(txreq.size < ETH_HLEN)) { netdev_dbg(vif->dev, "Bad packet size: %d\n", txreq.size); xenvif_tx_err(vif, &txreq, idx); break; } /* No crossing a page as the payload mustn't fragment. */ if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { netdev_err(vif->dev, "txreq.offset: %x, size: %u, end: %lu\n", txreq.offset, txreq.size, (txreq.offset&~PAGE_MASK) + txreq.size); xenvif_fatal_tx_err(vif); break; } index = pending_index(vif->pending_cons); pending_idx = vif->pending_ring[index]; data_len = (txreq.size > PKT_PROT_LEN && ret < XEN_NETBK_LEGACY_SLOTS_MAX) ? PKT_PROT_LEN : txreq.size; skb = alloc_skb(data_len + NET_SKB_PAD + NET_IP_ALIGN, GFP_ATOMIC | __GFP_NOWARN); if (unlikely(skb == NULL)) { netdev_dbg(vif->dev, "Can't allocate a skb in start_xmit.\n"); xenvif_tx_err(vif, &txreq, idx); break; } /* Packets passed to netif_rx() must have some headroom. */ skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN); if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) { struct xen_netif_extra_info *gso; gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; if (xenvif_set_skb_gso(vif, skb, gso)) { /* Failure in xenvif_set_skb_gso is fatal. */ kfree_skb(skb); break; } } /* XXX could copy straight to head */ page = xenvif_alloc_page(vif, pending_idx); if (!page) { kfree_skb(skb); xenvif_tx_err(vif, &txreq, idx); break; } gop->source.u.ref = txreq.gref; gop->source.domid = vif->domid; gop->source.offset = txreq.offset; gop->dest.u.gmfn = virt_to_mfn(page_address(page)); gop->dest.domid = DOMID_SELF; gop->dest.offset = txreq.offset; gop->len = txreq.size; gop->flags = GNTCOPY_source_gref; gop++; memcpy(&vif->pending_tx_info[pending_idx].req, &txreq, sizeof(txreq)); vif->pending_tx_info[pending_idx].head = index; *((u16 *)skb->data) = pending_idx; __skb_put(skb, data_len); skb_shinfo(skb)->nr_frags = ret; if (data_len < txreq.size) { skb_shinfo(skb)->nr_frags++; frag_set_pending_idx(&skb_shinfo(skb)->frags[0], pending_idx); } else { frag_set_pending_idx(&skb_shinfo(skb)->frags[0], INVALID_PENDING_IDX); } vif->pending_cons++; request_gop = xenvif_get_requests(vif, skb, txfrags, gop); if (request_gop == NULL) { kfree_skb(skb); xenvif_tx_err(vif, &txreq, idx); break; } gop = request_gop; __skb_queue_tail(&vif->tx_queue, skb); vif->tx.req_cons = idx; if ((gop-vif->tx_copy_ops) >= ARRAY_SIZE(vif->tx_copy_ops)) break; } return gop - vif->tx_copy_ops; }
static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) { struct sk_buff *skb; struct skb_data *entry; int retval = 0; unsigned long lockflags; size_t size = dev->rx_urb_size; #if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) if ((skb = alloc_skb (size + NET_IP_ALIGN + FOE_INFO_LEN, flags)) == NULL) { #else if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) { #endif netif_dbg(dev, rx_err, dev->net, "no rx skb\n"); usbnet_defer_kevent (dev, EVENT_RX_MEMORY); usb_free_urb (urb); return -ENOMEM; } #if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) skb_reserve (skb, NET_IP_ALIGN + FOE_INFO_LEN); #else skb_reserve (skb, NET_IP_ALIGN); #endif entry = (struct skb_data *) skb->cb; entry->urb = urb; entry->dev = dev; entry->state = rx_start; entry->length = 0; usb_fill_bulk_urb (urb, dev->udev, dev->in, skb->data, size, rx_complete, skb); spin_lock_irqsave (&dev->rxq.lock, lockflags); if (netif_running (dev->net) && netif_device_present (dev->net) && !test_bit (EVENT_RX_HALT, &dev->flags) && !test_bit (EVENT_DEV_ASLEEP, &dev->flags)) { switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) { case -EPIPE: usbnet_defer_kevent (dev, EVENT_RX_HALT); break; case -ENOMEM: usbnet_defer_kevent (dev, EVENT_RX_MEMORY); break; case -ENODEV: netif_dbg(dev, ifdown, dev->net, "device gone\n"); netif_device_detach (dev->net); break; case -EHOSTUNREACH: retval = -ENOLINK; break; default: netif_dbg(dev, rx_err, dev->net, "rx submit, %d\n", retval); tasklet_schedule (&dev->bh); break; case 0: __skb_queue_tail (&dev->rxq, skb); } } else { netif_dbg(dev, ifdown, dev->net, "rx: stopped\n"); retval = -ENOLINK; } spin_unlock_irqrestore (&dev->rxq.lock, lockflags); if (retval) { dev_kfree_skb_any (skb); usb_free_urb (urb); } return retval; } /*-------------------------------------------------------------------------*/ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) { if (dev->driver_info->rx_fixup && !dev->driver_info->rx_fixup (dev, skb)) goto error; // else network stack removes extra byte if we forced a short packet if (skb->len) usbnet_skb_return (dev, skb); else { netif_dbg(dev, rx_err, dev->net, "drop\n"); error: dev->net->stats.rx_errors++; skb_queue_tail (&dev->done, skb); } } /*-------------------------------------------------------------------------*/ static void rx_complete (struct urb *urb) { struct sk_buff *skb = (struct sk_buff *) urb->context; struct skb_data *entry = (struct skb_data *) skb->cb; struct usbnet *dev = entry->dev; int urb_status = urb->status; skb_put (skb, urb->actual_length); entry->state = rx_done; entry->urb = NULL; switch (urb_status) { /* success */ case 0: if (skb->len < dev->net->hard_header_len) { entry->state = rx_cleanup; dev->net->stats.rx_errors++; dev->net->stats.rx_length_errors++; netif_dbg(dev, rx_err, dev->net, "rx length %d\n", skb->len); } break; /* stalls need manual reset. this is rare ... except that * when going through USB 2.0 TTs, unplug appears this way. * we avoid the highspeed version of the ETIMEDOUT/EILSEQ * storm, recovering as needed. */ case -EPIPE: dev->net->stats.rx_errors++; usbnet_defer_kevent (dev, EVENT_RX_HALT); // FALLTHROUGH /* software-driven interface shutdown */ case -ECONNRESET: /* async unlink */ case -ESHUTDOWN: /* hardware gone */ netif_dbg(dev, ifdown, dev->net, "rx shutdown, code %d\n", urb_status); goto block; /* we get controller i/o faults during khubd disconnect() delays. * throttle down resubmits, to avoid log floods; just temporarily, * so we still recover when the fault isn't a khubd delay. */ case -EPROTO: case -ETIME: case -EILSEQ: dev->net->stats.rx_errors++; if (!timer_pending (&dev->delay)) { mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); netif_dbg(dev, link, dev->net, "rx throttle %d\n", urb_status); } block: entry->state = rx_cleanup; entry->urb = urb; urb = NULL; break; /* data overrun ... flush fifo? */ case -EOVERFLOW: dev->net->stats.rx_over_errors++; // FALLTHROUGH default: entry->state = rx_cleanup; dev->net->stats.rx_errors++; netif_dbg(dev, rx_err, dev->net, "rx status %d\n", urb_status); break; } defer_bh(dev, skb, &dev->rxq); if (urb) { if (netif_running (dev->net) && !test_bit (EVENT_RX_HALT, &dev->flags)) { rx_submit (dev, urb, GFP_ATOMIC); return; } usb_free_urb (urb); } netif_dbg(dev, rx_err, dev->net, "no read resubmitted\n"); } static void intr_complete (struct urb *urb) { struct usbnet *dev = urb->context; int status = urb->status; switch (status) { /* success */ case 0: dev->driver_info->status(dev, urb); break; /* software-driven interface shutdown */ case -ENOENT: /* urb killed */ case -ESHUTDOWN: /* hardware gone */ netif_dbg(dev, ifdown, dev->net, "intr shutdown, code %d\n", status); return; /* NOTE: not throttling like RX/TX, since this endpoint * already polls infrequently */ default: netdev_dbg(dev->net, "intr status %d\n", status); break; } if (!netif_running (dev->net)) return; memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); status = usb_submit_urb (urb, GFP_ATOMIC); if (status != 0) netif_err(dev, timer, dev->net, "intr resubmit --> %d\n", status); } /*-------------------------------------------------------------------------*/ void usbnet_pause_rx(struct usbnet *dev) { set_bit(EVENT_RX_PAUSED, &dev->flags); netif_dbg(dev, rx_status, dev->net, "paused rx queue enabled\n"); }
static int phylink_sfp_module_insert(void *upstream, const struct sfp_eeprom_id *id) { struct phylink *pl = upstream; __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, }; struct phylink_link_state config; phy_interface_t iface; int ret = 0; bool changed; u8 port; ASSERT_RTNL(); sfp_parse_support(pl->sfp_bus, id, support); port = sfp_parse_port(pl->sfp_bus, id, support); memset(&config, 0, sizeof(config)); linkmode_copy(config.advertising, support); config.interface = PHY_INTERFACE_MODE_NA; config.speed = SPEED_UNKNOWN; config.duplex = DUPLEX_UNKNOWN; config.pause = MLO_PAUSE_AN; config.an_enabled = pl->link_config.an_enabled; /* Ignore errors if we're expecting a PHY to attach later */ ret = phylink_validate(pl, support, &config); if (ret) { netdev_err(pl->netdev, "validation with support %*pb failed: %d\n", __ETHTOOL_LINK_MODE_MASK_NBITS, support, ret); return ret; } iface = sfp_select_interface(pl->sfp_bus, id, config.advertising); if (iface == PHY_INTERFACE_MODE_NA) { netdev_err(pl->netdev, "selection of interface failed, advertisement %*pb\n", __ETHTOOL_LINK_MODE_MASK_NBITS, config.advertising); return -EINVAL; } config.interface = iface; ret = phylink_validate(pl, support, &config); if (ret) { netdev_err(pl->netdev, "validation of %s/%s with support %*pb failed: %d\n", phylink_an_mode_str(MLO_AN_INBAND), phy_modes(config.interface), __ETHTOOL_LINK_MODE_MASK_NBITS, support, ret); return ret; } netdev_dbg(pl->netdev, "requesting link mode %s/%s with support %*pb\n", phylink_an_mode_str(MLO_AN_INBAND), phy_modes(config.interface), __ETHTOOL_LINK_MODE_MASK_NBITS, support); if (phy_interface_mode_is_8023z(iface) && pl->phydev) return -EINVAL; changed = !bitmap_equal(pl->supported, support, __ETHTOOL_LINK_MODE_MASK_NBITS); if (changed) { linkmode_copy(pl->supported, support); linkmode_copy(pl->link_config.advertising, config.advertising); } if (pl->link_an_mode != MLO_AN_INBAND || pl->link_config.interface != config.interface) { pl->link_config.interface = config.interface; pl->link_an_mode = MLO_AN_INBAND; changed = true; netdev_info(pl->netdev, "switched to %s/%s link mode\n", phylink_an_mode_str(MLO_AN_INBAND), phy_modes(config.interface)); } pl->link_port = port; if (changed && !test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) phylink_mac_config(pl, &pl->link_config); return ret; }
static int netvsc_probe(struct hv_device *dev, const struct hv_vmbus_device_id *dev_id) { struct net_device *net = NULL; struct net_device_context *net_device_ctx; struct netvsc_device_info device_info; struct netvsc_device *nvdev; int ret; u32 max_needed_headroom; net = alloc_etherdev_mq(sizeof(struct net_device_context), num_online_cpus()); if (!net) return -ENOMEM; max_needed_headroom = sizeof(struct hv_netvsc_packet) + RNDIS_AND_PPI_SIZE; netif_carrier_off(net); net_device_ctx = netdev_priv(net); net_device_ctx->device_ctx = dev; net_device_ctx->msg_enable = netif_msg_init(debug, default_msg); if (netif_msg_probe(net_device_ctx)) netdev_dbg(net, "netvsc msg_enable: %d\n", net_device_ctx->msg_enable); net_device_ctx->tx_stats = netdev_alloc_pcpu_stats(struct netvsc_stats); if (!net_device_ctx->tx_stats) { free_netdev(net); return -ENOMEM; } net_device_ctx->rx_stats = netdev_alloc_pcpu_stats(struct netvsc_stats); if (!net_device_ctx->rx_stats) { free_percpu(net_device_ctx->tx_stats); free_netdev(net); return -ENOMEM; } hv_set_drvdata(dev, net); INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change); INIT_WORK(&net_device_ctx->work, do_set_multicast); net->netdev_ops = &device_ops; net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO; net->ethtool_ops = ðtool_ops; SET_NETDEV_DEV(net, &dev->device); /* * Request additional head room in the skb. * We will use this space to build the rndis * heaser and other state we need to maintain. */ net->needed_headroom = max_needed_headroom; /* Notify the netvsc driver of the new device */ memset(&device_info, 0, sizeof(device_info)); device_info.ring_size = ring_size; device_info.max_num_vrss_chns = max_num_vrss_chns; ret = rndis_filter_device_add(dev, &device_info); if (ret != 0) { netdev_err(net, "unable to add netvsc device (ret %d)\n", ret); netvsc_free_netdev(net); hv_set_drvdata(dev, NULL); return ret; } memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); nvdev = hv_get_drvdata(dev); netif_set_real_num_tx_queues(net, nvdev->num_chn); netif_set_real_num_rx_queues(net, nvdev->num_chn); ret = register_netdev(net); if (ret != 0) { pr_err("Unable to register netdev.\n"); rndis_filter_device_remove(dev); netvsc_free_netdev(net); } else { schedule_delayed_work(&net_device_ctx->dwork, 0); } return ret; }
int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb) { struct rtllib_hdr_3addr *rsp = NULL; struct ba_record *pPendingBA, *pAdmittedBA; struct tx_ts_record *pTS = NULL; u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL; u16 *pStatusCode = NULL, *pBaTimeoutVal = NULL; union ba_param_set *pBaParamSet = NULL; u16 ReasonCode; if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) { netdev_warn(ieee->dev, "Invalid skb len in BARSP(%d / %d)\n", (int)skb->len, (int)(sizeof(struct rtllib_hdr_3addr) + 9)); return -1; } rsp = (struct rtllib_hdr_3addr *)skb->data; tag = (u8 *)rsp; dst = (u8 *)(&rsp->addr2[0]); tag += sizeof(struct rtllib_hdr_3addr); pDialogToken = tag + 2; pStatusCode = (u16 *)(tag + 3); pBaParamSet = (union ba_param_set *)(tag + 5); pBaTimeoutVal = (u16 *)(tag + 7); RT_TRACE(COMP_DBG, "====>rx ADDBARSP from : %pM\n", dst); if (ieee->current_network.qos_data.active == 0 || ieee->pHTInfo->bCurrentHTSupport == false || ieee->pHTInfo->bCurrentAMPDUEnable == false) { netdev_warn(ieee->dev, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable); ReasonCode = DELBA_REASON_UNKNOWN_BA; goto OnADDBARsp_Reject; } if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst, (u8)(pBaParamSet->field.TID), TX_DIR, false)) { netdev_warn(ieee->dev, "%s(): can't get TS\n", __func__); ReasonCode = DELBA_REASON_UNKNOWN_BA; goto OnADDBARsp_Reject; } pTS->bAddBaReqInProgress = false; pPendingBA = &pTS->TxPendingBARecord; pAdmittedBA = &pTS->TxAdmittedBARecord; if (pAdmittedBA->bValid == true) { netdev_dbg(ieee->dev, "%s(): ADDBA response already admitted\n", __func__); return -1; } else if ((pPendingBA->bValid == false) || (*pDialogToken != pPendingBA->DialogToken)) { netdev_warn(ieee->dev, "%s(): ADDBA Rsp. BA invalid, DELBA!\n", __func__); ReasonCode = DELBA_REASON_UNKNOWN_BA; goto OnADDBARsp_Reject; } else { netdev_dbg(ieee->dev, "%s(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", __func__, *pStatusCode); DeActivateBAEntry(ieee, pPendingBA); } if (*pStatusCode == ADDBA_STATUS_SUCCESS) { if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) { pTS->bAddBaReqDelayed = true; DeActivateBAEntry(ieee, pAdmittedBA); ReasonCode = DELBA_REASON_END_BA; goto OnADDBARsp_Reject; } pAdmittedBA->DialogToken = *pDialogToken; pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal; pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl; pAdmittedBA->BaParamSet = *pBaParamSet; DeActivateBAEntry(ieee, pAdmittedBA); ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal); } else { pTS->bAddBaReqDelayed = true; pTS->bDisable_AddBa = true; ReasonCode = DELBA_REASON_END_BA; goto OnADDBARsp_Reject; } return 0; OnADDBARsp_Reject: { struct ba_record BA; BA.BaParamSet = *pBaParamSet; rtllib_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode); return 0; } }
static int ibmveth_poll(struct napi_struct *napi, int budget) { struct ibmveth_adapter *adapter = container_of(napi, struct ibmveth_adapter, napi); struct net_device *netdev = adapter->netdev; int frames_processed = 0; unsigned long lpar_rc; restart_poll: do { if (!ibmveth_rxq_pending_buffer(adapter)) break; smp_rmb(); if (!ibmveth_rxq_buffer_valid(adapter)) { wmb(); /* suggested by larson1 */ adapter->rx_invalid_buffer++; netdev_dbg(netdev, "recycling invalid buffer\n"); ibmveth_rxq_recycle_buffer(adapter); } else { struct sk_buff *skb, *new_skb; int length = ibmveth_rxq_frame_length(adapter); int offset = ibmveth_rxq_frame_offset(adapter); int csum_good = ibmveth_rxq_csum_good(adapter); skb = ibmveth_rxq_get_buffer(adapter); new_skb = NULL; if (length < rx_copybreak) new_skb = netdev_alloc_skb(netdev, length); if (new_skb) { skb_copy_to_linear_data(new_skb, skb->data + offset, length); if (rx_flush) ibmveth_flush_buffer(skb->data, length + offset); if (!ibmveth_rxq_recycle_buffer(adapter)) kfree_skb(skb); skb = new_skb; } else { ibmveth_rxq_harvest_buffer(adapter); skb_reserve(skb, offset); } skb_put(skb, length); skb->protocol = eth_type_trans(skb, netdev); if (csum_good) skb->ip_summed = CHECKSUM_UNNECESSARY; netif_receive_skb(skb); /* send it up */ netdev->stats.rx_packets++; netdev->stats.rx_bytes += length; frames_processed++; } } while (frames_processed < budget); ibmveth_replenish_task(adapter); if (frames_processed < budget) { /* We think we are done - reenable interrupts, * then check once more to make sure we are done. */ lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_ENABLE); BUG_ON(lpar_rc != H_SUCCESS); napi_complete(napi); if (ibmveth_rxq_pending_buffer(adapter) && napi_reschedule(napi)) { lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); goto restart_poll; } } return frames_processed; }
static int mcf8390_init(struct net_device *dev) { static u32 offsets[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, }; struct ei_device *ei_local = netdev_priv(dev); unsigned char SA_prom[32]; u32 addr = dev->base_addr; int start_page, stop_page; int i, ret; mcf8390_reset_8390(dev); /* * Read the 16 bytes of station address PROM. * We must first initialize registers, * similar to NS8390_init(eifdev, 0). * We can't reliably read the SAPROM address without this. * (I learned the hard way!). */ { static const struct { u32 value; u32 offset; } program_seq[] = { {E8390_NODMA + E8390_PAGE0 + E8390_STOP, NE_CMD}, /* Select page 0 */ {0x48, NE_EN0_DCFG}, /* 0x48: Set byte-wide access */ {0x00, NE_EN0_RCNTLO}, /* Clear the count regs */ {0x00, NE_EN0_RCNTHI}, {0x00, NE_EN0_IMR}, /* Mask completion irq */ {0xFF, NE_EN0_ISR}, {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */ {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode */ {32, NE_EN0_RCNTLO}, {0x00, NE_EN0_RCNTHI}, {0x00, NE_EN0_RSARLO}, /* DMA starting at 0x0000 */ {0x00, NE_EN0_RSARHI}, {E8390_RREAD + E8390_START, NE_CMD}, }; for (i = 0; i < ARRAY_SIZE(program_seq); i++) { ei_outb(program_seq[i].value, addr + program_seq[i].offset); } } for (i = 0; i < 16; i++) { SA_prom[i] = ei_inb(addr + NE_DATAPORT); ei_inb(addr + NE_DATAPORT); } /* We must set the 8390 for word mode. */ ei_outb(0x49, addr + NE_EN0_DCFG); start_page = NESM_START_PG; stop_page = NESM_STOP_PG; /* Install the Interrupt handler */ ret = request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev); if (ret) return ret; for (i = 0; i < ETH_ALEN; i++) dev->dev_addr[i] = SA_prom[i]; netdev_dbg(dev, "Found ethernet address: %pM\n", dev->dev_addr); ei_local->name = "mcf8390"; ei_local->tx_start_page = start_page; ei_local->stop_page = stop_page; ei_local->word16 = 1; ei_local->rx_start_page = start_page + TX_PAGES; ei_local->reset_8390 = mcf8390_reset_8390; ei_local->block_input = mcf8390_block_input; ei_local->block_output = mcf8390_block_output; ei_local->get_8390_hdr = mcf8390_get_8390_hdr; ei_local->reg_offset = offsets; dev->netdev_ops = &mcf8390_netdev_ops; __NS8390_init(dev, 0); ret = register_netdev(dev); if (ret) { free_irq(dev->irq, dev); return ret; } netdev_info(dev, "addr=0x%08x irq=%d, Ethernet Address %pM\n", addr, dev->irq, dev->dev_addr); return 0; }
static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) { int rc, i; struct net_device *netdev; struct ibmveth_adapter *adapter; unsigned char *mac_addr_p; unsigned int *mcastFilterSize_p; dev_dbg(&dev->dev, "entering ibmveth_probe for UA 0x%x\n", dev->unit_address); mac_addr_p = (unsigned char *)vio_get_attribute(dev, VETH_MAC_ADDR, NULL); if (!mac_addr_p) { dev_err(&dev->dev, "Can't find VETH_MAC_ADDR attribute\n"); return -EINVAL; } mcastFilterSize_p = (unsigned int *)vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, NULL); if (!mcastFilterSize_p) { dev_err(&dev->dev, "Can't find VETH_MCAST_FILTER_SIZE " "attribute\n"); return -EINVAL; } netdev = alloc_etherdev(sizeof(struct ibmveth_adapter)); if (!netdev) return -ENOMEM; adapter = netdev_priv(netdev); dev_set_drvdata(&dev->dev, netdev); adapter->vdev = dev; adapter->netdev = netdev; adapter->mcastFilterSize = *mcastFilterSize_p; adapter->pool_config = 0; netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16); /* * Some older boxes running PHYP non-natively have an OF that returns * a 8-byte local-mac-address field (and the first 2 bytes have to be * ignored) while newer boxes' OF return a 6-byte field. Note that * IEEE 1275 specifies that local-mac-address must be a 6-byte field. * The RPA doc specifies that the first byte must be 10b, so we'll * just look for it to solve this 8 vs. 6 byte field issue */ if ((*mac_addr_p & 0x3) != 0x02) mac_addr_p += 2; adapter->mac_addr = 0; memcpy(&adapter->mac_addr, mac_addr_p, 6); netdev->irq = dev->irq; netdev->netdev_ops = &ibmveth_netdev_ops; netdev->ethtool_ops = &netdev_ethtool_ops; SET_NETDEV_DEV(netdev, &dev->dev); netdev->features |= NETIF_F_SG; memcpy(netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) { struct kobject *kobj = &adapter->rx_buff_pool[i].kobj; int error; ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i, pool_count[i], pool_size[i], pool_active[i]); error = kobject_init_and_add(kobj, &ktype_veth_pool, &dev->dev.kobj, "pool%d", i); if (!error) kobject_uevent(kobj, KOBJ_ADD); } netdev_dbg(netdev, "adapter @ 0x%p\n", adapter); adapter->buffer_list_dma = DMA_ERROR_CODE; adapter->filter_list_dma = DMA_ERROR_CODE; adapter->rx_queue.queue_dma = DMA_ERROR_CODE; netdev_dbg(netdev, "registering netdev...\n"); ibmveth_set_csum_offload(netdev, 1, ibmveth_set_tx_csum_flags); rc = register_netdev(netdev); if (rc) { netdev_dbg(netdev, "failed to register netdev rc=%d\n", rc); free_netdev(netdev); return rc; } netdev_dbg(netdev, "registered\n"); return 0; }
/* ---------------------------------------------------------------------------- mace_interrupt The interrupt handler. ---------------------------------------------------------------------------- */ static irqreturn_t mace_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *) dev_id; mace_private *lp = netdev_priv(dev); unsigned int ioaddr; int status; int IntrCnt = MACE_MAX_IR_ITERATIONS; if (dev == NULL) { pr_debug("mace_interrupt(): irq 0x%X for unknown device.\n", irq); return IRQ_NONE; } ioaddr = dev->base_addr; if (lp->tx_irq_disabled) { const char *msg; if (lp->tx_irq_disabled) msg = "Interrupt with tx_irq_disabled"; else msg = "Re-entering the interrupt handler"; netdev_notice(dev, "%s [isr=%02X, imr=%02X]\n", msg, inb(ioaddr + AM2150_MACE_BASE + MACE_IR), inb(ioaddr + AM2150_MACE_BASE + MACE_IMR)); /* WARNING: MACE_IR has been read! */ return IRQ_NONE; } if (!netif_device_present(dev)) { netdev_dbg(dev, "interrupt from dead card\n"); return IRQ_NONE; } do { /* WARNING: MACE_IR is a READ/CLEAR port! */ status = inb(ioaddr + AM2150_MACE_BASE + MACE_IR); pr_debug("mace_interrupt: irq 0x%X status 0x%X.\n", irq, status); if (status & MACE_IR_RCVINT) { mace_rx(dev, MACE_MAX_RX_ITERATIONS); } if (status & MACE_IR_XMTINT) { unsigned char fifofc; unsigned char xmtrc; unsigned char xmtfs; fifofc = inb(ioaddr + AM2150_MACE_BASE + MACE_FIFOFC); if ((fifofc & MACE_FIFOFC_XMTFC)==0) { lp->linux_stats.tx_errors++; outb(0xFF, ioaddr + AM2150_XMT_SKIP); } /* Transmit Retry Count (XMTRC, reg 4) */ xmtrc = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTRC); if (xmtrc & MACE_XMTRC_EXDEF) lp->mace_stats.exdef++; lp->mace_stats.xmtrc += (xmtrc & MACE_XMTRC_XMTRC); if ( (xmtfs = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTFS)) & MACE_XMTFS_XMTSV /* Transmit Status Valid */ ) { lp->mace_stats.xmtsv++; if (xmtfs & ~MACE_XMTFS_XMTSV) { if (xmtfs & MACE_XMTFS_UFLO) { /* Underflow. Indicates that the Transmit FIFO emptied before the end of frame was reached. */ lp->mace_stats.uflo++; } if (xmtfs & MACE_XMTFS_LCOL) { /* Late Collision */ lp->mace_stats.lcol++; } if (xmtfs & MACE_XMTFS_MORE) { /* MORE than one retry was needed */ lp->mace_stats.more++; } if (xmtfs & MACE_XMTFS_ONE) { /* Exactly ONE retry occurred */ lp->mace_stats.one++; } if (xmtfs & MACE_XMTFS_DEFER) { /* Transmission was defered */ lp->mace_stats.defer++; } if (xmtfs & MACE_XMTFS_LCAR) { /* Loss of carrier */ lp->mace_stats.lcar++; } if (xmtfs & MACE_XMTFS_RTRY) { /* Retry error: transmit aborted after 16 attempts */ lp->mace_stats.rtry++; } } /* if (xmtfs & ~MACE_XMTFS_XMTSV) */ } /* if (xmtfs & MACE_XMTFS_XMTSV) */ lp->linux_stats.tx_packets++; lp->tx_free_frames++; netif_wake_queue(dev); } /* if (status & MACE_IR_XMTINT) */ if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) { if (status & MACE_IR_JAB) { /* Jabber Error. Excessive transmit duration (20-150ms). */ lp->mace_stats.jab++; } if (status & MACE_IR_BABL) { /* Babble Error. >1518 bytes transmitted. */ lp->mace_stats.babl++; } if (status & MACE_IR_CERR) { /* Collision Error. CERR indicates the absence of the Signal Quality Error Test message after a packet transmission. */ lp->mace_stats.cerr++; } if (status & MACE_IR_RCVCCO) { /* Receive Collision Count Overflow; */ lp->mace_stats.rcvcco++; } if (status & MACE_IR_RNTPCO) { /* Runt Packet Count Overflow */ lp->mace_stats.rntpco++; } if (status & MACE_IR_MPCO) { /* Missed Packet Count Overflow */ lp->mace_stats.mpco++; } } /* if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) */ } while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt)); return IRQ_HANDLED; } /* mace_interrupt */
/* replenish the buffers for a pool. note that we don't need to * skb_reserve these since they are used for incoming... */ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool) { u32 i; u32 count = pool->size - atomic_read(&pool->available); u32 buffers_added = 0; struct sk_buff *skb; unsigned int free_index, index; u64 correlator; unsigned long lpar_rc; dma_addr_t dma_addr; mb(); for (i = 0; i < count; ++i) { union ibmveth_buf_desc desc; skb = netdev_alloc_skb(adapter->netdev, pool->buff_size); if (!skb) { netdev_dbg(adapter->netdev, "replenish: unable to allocate skb\n"); adapter->replenish_no_mem++; break; } free_index = pool->consumer_index; pool->consumer_index++; if (pool->consumer_index >= pool->size) pool->consumer_index = 0; index = pool->free_map[free_index]; BUG_ON(index == IBM_VETH_INVALID_MAP); BUG_ON(pool->skbuff[index] != NULL); dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, pool->buff_size, DMA_FROM_DEVICE); if (dma_mapping_error(&adapter->vdev->dev, dma_addr)) goto failure; pool->free_map[free_index] = IBM_VETH_INVALID_MAP; pool->dma_addr[index] = dma_addr; pool->skbuff[index] = skb; correlator = ((u64)pool->index << 32) | index; *(u64 *)skb->data = correlator; desc.fields.flags_len = IBMVETH_BUF_VALID | pool->buff_size; desc.fields.address = dma_addr; if (rx_flush) { unsigned int len = min(pool->buff_size, adapter->netdev->mtu + IBMVETH_BUFF_OH); ibmveth_flush_buffer(skb->data, len); } lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); if (lpar_rc != H_SUCCESS) { goto failure; } else { buffers_added++; adapter->replenish_add_buff_success++; } } mb(); atomic_add(buffers_added, &(pool->available)); return; failure: pool->free_map[free_index] = index; pool->skbuff[index] = NULL; if (pool->consumer_index == 0) pool->consumer_index = pool->size - 1; else pool->consumer_index--; if (!dma_mapping_error(&adapter->vdev->dev, dma_addr)) dma_unmap_single(&adapter->vdev->dev, pool->dma_addr[index], pool->buff_size, DMA_FROM_DEVICE); dev_kfree_skb_any(skb); adapter->replenish_add_buff_failure++; mb(); atomic_add(buffers_added, &(pool->available)); }
static int ti_hecc_error(struct net_device *ndev, int int_status, int err_status) { struct ti_hecc_priv *priv = netdev_priv(ndev); struct net_device_stats *stats = &ndev->stats; struct can_frame *cf; struct sk_buff *skb; /* propagate the error condition to the can stack */ skb = alloc_can_err_skb(ndev, &cf); if (!skb) { if (printk_ratelimit()) netdev_err(priv->ndev, "ti_hecc_error: alloc_can_err_skb() failed\n"); return -ENOMEM; } if (int_status & HECC_CANGIF_WLIF) { /* warning level int */ if ((int_status & HECC_CANGIF_BOIF) == 0) { priv->can.state = CAN_STATE_ERROR_WARNING; ++priv->can.can_stats.error_warning; cf->can_id |= CAN_ERR_CRTL; if (hecc_read(priv, HECC_CANTEC) > 96) cf->data[1] |= CAN_ERR_CRTL_TX_WARNING; if (hecc_read(priv, HECC_CANREC) > 96) cf->data[1] |= CAN_ERR_CRTL_RX_WARNING; } hecc_set_bit(priv, HECC_CANES, HECC_CANES_EW); netdev_dbg(priv->ndev, "Error Warning interrupt\n"); hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR); } if (int_status & HECC_CANGIF_EPIF) { /* error passive int */ if ((int_status & HECC_CANGIF_BOIF) == 0) { priv->can.state = CAN_STATE_ERROR_PASSIVE; ++priv->can.can_stats.error_passive; cf->can_id |= CAN_ERR_CRTL; if (hecc_read(priv, HECC_CANTEC) > 127) cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; if (hecc_read(priv, HECC_CANREC) > 127) cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; } hecc_set_bit(priv, HECC_CANES, HECC_CANES_EP); netdev_dbg(priv->ndev, "Error passive interrupt\n"); hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR); } /* * Need to check busoff condition in error status register too to * ensure warning interrupts don't hog the system */ if ((int_status & HECC_CANGIF_BOIF) || (err_status & HECC_CANES_BO)) { priv->can.state = CAN_STATE_BUS_OFF; cf->can_id |= CAN_ERR_BUSOFF; hecc_set_bit(priv, HECC_CANES, HECC_CANES_BO); hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR); /* Disable all interrupts in bus-off to avoid int hog */ hecc_write(priv, HECC_CANGIM, 0); can_bus_off(ndev); } if (err_status & HECC_BUS_ERROR) { ++priv->can.can_stats.bus_error; cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT; cf->data[2] |= CAN_ERR_PROT_UNSPEC; if (err_status & HECC_CANES_FE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_FE); cf->data[2] |= CAN_ERR_PROT_FORM; } if (err_status & HECC_CANES_BE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_BE); cf->data[2] |= CAN_ERR_PROT_BIT; } if (err_status & HECC_CANES_SE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_SE); cf->data[2] |= CAN_ERR_PROT_STUFF; } if (err_status & HECC_CANES_CRCE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE); cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL; } if (err_status & HECC_CANES_ACKE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE); cf->data[3] |= CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL; } } netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; return 0; }
static int ibmveth_open(struct net_device *netdev) { struct ibmveth_adapter *adapter = netdev_priv(netdev); u64 mac_address = 0; int rxq_entries = 1; unsigned long lpar_rc; int rc; union ibmveth_buf_desc rxq_desc; int i; struct device *dev; netdev_dbg(netdev, "open starting\n"); napi_enable(&adapter->napi); for(i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) rxq_entries += adapter->rx_buff_pool[i].size; adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL); adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL); if (!adapter->buffer_list_addr || !adapter->filter_list_addr) { netdev_err(netdev, "unable to allocate filter or buffer list " "pages\n"); rc = -ENOMEM; goto err_out; } adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * rxq_entries; adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, GFP_KERNEL); if (!adapter->rx_queue.queue_addr) { netdev_err(netdev, "unable to allocate rx queue pages\n"); rc = -ENOMEM; goto err_out; } dev = &adapter->vdev->dev; adapter->buffer_list_dma = dma_map_single(dev, adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL); adapter->filter_list_dma = dma_map_single(dev, adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL); adapter->rx_queue.queue_dma = dma_map_single(dev, adapter->rx_queue.queue_addr, adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL); if ((dma_mapping_error(dev, adapter->buffer_list_dma)) || (dma_mapping_error(dev, adapter->filter_list_dma)) || (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) { netdev_err(netdev, "unable to map filter or buffer list " "pages\n"); rc = -ENOMEM; goto err_out; } adapter->rx_queue.index = 0; adapter->rx_queue.num_slots = rxq_entries; adapter->rx_queue.toggle = 1; memcpy(&mac_address, netdev->dev_addr, netdev->addr_len); mac_address = mac_address >> 16; rxq_desc.fields.flags_len = IBMVETH_BUF_VALID | adapter->rx_queue.queue_len; rxq_desc.fields.address = adapter->rx_queue.queue_dma; netdev_dbg(netdev, "buffer list @ 0x%p\n", adapter->buffer_list_addr); netdev_dbg(netdev, "filter list @ 0x%p\n", adapter->filter_list_addr); netdev_dbg(netdev, "receive q @ 0x%p\n", adapter->rx_queue.queue_addr); h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address); if (lpar_rc != H_SUCCESS) { netdev_err(netdev, "h_register_logical_lan failed with %ld\n", lpar_rc); netdev_err(netdev, "buffer TCE:0x%llx filter TCE:0x%llx rxq " "desc:0x%llx MAC:0x%llx\n", adapter->buffer_list_dma, adapter->filter_list_dma, rxq_desc.desc, mac_address); rc = -ENONET; goto err_out; } for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) { if (!adapter->rx_buff_pool[i].active) continue; if (ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[i])) { netdev_err(netdev, "unable to alloc pool\n"); adapter->rx_buff_pool[i].active = 0; rc = -ENOMEM; goto err_out; } } netdev_dbg(netdev, "registering irq 0x%x\n", netdev->irq); rc = request_irq(netdev->irq, ibmveth_interrupt, 0, netdev->name, netdev); if (rc != 0) { netdev_err(netdev, "unable to request irq 0x%x, rc %d\n", netdev->irq, rc); do { rc = h_free_logical_lan(adapter->vdev->unit_address); } while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY)); goto err_out; } adapter->bounce_buffer = kmalloc(netdev->mtu + IBMVETH_BUFF_OH, GFP_KERNEL); if (!adapter->bounce_buffer) { netdev_err(netdev, "unable to allocate bounce buffer\n"); rc = -ENOMEM; goto err_out_free_irq; } adapter->bounce_buffer_dma = dma_map_single(&adapter->vdev->dev, adapter->bounce_buffer, netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, adapter->bounce_buffer_dma)) { netdev_err(netdev, "unable to map bounce buffer\n"); rc = -ENOMEM; goto err_out_free_irq; } netdev_dbg(netdev, "initial replenish cycle\n"); ibmveth_interrupt(netdev->irq, netdev); netif_start_queue(netdev); netdev_dbg(netdev, "open complete\n"); return 0; err_out_free_irq: free_irq(netdev->irq, netdev); err_out: ibmveth_cleanup(adapter); napi_disable(&adapter->napi); return rc; }
static int c_can_handle_bus_err(struct net_device *dev, enum c_can_lec_type lec_type) { struct c_can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct can_frame *cf; struct sk_buff *skb; /* * early exit if no lec update or no error. * no lec update means that no CAN bus event has been detected * since CPU wrote 0x7 value to status reg. */ if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR) return 0; /* propagate the error condition to the CAN stack */ skb = alloc_can_err_skb(dev, &cf); if (unlikely(!skb)) return 0; /* * check for 'last error code' which tells us the * type of the last error to occur on the CAN bus */ /* common for all type of bus errors */ priv->can.can_stats.bus_error++; stats->rx_errors++; cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; cf->data[2] |= CAN_ERR_PROT_UNSPEC; switch (lec_type) { case LEC_STUFF_ERROR: netdev_dbg(dev, "stuff error\n"); cf->data[2] |= CAN_ERR_PROT_STUFF; break; case LEC_FORM_ERROR: netdev_dbg(dev, "form error\n"); cf->data[2] |= CAN_ERR_PROT_FORM; break; case LEC_ACK_ERROR: netdev_dbg(dev, "ack error\n"); cf->data[3] |= (CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL); break; case LEC_BIT1_ERROR: netdev_dbg(dev, "bit1 error\n"); cf->data[2] |= CAN_ERR_PROT_BIT1; break; case LEC_BIT0_ERROR: netdev_dbg(dev, "bit0 error\n"); cf->data[2] |= CAN_ERR_PROT_BIT0; break; case LEC_CRC_ERROR: netdev_dbg(dev, "CRC error\n"); cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL); break; default: break; } /* set a `lec` value so that we can check for updates later */ priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); netif_receive_skb(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; return 1; }
static void amd_xgbe_an_state_machine(struct work_struct *work) { struct amd_xgbe_phy_priv *priv = container_of(work, struct amd_xgbe_phy_priv, an_work); struct phy_device *phydev = priv->phydev; enum amd_xgbe_phy_an cur_state = priv->an_state; int int_reg, int_mask; mutex_lock(&priv->an_mutex); /* Read the interrupt */ int_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT); if (!int_reg) goto out; next_int: if (int_reg < 0) { priv->an_state = AMD_XGBE_AN_ERROR; int_mask = XGBE_AN_INT_MASK; } else if (int_reg & XGBE_AN_PG_RCV) { priv->an_state = AMD_XGBE_AN_PAGE_RECEIVED; int_mask = XGBE_AN_PG_RCV; } else if (int_reg & XGBE_AN_INC_LINK) { priv->an_state = AMD_XGBE_AN_INCOMPAT_LINK; int_mask = XGBE_AN_INC_LINK; } else if (int_reg & XGBE_AN_INT_CMPLT) { priv->an_state = AMD_XGBE_AN_COMPLETE; int_mask = XGBE_AN_INT_CMPLT; } else { priv->an_state = AMD_XGBE_AN_ERROR; int_mask = 0; } /* Clear the interrupt to be processed */ int_reg &= ~int_mask; phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, int_reg); priv->an_result = priv->an_state; again: cur_state = priv->an_state; switch (priv->an_state) { case AMD_XGBE_AN_READY: priv->an_supported = 0; break; case AMD_XGBE_AN_PAGE_RECEIVED: priv->an_state = amd_xgbe_an_page_received(phydev); priv->an_supported++; break; case AMD_XGBE_AN_INCOMPAT_LINK: priv->an_supported = 0; priv->parallel_detect = 0; priv->an_state = amd_xgbe_an_incompat_link(phydev); break; case AMD_XGBE_AN_COMPLETE: priv->parallel_detect = priv->an_supported ? 0 : 1; netdev_dbg(phydev->attached_dev, "%s successful\n", priv->an_supported ? "Auto negotiation" : "Parallel detection"); break; case AMD_XGBE_AN_NO_LINK: break; default: priv->an_state = AMD_XGBE_AN_ERROR; } if (priv->an_state == AMD_XGBE_AN_NO_LINK) { int_reg = 0; phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); } else if (priv->an_state == AMD_XGBE_AN_ERROR) { netdev_err(phydev->attached_dev, "error during auto-negotiation, state=%u\n", cur_state); int_reg = 0; phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0); } if (priv->an_state >= AMD_XGBE_AN_COMPLETE) { priv->an_result = priv->an_state; priv->an_state = AMD_XGBE_AN_READY; priv->kr_state = AMD_XGBE_RX_BPA; priv->kx_state = AMD_XGBE_RX_BPA; } if (cur_state != priv->an_state) goto again; if (int_reg) goto next_int; out: enable_irq(priv->an_irq); mutex_unlock(&priv->an_mutex); }
static void usbnet_bh (unsigned long param) { struct usbnet *dev = (struct usbnet *) param; struct sk_buff *skb; struct skb_data *entry; while ((skb = skb_dequeue (&dev->done))) { entry = (struct skb_data *) skb->cb; switch (entry->state) { case rx_done: entry->state = rx_cleanup; rx_process (dev, skb); continue; case tx_done: case rx_cleanup: usb_free_urb (entry->urb); dev_kfree_skb (skb); continue; default: netdev_dbg(dev->net, "bogus skb state %d\n", entry->state); } } // waiting for all pending urbs to complete? if (dev->wait) { if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) { wake_up (dev->wait); } // or are we maybe short a few urbs? } else if (netif_running (dev->net) && netif_device_present (dev->net) && !timer_pending (&dev->delay) && !test_bit (EVENT_RX_HALT, &dev->flags)) { int temp = dev->rxq.qlen; int qlen = RX_QLEN (dev); if (temp < qlen) { struct urb *urb; int i; // don't refill the queue all at once for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) { urb = usb_alloc_urb (0, GFP_ATOMIC); if (urb != NULL) { if (rx_submit (dev, urb, GFP_ATOMIC) == -ENOLINK) return; } } if (temp != dev->rxq.qlen) netif_dbg(dev, link, dev->net, "rxqlen %d --> %d\n", temp, dev->rxq.qlen); if (dev->rxq.qlen < qlen) tasklet_schedule (&dev->bh); } if (dev->txq.qlen < TX_QLEN (dev)) netif_wake_queue (dev->net); } }
/** * axienet_mdio_setup - MDIO setup function * @lp: Pointer to axienet local data structure. * @np: Pointer to device node * * Return: 0 on success, -ETIMEDOUT on a timeout, -ENOMEM when * mdiobus_alloc (to allocate memory for mii bus structure) fails. * * Sets up the MDIO interface by initializing the MDIO clock and enabling the * MDIO interface in hardware. Register the MDIO interface. **/ int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np) { int ret; u32 clk_div, host_clock; struct mii_bus *bus; struct resource res; struct device_node *np1; /* clk_div can be calculated by deriving it from the equation: * fMDIO = fHOST / ((1 + clk_div) * 2) * * Where fMDIO <= 2500000, so we get: * fHOST / ((1 + clk_div) * 2) <= 2500000 * * Then we get: * 1 / ((1 + clk_div) * 2) <= (2500000 / fHOST) * * Then we get: * 1 / (1 + clk_div) <= ((2500000 * 2) / fHOST) * * Then we get: * 1 / (1 + clk_div) <= (5000000 / fHOST) * * So: * (1 + clk_div) >= (fHOST / 5000000) * * And finally: * clk_div >= (fHOST / 5000000) - 1 * * fHOST can be read from the flattened device tree as property * "clock-frequency" from the CPU */ np1 = of_find_node_by_name(NULL, "cpu"); if (!np1) { netdev_warn(lp->ndev, "Could not find CPU device node.\n"); netdev_warn(lp->ndev, "Setting MDIO clock divisor to default %d\n", DEFAULT_CLOCK_DIVISOR); clk_div = DEFAULT_CLOCK_DIVISOR; goto issue; } if (of_property_read_u32(np1, "clock-frequency", &host_clock)) { netdev_warn(lp->ndev, "clock-frequency property not found.\n"); netdev_warn(lp->ndev, "Setting MDIO clock divisor to default %d\n", DEFAULT_CLOCK_DIVISOR); clk_div = DEFAULT_CLOCK_DIVISOR; of_node_put(np1); goto issue; } clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1; /* If there is any remainder from the division of * fHOST / (MAX_MDIO_FREQ * 2), then we need to add * 1 to the clock divisor or we will surely be above 2.5 MHz */ if (host_clock % (MAX_MDIO_FREQ * 2)) clk_div++; netdev_dbg(lp->ndev, "Setting MDIO clock divisor to %u/%u Hz host clock.\n", clk_div, host_clock); of_node_put(np1); issue: axienet_iow(lp, XAE_MDIO_MC_OFFSET, (((u32) clk_div) | XAE_MDIO_MC_MDIOEN_MASK)); ret = axienet_mdio_wait_until_ready(lp); if (ret < 0) return ret; bus = mdiobus_alloc(); if (!bus) return -ENOMEM; np1 = of_get_parent(lp->phy_node); of_address_to_resource(np1, 0, &res); snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx", (unsigned long long) res.start); bus->priv = lp; bus->name = "Xilinx Axi Ethernet MDIO"; bus->read = axienet_mdio_read; bus->write = axienet_mdio_write; bus->parent = lp->dev; lp->mii_bus = bus; ret = of_mdiobus_register(bus, np1); if (ret) { mdiobus_free(bus); return ret; } return 0; }
void HTConstructCapabilityElement(struct rtllib_device *ieee, u8 *posHTCap, u8 *len, u8 IsEncrypt, bool bAssoc) { struct rt_hi_throughput *pHT = ieee->pHTInfo; struct ht_capab_ele *pCapELE = NULL; if ((posHTCap == NULL) || (pHT == NULL)) { netdev_warn(ieee->dev, "%s(): posHTCap and pHTInfo are null\n", __func__); return; } memset(posHTCap, 0, *len); if ((bAssoc) && (pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC)) { u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; memcpy(posHTCap, EWC11NHTCap, sizeof(EWC11NHTCap)); pCapELE = (struct ht_capab_ele *)&(posHTCap[4]); *len = 30 + 2; } else { pCapELE = (struct ht_capab_ele *)posHTCap; *len = 26 + 2; } pCapELE->AdvCoding = 0; if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) pCapELE->ChlWidth = 0; else pCapELE->ChlWidth = (pHT->bRegBW40MHz ? 1 : 0); pCapELE->MimoPwrSave = pHT->SelfMimoPs; pCapELE->GreenField = 0; pCapELE->ShortGI20Mhz = 1; pCapELE->ShortGI40Mhz = 1; pCapELE->TxSTBC = 1; pCapELE->RxSTBC = 0; pCapELE->DelayBA = 0; pCapELE->MaxAMSDUSize = (MAX_RECEIVE_BUFFER_SIZE >= 7935) ? 1 : 0; pCapELE->DssCCk = ((pHT->bRegBW40MHz) ? (pHT->bRegSuppCCK ? 1 : 0) : 0); pCapELE->PSMP = 0; pCapELE->LSigTxopProtect = 0; netdev_dbg(ieee->dev, "TX HT cap/info ele BW=%d MaxAMSDUSize:%d DssCCk:%d\n", pCapELE->ChlWidth, pCapELE->MaxAMSDUSize, pCapELE->DssCCk); if (IsEncrypt) { pCapELE->MPDUDensity = 7; pCapELE->MaxRxAMPDUFactor = 2; } else { pCapELE->MaxRxAMPDUFactor = 3; pCapELE->MPDUDensity = 0; } memcpy(pCapELE->MCS, ieee->Regdot11HTOperationalRateSet, 16); memset(&pCapELE->ExtHTCapInfo, 0, 2); memset(pCapELE->TxBFCap, 0, 4); pCapELE->ASCap = 0; if (bAssoc) { if (pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS15) pCapELE->MCS[1] &= 0x7f; if (pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS14) pCapELE->MCS[1] &= 0xbf; if (pHT->IOTAction & HT_IOT_ACT_DISABLE_ALL_2SS) pCapELE->MCS[1] &= 0x00; if (pHT->IOTAction & HT_IOT_ACT_DISABLE_RX_40MHZ_SHORT_GI) pCapELE->ShortGI40Mhz = 0; if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) { pCapELE->ChlWidth = 0; pCapELE->MCS[1] = 0; } } }
static void grcan_err(struct net_device *dev, u32 sources, u32 status) { struct grcan_priv *priv = netdev_priv(dev); struct grcan_registers __iomem *regs = priv->regs; struct grcan_dma *dma = &priv->dma; struct net_device_stats *stats = &dev->stats; struct can_frame cf; /* Zero potential error_frame */ memset(&cf, 0, sizeof(cf)); /* Message lost interrupt. This might be due to arbitration error, but * is also triggered when there is no one else on the can bus or when * there is a problem with the hardware interface or the bus itself. As * arbitration errors can not be singled out, no error frames are * generated reporting this event as an arbitration error. */ if (sources & GRCAN_IRQ_TXLOSS) { /* Take care of failed one-shot transmit */ if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) grcan_lost_one_shot_frame(dev); /* Stop printing as soon as error passive or bus off is in * effect to limit the amount of txloss debug printouts. */ if (!(status & GRCAN_STAT_ERRCTR_RELATED)) { netdev_dbg(dev, "tx message lost\n"); stats->tx_errors++; } } /* Conditions dealing with the error counters. There is no interrupt for * error warning, but there are interrupts for increases of the error * counters. */ if ((sources & GRCAN_IRQ_ERRCTR_RELATED) || (status & GRCAN_STAT_ERRCTR_RELATED)) { enum can_state state = priv->can.state; enum can_state oldstate = state; u32 txerr = (status & GRCAN_STAT_TXERRCNT) >> GRCAN_STAT_TXERRCNT_BIT; u32 rxerr = (status & GRCAN_STAT_RXERRCNT) >> GRCAN_STAT_RXERRCNT_BIT; /* Figure out current state */ if (status & GRCAN_STAT_OFF) { state = CAN_STATE_BUS_OFF; } else if (status & GRCAN_STAT_PASS) { state = CAN_STATE_ERROR_PASSIVE; } else if (txerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT || rxerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT) { state = CAN_STATE_ERROR_WARNING; } else { state = CAN_STATE_ERROR_ACTIVE; } /* Handle and report state changes */ if (state != oldstate) { switch (state) { case CAN_STATE_BUS_OFF: netdev_dbg(dev, "bus-off\n"); netif_carrier_off(dev); priv->can.can_stats.bus_off++; /* Prevent the hardware from recovering from bus * off on its own if restart is disabled. */ if (!priv->can.restart_ms) grcan_stop_hardware(dev); cf.can_id |= CAN_ERR_BUSOFF; break; case CAN_STATE_ERROR_PASSIVE: netdev_dbg(dev, "Error passive condition\n"); priv->can.can_stats.error_passive++; cf.can_id |= CAN_ERR_CRTL; if (txerr >= GRCAN_STAT_ERRCNT_PASSIVE_LIMIT) cf.data[1] |= CAN_ERR_CRTL_TX_PASSIVE; if (rxerr >= GRCAN_STAT_ERRCNT_PASSIVE_LIMIT) cf.data[1] |= CAN_ERR_CRTL_RX_PASSIVE; break; case CAN_STATE_ERROR_WARNING: netdev_dbg(dev, "Error warning condition\n"); priv->can.can_stats.error_warning++; cf.can_id |= CAN_ERR_CRTL; if (txerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT) cf.data[1] |= CAN_ERR_CRTL_TX_WARNING; if (rxerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT) cf.data[1] |= CAN_ERR_CRTL_RX_WARNING; break; case CAN_STATE_ERROR_ACTIVE: netdev_dbg(dev, "Error active condition\n"); cf.can_id |= CAN_ERR_CRTL; break; default: /* There are no others at this point */ break; } cf.data[6] = txerr; cf.data[7] = rxerr; priv->can.state = state; } /* Report automatic restarts */ if (priv->can.restart_ms && oldstate == CAN_STATE_BUS_OFF) { unsigned long flags; cf.can_id |= CAN_ERR_RESTARTED; netdev_dbg(dev, "restarted\n"); priv->can.can_stats.restarts++; netif_carrier_on(dev); spin_lock_irqsave(&priv->lock, flags); if (!priv->resetting && !priv->closing) { u32 txwr = grcan_read_reg(®s->txwr); if (grcan_txspace(dma->tx.size, txwr, priv->eskbp)) netif_wake_queue(dev); } spin_unlock_irqrestore(&priv->lock, flags); } } /* Data overrun interrupt */ if ((sources & GRCAN_IRQ_OR) || (status & GRCAN_STAT_OR)) { netdev_dbg(dev, "got data overrun interrupt\n"); stats->rx_over_errors++; stats->rx_errors++; cf.can_id |= CAN_ERR_CRTL; cf.data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; } /* AHB bus error interrupts (not CAN bus errors) - shut down the * device. */ if (sources & (GRCAN_IRQ_TXAHBERR | GRCAN_IRQ_RXAHBERR) || (status & GRCAN_STAT_AHBERR)) { char *txrx = ""; unsigned long flags; if (sources & GRCAN_IRQ_TXAHBERR) { txrx = "on tx "; stats->tx_errors++; } else if (sources & GRCAN_IRQ_RXAHBERR) { txrx = "on rx "; stats->rx_errors++; } netdev_err(dev, "Fatal AHB buss error %s- halting device\n", txrx); spin_lock_irqsave(&priv->lock, flags); /* Prevent anything to be enabled again and halt device */ priv->closing = true; netif_stop_queue(dev); grcan_stop_hardware(dev); priv->can.state = CAN_STATE_STOPPED; spin_unlock_irqrestore(&priv->lock, flags); } /* Pass on error frame if something to report, * i.e. id contains some information */ if (cf.can_id) { struct can_frame *skb_cf; struct sk_buff *skb = alloc_can_err_skb(dev, &skb_cf); if (skb == NULL) { netdev_dbg(dev, "could not allocate error frame\n"); return; } skb_cf->can_id |= cf.can_id; memcpy(skb_cf->data, cf.data, sizeof(cf.data)); netif_rx(skb); } }