aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReece R. Pollack2015-02-20 17:36:40 -0600
committerReece R. Pollack2015-02-24 12:07:16 -0600
commit7710b4b7519ec0162d18fce7d85f6b22dd07fc7f (patch)
treef01f6e3a916bb4cd1930f318bd25869fc7fe64fd
parentdadb6a5634a3ed8138f577e98715fbc378841b5a (diff)
downloadlinux-7710b4b7519ec0162d18fce7d85f6b22dd07fc7f.tar.gz
linux-7710b4b7519ec0162d18fce7d85f6b22dd07fc7f.tar.xz
linux-7710b4b7519ec0162d18fce7d85f6b22dd07fc7f.zip
net: keystone: Add TX queue depth resizing to NetCP QoS
This patch makes the TX queue depths (really the number of DMA descriptors available) visible and modifiable in sysfs. Also exposed queue name and device multi-interface mode. This change affects ONLY the NetCP QoS module, and does not apply to other NetCP modules (PA, SA, etc). Signed-off-by: Reece R. Pollack <x0183204@ti.com>
-rw-r--r--drivers/net/ethernet/ti/keystone_qos.c127
1 files changed, 126 insertions, 1 deletions
diff --git a/drivers/net/ethernet/ti/keystone_qos.c b/drivers/net/ethernet/ti/keystone_qos.c
index 18366346865..2a3726cd77e 100644
--- a/drivers/net/ethernet/ti/keystone_qos.c
+++ b/drivers/net/ethernet/ti/keystone_qos.c
@@ -41,6 +41,7 @@ struct qos_channel {
41 const char *tx_chan_name; 41 const char *tx_chan_name;
42 u32 tx_queue_depth; 42 u32 tx_queue_depth;
43 struct netcp_tx_pipe tx_pipe; 43 struct netcp_tx_pipe tx_pipe;
44 struct kobject kobj;
44}; 45};
45 46
46struct qos_device { 47struct qos_device {
@@ -48,16 +49,104 @@ struct qos_device {
48 struct device *dev; 49 struct device *dev;
49 struct device_node *node; 50 struct device_node *node;
50 u32 multi_if; 51 u32 multi_if;
52 struct kobject kobj;
51}; 53};
52 54
53struct qos_intf { 55struct qos_intf {
56 struct qos_device *qdev;
54 struct net_device *ndev; 57 struct net_device *ndev;
55 struct device *dev; 58 struct device *dev;
59 struct kobject kobj;
56 int num_channels; 60 int num_channels;
57 int max_channels; 61 int max_channels;
58 struct qos_channel channels[1]; 62 struct qos_channel channels[1];
63 /* NB: channels is allocated dynamically */
59}; 64};
60 65
66/*
67 * Sysfs stuff related to QoS TX Channels
68 */
69#define kobj_to_qchan(kobj) container_of(kobj, struct qos_channel, kobj)
70
71static ssize_t qos_txchan_show(struct kobject *kobj,
72 struct kobj_attribute *attr,
73 char *buf)
74{
75 struct qos_channel *qos_chan = kobj_to_qchan(kobj);
76 return snprintf(buf, PAGE_SIZE, "%s\n", qos_chan->tx_chan_name);
77}
78
79struct kobj_attribute qos_txchan_attr =
80 __ATTR(tx-channel, S_IRUGO, qos_txchan_show, NULL);
81
82
83static ssize_t qos_txdepth_show(struct kobject *kobj,
84 struct kobj_attribute *attr,
85 char *buf)
86{
87 struct qos_channel *qos_chan = kobj_to_qchan(kobj);
88 return snprintf(buf, PAGE_SIZE, "%u\n", qos_chan->tx_queue_depth);
89}
90
91static ssize_t qos_txdepth_store(struct kobject *kobj,
92 struct kobj_attribute *attr,
93 const char *buf, size_t count)
94{
95 struct qos_channel *qos_chan = kobj_to_qchan(kobj);
96 unsigned int val;
97
98 if (kstrtouint(buf, 0, &val) < 0)
99 return -EINVAL;
100
101 qos_chan->tx_queue_depth = val;
102
103 return count;
104}
105
106struct kobj_attribute qos_txdepth_attr =
107 __ATTR(tx_queue_depth, S_IRUGO | S_IWUSR,
108 qos_txdepth_show, qos_txdepth_store);
109
110static struct attribute *qos_txchan_attrs[] = {
111 &qos_txchan_attr.attr,
112 &qos_txdepth_attr.attr,
113 NULL
114};
115
116static struct kobj_type qos_chan_ktype = {
117 .sysfs_ops = &kobj_sysfs_ops,
118 .default_attrs = qos_txchan_attrs,
119};
120
121/* Sysfs stuff related to QoS Interfaces */
122static struct kobj_type qos_intf_ktype = {
123 .sysfs_ops = &kobj_sysfs_ops,
124};
125
126/* Sysfs stuff related to QoS Instances */
127#define kobj_to_qdev(kobj) container_of(kobj, struct qos_device, kobj)
128static ssize_t qos_multi_if_show(struct kobject *kobj,
129 struct kobj_attribute *attr,
130 char *buf)
131{
132 struct qos_device *qos_dev = kobj_to_qdev(kobj);
133 return snprintf(buf, PAGE_SIZE, "%u\n", qos_dev->multi_if);
134}
135
136struct kobj_attribute qos_multi_if_attr =
137 __ATTR(multi-interface, S_IRUGO, qos_multi_if_show, NULL);
138
139static struct attribute *qos_inst_attrs[] = {
140 &qos_multi_if_attr.attr,
141 NULL
142};
143
144static struct kobj_type qos_inst_ktype = {
145 .sysfs_ops = &kobj_sysfs_ops,
146 .default_attrs = qos_inst_attrs,
147};
148
149
61static int qos_tx_hook(int order, void *data, struct netcp_packet *p_info) 150static int qos_tx_hook(int order, void *data, struct netcp_packet *p_info)
62{ 151{
63 struct qos_intf *qos_intf = data; 152 struct qos_intf *qos_intf = data;
@@ -148,6 +237,19 @@ static int init_channel(struct qos_intf *qos_intf,
148 } 237 }
149 dev_dbg(qos_intf->dev, "tx_queue_depth %u\n", qchan->tx_queue_depth); 238 dev_dbg(qos_intf->dev, "tx_queue_depth %u\n", qchan->tx_queue_depth);
150 239
240 /* Create the per-channel entry and attributes */
241 ret = kobject_init_and_add(&qchan->kobj, &qos_chan_ktype,
242 kobject_get(&qos_intf->kobj), node->name);
243 if (ret) {
244 dev_err(qos_intf->dev,
245 "failed to create %s/%s/%s sysfs entry\n",
246 qos_intf->qdev->kobj.name, qos_intf->kobj.name,
247 node->name);
248 kobject_put(&qchan->kobj);
249 kobject_put(&qos_intf->kobj);
250 return ret;
251 }
252
151 return 0; 253 return 0;
152} 254}
153 255
@@ -173,6 +275,7 @@ static int qos_attach(void *inst_priv, struct net_device *ndev,
173 } 275 }
174 qos_intf->max_channels = max_channels; 276 qos_intf->max_channels = max_channels;
175 277
278 qos_intf->qdev = qos_dev;
176 qos_intf->ndev = ndev; 279 qos_intf->ndev = ndev;
177 qos_intf->dev = qos_dev->dev; 280 qos_intf->dev = qos_dev->dev;
178 281
@@ -190,6 +293,17 @@ static int qos_attach(void *inst_priv, struct net_device *ndev,
190 goto exit; 293 goto exit;
191 } 294 }
192 295
296 /* Create the per-interface sysfs entry */
297 ret = kobject_init_and_add(&qos_intf->kobj, &qos_intf_ktype,
298 kobject_get(&qos_intf->qdev->kobj), node_name);
299 if (ret) {
300 dev_err(qos_intf->dev, "failed to create %s/%s sysfs entry\n",
301 qos_intf->qdev->kobj.name, node_name);
302 kobject_put(&qos_intf->kobj);
303 kobject_put(&qos_intf->qdev->kobj);
304 goto exit;
305 }
306
193 qos_intf->num_channels = 0; 307 qos_intf->num_channels = 0;
194 for_each_child_of_node(interface, channel) { 308 for_each_child_of_node(interface, channel) {
195 if (qos_intf->num_channels >= max_channels) { 309 if (qos_intf->num_channels >= max_channels) {
@@ -245,7 +359,7 @@ static int qos_probe(struct netcp_device *netcp_device,
245{ 359{
246 struct qos_device *qos_dev; 360 struct qos_device *qos_dev;
247 int ret = 0; 361 int ret = 0;
248 362
249 qos_dev = devm_kzalloc(dev, sizeof(struct qos_device), GFP_KERNEL); 363 qos_dev = devm_kzalloc(dev, sizeof(struct qos_device), GFP_KERNEL);
250 if (!qos_dev) { 364 if (!qos_dev) {
251 dev_err(dev, "memory allocation failed\n"); 365 dev_err(dev, "memory allocation failed\n");
@@ -266,6 +380,17 @@ static int qos_probe(struct netcp_device *netcp_device,
266 if (of_find_property(node, "multi-interface", NULL)) 380 if (of_find_property(node, "multi-interface", NULL))
267 qos_dev->multi_if = 1; 381 qos_dev->multi_if = 1;
268 382
383 /* Create the per-instance sysfs entry */
384 ret = kobject_init_and_add(&qos_dev->kobj, &qos_inst_ktype,
385 kobject_get(&dev->kobj), node->name);
386 if (ret) {
387 dev_err(dev, "failed to create %s sysfs entry\n",
388 node->name);
389 kobject_put(&qos_dev->kobj);
390 kobject_put(&dev->kobj);
391 goto exit;
392 }
393
269 return 0; 394 return 0;
270 395
271exit: 396exit: