diff options
Diffstat (limited to 'net/dsa/dsa.c')
-rw-r--r-- | net/dsa/dsa.c | 39 |
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 | ||
126 | const struct dsa_device_ops *dsa_tag_driver_get(int tag_protocol) | 126 | const 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 | ||
140 | void dsa_tag_driver_put(const struct dsa_device_ops *ops) | 159 | void 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 | ||
144 | static int dev_is_class(struct device *dev, void *class) | 173 | static int dev_is_class(struct device *dev, void *class) |