diff options
author | Olof Johansson <olof@lixom.net> | 2016-06-19 08:57:48 +0300 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2016-06-19 08:57:48 +0300 |
commit | 58935f24a996cb55595c29dd5303bd9b778c8b00 (patch) | |
tree | a234f5328286290c64ca07d508224b19c1d3e89e /drivers/net/ethernet/atheros/alx/main.c | |
parent | 9503427e916aea7ec2cc429504f82d7200ab4bcd (diff) | |
parent | 6b41d44862e8f3a4b95102c6ff6cad3fccc7994b (diff) | |
download | linux-58935f24a996cb55595c29dd5303bd9b778c8b00.tar.xz |
Merge tag 'omap-for-v4.7/fixes-powedomain' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into fixes
Fixes for omaps for v4.7-rc cycle:
- Fix dra7 for hardware issues limiting L4Per and L3init power domains
to on state. Without this the devices may not work correctly after
some time of use because of asymmetric aging. And related to this,
let's also remove the unusable states.
- Always select omap interconnect for am43x as otherwise the am43x
only configurations will not boot properly. This can happen easily
for any product kernels that leave out other SoCs to save memory.
- Fix DSS PLL2 addresses that have gone unused for now
- Select erratum 430973 for omap3, this is now safe to do and can
save quite a bit of debugging time for people who may have left
it out.
* tag 'omap-for-v4.7/fixes-powedomain' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap:
ARM: OMAP: DRA7: powerdomain data: Remove unused pwrsts_mem_ret
ARM: OMAP: DRA7: powerdomain data: Remove unused pwrsts_logic_ret
ARM: OMAP: DRA7: powerdomain data: Set L3init and L4per to ON
ARM: OMAP2+: Select OMAP_INTERCONNECT for SOC_AM43XX
ARM: dts: DRA74x: fix DSS PLL2 addresses
ARM: OMAP2: Enable Errata 430973 for OMAP3
+ Linux 4.7-rc2
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/net/ethernet/atheros/alx/main.c')
-rw-r--r-- | drivers/net/ethernet/atheros/alx/main.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index 9fe8b5e310d1..c98acdc0d14f 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -70,6 +70,35 @@ static void alx_free_txbuf(struct alx_priv *alx, int entry) } } +static struct sk_buff *alx_alloc_skb(struct alx_priv *alx, gfp_t gfp) +{ + struct sk_buff *skb; + struct page *page; + + if (alx->rx_frag_size > PAGE_SIZE) + return __netdev_alloc_skb(alx->dev, alx->rxbuf_size, gfp); + + page = alx->rx_page; + if (!page) { + alx->rx_page = page = alloc_page(gfp); + if (unlikely(!page)) + return NULL; + alx->rx_page_offset = 0; + } + + skb = build_skb(page_address(page) + alx->rx_page_offset, + alx->rx_frag_size); + if (likely(skb)) { + alx->rx_page_offset += alx->rx_frag_size; + if (alx->rx_page_offset >= PAGE_SIZE) + alx->rx_page = NULL; + else + get_page(page); + } + return skb; +} + + static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp) { struct alx_rx_queue *rxq = &alx->rxq; @@ -86,7 +115,7 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp) while (!cur_buf->skb && next != rxq->read_idx) { struct alx_rfd *rfd = &rxq->rfd[cur]; - skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size, gfp); + skb = alx_alloc_skb(alx, gfp); if (!skb) break; dma = dma_map_single(&alx->hw.pdev->dev, @@ -124,6 +153,7 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp) alx_write_mem16(&alx->hw, ALX_RFD_PIDX, cur); } + return count; } @@ -592,6 +622,11 @@ static void alx_free_rings(struct alx_priv *alx) kfree(alx->txq.bufs); kfree(alx->rxq.bufs); + if (alx->rx_page) { + put_page(alx->rx_page); + alx->rx_page = NULL; + } + dma_free_coherent(&alx->hw.pdev->dev, alx->descmem.size, alx->descmem.virt, @@ -646,6 +681,7 @@ static int alx_request_irq(struct alx_priv *alx) alx->dev->name, alx); if (!err) goto out; + /* fall back to legacy interrupt */ pci_disable_msi(alx->hw.pdev); } @@ -689,6 +725,7 @@ static int alx_init_sw(struct alx_priv *alx) struct pci_dev *pdev = alx->hw.pdev; struct alx_hw *hw = &alx->hw; int err; + unsigned int head_size; err = alx_identify_hw(alx); if (err) { @@ -704,7 +741,12 @@ static int alx_init_sw(struct alx_priv *alx) hw->smb_timer = 400; hw->mtu = alx->dev->mtu; + alx->rxbuf_size = ALX_MAX_FRAME_LEN(hw->mtu); + head_size = SKB_DATA_ALIGN(alx->rxbuf_size + NET_SKB_PAD) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + alx->rx_frag_size = roundup_pow_of_two(head_size); + alx->tx_ringsz = 256; alx->rx_ringsz = 512; hw->imt = 200; @@ -806,6 +848,7 @@ static int alx_change_mtu(struct net_device *netdev, int mtu) { struct alx_priv *alx = netdev_priv(netdev); int max_frame = ALX_MAX_FRAME_LEN(mtu); + unsigned int head_size; if ((max_frame < ALX_MIN_FRAME_SIZE) || (max_frame > ALX_MAX_FRAME_SIZE)) @@ -817,6 +860,9 @@ static int alx_change_mtu(struct net_device *netdev, int mtu) netdev->mtu = mtu; alx->hw.mtu = mtu; alx->rxbuf_size = max(max_frame, ALX_DEF_RXBUF_SIZE); + head_size = SKB_DATA_ALIGN(alx->rxbuf_size + NET_SKB_PAD) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + alx->rx_frag_size = roundup_pow_of_two(head_size); netdev_update_features(netdev); if (netif_running(netdev)) alx_reinit(alx); |