static void setup_etheraddr(char *str, unsigned char *addr, char *name) { char *end; int i; if(str == NULL) goto random; for(i=0;i<6;i++){ addr[i] = simple_strtoul(str, &end, 16); if((end == str) || ((*end != ':') && (*end != ',') && (*end != '\0'))){ printk(KERN_ERR "setup_etheraddr: failed to parse '%s' " "as an ethernet address\n", str); goto random; } str = end + 1; } if (is_multicast_ether_addr(addr)) { printk(KERN_ERR "Attempt to assign a multicast ethernet address to a " "device disallowed\n"); goto random; } if (!is_valid_ether_addr(addr)) { printk(KERN_ERR "Attempt to assign an invalid ethernet address to a " "device disallowed\n"); goto random; } if (!is_local_ether_addr(addr)) { printk(KERN_WARNING "Warning: attempt to assign a globally valid ethernet " "address to a device\n"); printk(KERN_WARNING "You should better enable the 2nd " "rightmost bit in the first byte of the MAC,\n"); printk(KERN_WARNING "i.e. %02x:%02x:%02x:%02x:%02x:%02x\n", addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4], addr[5]); goto random; } return; random: printk(KERN_INFO "Choosing a random ethernet address for device %s\n", name); random_ether_addr(addr); }
static netdev_tx_t fjes_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct fjes_adapter *adapter = netdev_priv(netdev); struct fjes_hw *hw = &adapter->hw; int max_epid, my_epid, dest_epid; enum ep_partner_status pstatus; struct netdev_queue *cur_queue; char shortpkt[VLAN_ETH_HLEN]; bool is_multi, vlan; struct ethhdr *eth; u16 queue_no = 0; u16 vlan_id = 0; netdev_tx_t ret; char *data; int len; ret = NETDEV_TX_OK; is_multi = false; cur_queue = netdev_get_tx_queue(netdev, queue_no); eth = (struct ethhdr *)skb->data; my_epid = hw->my_epid; vlan = (vlan_get_tag(skb, &vlan_id) == 0) ? true : false; data = skb->data; len = skb->len; if (is_multicast_ether_addr(eth->h_dest)) { dest_epid = 0; max_epid = hw->max_epid; is_multi = true; } else if (is_local_ether_addr(eth->h_dest)) { dest_epid = eth->h_dest[ETH_ALEN - 1]; max_epid = dest_epid + 1; if ((eth->h_dest[0] == 0x02) && (0x00 == (eth->h_dest[1] | eth->h_dest[2] | eth->h_dest[3] | eth->h_dest[4])) && (dest_epid < hw->max_epid)) { ; } else { dest_epid = 0; max_epid = 0; ret = NETDEV_TX_OK; adapter->stats64.tx_packets += 1; hw->ep_shm_info[my_epid].net_stats.tx_packets += 1; adapter->stats64.tx_bytes += len; hw->ep_shm_info[my_epid].net_stats.tx_bytes += len; } } else { dest_epid = 0; max_epid = 0; ret = NETDEV_TX_OK; adapter->stats64.tx_packets += 1; hw->ep_shm_info[my_epid].net_stats.tx_packets += 1; adapter->stats64.tx_bytes += len; hw->ep_shm_info[my_epid].net_stats.tx_bytes += len; } for (; dest_epid < max_epid; dest_epid++) { if (my_epid == dest_epid) continue; pstatus = fjes_hw_get_partner_ep_status(hw, dest_epid); if (pstatus != EP_PARTNER_SHARED) { if (!is_multi) hw->ep_shm_info[dest_epid].ep_stats .tx_dropped_not_shared += 1; ret = NETDEV_TX_OK; } else if (!fjes_hw_check_epbuf_version( &adapter->hw.ep_shm_info[dest_epid].rx, 0)) { /* version is NOT 0 */ adapter->stats64.tx_carrier_errors += 1; hw->ep_shm_info[dest_epid].net_stats .tx_carrier_errors += 1; hw->ep_shm_info[dest_epid].ep_stats .tx_dropped_ver_mismatch += 1; ret = NETDEV_TX_OK; } else if (!fjes_hw_check_mtu( &adapter->hw.ep_shm_info[dest_epid].rx, netdev->mtu)) { adapter->stats64.tx_dropped += 1; hw->ep_shm_info[dest_epid].net_stats.tx_dropped += 1; adapter->stats64.tx_errors += 1; hw->ep_shm_info[dest_epid].net_stats.tx_errors += 1; hw->ep_shm_info[dest_epid].ep_stats .tx_dropped_buf_size_mismatch += 1; ret = NETDEV_TX_OK; } else if (vlan && !fjes_hw_check_vlan_id( &adapter->hw.ep_shm_info[dest_epid].rx, vlan_id)) { hw->ep_shm_info[dest_epid].ep_stats .tx_dropped_vlanid_mismatch += 1; ret = NETDEV_TX_OK; } else { if (len < VLAN_ETH_HLEN) { memset(shortpkt, 0, VLAN_ETH_HLEN); memcpy(shortpkt, skb->data, skb->len); len = VLAN_ETH_HLEN; data = shortpkt; } if (adapter->tx_retry_count == 0) { adapter->tx_start_jiffies = jiffies; adapter->tx_retry_count = 1; } else { adapter->tx_retry_count++; } if (fjes_tx_send(adapter, dest_epid, data, len)) { if (is_multi) { ret = NETDEV_TX_OK; } else if ( ((long)jiffies - (long)adapter->tx_start_jiffies) >= FJES_TX_RETRY_TIMEOUT) { adapter->stats64.tx_fifo_errors += 1; hw->ep_shm_info[dest_epid].net_stats .tx_fifo_errors += 1; adapter->stats64.tx_errors += 1; hw->ep_shm_info[dest_epid].net_stats .tx_errors += 1; ret = NETDEV_TX_OK; } else { netif_trans_update(netdev); hw->ep_shm_info[dest_epid].ep_stats .tx_buffer_full += 1; netif_tx_stop_queue(cur_queue); if (!work_pending(&adapter->tx_stall_task)) queue_work(adapter->txrx_wq, &adapter->tx_stall_task); ret = NETDEV_TX_BUSY; } } else { if (!is_multi) { adapter->stats64.tx_packets += 1; hw->ep_shm_info[dest_epid].net_stats .tx_packets += 1; adapter->stats64.tx_bytes += len; hw->ep_shm_info[dest_epid].net_stats .tx_bytes += len; } adapter->tx_retry_count = 0; ret = NETDEV_TX_OK; } } } if (ret == NETDEV_TX_OK) { dev_kfree_skb(skb); if (is_multi) { adapter->stats64.tx_packets += 1; hw->ep_shm_info[my_epid].net_stats.tx_packets += 1; adapter->stats64.tx_bytes += 1; hw->ep_shm_info[my_epid].net_stats.tx_bytes += len; } } return ret; }