diff options
author | Mike Marciniszyn <mike.marciniszyn@intel.com> | 2012-07-19 09:04:04 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2012-07-19 14:20:04 -0400 |
commit | 36a8f01cd24b125aa027c71c1288588edde5322d (patch) | |
tree | e8f3e5dd99bac1a750b7113c00d973cec12cd23c /drivers/infiniband/hw/qib/qib_sysfs.c | |
parent | 551ace124d0ef471e8a5fee3ef9e5bb7460251be (diff) |
IB/qib: Add congestion control agent implementation
Add a congestion control agent in the driver that handles gets and
sets from the congestion control manager in the fabric for the
Performance Scale Messaging (PSM) library.
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw/qib/qib_sysfs.c')
-rw-r--r-- | drivers/infiniband/hw/qib/qib_sysfs.c | 158 |
1 files changed, 149 insertions, 9 deletions
diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c index dd9cd49d0979..ae78305b59d0 100644 --- a/drivers/infiniband/hw/qib/qib_sysfs.c +++ b/drivers/infiniband/hw/qib/qib_sysfs.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved. | 2 | * Copyright (c) 2012 Intel Corporation. All rights reserved. |
3 | * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. | ||
3 | * Copyright (c) 2006 PathScale, Inc. All rights reserved. | 4 | * Copyright (c) 2006 PathScale, Inc. All rights reserved. |
4 | * | 5 | * |
5 | * This software is available to you under a choice of one of two | 6 | * This software is available to you under a choice of one of two |
@@ -33,6 +34,7 @@ | |||
33 | #include <linux/ctype.h> | 34 | #include <linux/ctype.h> |
34 | 35 | ||
35 | #include "qib.h" | 36 | #include "qib.h" |
37 | #include "qib_mad.h" | ||
36 | 38 | ||
37 | /** | 39 | /** |
38 | * qib_parse_ushort - parse an unsigned short value in an arbitrary base | 40 | * qib_parse_ushort - parse an unsigned short value in an arbitrary base |
@@ -231,6 +233,98 @@ static struct attribute *port_default_attributes[] = { | |||
231 | NULL | 233 | NULL |
232 | }; | 234 | }; |
233 | 235 | ||
236 | /* | ||
237 | * Start of per-port congestion control structures and support code | ||
238 | */ | ||
239 | |||
240 | /* | ||
241 | * Congestion control table size followed by table entries | ||
242 | */ | ||
243 | static ssize_t read_cc_table_bin(struct file *filp, struct kobject *kobj, | ||
244 | struct bin_attribute *bin_attr, | ||
245 | char *buf, loff_t pos, size_t count) | ||
246 | { | ||
247 | int ret; | ||
248 | struct qib_pportdata *ppd = | ||
249 | container_of(kobj, struct qib_pportdata, pport_cc_kobj); | ||
250 | |||
251 | if (!qib_cc_table_size || !ppd->ccti_entries_shadow) | ||
252 | return -EINVAL; | ||
253 | |||
254 | ret = ppd->total_cct_entry * sizeof(struct ib_cc_table_entry_shadow) | ||
255 | + sizeof(__be16); | ||
256 | |||
257 | if (pos > ret) | ||
258 | return -EINVAL; | ||
259 | |||
260 | if (count > ret - pos) | ||
261 | count = ret - pos; | ||
262 | |||
263 | if (!count) | ||
264 | return count; | ||
265 | |||
266 | spin_lock(&ppd->cc_shadow_lock); | ||
267 | memcpy(buf, ppd->ccti_entries_shadow, count); | ||
268 | spin_unlock(&ppd->cc_shadow_lock); | ||
269 | |||
270 | return count; | ||
271 | } | ||
272 | |||
273 | static void qib_port_release(struct kobject *kobj) | ||
274 | { | ||
275 | /* nothing to do since memory is freed by qib_free_devdata() */ | ||
276 | } | ||
277 | |||
278 | static struct kobj_type qib_port_cc_ktype = { | ||
279 | .release = qib_port_release, | ||
280 | }; | ||
281 | |||
282 | static struct bin_attribute cc_table_bin_attr = { | ||
283 | .attr = {.name = "cc_table_bin", .mode = 0444}, | ||
284 | .read = read_cc_table_bin, | ||
285 | .size = PAGE_SIZE, | ||
286 | }; | ||
287 | |||
288 | /* | ||
289 | * Congestion settings: port control, control map and an array of 16 | ||
290 | * entries for the congestion entries - increase, timer, event log | ||
291 | * trigger threshold and the minimum injection rate delay. | ||
292 | */ | ||
293 | static ssize_t read_cc_setting_bin(struct file *filp, struct kobject *kobj, | ||
294 | struct bin_attribute *bin_attr, | ||
295 | char *buf, loff_t pos, size_t count) | ||
296 | { | ||
297 | int ret; | ||
298 | struct qib_pportdata *ppd = | ||
299 | container_of(kobj, struct qib_pportdata, pport_cc_kobj); | ||
300 | |||
301 | if (!qib_cc_table_size || !ppd->congestion_entries_shadow) | ||
302 | return -EINVAL; | ||
303 | |||
304 | ret = sizeof(struct ib_cc_congestion_setting_attr_shadow); | ||
305 | |||
306 | if (pos > ret) | ||
307 | return -EINVAL; | ||
308 | if (count > ret - pos) | ||
309 | count = ret - pos; | ||
310 | |||
311 | if (!count) | ||
312 | return count; | ||
313 | |||
314 | spin_lock(&ppd->cc_shadow_lock); | ||
315 | memcpy(buf, ppd->congestion_entries_shadow, count); | ||
316 | spin_unlock(&ppd->cc_shadow_lock); | ||
317 | |||
318 | return count; | ||
319 | } | ||
320 | |||
321 | static struct bin_attribute cc_setting_bin_attr = { | ||
322 | .attr = {.name = "cc_settings_bin", .mode = 0444}, | ||
323 | .read = read_cc_setting_bin, | ||
324 | .size = PAGE_SIZE, | ||
325 | }; | ||
326 | |||
327 | |||
234 | static ssize_t qib_portattr_show(struct kobject *kobj, | 328 | static ssize_t qib_portattr_show(struct kobject *kobj, |
235 | struct attribute *attr, char *buf) | 329 | struct attribute *attr, char *buf) |
236 | { | 330 | { |
@@ -253,10 +347,6 @@ static ssize_t qib_portattr_store(struct kobject *kobj, | |||
253 | return pattr->store(ppd, buf, len); | 347 | return pattr->store(ppd, buf, len); |
254 | } | 348 | } |
255 | 349 | ||
256 | static void qib_port_release(struct kobject *kobj) | ||
257 | { | ||
258 | /* nothing to do since memory is freed by qib_free_devdata() */ | ||
259 | } | ||
260 | 350 | ||
261 | static const struct sysfs_ops qib_port_ops = { | 351 | static const struct sysfs_ops qib_port_ops = { |
262 | .show = qib_portattr_show, | 352 | .show = qib_portattr_show, |
@@ -670,7 +760,7 @@ int qib_create_port_files(struct ib_device *ibdev, u8 port_num, | |||
670 | if (ret) { | 760 | if (ret) { |
671 | qib_dev_err(dd, "Skipping sl2vl sysfs info, " | 761 | qib_dev_err(dd, "Skipping sl2vl sysfs info, " |
672 | "(err %d) port %u\n", ret, port_num); | 762 | "(err %d) port %u\n", ret, port_num); |
673 | goto bail_sl; | 763 | goto bail_link; |
674 | } | 764 | } |
675 | kobject_uevent(&ppd->sl2vl_kobj, KOBJ_ADD); | 765 | kobject_uevent(&ppd->sl2vl_kobj, KOBJ_ADD); |
676 | 766 | ||
@@ -679,15 +769,57 @@ int qib_create_port_files(struct ib_device *ibdev, u8 port_num, | |||
679 | if (ret) { | 769 | if (ret) { |
680 | qib_dev_err(dd, "Skipping diag_counters sysfs info, " | 770 | qib_dev_err(dd, "Skipping diag_counters sysfs info, " |
681 | "(err %d) port %u\n", ret, port_num); | 771 | "(err %d) port %u\n", ret, port_num); |
682 | goto bail_diagc; | 772 | goto bail_sl; |
683 | } | 773 | } |
684 | kobject_uevent(&ppd->diagc_kobj, KOBJ_ADD); | 774 | kobject_uevent(&ppd->diagc_kobj, KOBJ_ADD); |
685 | 775 | ||
776 | if (!qib_cc_table_size || !ppd->congestion_entries_shadow) | ||
777 | return 0; | ||
778 | |||
779 | ret = kobject_init_and_add(&ppd->pport_cc_kobj, &qib_port_cc_ktype, | ||
780 | kobj, "CCMgtA"); | ||
781 | if (ret) { | ||
782 | qib_dev_err(dd, | ||
783 | "Skipping Congestion Control sysfs info, (err %d) port %u\n", | ||
784 | ret, port_num); | ||
785 | goto bail_diagc; | ||
786 | } | ||
787 | |||
788 | kobject_uevent(&ppd->pport_cc_kobj, KOBJ_ADD); | ||
789 | |||
790 | ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, | ||
791 | &cc_setting_bin_attr); | ||
792 | if (ret) { | ||
793 | qib_dev_err(dd, | ||
794 | "Skipping Congestion Control setting sysfs info, (err %d) port %u\n", | ||
795 | ret, port_num); | ||
796 | goto bail_cc; | ||
797 | } | ||
798 | |||
799 | ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, | ||
800 | &cc_table_bin_attr); | ||
801 | if (ret) { | ||
802 | qib_dev_err(dd, | ||
803 | "Skipping Congestion Control table sysfs info, (err %d) port %u\n", | ||
804 | ret, port_num); | ||
805 | goto bail_cc_entry_bin; | ||
806 | } | ||
807 | |||
808 | qib_devinfo(dd->pcidev, | ||
809 | "IB%u: Congestion Control Agent enabled for port %d\n", | ||
810 | dd->unit, port_num); | ||
811 | |||
686 | return 0; | 812 | return 0; |
687 | 813 | ||
814 | bail_cc_entry_bin: | ||
815 | sysfs_remove_bin_file(&ppd->pport_cc_kobj, &cc_setting_bin_attr); | ||
816 | bail_cc: | ||
817 | kobject_put(&ppd->pport_cc_kobj); | ||
688 | bail_diagc: | 818 | bail_diagc: |
689 | kobject_put(&ppd->sl2vl_kobj); | 819 | kobject_put(&ppd->diagc_kobj); |
690 | bail_sl: | 820 | bail_sl: |
821 | kobject_put(&ppd->sl2vl_kobj); | ||
822 | bail_link: | ||
691 | kobject_put(&ppd->pport_kobj); | 823 | kobject_put(&ppd->pport_kobj); |
692 | bail: | 824 | bail: |
693 | return ret; | 825 | return ret; |
@@ -720,7 +852,15 @@ void qib_verbs_unregister_sysfs(struct qib_devdata *dd) | |||
720 | 852 | ||
721 | for (i = 0; i < dd->num_pports; i++) { | 853 | for (i = 0; i < dd->num_pports; i++) { |
722 | ppd = &dd->pport[i]; | 854 | ppd = &dd->pport[i]; |
723 | kobject_put(&ppd->pport_kobj); | 855 | if (qib_cc_table_size && |
856 | ppd->congestion_entries_shadow) { | ||
857 | sysfs_remove_bin_file(&ppd->pport_cc_kobj, | ||
858 | &cc_setting_bin_attr); | ||
859 | sysfs_remove_bin_file(&ppd->pport_cc_kobj, | ||
860 | &cc_table_bin_attr); | ||
861 | kobject_put(&ppd->pport_cc_kobj); | ||
862 | } | ||
724 | kobject_put(&ppd->sl2vl_kobj); | 863 | kobject_put(&ppd->sl2vl_kobj); |
864 | kobject_put(&ppd->pport_kobj); | ||
725 | } | 865 | } |
726 | } | 866 | } |