diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/ses.c | 44 |
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 | ||
36 | struct ses_device { | 36 | struct 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]; |