summaryrefslogtreecommitdiffstats
path: root/net/dsa/dsa.c
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2019-04-28 13:37:20 -0400
committerDavid S. Miller <davem@davemloft.net>2019-04-28 19:41:01 -0400
commit3675617531443a503f674e71e70248b9c5a205cd (patch)
treec58c401dc42ec49b59a5321a76509eba5831a2ca /net/dsa/dsa.c
parent4dad81ee14479c74973ee669612a367b3a675743 (diff)
dsa: Make use of the list of tag drivers
Implement the _get and _put functions to make use of the list of tag drivers. Also, trigger the loading of the module, based on the alias information. The _get function takes a reference on the tag driver, so it cannot be unloaded, and the _put function releases the reference. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> v2: Make tag_driver_register void Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa/dsa.c')
-rw-r--r--net/dsa/dsa.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 54e89c97ce11..67d21647c500 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -125,20 +125,49 @@ const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops)
125 125
126const struct dsa_device_ops *dsa_tag_driver_get(int tag_protocol) 126const struct dsa_device_ops *dsa_tag_driver_get(int tag_protocol)
127{ 127{
128 struct dsa_tag_driver *dsa_tag_driver;
128 const struct dsa_device_ops *ops; 129 const struct dsa_device_ops *ops;
130 char module_name[128];
131 bool found = false;
129 132
130 if (tag_protocol >= DSA_TAG_LAST) 133 snprintf(module_name, 127, "%s%d", DSA_TAG_DRIVER_ALIAS,
131 return ERR_PTR(-EINVAL); 134 tag_protocol);
132 ops = dsa_device_ops[tag_protocol];
133 135
134 if (!ops) 136 request_module(module_name);
135 return ERR_PTR(-ENOPROTOOPT); 137
138 mutex_lock(&dsa_tag_drivers_lock);
139 list_for_each_entry(dsa_tag_driver, &dsa_tag_drivers_list, list) {
140 ops = dsa_tag_driver->ops;
141 if (ops->proto == tag_protocol) {
142 found = true;
143 break;
144 }
145 }
146
147 if (found) {
148 if (!try_module_get(dsa_tag_driver->owner))
149 ops = ERR_PTR(-ENOPROTOOPT);
150 } else {
151 ops = ERR_PTR(-ENOPROTOOPT);
152 }
153
154 mutex_unlock(&dsa_tag_drivers_lock);
136 155
137 return ops; 156 return ops;
138} 157}
139 158
140void dsa_tag_driver_put(const struct dsa_device_ops *ops) 159void dsa_tag_driver_put(const struct dsa_device_ops *ops)
141{ 160{
161 struct dsa_tag_driver *dsa_tag_driver;
162
163 mutex_lock(&dsa_tag_drivers_lock);
164 list_for_each_entry(dsa_tag_driver, &dsa_tag_drivers_list, list) {
165 if (dsa_tag_driver->ops == ops) {
166 module_put(dsa_tag_driver->owner);
167 break;
168 }
169 }
170 mutex_unlock(&dsa_tag_drivers_lock);
142} 171}
143 172
144static int dev_is_class(struct device *dev, void *class) 173static int dev_is_class(struct device *dev, void *class)