diff options
author | Markus Stockhausen <stockhausen@collogia.de> | 2014-10-04 09:35:15 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-11-12 05:15:55 -0500 |
commit | d2fd76e6f60ce438e98512236138a3527ad6a736 (patch) | |
tree | 0e6f008a96adebdf5a32fee3d9699bc3a7943e17 | |
parent | 2bec708a88ce053ffcb0dd8e373d1e46c6dc38a4 (diff) |
enclosure: handle non-unique element descriptors
Some SES devices give non-unique Element Descriptors as part of the
Element Descriptor diag page. Since we use these for creating sysfs
entries, they need to be unique. The specification doesn't require
these to be unique.
Eg:
$ sg_ses -p 7 /dev/sg0
FTS CORP TXS6_SAS20BPX12 0500
enclosure services device
Element descriptor In diagnostic page:
generation code: 0x0
element descriptor by type list
Element type: Array device, subenclosure id: 0
Overall descriptor: ArrayDevicesInSubEnclsr0
Element 1 descriptor: ArrayDevice00
Element 2 descriptor: ArrayDevice01
Element 3 descriptor: ArrayDevice02
Element 4 descriptor: ArrayDevice03
Element 5 descriptor: ArrayDevice03
Element 6 descriptor: ArrayDevice03
Element 7 descriptor: ArrayDevice03
Element 8 descriptor: ArrayDevice03
Element 9 descriptor: ArrayDevice03
Element 10 descriptor: ArrayDevice03
Element 11 descriptor: ArrayDevice03
Element 12 descriptor: ArrayDevice03
Based on http://thread.gmane.org/gmane.linux.scsi/69289. This
version implements James' ideas about the naming convention
Signed-off-by: Markus Stockhausen <stockhausen@collogia.de>
Acked-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r-- | drivers/misc/enclosure.c | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c index 2cf2bbc0b927..180a5442fd4b 100644 --- a/drivers/misc/enclosure.c +++ b/drivers/misc/enclosure.c | |||
@@ -187,6 +187,7 @@ void enclosure_unregister(struct enclosure_device *edev) | |||
187 | EXPORT_SYMBOL_GPL(enclosure_unregister); | 187 | EXPORT_SYMBOL_GPL(enclosure_unregister); |
188 | 188 | ||
189 | #define ENCLOSURE_NAME_SIZE 64 | 189 | #define ENCLOSURE_NAME_SIZE 64 |
190 | #define COMPONENT_NAME_SIZE 64 | ||
190 | 191 | ||
191 | static void enclosure_link_name(struct enclosure_component *cdev, char *name) | 192 | static void enclosure_link_name(struct enclosure_component *cdev, char *name) |
192 | { | 193 | { |
@@ -246,6 +247,29 @@ static void enclosure_component_release(struct device *dev) | |||
246 | put_device(dev->parent); | 247 | put_device(dev->parent); |
247 | } | 248 | } |
248 | 249 | ||
250 | static struct enclosure_component * | ||
251 | enclosure_component_find_by_name(struct enclosure_device *edev, | ||
252 | const char *name) | ||
253 | { | ||
254 | int i; | ||
255 | const char *cname; | ||
256 | struct enclosure_component *ecomp; | ||
257 | |||
258 | if (!edev || !name || !name[0]) | ||
259 | return NULL; | ||
260 | |||
261 | for (i = 0; i < edev->components; i++) { | ||
262 | ecomp = &edev->component[i]; | ||
263 | cname = dev_name(&ecomp->cdev); | ||
264 | if (ecomp->number != -1 && | ||
265 | cname && cname[0] && | ||
266 | !strcmp(cname, name)) | ||
267 | return ecomp; | ||
268 | } | ||
269 | |||
270 | return NULL; | ||
271 | } | ||
272 | |||
249 | static const struct attribute_group *enclosure_component_groups[]; | 273 | static const struct attribute_group *enclosure_component_groups[]; |
250 | 274 | ||
251 | /** | 275 | /** |
@@ -269,7 +293,8 @@ enclosure_component_register(struct enclosure_device *edev, | |||
269 | { | 293 | { |
270 | struct enclosure_component *ecomp; | 294 | struct enclosure_component *ecomp; |
271 | struct device *cdev; | 295 | struct device *cdev; |
272 | int err; | 296 | int err, i; |
297 | char newname[COMPONENT_NAME_SIZE]; | ||
273 | 298 | ||
274 | if (number >= edev->components) | 299 | if (number >= edev->components) |
275 | return ERR_PTR(-EINVAL); | 300 | return ERR_PTR(-EINVAL); |
@@ -283,9 +308,20 @@ enclosure_component_register(struct enclosure_device *edev, | |||
283 | ecomp->number = number; | 308 | ecomp->number = number; |
284 | cdev = &ecomp->cdev; | 309 | cdev = &ecomp->cdev; |
285 | cdev->parent = get_device(&edev->edev); | 310 | cdev->parent = get_device(&edev->edev); |
286 | if (name && name[0]) | 311 | |
287 | dev_set_name(cdev, "%s", name); | 312 | if (name && name[0]) { |
288 | else | 313 | /* Some hardware (e.g. enclosure in RX300 S6) has components |
314 | * with non unique names. Registering duplicates in sysfs | ||
315 | * will lead to warnings during bootup. So make the names | ||
316 | * unique by appending consecutive numbers -1, -2, ... */ | ||
317 | i = 1; | ||
318 | snprintf(newname, COMPONENT_NAME_SIZE, | ||
319 | "%s", name); | ||
320 | while (enclosure_component_find_by_name(edev, newname)) | ||
321 | snprintf(newname, COMPONENT_NAME_SIZE, | ||
322 | "%s-%i", name, i++); | ||
323 | dev_set_name(cdev, "%s", newname); | ||
324 | } else | ||
289 | dev_set_name(cdev, "%u", number); | 325 | dev_set_name(cdev, "%u", number); |
290 | 326 | ||
291 | cdev->release = enclosure_component_release; | 327 | cdev->release = enclosure_component_release; |