diff options
Diffstat (limited to 'drivers/net/ethernet/ti/keystone_qos.c')
-rw-r--r-- | drivers/net/ethernet/ti/keystone_qos.c | 129 |
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 | ||
46 | struct qos_device { | 47 | struct 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 | ||
53 | struct qos_intf { | 55 | struct 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 | |||
71 | static 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 | |||
79 | struct kobj_attribute qos_txchan_attr = | ||
80 | __ATTR(tx-channel, S_IRUGO, qos_txchan_show, NULL); | ||
81 | |||
82 | |||
83 | static 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 | |||
91 | static 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 | |||
108 | struct kobj_attribute qos_txdepth_attr = | ||
109 | __ATTR(tx_queue_depth, S_IRUGO | S_IWUSR, | ||
110 | qos_txdepth_show, qos_txdepth_store); | ||
111 | |||
112 | static struct attribute *qos_txchan_attrs[] = { | ||
113 | &qos_txchan_attr.attr, | ||
114 | &qos_txdepth_attr.attr, | ||
115 | NULL | ||
116 | }; | ||
117 | |||
118 | static 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 */ | ||
124 | static 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) | ||
130 | static 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 | |||
138 | struct kobj_attribute qos_multi_if_attr = | ||
139 | __ATTR(multi-interface, S_IRUGO, qos_multi_if_show, NULL); | ||
140 | |||
141 | static struct attribute *qos_inst_attrs[] = { | ||
142 | &qos_multi_if_attr.attr, | ||
143 | NULL | ||
144 | }; | ||
145 | |||
146 | static struct kobj_type qos_inst_ktype = { | ||
147 | .sysfs_ops = &kobj_sysfs_ops, | ||
148 | .default_attrs = qos_inst_attrs, | ||
149 | }; | ||
150 | |||
151 | |||
61 | static int qos_tx_hook(int order, void *data, struct netcp_packet *p_info) | 152 | static 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 | ||
271 | exit: | 398 | exit: |