1 // SPDX-License-Identifier: GPL-2.0 2 3 /* Copyright (C) 2021-2024 Linaro Ltd. */ 4 5 #include <linux/device.h> 6 #include <linux/sysfs.h> 7 #include <linux/types.h> 8 9 #include "ipa.h" 10 #include "ipa_sysfs.h" 11 #include "ipa_version.h" 12 13 static const char *ipa_version_string(struct ipa *ipa) 14 { 15 switch (ipa->version) { 16 case IPA_VERSION_3_0: 17 return "3.0"; 18 case IPA_VERSION_3_1: 19 return "3.1"; 20 case IPA_VERSION_3_5: 21 return "3.5"; 22 case IPA_VERSION_3_5_1: 23 return "3.5.1"; 24 case IPA_VERSION_4_0: 25 return "4.0"; 26 case IPA_VERSION_4_1: 27 return "4.1"; 28 case IPA_VERSION_4_2: 29 return "4.2"; 30 case IPA_VERSION_4_5: 31 return "4.5"; 32 case IPA_VERSION_4_7: 33 return "4.7"; 34 case IPA_VERSION_4_9: 35 return "4.9"; 36 case IPA_VERSION_4_11: 37 return "4.11"; 38 case IPA_VERSION_5_0: 39 return "5.0"; 40 case IPA_VERSION_5_1: 41 return "5.1"; 42 case IPA_VERSION_5_2: 43 return "5.2"; 44 case IPA_VERSION_5_5: 45 return "5.5"; 46 default: 47 return "0.0"; /* Should not happen */ 48 } 49 } 50 51 static ssize_t 52 version_show(struct device *dev, struct device_attribute *attr, char *buf) 53 { 54 struct ipa *ipa = dev_get_drvdata(dev); 55 56 return sysfs_emit(buf, "%s\n", ipa_version_string(ipa)); 57 } 58 59 static DEVICE_ATTR_RO(version); 60 61 static struct attribute *ipa_attrs[] = { 62 &dev_attr_version.attr, 63 NULL 64 }; 65 66 const struct attribute_group ipa_attribute_group = { 67 .attrs = ipa_attrs, 68 }; 69 70 static const char *ipa_offload_string(struct ipa *ipa) 71 { 72 return ipa->version < IPA_VERSION_4_5 ? "MAPv4" : "MAPv5"; 73 } 74 75 static ssize_t rx_offload_show(struct device *dev, 76 struct device_attribute *attr, char *buf) 77 { 78 struct ipa *ipa = dev_get_drvdata(dev); 79 80 return sysfs_emit(buf, "%s\n", ipa_offload_string(ipa)); 81 } 82 83 static DEVICE_ATTR_RO(rx_offload); 84 85 static ssize_t tx_offload_show(struct device *dev, 86 struct device_attribute *attr, char *buf) 87 { 88 struct ipa *ipa = dev_get_drvdata(dev); 89 90 return sysfs_emit(buf, "%s\n", ipa_offload_string(ipa)); 91 } 92 93 static DEVICE_ATTR_RO(tx_offload); 94 95 static struct attribute *ipa_feature_attrs[] = { 96 &dev_attr_rx_offload.attr, 97 &dev_attr_tx_offload.attr, 98 NULL 99 }; 100 101 const struct attribute_group ipa_feature_attribute_group = { 102 .name = "feature", 103 .attrs = ipa_feature_attrs, 104 }; 105 106 static umode_t ipa_endpoint_id_is_visible(struct kobject *kobj, 107 struct attribute *attr, int n) 108 { 109 struct ipa *ipa = dev_get_drvdata(kobj_to_dev(kobj)); 110 struct device_attribute *dev_attr; 111 struct dev_ext_attribute *ea; 112 bool visible; 113 114 /* An endpoint id attribute is only visible if it's defined */ 115 dev_attr = container_of(attr, struct device_attribute, attr); 116 ea = container_of(dev_attr, struct dev_ext_attribute, attr); 117 118 visible = !!ipa->name_map[(enum ipa_endpoint_name)(uintptr_t)ea->var]; 119 120 return visible ? attr->mode : 0; 121 } 122 123 static ssize_t endpoint_id_attr_show(struct device *dev, 124 struct device_attribute *attr, char *buf) 125 { 126 struct ipa *ipa = dev_get_drvdata(dev); 127 struct ipa_endpoint *endpoint; 128 struct dev_ext_attribute *ea; 129 130 ea = container_of(attr, struct dev_ext_attribute, attr); 131 endpoint = ipa->name_map[(enum ipa_endpoint_name)(uintptr_t)ea->var]; 132 133 return sysfs_emit(buf, "%u\n", endpoint->endpoint_id); 134 } 135 136 #define ENDPOINT_ID_ATTR(_n, _endpoint_name) \ 137 static struct dev_ext_attribute dev_attr_endpoint_id_ ## _n = { \ 138 .attr = __ATTR(_n, 0444, endpoint_id_attr_show, NULL), \ 139 .var = (void *)(_endpoint_name), \ 140 } 141 142 ENDPOINT_ID_ATTR(modem_rx, IPA_ENDPOINT_AP_MODEM_RX); 143 ENDPOINT_ID_ATTR(modem_tx, IPA_ENDPOINT_AP_MODEM_TX); 144 145 static struct attribute *ipa_endpoint_id_attrs[] = { 146 &dev_attr_endpoint_id_modem_rx.attr.attr, 147 &dev_attr_endpoint_id_modem_tx.attr.attr, 148 NULL 149 }; 150 151 const struct attribute_group ipa_endpoint_id_attribute_group = { 152 .name = "endpoint_id", 153 .is_visible = ipa_endpoint_id_is_visible, 154 .attrs = ipa_endpoint_id_attrs, 155 }; 156 157 /* Reuse endpoint ID attributes for the legacy modem endpoint IDs */ 158 #define MODEM_ATTR(_n, _endpoint_name) \ 159 static struct dev_ext_attribute dev_attr_modem_ ## _n = { \ 160 .attr = __ATTR(_n, 0444, endpoint_id_attr_show, NULL), \ 161 .var = (void *)(_endpoint_name), \ 162 } 163 164 MODEM_ATTR(rx_endpoint_id, IPA_ENDPOINT_AP_MODEM_RX); 165 MODEM_ATTR(tx_endpoint_id, IPA_ENDPOINT_AP_MODEM_TX); 166 167 static struct attribute *ipa_modem_attrs[] = { 168 &dev_attr_modem_rx_endpoint_id.attr.attr, 169 &dev_attr_modem_tx_endpoint_id.attr.attr, 170 NULL, 171 }; 172 173 const struct attribute_group ipa_modem_attribute_group = { 174 .name = "modem", 175 .attrs = ipa_modem_attrs, 176 }; 177