aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@suse.de>2011-03-18 11:24:23 -0400
committerJames Bottomley <James.Bottomley@suse.de>2011-03-23 12:37:09 -0400
commit8c3adc796f32fa4878ec843f8960717ba377e024 (patch)
tree993df6f496462a43839d8feadef3c1ae3ec4b855 /drivers
parentd9f7f37b90e7b0180961cb6567ae423ac3757db8 (diff)
[SCSI] ses: add subenclosure support
There have been many complaints that an enclosure with subenclosures isn't attached to by the ses driver. Until now, though, no-one had been willing to provide access to one. Subenclosures are added simply by flattening the tree (i.e. all subenclosure devices show up under the one main device). This may have consequences if the naming is only unique per subenclosure, but that's a bug for another day. The tested array had no page 7, so no device naming at all. It also only had the disk devices on one of its subenclosures (all the others had power, fans, temperature and various sensors), so testing of this is fairly rudimentary. Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/ses.c44
1 files changed, 25 insertions, 19 deletions
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index 3b00e907b917..eb7a3e85304f 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -35,9 +35,11 @@
35 35
36struct ses_device { 36struct ses_device {
37 unsigned char *page1; 37 unsigned char *page1;
38 unsigned char *page1_types;
38 unsigned char *page2; 39 unsigned char *page2;
39 unsigned char *page10; 40 unsigned char *page10;
40 short page1_len; 41 short page1_len;
42 short page1_num_types;
41 short page2_len; 43 short page2_len;
42 short page10_len; 44 short page10_len;
43}; 45};
@@ -110,12 +112,12 @@ static int ses_set_page2_descriptor(struct enclosure_device *edev,
110 int i, j, count = 0, descriptor = ecomp->number; 112 int i, j, count = 0, descriptor = ecomp->number;
111 struct scsi_device *sdev = to_scsi_device(edev->edev.parent); 113 struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
112 struct ses_device *ses_dev = edev->scratch; 114 struct ses_device *ses_dev = edev->scratch;
113 unsigned char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11]; 115 unsigned char *type_ptr = ses_dev->page1_types;
114 unsigned char *desc_ptr = ses_dev->page2 + 8; 116 unsigned char *desc_ptr = ses_dev->page2 + 8;
115 117
116 /* Clear everything */ 118 /* Clear everything */
117 memset(desc_ptr, 0, ses_dev->page2_len - 8); 119 memset(desc_ptr, 0, ses_dev->page2_len - 8);
118 for (i = 0; i < ses_dev->page1[10]; i++, type_ptr += 4) { 120 for (i = 0; i < ses_dev->page1_num_types; i++, type_ptr += 4) {
119 for (j = 0; j < type_ptr[1]; j++) { 121 for (j = 0; j < type_ptr[1]; j++) {
120 desc_ptr += 4; 122 desc_ptr += 4;
121 if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE && 123 if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE &&
@@ -140,12 +142,12 @@ static unsigned char *ses_get_page2_descriptor(struct enclosure_device *edev,
140 int i, j, count = 0, descriptor = ecomp->number; 142 int i, j, count = 0, descriptor = ecomp->number;
141 struct scsi_device *sdev = to_scsi_device(edev->edev.parent); 143 struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
142 struct ses_device *ses_dev = edev->scratch; 144 struct ses_device *ses_dev = edev->scratch;
143 unsigned char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11]; 145 unsigned char *type_ptr = ses_dev->page1_types;
144 unsigned char *desc_ptr = ses_dev->page2 + 8; 146 unsigned char *desc_ptr = ses_dev->page2 + 8;
145 147
146 ses_recv_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len); 148 ses_recv_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len);
147 149
148 for (i = 0; i < ses_dev->page1[10]; i++, type_ptr += 4) { 150 for (i = 0; i < ses_dev->page1_num_types; i++, type_ptr += 4) {
149 for (j = 0; j < type_ptr[1]; j++) { 151 for (j = 0; j < type_ptr[1]; j++) {
150 desc_ptr += 4; 152 desc_ptr += 4;
151 if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE && 153 if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE &&
@@ -358,7 +360,7 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
358 unsigned char *buf = NULL, *type_ptr, *desc_ptr, *addl_desc_ptr = NULL; 360 unsigned char *buf = NULL, *type_ptr, *desc_ptr, *addl_desc_ptr = NULL;
359 int i, j, page7_len, len, components; 361 int i, j, page7_len, len, components;
360 struct ses_device *ses_dev = edev->scratch; 362 struct ses_device *ses_dev = edev->scratch;
361 int types = ses_dev->page1[10]; 363 int types = ses_dev->page1_num_types;
362 unsigned char *hdr_buf = kzalloc(INIT_ALLOC_SIZE, GFP_KERNEL); 364 unsigned char *hdr_buf = kzalloc(INIT_ALLOC_SIZE, GFP_KERNEL);
363 365
364 if (!hdr_buf) 366 if (!hdr_buf)
@@ -393,7 +395,7 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
393 } 395 }
394 if (ses_dev->page10) 396 if (ses_dev->page10)
395 addl_desc_ptr = ses_dev->page10 + 8; 397 addl_desc_ptr = ses_dev->page10 + 8;
396 type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11]; 398 type_ptr = ses_dev->page1_types;
397 components = 0; 399 components = 0;
398 for (i = 0; i < types; i++, type_ptr += 4) { 400 for (i = 0; i < types; i++, type_ptr += 4) {
399 for (j = 0; j < type_ptr[1]; j++) { 401 for (j = 0; j < type_ptr[1]; j++) {
@@ -503,6 +505,7 @@ static int ses_intf_add(struct device *cdev,
503 u32 result; 505 u32 result;
504 int i, types, len, components = 0; 506 int i, types, len, components = 0;
505 int err = -ENOMEM; 507 int err = -ENOMEM;
508 int num_enclosures;
506 struct enclosure_device *edev; 509 struct enclosure_device *edev;
507 struct ses_component *scomp = NULL; 510 struct ses_component *scomp = NULL;
508 511
@@ -530,16 +533,6 @@ static int ses_intf_add(struct device *cdev,
530 if (result) 533 if (result)
531 goto recv_failed; 534 goto recv_failed;
532 535
533 if (hdr_buf[1] != 0) {
534 /* FIXME: need subenclosure support; I've just never
535 * seen a device with subenclosures and it makes the
536 * traversal routines more complex */
537 sdev_printk(KERN_ERR, sdev,
538 "FIXME driver has no support for subenclosures (%d)\n",
539 hdr_buf[1]);
540 goto err_free;
541 }
542
543 len = (hdr_buf[2] << 8) + hdr_buf[3] + 4; 536 len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
544 buf = kzalloc(len, GFP_KERNEL); 537 buf = kzalloc(len, GFP_KERNEL);
545 if (!buf) 538 if (!buf)
@@ -549,11 +542,24 @@ static int ses_intf_add(struct device *cdev,
549 if (result) 542 if (result)
550 goto recv_failed; 543 goto recv_failed;
551 544
552 types = buf[10]; 545 types = 0;
553 546
554 type_ptr = buf + 12 + buf[11]; 547 /* we always have one main enclosure and the rest are referred
548 * to as secondary subenclosures */
549 num_enclosures = buf[1] + 1;
555 550
556 for (i = 0; i < types; i++, type_ptr += 4) { 551 /* begin at the enclosure descriptor */
552 type_ptr = buf + 8;
553 /* skip all the enclosure descriptors */
554 for (i = 0; i < num_enclosures && type_ptr < buf + len; i++) {
555 types += type_ptr[2];
556 type_ptr += type_ptr[3] + 4;
557 }
558
559 ses_dev->page1_types = type_ptr;
560 ses_dev->page1_num_types = types;
561
562 for (i = 0; i < types && type_ptr < buf + len; i++, type_ptr += 4) {
557 if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE || 563 if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
558 type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) 564 type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE)
559 components += type_ptr[1]; 565 components += type_ptr[1];