diff options
Diffstat (limited to 'drivers/net/ethernet/ti/davinci_cpdma.c')
| -rw-r--r-- | drivers/net/ethernet/ti/davinci_cpdma.c | 77 | 
1 files changed, 62 insertions, 15 deletions
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index 49956730cd8..ee13dc78430 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -60,6 +60,9 @@  #define CPDMA_DESC_EOQ		BIT(28)  #define CPDMA_DESC_TD_COMPLETE	BIT(27)  #define CPDMA_DESC_PASS_CRC	BIT(26) +#define CPDMA_DESC_TO_PORT_EN	BIT(20) +#define CPDMA_TO_PORT_SHIFT	16 +#define CPDMA_DESC_PORT_MASK	(BIT(18) | BIT(17) | BIT(16))  #define CPDMA_TEARDOWN_VALUE	0xfffffffc @@ -105,13 +108,13 @@ struct cpdma_ctlr {  };  struct cpdma_chan { +	struct cpdma_desc __iomem	*head, *tail; +	void __iomem			*hdp, *cp, *rxfree;  	enum cpdma_state		state;  	struct cpdma_ctlr		*ctlr;  	int				chan_num;  	spinlock_t			lock; -	struct cpdma_desc __iomem	*head, *tail;  	int				count; -	void __iomem			*hdp, *cp, *rxfree;  	u32				mask;  	cpdma_handler_fn		handler;  	enum dma_data_direction		dir; @@ -132,6 +135,14 @@ struct cpdma_chan {  #define chan_write(chan, fld, v)	__raw_writel(v, (chan)->fld)  #define desc_write(desc, fld, v)	__raw_writel((u32)(v), &(desc)->fld) +#define cpdma_desc_to_port(chan, mode, directed)			\ +	do {								\ +		if (!is_rx_chan(chan) && ((directed == 1) ||		\ +					  (directed == 2)))		\ +			mode |= (CPDMA_DESC_TO_PORT_EN |		\ +				 (directed << CPDMA_TO_PORT_SHIFT));	\ +	} while (0) +  /*   * Utility constructs for a cpdma descriptor pool.  Some devices (e.g. davinci   * emac) have dedicated on-chip memory for these descriptors.  Some other @@ -217,17 +228,27 @@ desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma)  }  static struct cpdma_desc __iomem * -cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc) +cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc, bool is_rx)  {  	unsigned long flags;  	int index; +	int desc_start; +	int desc_end;  	struct cpdma_desc __iomem *desc = NULL;  	spin_lock_irqsave(&pool->lock, flags); -	index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0, -					   num_desc, 0); -	if (index < pool->num_desc) { +	if (is_rx) { +		desc_start = 0; +		desc_end = pool->num_desc/2; +	 } else { +		desc_start = pool->num_desc/2; +		desc_end = pool->num_desc; +	} + +	index = bitmap_find_next_zero_area(pool->bitmap, +				desc_end, desc_start, num_desc, 0); +	if (index < desc_end) {  		bitmap_set(pool->bitmap, index, num_desc);  		desc = pool->iomap + pool->desc_size * index;  		pool->used_desc++; @@ -439,10 +460,8 @@ int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)  	if (ctlr->state != CPDMA_STATE_IDLE)  		cpdma_ctlr_stop(ctlr); -	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) { -		if (ctlr->channels[i]) -			cpdma_chan_destroy(ctlr->channels[i]); -	} +	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) +		cpdma_chan_destroy(ctlr->channels[i]);  	cpdma_desc_pool_destroy(ctlr->pool);  	spin_unlock_irqrestore(&ctlr->lock, flags); @@ -473,11 +492,13 @@ int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)  	spin_unlock_irqrestore(&ctlr->lock, flags);  	return 0;  } +EXPORT_SYMBOL_GPL(cpdma_ctlr_int_ctrl); -void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr) +void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr, u32 value)  { -	dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0); +	dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, value);  } +EXPORT_SYMBOL_GPL(cpdma_ctlr_eoi);  struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,  				     cpdma_handler_fn handler) @@ -652,7 +673,7 @@ static void __cpdma_chan_submit(struct cpdma_chan *chan,  }  int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data, -		      int len, gfp_t gfp_mask) +		      int len, int directed, gfp_t gfp_mask)  {  	struct cpdma_ctlr		*ctlr = chan->ctlr;  	struct cpdma_desc __iomem	*desc; @@ -668,7 +689,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,  		goto unlock_ret;  	} -	desc = cpdma_desc_alloc(ctlr->pool, 1); +	desc = cpdma_desc_alloc(ctlr->pool, 1, is_rx_chan(chan));  	if (!desc) {  		chan->stats.desc_alloc_fail++;  		ret = -ENOMEM; @@ -682,6 +703,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,  	buffer = dma_map_single(ctlr->dev, data, len, chan->dir);  	mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP; +	cpdma_desc_to_port(chan, mode, directed);  	desc_write(desc, hw_next,   0);  	desc_write(desc, hw_buffer, buffer); @@ -704,6 +726,29 @@ unlock_ret:  }  EXPORT_SYMBOL_GPL(cpdma_chan_submit); +bool cpdma_check_free_tx_desc(struct cpdma_chan *chan) +{ +	unsigned long flags; +	int index; +	bool ret; +	struct cpdma_ctlr	*ctlr = chan->ctlr; +	struct cpdma_desc_pool	*pool = ctlr->pool; + +	spin_lock_irqsave(&pool->lock, flags); + +	index = bitmap_find_next_zero_area(pool->bitmap, +				pool->num_desc, pool->num_desc/2, 1, 0); + +	if (index < pool->num_desc) +		ret = true; +	else +		ret = false; + +	spin_unlock_irqrestore(&pool->lock, flags); +	return ret; +} +EXPORT_SYMBOL_GPL(cpdma_check_free_tx_desc); +  static void __cpdma_chan_free(struct cpdma_chan *chan,  			      struct cpdma_desc __iomem *desc,  			      int outlen, int status) @@ -749,7 +794,8 @@ static int __cpdma_chan_process(struct cpdma_chan *chan)  		status = -EBUSY;  		goto unlock_ret;  	} -	status	= status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE); +	status	= status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE | +			    CPDMA_DESC_PORT_MASK);  	chan->head = desc_from_phys(pool, desc_read(desc, hw_next));  	chan_write(chan, cp, desc_dma); @@ -984,3 +1030,4 @@ unlock_ret:  	spin_unlock_irqrestore(&ctlr->lock, flags);  	return ret;  } +EXPORT_SYMBOL_GPL(cpdma_control_set);  |