diff options
Diffstat (limited to 'drivers/net/ethernet/atheros/atl1c/atl1c_main.c')
| -rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 142 |
1 files changed, 50 insertions, 92 deletions
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 1c6246a5dc22..7efa3fc257b3 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -207,16 +207,6 @@ static inline void atl1c_irq_disable(struct atl1c_adapter *adapter) synchronize_irq(adapter->pdev->irq); } -/** - * atl1c_irq_reset - reset interrupt confiure on the NIC - * @adapter: board private structure - */ -static inline void atl1c_irq_reset(struct atl1c_adapter *adapter) -{ - atomic_set(&adapter->irq_sem, 1); - atl1c_irq_enable(adapter); -} - /* * atl1c_wait_until_idle - wait up to AT_HW_MAX_IDLE_DELAY reads * of the idle status register until the device is actually idle @@ -241,8 +231,8 @@ static u32 atl1c_wait_until_idle(struct atl1c_hw *hw, u32 modu_ctrl) */ static void atl1c_phy_config(struct timer_list *t) { - struct atl1c_adapter *adapter = from_timer(adapter, t, - phy_config_timer); + struct atl1c_adapter *adapter = timer_container_of(adapter, t, + phy_config_timer); struct atl1c_hw *hw = &adapter->hw; unsigned long flags; @@ -367,7 +357,7 @@ static void atl1c_common_task(struct work_struct *work) static void atl1c_del_timer(struct atl1c_adapter *adapter) { - del_timer_sync(&adapter->phy_config_timer); + timer_delete_sync(&adapter->phy_config_timer); } @@ -482,7 +472,7 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p) if (netif_running(netdev)) return -EBUSY; - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + eth_hw_addr_set(netdev, addr->sa_data); memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr); @@ -493,15 +483,10 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p) static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter, struct net_device *dev) { - unsigned int head_size; int mtu = dev->mtu; adapter->rx_buffer_len = mtu > AT_RX_BUF_SIZE ? roundup(mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN, 8) : AT_RX_BUF_SIZE; - - head_size = SKB_DATA_ALIGN(adapter->rx_buffer_len + NET_SKB_PAD + NET_IP_ALIGN) + - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - adapter->rx_frag_size = roundup_pow_of_two(head_size); } static netdev_features_t atl1c_fix_features(struct net_device *netdev, @@ -576,7 +561,7 @@ static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) if (netif_running(netdev)) { while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) msleep(1); - netdev->mtu = new_mtu; + WRITE_ONCE(netdev->mtu, new_mtu); adapter->hw.max_frame_size = new_mtu; atl1c_set_rxbufsize(adapter, netdev); atl1c_down(adapter); @@ -857,7 +842,8 @@ static int atl1c_sw_init(struct atl1c_adapter *adapter) } static inline void atl1c_clean_buffer(struct pci_dev *pdev, - struct atl1c_buffer *buffer_info) + struct atl1c_buffer *buffer_info, + int budget) { u16 pci_driection; if (buffer_info->flags & ATL1C_BUFFER_FREE) @@ -876,7 +862,7 @@ static inline void atl1c_clean_buffer(struct pci_dev *pdev, buffer_info->length, pci_driection); } if (buffer_info->skb) - dev_consume_skb_any(buffer_info->skb); + napi_consume_skb(buffer_info->skb, budget); buffer_info->dma = 0; buffer_info->skb = NULL; ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); @@ -897,10 +883,10 @@ static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter, ring_count = tpd_ring->count; for (index = 0; index < ring_count; index++) { buffer_info = &tpd_ring->buffer_info[index]; - atl1c_clean_buffer(pdev, buffer_info); + atl1c_clean_buffer(pdev, buffer_info, 0); } - netdev_reset_queue(adapter->netdev); + netdev_tx_reset_queue(netdev_get_tx_queue(adapter->netdev, queue)); /* Zero out Tx-buffers */ memset(tpd_ring->desc, 0, sizeof(struct atl1c_tpd_desc) * @@ -924,7 +910,7 @@ static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter, u32 queue) for (j = 0; j < rfd_ring->count; j++) { buffer_info = &rfd_ring->buffer_info[j]; - atl1c_clean_buffer(pdev, buffer_info); + atl1c_clean_buffer(pdev, buffer_info, 0); } /* zero out the descriptor ring */ memset(rfd_ring->desc, 0, rfd_ring->size); @@ -974,7 +960,6 @@ static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) static void atl1c_free_ring_resources(struct atl1c_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; - int i; dma_free_coherent(&pdev->dev, adapter->ring_header.size, adapter->ring_header.desc, adapter->ring_header.dma); @@ -987,12 +972,6 @@ static void atl1c_free_ring_resources(struct atl1c_adapter *adapter) kfree(adapter->tpd_ring[0].buffer_info); adapter->tpd_ring[0].buffer_info = NULL; } - for (i = 0; i < adapter->rx_queue_count; ++i) { - if (adapter->rrd_ring[i].rx_page) { - put_page(adapter->rrd_ring[i].rx_page); - adapter->rrd_ring[i].rx_page = NULL; - } - } } /** @@ -1051,7 +1030,7 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) * each ring/block may need up to 8 bytes for alignment, hence the * additional bytes tacked onto the end. */ - ring_header->size = size = + ring_header->size = sizeof(struct atl1c_tpd_desc) * tpd_ring->count * tqc + sizeof(struct atl1c_rx_free_desc) * rfd_ring->count * rqc + sizeof(struct atl1c_recv_ret_status) * rfd_ring->count * rqc + @@ -1629,7 +1608,7 @@ static int atl1c_clean_tx(struct napi_struct *napi, int budget) total_bytes += buffer_info->skb->len; total_packets++; } - atl1c_clean_buffer(pdev, buffer_info); + atl1c_clean_buffer(pdev, buffer_info, budget); if (++next_to_clean == tpd_ring->count) next_to_clean = 0; atomic_set(&tpd_ring->next_to_clean, next_to_clean); @@ -1764,48 +1743,11 @@ static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter, skb_checksum_none_assert(skb); } -static struct sk_buff *atl1c_alloc_skb(struct atl1c_adapter *adapter, - u32 queue, bool napi_mode) -{ - struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[queue]; - struct sk_buff *skb; - struct page *page; - - if (adapter->rx_frag_size > PAGE_SIZE) { - if (likely(napi_mode)) - return napi_alloc_skb(&rrd_ring->napi, - adapter->rx_buffer_len); - else - return netdev_alloc_skb_ip_align(adapter->netdev, - adapter->rx_buffer_len); - } - - page = rrd_ring->rx_page; - if (!page) { - page = alloc_page(GFP_ATOMIC); - if (unlikely(!page)) - return NULL; - rrd_ring->rx_page = page; - rrd_ring->rx_page_offset = 0; - } - - skb = build_skb(page_address(page) + rrd_ring->rx_page_offset, - adapter->rx_frag_size); - if (likely(skb)) { - skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN); - rrd_ring->rx_page_offset += adapter->rx_frag_size; - if (rrd_ring->rx_page_offset >= PAGE_SIZE) - rrd_ring->rx_page = NULL; - else - get_page(page); - } - return skb; -} - static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, u32 queue, bool napi_mode) { struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[queue]; + struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[queue]; struct pci_dev *pdev = adapter->pdev; struct atl1c_buffer *buffer_info, *next_info; struct sk_buff *skb; @@ -1824,13 +1766,27 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, u32 queue, while (next_info->flags & ATL1C_BUFFER_FREE) { rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use); - skb = atl1c_alloc_skb(adapter, queue, napi_mode); + /* When DMA RX address is set to something like + * 0x....fc0, it will be very likely to cause DMA + * RFD overflow issue. + * + * To work around it, we apply rx skb with 64 bytes + * longer space, and offset the address whenever + * 0x....fc0 is detected. + */ + if (likely(napi_mode)) + skb = napi_alloc_skb(&rrd_ring->napi, adapter->rx_buffer_len + 64); + else + skb = netdev_alloc_skb(adapter->netdev, adapter->rx_buffer_len + 64); if (unlikely(!skb)) { if (netif_msg_rx_err(adapter)) dev_warn(&pdev->dev, "alloc rx buffer failed\n"); break; } + if (((unsigned long)skb->data & 0xfff) == 0xfc0) + skb_reserve(skb, 64); + /* * Make buffer alignment 2 beyond a 16 byte boundary * this will result in a 16 byte aligned IP header after @@ -1847,7 +1803,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, u32 queue, buffer_info->skb = NULL; buffer_info->length = 0; ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); - netif_warn(adapter, rx_err, adapter->netdev, "RX pci_map_single failed"); + netif_warn(adapter, rx_err, adapter->netdev, "RX dma_map_single failed"); break; } buffer_info->dma = mapping; @@ -2072,7 +2028,7 @@ static u16 atl1c_cal_tpd_req(const struct sk_buff *skb) tpd_req = skb_shinfo(skb)->nr_frags + 1; if (skb_is_gso(skb)) { - proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + proto_hdr_len = skb_tcp_all_headers(skb); if (proto_hdr_len < skb_headlen(skb)) tpd_req++; if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) @@ -2104,10 +2060,13 @@ static int atl1c_tso_csum(struct atl1c_adapter *adapter, real_len = (((unsigned char *)ip_hdr(skb) - skb->data) + ntohs(ip_hdr(skb)->tot_len)); - if (real_len < skb->len) - pskb_trim(skb, real_len); + if (real_len < skb->len) { + err = pskb_trim(skb, real_len); + if (err) + return err; + } - hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); + hdr_len = skb_tcp_all_headers(skb); if (unlikely(skb->len == hdr_len)) { /* only xsum need */ if (netif_msg_tx_queued(adapter)) @@ -2132,7 +2091,7 @@ static int atl1c_tso_csum(struct atl1c_adapter *adapter, *tpd = atl1c_get_tpd(adapter, queue); ipv6_hdr(skb)->payload_len = 0; /* check payload == 0 byte ? */ - hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); + hdr_len = skb_tcp_all_headers(skb); if (unlikely(skb->len == hdr_len)) { /* only xsum need */ if (netif_msg_tx_queued(adapter)) @@ -2193,7 +2152,7 @@ static void atl1c_tx_rollback(struct atl1c_adapter *adpt, while (index != tpd_ring->next_to_use) { tpd = ATL1C_TPD_DESC(tpd_ring, index); buffer_info = &tpd_ring->buffer_info[index]; - atl1c_clean_buffer(adpt->pdev, buffer_info); + atl1c_clean_buffer(adpt->pdev, buffer_info, 0); memset(tpd, 0, sizeof(struct atl1c_tpd_desc)); if (++index == tpd_ring->count) index = 0; @@ -2219,7 +2178,8 @@ static int atl1c_tx_map(struct atl1c_adapter *adapter, tso = (tpd->word1 >> TPD_LSO_EN_SHIFT) & TPD_LSO_EN_MASK; if (tso) { /* TSO */ - map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + hdr_len = skb_tcp_all_headers(skb); + map_len = hdr_len; use_tpd = tpd; buffer_info = atl1c_get_tx_buffer(adapter, use_tpd); @@ -2609,7 +2569,7 @@ static const struct net_device_ops atl1c_netdev_ops = { .ndo_change_mtu = atl1c_change_mtu, .ndo_fix_features = atl1c_fix_features, .ndo_set_features = atl1c_set_features, - .ndo_do_ioctl = atl1c_ioctl, + .ndo_eth_ioctl = atl1c_ioctl, .ndo_tx_timeout = atl1c_tx_timeout, .ndo_get_stats = atl1c_get_stats, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -2662,10 +2622,8 @@ static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* enable device (incl. PCI PM wakeup and hotplug setup) */ err = pci_enable_device_mem(pdev); - if (err) { - dev_err(&pdev->dev, "cannot enable PCI device\n"); - return err; - } + if (err) + return dev_err_probe(&pdev->dev, err, "cannot enable PCI device\n"); /* * The atl1c chip can DMA to 64-bit addresses, but it uses a single @@ -2730,13 +2688,13 @@ static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->mii.mdio_write = atl1c_mdio_write; adapter->mii.phy_id_mask = 0x1f; adapter->mii.reg_num_mask = MDIO_CTRL_REG_MASK; - dev_set_threaded(netdev, true); + netif_threaded_enable(netdev); for (i = 0; i < adapter->rx_queue_count; ++i) netif_napi_add(netdev, &adapter->rrd_ring[i].napi, - atl1c_clean_rx, 64); + atl1c_clean_rx); for (i = 0; i < adapter->tx_queue_count; ++i) - netif_napi_add(netdev, &adapter->tpd_ring[i].napi, - atl1c_clean_tx, 64); + netif_napi_add_tx(netdev, &adapter->tpd_ring[i].napi, + atl1c_clean_tx); timer_setup(&adapter->phy_config_timer, atl1c_phy_config, 0); /* setup the private structure */ err = atl1c_sw_init(adapter); @@ -2769,7 +2727,7 @@ static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* got a random MAC address, set NET_ADDR_RANDOM to netdev */ netdev->addr_assign_type = NET_ADDR_RANDOM; } - memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); + eth_hw_addr_set(netdev, adapter->hw.mac_addr); if (netif_msg_probe(adapter)) dev_dbg(&pdev->dev, "mac address : %pM\n", adapter->hw.mac_addr); @@ -2851,7 +2809,7 @@ static pci_ers_result_t atl1c_io_error_detected(struct pci_dev *pdev, pci_disable_device(pdev); - /* Request a slot slot reset. */ + /* Request a slot reset. */ return PCI_ERS_RESULT_NEED_RESET; } |
