Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Browse files Browse the repository at this point in the history
Pull networking fixes from David Miller:

 1) Don't OOPS on socket AIO, from Christoph Hellwig.

 2) Scheduled scans should be aborted upon RFKILL, from Emmanuel
    Grumbach.

 3) Fix sleep in atomic context in kvaser_usb, from Ahmed S Darwish.

 4) Fix RCU locking across copy_to_user() in bpf code, from Alexei
    Starovoitov.

 5) Lots of crash, memory leak, short TX packet et al bug fixes in
    sh_eth from Ben Hutchings.

 6) Fix memory corruption in SCTP wrt.  INIT collitions, from Daniel
    Borkmann.

 7) Fix return value logic for poll handlers in netxen, enic, and bnx2x.
    From Eric Dumazet and Govindarajulu Varadarajan.

 8) Header length calculation fix in mac80211 from Fred Chou.

 9) mv643xx_eth doesn't handle highmem correctly in non-TSO code paths.
    From Ezequiel Garcia.

10) udp_diag has bogus logic in it's hash chain skipping, copy same fix
    tcp diag used.  From Herbert Xu.

11) amd-xgbe programs wrong rx flow control register, from Thomas
    Lendacky.

12) Fix race leading to use after free in ping receive path, from Subash
    Abhinov Kasiviswanathan.

13) Cache redirect routes otherwise we can get a heavy backlog of rcu
    jobs liberating DST_NOCACHE entries.  From Hannes Frederic Sowa.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (48 commits)
  net: don't OOPS on socket aio
  stmmac: prevent probe drivers to crash kernel
  bnx2x: fix napi poll return value for repoll
  ipv6: replacing a rt6_info needs to purge possible propagated rt6_infos too
  sh_eth: Fix DMA-API usage for RX buffers
  sh_eth: Check for DMA mapping errors on transmit
  sh_eth: Ensure DMA engines are stopped before freeing buffers
  sh_eth: Remove RX overflow log messages
  ping: Fix race in free in receive path
  udp_diag: Fix socket skipping within chain
  can: kvaser_usb: Fix state handling upon BUS_ERROR events
  can: kvaser_usb: Retry the first bulk transfer on -ETIMEDOUT
  can: kvaser_usb: Send correct context to URB completion
  can: kvaser_usb: Do not sleep in atomic context
  ipv4: try to cache dst_entries which would cause a redirect
  samples: bpf: relax test_maps check
  bpf: rcu lock must not be held when calling copy_to_user()
  net: sctp: fix slab corruption from use after free on INIT collisions
  net: mv643xx_eth: Fix highmem support in non-TSO egress path
  sh_eth: Fix serialisation of interrupt disable with interrupt & NAPI handlers
  ...
  • Loading branch information
torvalds committed Jan 27, 2015
2 parents 7da323b + 06539d3 commit 59343cd
Show file tree
Hide file tree
Showing 42 changed files with 667 additions and 334 deletions.
8 changes: 4 additions & 4 deletions arch/arm/boot/dts/imx6sx-sdb.dts
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,12 @@
#address-cells = <1>;
#size-cells = <0>;

ethphy1: ethernet-phy@0 {
reg = <0>;
ethphy1: ethernet-phy@1 {
reg = <1>;
};

ethphy2: ethernet-phy@1 {
reg = <1>;
ethphy2: ethernet-phy@2 {
reg = <2>;
};
};
};
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/can/c_can/c_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,9 @@ static void c_can_stop(struct net_device *dev)

c_can_irq_control(priv, false);

/* put ctrl to init on stop to end ongoing transmission */
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_INIT);

/* deactivate pins */
pinctrl_pm_select_sleep_state(dev->dev.parent);
priv->can.state = CAN_STATE_STOPPED;
Expand Down
28 changes: 15 additions & 13 deletions drivers/net/can/usb/kvaser_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv,
usb_sndbulkpipe(dev->udev,
dev->bulk_out->bEndpointAddress),
buf, msg->len,
kvaser_usb_simple_msg_callback, priv);
kvaser_usb_simple_msg_callback, netdev);
usb_anchor_urb(urb, &priv->tx_submitted);

err = usb_submit_urb(urb, GFP_ATOMIC);
Expand Down Expand Up @@ -662,11 +662,6 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev,
priv = dev->nets[channel];
stats = &priv->netdev->stats;

if (status & M16C_STATE_BUS_RESET) {
kvaser_usb_unlink_tx_urbs(priv);
return;
}

skb = alloc_can_err_skb(priv->netdev, &cf);
if (!skb) {
stats->rx_dropped++;
Expand All @@ -677,7 +672,7 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev,

netdev_dbg(priv->netdev, "Error status: 0x%02x\n", status);

if (status & M16C_STATE_BUS_OFF) {
if (status & (M16C_STATE_BUS_OFF | M16C_STATE_BUS_RESET)) {
cf->can_id |= CAN_ERR_BUSOFF;

priv->can.can_stats.bus_off++;
Expand All @@ -703,9 +698,7 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev,
}

new_state = CAN_STATE_ERROR_PASSIVE;
}

if (status == M16C_STATE_BUS_ERROR) {
} else if (status & M16C_STATE_BUS_ERROR) {
if ((priv->can.state < CAN_STATE_ERROR_WARNING) &&
((txerr >= 96) || (rxerr >= 96))) {
cf->can_id |= CAN_ERR_CRTL;
Expand All @@ -715,7 +708,8 @@ static void kvaser_usb_rx_error(const struct kvaser_usb *dev,

priv->can.can_stats.error_warning++;
new_state = CAN_STATE_ERROR_WARNING;
} else if (priv->can.state > CAN_STATE_ERROR_ACTIVE) {
} else if ((priv->can.state > CAN_STATE_ERROR_ACTIVE) &&
((txerr < 96) && (rxerr < 96))) {
cf->can_id |= CAN_ERR_PROT;
cf->data[2] = CAN_ERR_PROT_ACTIVE;

Expand Down Expand Up @@ -1590,7 +1584,7 @@ static int kvaser_usb_probe(struct usb_interface *intf,
{
struct kvaser_usb *dev;
int err = -ENOMEM;
int i;
int i, retry = 3;

dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
Expand All @@ -1608,7 +1602,15 @@ static int kvaser_usb_probe(struct usb_interface *intf,

usb_set_intfdata(intf, dev);

err = kvaser_usb_get_software_info(dev);
/* On some x86 laptops, plugging a Kvaser device again after
* an unplug makes the firmware always ignore the very first
* command. For such a case, provide some room for retries
* instead of completely exiting the driver.
*/
do {
err = kvaser_usb_get_software_info(dev);
} while (--retry && err == -ETIMEDOUT);

if (err) {
dev_err(&intf->dev,
"Cannot get software infos, error %d\n", err);
Expand Down
9 changes: 5 additions & 4 deletions drivers/net/ethernet/amd/xgbe/xgbe-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -767,16 +767,17 @@
#define MTL_Q_RQOMR 0x40
#define MTL_Q_RQMPOCR 0x44
#define MTL_Q_RQDR 0x4c
#define MTL_Q_RQFCR 0x50
#define MTL_Q_IER 0x70
#define MTL_Q_ISR 0x74

/* MTL queue register entry bit positions and sizes */
#define MTL_Q_RQFCR_RFA_INDEX 1
#define MTL_Q_RQFCR_RFA_WIDTH 6
#define MTL_Q_RQFCR_RFD_INDEX 17
#define MTL_Q_RQFCR_RFD_WIDTH 6
#define MTL_Q_RQOMR_EHFC_INDEX 7
#define MTL_Q_RQOMR_EHFC_WIDTH 1
#define MTL_Q_RQOMR_RFA_INDEX 8
#define MTL_Q_RQOMR_RFA_WIDTH 3
#define MTL_Q_RQOMR_RFD_INDEX 13
#define MTL_Q_RQOMR_RFD_WIDTH 3
#define MTL_Q_RQOMR_RQS_INDEX 16
#define MTL_Q_RQOMR_RQS_WIDTH 9
#define MTL_Q_RQOMR_RSF_INDEX 5
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/amd/xgbe/xgbe-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2079,10 +2079,10 @@ static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata)

for (i = 0; i < pdata->rx_q_count; i++) {
/* Activate flow control when less than 4k left in fifo */
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RFA, 2);
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFA, 2);

/* De-activate flow control when more than 6k left in fifo */
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RFD, 4);
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFD, 4);
}
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
Original file line number Diff line number Diff line change
Expand Up @@ -3175,7 +3175,7 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
}
#endif
if (!bnx2x_fp_lock_napi(fp))
return work_done;
return budget;

for_each_cos_in_tx_queue(fp, cos)
if (bnx2x_tx_queue_has_work(fp->txdata_ptr[cos]))
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/cisco/enic/enic_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1335,7 +1335,7 @@ static int enic_poll_msix_rq(struct napi_struct *napi, int budget)
int err;

if (!enic_poll_lock_napi(&enic->rq[rq]))
return work_done;
return budget;
/* Service RQ
*/

Expand Down
59 changes: 49 additions & 10 deletions drivers/net/ethernet/marvell/mv643xx_eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ static char mv643xx_eth_driver_version[] = "1.4";
#define IS_TSO_HEADER(txq, addr) \
((addr >= txq->tso_hdrs_dma) && \
(addr < txq->tso_hdrs_dma + txq->tx_ring_size * TSO_HEADER_SIZE))

#define DESC_DMA_MAP_SINGLE 0
#define DESC_DMA_MAP_PAGE 1

/*
* RX/TX descriptors.
*/
Expand Down Expand Up @@ -362,6 +366,7 @@ struct tx_queue {
dma_addr_t tso_hdrs_dma;

struct tx_desc *tx_desc_area;
char *tx_desc_mapping; /* array to track the type of the dma mapping */
dma_addr_t tx_desc_dma;
int tx_desc_area_size;

Expand Down Expand Up @@ -750,6 +755,7 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq,
if (txq->tx_curr_desc == txq->tx_ring_size)
txq->tx_curr_desc = 0;
desc = &txq->tx_desc_area[tx_index];
txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE;

desc->l4i_chk = 0;
desc->byte_cnt = length;
Expand Down Expand Up @@ -879,14 +885,13 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)
skb_frag_t *this_frag;
int tx_index;
struct tx_desc *desc;
void *addr;

this_frag = &skb_shinfo(skb)->frags[frag];
addr = page_address(this_frag->page.p) + this_frag->page_offset;
tx_index = txq->tx_curr_desc++;
if (txq->tx_curr_desc == txq->tx_ring_size)
txq->tx_curr_desc = 0;
desc = &txq->tx_desc_area[tx_index];
txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_PAGE;

/*
* The last fragment will generate an interrupt
Expand All @@ -902,8 +907,9 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)

desc->l4i_chk = 0;
desc->byte_cnt = skb_frag_size(this_frag);
desc->buf_ptr = dma_map_single(mp->dev->dev.parent, addr,
desc->byte_cnt, DMA_TO_DEVICE);
desc->buf_ptr = skb_frag_dma_map(mp->dev->dev.parent,
this_frag, 0, desc->byte_cnt,
DMA_TO_DEVICE);
}
}

Expand Down Expand Up @@ -936,6 +942,7 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb,
if (txq->tx_curr_desc == txq->tx_ring_size)
txq->tx_curr_desc = 0;
desc = &txq->tx_desc_area[tx_index];
txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE;

if (nr_frags) {
txq_submit_frag_skb(txq, skb);
Expand Down Expand Up @@ -1047,9 +1054,12 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
int tx_index;
struct tx_desc *desc;
u32 cmd_sts;
char desc_dma_map;

tx_index = txq->tx_used_desc;
desc = &txq->tx_desc_area[tx_index];
desc_dma_map = txq->tx_desc_mapping[tx_index];

cmd_sts = desc->cmd_sts;

if (cmd_sts & BUFFER_OWNED_BY_DMA) {
Expand All @@ -1065,9 +1075,19 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
reclaimed++;
txq->tx_desc_count--;

if (!IS_TSO_HEADER(txq, desc->buf_ptr))
dma_unmap_single(mp->dev->dev.parent, desc->buf_ptr,
desc->byte_cnt, DMA_TO_DEVICE);
if (!IS_TSO_HEADER(txq, desc->buf_ptr)) {

if (desc_dma_map == DESC_DMA_MAP_PAGE)
dma_unmap_page(mp->dev->dev.parent,
desc->buf_ptr,
desc->byte_cnt,
DMA_TO_DEVICE);
else
dma_unmap_single(mp->dev->dev.parent,
desc->buf_ptr,
desc->byte_cnt,
DMA_TO_DEVICE);
}

if (cmd_sts & TX_ENABLE_INTERRUPT) {
struct sk_buff *skb = __skb_dequeue(&txq->tx_skb);
Expand Down Expand Up @@ -1996,6 +2016,7 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)
struct tx_queue *txq = mp->txq + index;
struct tx_desc *tx_desc;
int size;
int ret;
int i;

txq->index = index;
Expand Down Expand Up @@ -2048,18 +2069,34 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)
nexti * sizeof(struct tx_desc);
}

txq->tx_desc_mapping = kcalloc(txq->tx_ring_size, sizeof(char),
GFP_KERNEL);
if (!txq->tx_desc_mapping) {
ret = -ENOMEM;
goto err_free_desc_area;
}

/* Allocate DMA buffers for TSO MAC/IP/TCP headers */
txq->tso_hdrs = dma_alloc_coherent(mp->dev->dev.parent,
txq->tx_ring_size * TSO_HEADER_SIZE,
&txq->tso_hdrs_dma, GFP_KERNEL);
if (txq->tso_hdrs == NULL) {
dma_free_coherent(mp->dev->dev.parent, txq->tx_desc_area_size,
txq->tx_desc_area, txq->tx_desc_dma);
return -ENOMEM;
ret = -ENOMEM;
goto err_free_desc_mapping;
}
skb_queue_head_init(&txq->tx_skb);

return 0;

err_free_desc_mapping:
kfree(txq->tx_desc_mapping);
err_free_desc_area:
if (index == 0 && size <= mp->tx_desc_sram_size)
iounmap(txq->tx_desc_area);
else
dma_free_coherent(mp->dev->dev.parent, txq->tx_desc_area_size,
txq->tx_desc_area, txq->tx_desc_dma);
return ret;
}

static void txq_deinit(struct tx_queue *txq)
Expand All @@ -2077,6 +2114,8 @@ static void txq_deinit(struct tx_queue *txq)
else
dma_free_coherent(mp->dev->dev.parent, txq->tx_desc_area_size,
txq->tx_desc_area, txq->tx_desc_dma);
kfree(txq->tx_desc_mapping);

if (txq->tso_hdrs)
dma_free_coherent(mp->dev->dev.parent,
txq->tx_ring_size * TSO_HEADER_SIZE,
Expand Down
5 changes: 4 additions & 1 deletion drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2388,7 +2388,10 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget)

work_done = netxen_process_rcv_ring(sds_ring, budget);

if ((work_done < budget) && tx_complete) {
if (!tx_complete)
work_done = budget;

if (work_done < budget) {
napi_complete(&sds_ring->napi);
if (test_bit(__NX_DEV_UP, &adapter->state))
netxen_nic_enable_int(sds_ring);
Expand Down
Loading

0 comments on commit 59343cd

Please sign in to comment.