mirror of
https://github.com/adulau/aha.git
synced 2025-01-04 23:23:18 +00:00
cxgb3 - Fix dma mapping error path
Take potential dma mapping errors in account. Signed-off-by: Divy Le Ray <divy@chelsio.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
parent
03194379a7
commit
b1fb1f280d
1 changed files with 41 additions and 12 deletions
|
@ -376,13 +376,16 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
|
||||||
* Add a buffer of the given length to the supplied HW and SW Rx
|
* Add a buffer of the given length to the supplied HW and SW Rx
|
||||||
* descriptors.
|
* descriptors.
|
||||||
*/
|
*/
|
||||||
static inline void add_one_rx_buf(void *va, unsigned int len,
|
static inline int add_one_rx_buf(void *va, unsigned int len,
|
||||||
struct rx_desc *d, struct rx_sw_desc *sd,
|
struct rx_desc *d, struct rx_sw_desc *sd,
|
||||||
unsigned int gen, struct pci_dev *pdev)
|
unsigned int gen, struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
dma_addr_t mapping;
|
dma_addr_t mapping;
|
||||||
|
|
||||||
mapping = pci_map_single(pdev, va, len, PCI_DMA_FROMDEVICE);
|
mapping = pci_map_single(pdev, va, len, PCI_DMA_FROMDEVICE);
|
||||||
|
if (unlikely(pci_dma_mapping_error(mapping)))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
pci_unmap_addr_set(sd, dma_addr, mapping);
|
pci_unmap_addr_set(sd, dma_addr, mapping);
|
||||||
|
|
||||||
d->addr_lo = cpu_to_be32(mapping);
|
d->addr_lo = cpu_to_be32(mapping);
|
||||||
|
@ -390,6 +393,7 @@ static inline void add_one_rx_buf(void *va, unsigned int len,
|
||||||
wmb();
|
wmb();
|
||||||
d->len_gen = cpu_to_be32(V_FLD_GEN1(gen));
|
d->len_gen = cpu_to_be32(V_FLD_GEN1(gen));
|
||||||
d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
|
d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp)
|
static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp)
|
||||||
|
@ -424,13 +428,16 @@ static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp)
|
||||||
* allocated with the supplied gfp flags. The caller must assure that
|
* allocated with the supplied gfp flags. The caller must assure that
|
||||||
* @n does not exceed the queue's capacity.
|
* @n does not exceed the queue's capacity.
|
||||||
*/
|
*/
|
||||||
static void refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp)
|
static int refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp)
|
||||||
{
|
{
|
||||||
void *buf_start;
|
void *buf_start;
|
||||||
struct rx_sw_desc *sd = &q->sdesc[q->pidx];
|
struct rx_sw_desc *sd = &q->sdesc[q->pidx];
|
||||||
struct rx_desc *d = &q->desc[q->pidx];
|
struct rx_desc *d = &q->desc[q->pidx];
|
||||||
|
unsigned int count = 0;
|
||||||
|
|
||||||
while (n--) {
|
while (n--) {
|
||||||
|
int err;
|
||||||
|
|
||||||
if (q->use_pages) {
|
if (q->use_pages) {
|
||||||
if (unlikely(alloc_pg_chunk(q, sd, gfp))) {
|
if (unlikely(alloc_pg_chunk(q, sd, gfp))) {
|
||||||
nomem: q->alloc_failed++;
|
nomem: q->alloc_failed++;
|
||||||
|
@ -447,8 +454,16 @@ nomem: q->alloc_failed++;
|
||||||
buf_start = skb->data;
|
buf_start = skb->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen,
|
err = add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen,
|
||||||
adap->pdev);
|
adap->pdev);
|
||||||
|
if (unlikely(err)) {
|
||||||
|
if (!q->use_pages) {
|
||||||
|
kfree_skb(sd->skb);
|
||||||
|
sd->skb = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
d++;
|
d++;
|
||||||
sd++;
|
sd++;
|
||||||
if (++q->pidx == q->size) {
|
if (++q->pidx == q->size) {
|
||||||
|
@ -458,9 +473,13 @@ nomem: q->alloc_failed++;
|
||||||
d = q->desc;
|
d = q->desc;
|
||||||
}
|
}
|
||||||
q->credits++;
|
q->credits++;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
wmb();
|
wmb();
|
||||||
t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id));
|
if (likely(count))
|
||||||
|
t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id));
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl)
|
static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl)
|
||||||
|
@ -2618,7 +2637,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
|
||||||
int irq_vec_idx, const struct qset_params *p,
|
int irq_vec_idx, const struct qset_params *p,
|
||||||
int ntxq, struct net_device *dev)
|
int ntxq, struct net_device *dev)
|
||||||
{
|
{
|
||||||
int i, ret = -ENOMEM;
|
int i, avail, ret = -ENOMEM;
|
||||||
struct sge_qset *q = &adapter->sge.qs[id];
|
struct sge_qset *q = &adapter->sge.qs[id];
|
||||||
|
|
||||||
init_qset_cntxt(q, id);
|
init_qset_cntxt(q, id);
|
||||||
|
@ -2741,9 +2760,19 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
|
||||||
q->adap = adapter;
|
q->adap = adapter;
|
||||||
q->netdev = dev;
|
q->netdev = dev;
|
||||||
t3_update_qset_coalesce(q, p);
|
t3_update_qset_coalesce(q, p);
|
||||||
|
avail = refill_fl(adapter, &q->fl[0], q->fl[0].size, GFP_KERNEL);
|
||||||
|
if (!avail) {
|
||||||
|
CH_ALERT(adapter, "free list queue 0 initialization failed\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (avail < q->fl[0].size)
|
||||||
|
CH_WARN(adapter, "free list queue 0 enabled with %d credits\n",
|
||||||
|
avail);
|
||||||
|
|
||||||
refill_fl(adapter, &q->fl[0], q->fl[0].size, GFP_KERNEL);
|
avail = refill_fl(adapter, &q->fl[1], q->fl[1].size, GFP_KERNEL);
|
||||||
refill_fl(adapter, &q->fl[1], q->fl[1].size, GFP_KERNEL);
|
if (avail < q->fl[1].size)
|
||||||
|
CH_WARN(adapter, "free list queue 1 enabled with %d credits\n",
|
||||||
|
avail);
|
||||||
refill_rspq(adapter, &q->rspq, q->rspq.size - 1);
|
refill_rspq(adapter, &q->rspq, q->rspq.size - 1);
|
||||||
|
|
||||||
t3_write_reg(adapter, A_SG_GTS, V_RSPQ(q->rspq.cntxt_id) |
|
t3_write_reg(adapter, A_SG_GTS, V_RSPQ(q->rspq.cntxt_id) |
|
||||||
|
@ -2752,9 +2781,9 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
|
||||||
mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
|
mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_unlock:
|
err_unlock:
|
||||||
spin_unlock_irq(&adapter->sge.reg_lock);
|
spin_unlock_irq(&adapter->sge.reg_lock);
|
||||||
err:
|
err:
|
||||||
t3_free_qset(adapter, q);
|
t3_free_qset(adapter, q);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue