All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/2] Fix warnings in cxgb3
@ 2013-05-21 14:21 Vipul Pandya
  2013-05-21 14:21 ` [PATCH net-next 1/2] cxgb3: Fix warning about using rcu_dereference when not in a rcu-locked section Vipul Pandya
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Vipul Pandya @ 2013-05-21 14:21 UTC (permalink / raw)
  To: netdev; +Cc: davem, divy, dm, santosh, fenlason, vipul

The first warning is about using rcu_dereference() when not in a rcu-locked
section. It only happens on initialization hence fix the initialization to not
rcu_dereference().

The second warning is about not checking that a *dma_map*() call succeeded.
This patch adds checks at approprate places.

We request this patch series to get merged via net-next tree.

Thanks,
Vipul

Jay Fenlason (1):
  cxgb3: Fix warning about using rcu_dereference when not in a
    rcu-locked section

Santosh Rastapur (1):
  cxgb3: Check and handle the dma mapping errors

 drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c |   9 +-
 drivers/net/ethernet/chelsio/cxgb3/sge.c           | 105 ++++++++++++++++-----
 2 files changed, 87 insertions(+), 27 deletions(-)

-- 
1.8.0

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH net-next 1/2] cxgb3: Fix warning about using rcu_dereference when not in a rcu-locked section
  2013-05-21 14:21 [PATCH net-next 0/2] Fix warnings in cxgb3 Vipul Pandya
@ 2013-05-21 14:21 ` Vipul Pandya
  2013-05-21 14:21 ` [PATCH net-next 2/2] cxgb3: Check and handle the dma mapping errors Vipul Pandya
  2013-05-23  7:04 ` [PATCH net-next 0/2] Fix warnings in cxgb3 David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: Vipul Pandya @ 2013-05-21 14:21 UTC (permalink / raw)
  To: netdev; +Cc: davem, divy, dm, santosh, fenlason, vipul

From: Jay Fenlason <fenlason@redhat.com>

It is about using rcu_dereference() when not in a rcu-locked section. It only
happens on initialization hence fix the initialization to not rcu_dereference()

Signed-off-by: Jay Fenlason <fenlason@redhat.com>
---
 drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
index 0c96e5f..4058b85 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
@@ -1246,6 +1246,7 @@ int cxgb3_offload_activate(struct adapter *adapter)
 	struct tid_range stid_range, tid_range;
 	struct mtutab mtutab;
 	unsigned int l2t_capacity;
+	struct l2t_data *l2td;
 
 	t = kzalloc(sizeof(*t), GFP_KERNEL);
 	if (!t)
@@ -1261,8 +1262,8 @@ int cxgb3_offload_activate(struct adapter *adapter)
 		goto out_free;
 
 	err = -ENOMEM;
-	RCU_INIT_POINTER(dev->l2opt, t3_init_l2t(l2t_capacity));
-	if (!L2DATA(dev))
+	l2td = t3_init_l2t(l2t_capacity);
+	if (!l2td)
 		goto out_free;
 
 	natids = min(tid_range.num / 2, MAX_ATIDS);
@@ -1279,6 +1280,7 @@ int cxgb3_offload_activate(struct adapter *adapter)
 	INIT_LIST_HEAD(&t->list_node);
 	t->dev = dev;
 
+	RCU_INIT_POINTER(dev->l2opt, l2td);
 	T3C_DATA(dev) = t;
 	dev->recv = process_rx;
 	dev->neigh_update = t3_l2t_update;
@@ -1294,8 +1296,7 @@ int cxgb3_offload_activate(struct adapter *adapter)
 	return 0;
 
 out_free_l2t:
-	t3_free_l2t(L2DATA(dev));
-	RCU_INIT_POINTER(dev->l2opt, NULL);
+	t3_free_l2t(l2td);
 out_free:
 	kfree(t);
 	return err;
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH net-next 2/2] cxgb3: Check and handle the dma mapping errors
  2013-05-21 14:21 [PATCH net-next 0/2] Fix warnings in cxgb3 Vipul Pandya
  2013-05-21 14:21 ` [PATCH net-next 1/2] cxgb3: Fix warning about using rcu_dereference when not in a rcu-locked section Vipul Pandya
@ 2013-05-21 14:21 ` Vipul Pandya
  2013-05-23  7:04 ` [PATCH net-next 0/2] Fix warnings in cxgb3 David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: Vipul Pandya @ 2013-05-21 14:21 UTC (permalink / raw)
  To: netdev; +Cc: davem, divy, dm, santosh, fenlason, vipul

From: Santosh Rastapur <santosh@chelsio.com>

This patch adds checks at approprate places whether *dma_map*() call has
succeeded or not.

Signed-off-by: Santosh Rastapur <santosh@chelsio.com>
Reviewed-by: Jay Fenlason <fenlason@redhat.com>
---
 drivers/net/ethernet/chelsio/cxgb3/sge.c | 105 ++++++++++++++++++++++++-------
 1 file changed, 82 insertions(+), 23 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c
index f12e6b8..2fd773e 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
@@ -455,6 +455,11 @@ static int alloc_pg_chunk(struct adapter *adapter, struct sge_fl *q,
 		q->pg_chunk.offset = 0;
 		mapping = pci_map_page(adapter->pdev, q->pg_chunk.page,
 				       0, q->alloc_size, PCI_DMA_FROMDEVICE);
+		if (unlikely(pci_dma_mapping_error(adapter->pdev, mapping))) {
+			__free_pages(q->pg_chunk.page, order);
+			q->pg_chunk.page = NULL;
+			return -EIO;
+		}
 		q->pg_chunk.mapping = mapping;
 	}
 	sd->pg_chunk = q->pg_chunk;
@@ -949,40 +954,75 @@ static inline unsigned int calc_tx_descs(const struct sk_buff *skb)
 	return flits_to_desc(flits);
 }
 
+
+/*	map_skb - map a packet main body and its page fragments
+ *	@pdev: the PCI device
+ *	@skb: the packet
+ *	@addr: placeholder to save the mapped addresses
+ *
+ *	map the main body of an sk_buff and its page fragments, if any.
+ */
+static int map_skb(struct pci_dev *pdev, const struct sk_buff *skb,
+		   dma_addr_t *addr)
+{
+	const skb_frag_t *fp, *end;
+	const struct skb_shared_info *si;
+
+	*addr = pci_map_single(pdev, skb->data, skb_headlen(skb),
+			       PCI_DMA_TODEVICE);
+	if (pci_dma_mapping_error(pdev, *addr))
+		goto out_err;
+
+	si = skb_shinfo(skb);
+	end = &si->frags[si->nr_frags];
+
+	for (fp = si->frags; fp < end; fp++) {
+		*++addr = skb_frag_dma_map(&pdev->dev, fp, 0, skb_frag_size(fp),
+					   DMA_TO_DEVICE);
+		if (pci_dma_mapping_error(pdev, *addr))
+			goto unwind;
+	}
+	return 0;
+
+unwind:
+	while (fp-- > si->frags)
+		dma_unmap_page(&pdev->dev, *--addr, skb_frag_size(fp),
+			       DMA_TO_DEVICE);
+
+	pci_unmap_single(pdev, addr[-1], skb_headlen(skb), PCI_DMA_TODEVICE);
+out_err:
+	return -ENOMEM;
+}
+
 /**
- *	make_sgl - populate a scatter/gather list for a packet
+ *	write_sgl - populate a scatter/gather list for a packet
  *	@skb: the packet
  *	@sgp: the SGL to populate
  *	@start: start address of skb main body data to include in the SGL
  *	@len: length of skb main body data to include in the SGL
- *	@pdev: the PCI device
+ *	@addr: the list of the mapped addresses
  *
- *	Generates a scatter/gather list for the buffers that make up a packet
+ *	Copies the scatter/gather list for the buffers that make up a packet
  *	and returns the SGL size in 8-byte words.  The caller must size the SGL
  *	appropriately.
  */
-static inline unsigned int make_sgl(const struct sk_buff *skb,
+static inline unsigned int write_sgl(const struct sk_buff *skb,
 				    struct sg_ent *sgp, unsigned char *start,
-				    unsigned int len, struct pci_dev *pdev)
+				    unsigned int len, const dma_addr_t *addr)
 {
-	dma_addr_t mapping;
-	unsigned int i, j = 0, nfrags;
+	unsigned int i, j = 0, k = 0, nfrags;
 
 	if (len) {
-		mapping = pci_map_single(pdev, start, len, PCI_DMA_TODEVICE);
 		sgp->len[0] = cpu_to_be32(len);
-		sgp->addr[0] = cpu_to_be64(mapping);
-		j = 1;
+		sgp->addr[j++] = cpu_to_be64(addr[k++]);
 	}
 
 	nfrags = skb_shinfo(skb)->nr_frags;
 	for (i = 0; i < nfrags; i++) {
 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
-		mapping = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
-					   DMA_TO_DEVICE);
 		sgp->len[j] = cpu_to_be32(skb_frag_size(frag));
-		sgp->addr[j] = cpu_to_be64(mapping);
+		sgp->addr[j] = cpu_to_be64(addr[k++]);
 		j ^= 1;
 		if (j == 0)
 			++sgp;
@@ -1138,7 +1178,7 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb,
 			    const struct port_info *pi,
 			    unsigned int pidx, unsigned int gen,
 			    struct sge_txq *q, unsigned int ndesc,
-			    unsigned int compl)
+			    unsigned int compl, const dma_addr_t *addr)
 {
 	unsigned int flits, sgl_flits, cntrl, tso_info;
 	struct sg_ent *sgp, sgl[MAX_SKB_FRAGS / 2 + 1];
@@ -1196,7 +1236,7 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb,
 	}
 
 	sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
-	sgl_flits = make_sgl(skb, sgp, skb->data, skb_headlen(skb), adap->pdev);
+	sgl_flits = write_sgl(skb, sgp, skb->data, skb_headlen(skb), addr);
 
 	write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits, gen,
 			 htonl(V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT) | compl),
@@ -1227,6 +1267,7 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct netdev_queue *txq;
 	struct sge_qset *qs;
 	struct sge_txq *q;
+	dma_addr_t addr[MAX_SKB_FRAGS + 1];
 
 	/*
 	 * The chip min packet length is 9 octets but play safe and reject
@@ -1255,6 +1296,11 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 		return NETDEV_TX_BUSY;
 	}
 
+	if (unlikely(map_skb(adap->pdev, skb, addr) < 0)) {
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
 	q->in_use += ndesc;
 	if (unlikely(credits - ndesc < q->stop_thres)) {
 		t3_stop_tx_queue(txq, qs, q);
@@ -1312,7 +1358,7 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (likely(!skb_shared(skb)))
 		skb_orphan(skb);
 
-	write_tx_pkt_wr(adap, skb, pi, pidx, gen, q, ndesc, compl);
+	write_tx_pkt_wr(adap, skb, pi, pidx, gen, q, ndesc, compl, addr);
 	check_ring_tx_db(adap, q);
 	return NETDEV_TX_OK;
 }
@@ -1578,7 +1624,8 @@ static void setup_deferred_unmapping(struct sk_buff *skb, struct pci_dev *pdev,
  */
 static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb,
 			  struct sge_txq *q, unsigned int pidx,
-			  unsigned int gen, unsigned int ndesc)
+			  unsigned int gen, unsigned int ndesc,
+			  const dma_addr_t *addr)
 {
 	unsigned int sgl_flits, flits;
 	struct work_request_hdr *from;
@@ -1599,9 +1646,9 @@ static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb,
 
 	flits = skb_transport_offset(skb) / 8;
 	sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
-	sgl_flits = make_sgl(skb, sgp, skb_transport_header(skb),
+	sgl_flits = write_sgl(skb, sgp, skb_transport_header(skb),
 			     skb->tail - skb->transport_header,
-			     adap->pdev);
+			     addr);
 	if (need_skb_unmap()) {
 		setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits);
 		skb->destructor = deferred_unmap_destructor;
@@ -1659,6 +1706,11 @@ again:	reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
 		goto again;
 	}
 
+	if (map_skb(adap->pdev, skb, (dma_addr_t *)skb->head)) {
+		spin_unlock(&q->lock);
+		return NET_XMIT_SUCCESS;
+	}
+
 	gen = q->gen;
 	q->in_use += ndesc;
 	pidx = q->pidx;
@@ -1669,7 +1721,7 @@ again:	reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
 	}
 	spin_unlock(&q->lock);
 
-	write_ofld_wr(adap, skb, q, pidx, gen, ndesc);
+	write_ofld_wr(adap, skb, q, pidx, gen, ndesc, (dma_addr_t *)skb->head);
 	check_ring_tx_db(adap, q);
 	return NET_XMIT_SUCCESS;
 }
@@ -1687,6 +1739,7 @@ static void restart_offloadq(unsigned long data)
 	struct sge_txq *q = &qs->txq[TXQ_OFLD];
 	const struct port_info *pi = netdev_priv(qs->netdev);
 	struct adapter *adap = pi->adapter;
+	unsigned int written = 0;
 
 	spin_lock(&q->lock);
 again:	reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
@@ -1706,10 +1759,14 @@ again:	reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
 			break;
 		}
 
+		if (map_skb(adap->pdev, skb, (dma_addr_t *)skb->head))
+			break;
+
 		gen = q->gen;
 		q->in_use += ndesc;
 		pidx = q->pidx;
 		q->pidx += ndesc;
+		written += ndesc;
 		if (q->pidx >= q->size) {
 			q->pidx -= q->size;
 			q->gen ^= 1;
@@ -1717,7 +1774,8 @@ again:	reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
 		__skb_unlink(skb, &q->sendq);
 		spin_unlock(&q->lock);
 
-		write_ofld_wr(adap, skb, q, pidx, gen, ndesc);
+		write_ofld_wr(adap, skb, q, pidx, gen, ndesc,
+			     (dma_addr_t *)skb->head);
 		spin_lock(&q->lock);
 	}
 	spin_unlock(&q->lock);
@@ -1727,8 +1785,9 @@ again:	reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK);
 	set_bit(TXQ_LAST_PKT_DB, &q->flags);
 #endif
 	wmb();
-	t3_write_reg(adap, A_SG_KDOORBELL,
-		     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
+	if (likely(written))
+		t3_write_reg(adap, A_SG_KDOORBELL,
+			     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
 }
 
 /**
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH net-next 0/2] Fix warnings in cxgb3
  2013-05-21 14:21 [PATCH net-next 0/2] Fix warnings in cxgb3 Vipul Pandya
  2013-05-21 14:21 ` [PATCH net-next 1/2] cxgb3: Fix warning about using rcu_dereference when not in a rcu-locked section Vipul Pandya
  2013-05-21 14:21 ` [PATCH net-next 2/2] cxgb3: Check and handle the dma mapping errors Vipul Pandya
@ 2013-05-23  7:04 ` David Miller
  2 siblings, 0 replies; 4+ messages in thread
From: David Miller @ 2013-05-23  7:04 UTC (permalink / raw)
  To: vipul; +Cc: netdev, divy, dm, santosh, fenlason

From: Vipul Pandya <vipul@chelsio.com>
Date: Tue, 21 May 2013 19:51:27 +0530

> The first warning is about using rcu_dereference() when not in a rcu-locked
> section. It only happens on initialization hence fix the initialization to not
> rcu_dereference().
> 
> The second warning is about not checking that a *dma_map*() call succeeded.
> This patch adds checks at approprate places.
> 
> We request this patch series to get merged via net-next tree.

All applied, thanks.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-05-23  7:04 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-21 14:21 [PATCH net-next 0/2] Fix warnings in cxgb3 Vipul Pandya
2013-05-21 14:21 ` [PATCH net-next 1/2] cxgb3: Fix warning about using rcu_dereference when not in a rcu-locked section Vipul Pandya
2013-05-21 14:21 ` [PATCH net-next 2/2] cxgb3: Check and handle the dma mapping errors Vipul Pandya
2013-05-23  7:04 ` [PATCH net-next 0/2] Fix warnings in cxgb3 David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.