aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSandeep Paulraj <s-paulraj@ti.com>2012-09-17 12:41:28 -0400
committerCyril Chemparathy <cyril@ti.com>2012-09-21 10:44:12 -0400
commit1a3261fa98b39f283c318024d58469891979fa0b (patch)
tree65cff815fd0ecddf5186134763b007dbd93f7b36
parent3e3cf16d08ccdba7cc213d004b42340f47dc12a9 (diff)
downloadlinux-keystone-1a3261fa98b39f283c318024d58469891979fa0b.tar.gz
dma: keystone: add support for more than 4096 queues
The existing implementation of the keystone dma engine prevented queues above 4095 from being used. This commit adds support in the keystone dma engine to enable queues greater than 4095 to be used. Any queue from 4096 to 8192 logically belongs to another queue manager. So based on the queue number we calculate the queue manager number. The existing implementation was never writing the queue manager number into the appropriate locations in the descriptor and the packet dma rx flow register. At reset this value was zero and things worked. While using any queue above 4095, we have to appropriatley calculate the queue manager number and put it in the descriptor and the appropriate packet dma rx flow register. Also, the driver was not modifying the qm_base_address registers in the global packet dma control registers. Again on reset, the appropriate value is set into QM0 base address register and the others are 0. This also prevents queues greater than 4095 from being used. To this effect, device tree support is being added. We can have a maximum of 4 logical queue managers but in the current generation of devices we have 2. From device tree we apprise the driver of the number of queue managers using the binding logical-queue-managers. In the device tree we also define the qm-base-address for each logical queue manager using an array. Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
-rw-r--r--Documentation/devicetree/bindings/dma/keystone-pktdma.txt51
-rw-r--r--drivers/dma/keystone-pktdma.c46
2 files changed, 55 insertions, 42 deletions
diff --git a/Documentation/devicetree/bindings/dma/keystone-pktdma.txt b/Documentation/devicetree/bindings/dma/keystone-pktdma.txt
index f367b2ce8ee3a3..d82e6a09dcea71 100644
--- a/Documentation/devicetree/bindings/dma/keystone-pktdma.txt
+++ b/Documentation/devicetree/bindings/dma/keystone-pktdma.txt
@@ -37,49 +37,15 @@ channel: the actual channel number to be used.
priority: the priority associated with a channel.
flow: the RX flow that will be used. Applicable only for
RX.
+logical-queue-managers: number of logical queue managers
+queues-per-queue-manager: the number of queues per queue manager
+qm-base-address: the actual VBUSM address that needs to be programmed into
+ each QM_BASE_ADDR register. The number of distinct values
+ should be equal to the number of logical queue managers.
-2 examples are provided below. infradma is the packet dma instance associated
-with the queue manage susbsystem. padma is packet dma instance associated
+An examples is provided below. padma is packet dma instance associated
with the packet accelerator susbsystem.
-infradma: pktdma@2a6c000 {
- compatible = "ti,keystone-pktdma";
- reg = <0x2a6c000 0x100 /* 0 - global */
- 0x2a6c400 0x400 /* 1 - txchan */
- 0x2a6c800 0x400 /* 2 - rxchan */
- 0x2a6cc00 0x400 /* 3 - txsched */
- 0x2a6d000 0x400>; /* 4 - rxflow */
- loop-back;
- /* big-endian; */
- /* enable-all; */
- /* debug; */
- channels {
- vethtx {
- transmit;
- label = "vethtx";
- pool = "pool-veth";
- descriptors = <128>;
- submit-queue = <800>;
- /* complete-queue = <xx>; */
- /* debug; */
- channel = <0>;
- priority = <1>;
- flowtag = <1>;
- };
- vethrx {
- receive;
- label = "vethrx";
- pool = "pool-veth";
- descriptors = <128>;
- /* submit-queue = <xx>; */
- /* complete-queue = <xx>; */
- /* debug; */
- channel = <0>;
- flow = <0>;
- };
- };
- };
-
padma: pktdma@2004000 {
compatible = "ti,keystone-pktdma";
reg = <0x2004000 0x100 /* 0 - global */
@@ -91,6 +57,11 @@ infradma: pktdma@2a6c000 {
/* bigendian; */
enable-all;
/* debug; */
+
+ logical-queue-managers = <2>;
+ queues-per-queue-manager = <4096>;
+ qm-base-address = <0x34020000 0x34030000>;
+
channels {
nettx {
transmit;
diff --git a/drivers/dma/keystone-pktdma.c b/drivers/dma/keystone-pktdma.c
index a3fd6cb679baac..a7f9e609e71057 100644
--- a/drivers/dma/keystone-pktdma.c
+++ b/drivers/dma/keystone-pktdma.c
@@ -50,6 +50,7 @@
#define DESC_PSFLAGS_SHIFT 16
#define DESC_RETQ_MASK BITS(14)
#define DESC_RETQ_SHIFT 0
+#define DESC_RETQMGR_SHIFT 12
#define DESC_FLOWTAG_MASK BITS(8)
#define DESC_FLOWTAG_SHIFT 16
#define DESC_LEN_MASK BITS(22)
@@ -158,6 +159,9 @@ struct keystone_dma_device {
struct clk *clk;
bool big_endian, loopback, enable_all;
unsigned tx_priority, rx_priority;
+ unsigned logical_queue_managers;
+ unsigned queues_per_queue_manager;
+ unsigned qm_base_address[4];
struct reg_global __iomem *reg_global;
struct reg_chan __iomem *reg_tx_chan;
struct reg_rx_flow __iomem *reg_rx_flow;
@@ -197,6 +201,7 @@ struct keystone_dma_chan {
void *descs;
int qnum_submit[KEYSTONE_QUEUES_PER_CHAN];
int qnum_complete;
+ int dest_queue_manager;
struct dma_notify_info notify_info;
wait_queue_head_t state_wait_queue;
@@ -767,6 +772,7 @@ static void chan_destroy_queues(struct keystone_dma_chan *chan)
}
chan->q_complete = NULL;
chan->qnum_complete = 0;
+ chan->dest_queue_manager = 0;
for (i = 0; i < KEYSTONE_QUEUES_PER_CHAN; ++i) {
if (chan->q_submit[i])
@@ -782,6 +788,7 @@ static void chan_destroy_queues(struct keystone_dma_chan *chan)
static int chan_setup_queues(struct keystone_dma_chan *chan)
{
+ struct keystone_dma_device *dma = chan->dma;
unsigned flags = O_RDWR;
struct hwqueue *q;
int ret = 0;
@@ -834,6 +841,8 @@ static int chan_setup_queues(struct keystone_dma_chan *chan)
}
chan->qnum_complete = hwqueue_get_id(q);
chan->q_complete = q;
+ chan->dest_queue_manager = chan->qnum_complete /
+ dma->queues_per_queue_manager;
/* setup queue notifier */
ret = hwqueue_set_notifier(q, chan_complete_callback, chan);
@@ -876,7 +885,9 @@ static int chan_start(struct keystone_dma_chan *chan)
if (chan->reg_rx_flow) {
v = CHAN_HAS_EPIB | CHAN_HAS_PSINFO;
- v |= chan->qnum_complete | (DESC_TYPE_HOST << DESC_TYPE_SHIFT);
+ v |= chan->qnum_complete |
+ (chan->dest_queue_manager << DESC_RETQMGR_SHIFT) |
+ (DESC_TYPE_HOST << DESC_TYPE_SHIFT);
__raw_writel(v, &chan->reg_rx_flow->control);
__raw_writel(0, &chan->reg_rx_flow->tags);
@@ -1154,6 +1165,10 @@ static void keystone_dma_hw_init(struct keystone_dma_device *dma)
}
}
+ for (i = 0; i < dma->logical_queue_managers; i++)
+ __raw_writel(dma->qm_base_address[i],
+ &dma->reg_global->qm_base_address[i]);
+
}
static void keystone_dma_hw_destroy(struct keystone_dma_device *dma)
@@ -1523,7 +1538,8 @@ chan_prep_slave_sg(struct dma_chan *achan, struct scatterlist *_sg,
packet_info = ((epib ? DESC_HAS_EPIB : 0) |
pslen << DESC_PSLEN_SHIFT |
psflags << DESC_PSFLAGS_SHIFT |
- chan->qnum_complete << DESC_RETQ_SHIFT);
+ chan->qnum_complete << DESC_RETQ_SHIFT |
+ chan->dest_queue_manager << DESC_RETQMGR_SHIFT);
/* Walk backwards through the scatterlist */
next_desc = 0;
@@ -1932,6 +1948,8 @@ static int __devinit keystone_dma_probe(struct platform_device *pdev)
resource_size_t size;
int ret, num_chan = 0;
u32 priority;
+ u32 config[4];
+ u32 i;
if (!node) {
dev_err(&pdev->dev, "could not find device info\n");
@@ -2002,6 +2020,30 @@ static int __devinit keystone_dma_probe(struct platform_device *pdev)
}
dma->tx_priority = priority;
+ ret = of_property_read_u32(node, "logical-queue-managers",
+ &dma->logical_queue_managers);
+ if (ret < 0) {
+ dev_dbg(&pdev->dev, "unspecified number of logical "
+ "queue managers\n");
+ dma->logical_queue_managers = 2;
+ }
+
+ ret = of_property_read_u32(node, "queues-per-queue-manager",
+ &dma->queues_per_queue_manager);
+ if (ret < 0) {
+ dev_dbg(&pdev->dev, "unspecified number of queues per "
+ "queue manager\n");
+ dma->queues_per_queue_manager = 4096;
+ }
+
+ ret = of_property_read_u32_array(node, "qm-base-address",
+ config, dma->logical_queue_managers);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < dma->logical_queue_managers; i++)
+ dma->qm_base_address[i] = config[i];
+
dma->max_rx_chan = max_rx_chan;
dma->max_rx_flow = max_rx_flow;
dma->max_tx_chan = min(max_tx_chan, max_tx_sched);