aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/ti/keystone_qos.c')
-rw-r--r--drivers/net/ethernet/ti/keystone_qos.c129
1 files changed, 128 insertions, 1 deletions
diff --git a/drivers/net/ethernet/ti/keystone_qos.c b/drivers/net/ethernet/ti/keystone_qos.c
index 18366346865..062f733f9e3 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,106 @@ 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 struct netcp_tx_pipe *tx_pipe = &qos_chan->tx_pipe;
97 unsigned int val;
98
99 if (kstrtouint(buf, 0, &val) < 0)
100 return -EINVAL;
101
102 qos_chan->tx_queue_depth = val;
103 tx_pipe->dma_queue_depth = val;
104
105 return count;
106}
107
108struct kobj_attribute qos_txdepth_attr =
109 __ATTR(tx_queue_depth, S_IRUGO | S_IWUSR,
110 qos_txdepth_show, qos_txdepth_store);
111
112static struct attribute *qos_txchan_attrs[] = {
113 &qos_txchan_attr.attr,
114 &qos_txdepth_attr.attr,
115 NULL
116};
117
118static struct kobj_type qos_chan_ktype = {
119 .sysfs_ops = &kobj_sysfs_ops,
120 .default_attrs = qos_txchan_attrs,
121};
122
123/* Sysfs stuff related to QoS Interfaces */
124static struct kobj_type qos_intf_ktype = {
125 .sysfs_ops = &kobj_sysfs_ops,
126};
127
128/* Sysfs stuff related to QoS Instances */
129#define kobj_to_qdev(kobj) container_of(kobj, struct qos_device, kobj)
130static ssize_t qos_multi_if_show(struct kobject *kobj,
131 struct kobj_attribute *attr,
132 char *buf)
133{
134 struct qos_device *qos_dev = kobj_to_qdev(kobj);
135 return snprintf(buf, PAGE_SIZE, "%u\n", qos_dev->multi_if);
136}
137
138struct kobj_attribute qos_multi_if_attr =
139 __ATTR(multi-interface, S_IRUGO, qos_multi_if_show, NULL);
140
141static struct attribute *qos_inst_attrs[] = {
142 &qos_multi_if_attr.attr,
143 NULL
144};
145
146static struct kobj_type qos_inst_ktype = {
147 .sysfs_ops = &kobj_sysfs_ops,
148 .default_attrs = qos_inst_attrs,
149};
150
151
61static int qos_tx_hook(int order, void *data, struct netcp_packet *p_info) 152static int qos_tx_hook(int order, void *data, struct netcp_packet *p_info)
62{ 153{
63 struct qos_intf *qos_intf = data; 154 struct qos_intf *qos_intf = data;
@@ -148,6 +239,19 @@ static int init_channel(struct qos_intf *qos_intf,
148 } 239 }
149 dev_dbg(qos_intf->dev, "tx_queue_depth %u\n", qchan->tx_queue_depth); 240 dev_dbg(qos_intf->dev, "tx_queue_depth %u\n", qchan->tx_queue_depth);
150 241
242 /* Create the per-channel entry and attributes */
243 ret = kobject_init_and_add(&qchan->kobj, &qos_chan_ktype,
244 kobject_get(&qos_intf->kobj), node->name);
245 if (ret) {
246 dev_err(qos_intf->dev,
247 "failed to create %s/%s/%s sysfs entry\n",
248 qos_intf->qdev->kobj.name, qos_intf->kobj.name,
249 node->name);
250 kobject_put(&qchan->kobj);
251 kobject_put(&qos_intf->kobj);
252 return ret;
253 }
254
151 return 0; 255 return 0;
152} 256}
153 257
@@ -173,6 +277,7 @@ static int qos_attach(void *inst_priv, struct net_device *ndev,
173 } 277 }
174 qos_intf->max_channels = max_channels; 278 qos_intf->max_channels = max_channels;
175 279
280 qos_intf->qdev = qos_dev;
176 qos_intf->ndev = ndev; 281 qos_intf->ndev = ndev;
177 qos_intf->dev = qos_dev->dev; 282 qos_intf->dev = qos_dev->dev;
178 283
@@ -190,6 +295,17 @@ static int qos_attach(void *inst_priv, struct net_device *ndev,
190 goto exit; 295 goto exit;
191 } 296 }
192 297
298 /* Create the per-interface sysfs entry */
299 ret = kobject_init_and_add(&qos_intf->kobj, &qos_intf_ktype,
300 kobject_get(&qos_intf->qdev->kobj), node_name);
301 if (ret) {
302 dev_err(qos_intf->dev, "failed to create %s/%s sysfs entry\n",
303 qos_intf->qdev->kobj.name, node_name);
304 kobject_put(&qos_intf->kobj);
305 kobject_put(&qos_intf->qdev->kobj);
306 goto exit;
307 }
308
193 qos_intf->num_channels = 0; 309 qos_intf->num_channels = 0;
194 for_each_child_of_node(interface, channel) { 310 for_each_child_of_node(interface, channel) {
195 if (qos_intf->num_channels >= max_channels) { 311 if (qos_intf->num_channels >= max_channels) {
@@ -245,7 +361,7 @@ static int qos_probe(struct netcp_device *netcp_device,
245{ 361{
246 struct qos_device *qos_dev; 362 struct qos_device *qos_dev;
247 int ret = 0; 363 int ret = 0;
248 364
249 qos_dev = devm_kzalloc(dev, sizeof(struct qos_device), GFP_KERNEL); 365 qos_dev = devm_kzalloc(dev, sizeof(struct qos_device), GFP_KERNEL);
250 if (!qos_dev) { 366 if (!qos_dev) {
251 dev_err(dev, "memory allocation failed\n"); 367 dev_err(dev, "memory allocation failed\n");
@@ -266,6 +382,17 @@ static int qos_probe(struct netcp_device *netcp_device,
266 if (of_find_property(node, "multi-interface", NULL)) 382 if (of_find_property(node, "multi-interface", NULL))
267 qos_dev->multi_if = 1; 383 qos_dev->multi_if = 1;
268 384
385 /* Create the per-instance sysfs entry */
386 ret = kobject_init_and_add(&qos_dev->kobj, &qos_inst_ktype,
387 kobject_get(&dev->kobj), node->name);
388 if (ret) {
389 dev_err(dev, "failed to create %s sysfs entry\n",
390 node->name);
391 kobject_put(&qos_dev->kobj);
392 kobject_put(&dev->kobj);
393 goto exit;
394 }
395
269 return 0; 396 return 0;
270 397
271exit: 398exit: