aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
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];