Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 161038
b: refs/heads/master
c: 21fab1d
h: refs/heads/master
v: v3
  • Loading branch information
James Bottomley authored and James Bottomley committed Aug 22, 2009
1 parent cb2cd19 commit 94158b8
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 72 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 43d8eb9cfd0aea93be32181c64e18191b69c211c
refs/heads/master: 21fab1d0595eacf781705ec3509012a28f298245
3 changes: 3 additions & 0 deletions trunk/drivers/misc/enclosure.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,9 @@ int enclosure_add_device(struct enclosure_device *edev, int component,

cdev = &edev->component[component];

if (cdev->dev == dev)
return -EEXIST;

if (cdev->dev)
enclosure_remove_links(cdev);

Expand Down
168 changes: 97 additions & 71 deletions trunk/drivers/scsi/ses.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,97 @@ static int ses_enclosure_find_by_addr(struct enclosure_device *edev,
return 0;
}

#define INIT_ALLOC_SIZE 32

static void ses_enclosure_data_process(struct enclosure_device *edev,
struct scsi_device *sdev,
int create)
{
u32 result;
unsigned char *buf = NULL, *type_ptr, *desc_ptr, *addl_desc_ptr = NULL;
int i, j, page7_len, len, components;
struct ses_device *ses_dev = edev->scratch;
int types = ses_dev->page1[10];
unsigned char *hdr_buf = kzalloc(INIT_ALLOC_SIZE, GFP_KERNEL);

if (!hdr_buf)
goto simple_populate;

/* re-read page 10 */
if (ses_dev->page10)
ses_recv_diag(sdev, 10, ses_dev->page10, ses_dev->page10_len);
/* Page 7 for the descriptors is optional */
result = ses_recv_diag(sdev, 7, hdr_buf, INIT_ALLOC_SIZE);
if (result)
goto simple_populate;

page7_len = len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
/* add 1 for trailing '\0' we'll use */
buf = kzalloc(len + 1, GFP_KERNEL);
if (!buf)
goto simple_populate;
result = ses_recv_diag(sdev, 7, buf, len);
if (result) {
simple_populate:
kfree(buf);
buf = NULL;
desc_ptr = NULL;
len = 0;
page7_len = 0;
} else {
desc_ptr = buf + 8;
len = (desc_ptr[2] << 8) + desc_ptr[3];
/* skip past overall descriptor */
desc_ptr += len + 4;
if (ses_dev->page10)
addl_desc_ptr = ses_dev->page10 + 8;
}
type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
components = 0;
for (i = 0; i < types; i++, type_ptr += 4) {
for (j = 0; j < type_ptr[1]; j++) {
char *name = NULL;
struct enclosure_component *ecomp;

if (desc_ptr) {
if (desc_ptr >= buf + page7_len) {
desc_ptr = NULL;
} else {
len = (desc_ptr[2] << 8) + desc_ptr[3];
desc_ptr += 4;
/* Add trailing zero - pushes into
* reserved space */
desc_ptr[len] = '\0';
name = desc_ptr;
}
}
if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) {

if (create)
ecomp = enclosure_component_register(edev,
components++,
type_ptr[0],
name);
else
ecomp = &edev->component[components++];

if (!IS_ERR(ecomp) && addl_desc_ptr)
ses_process_descriptor(ecomp,
addl_desc_ptr);
}
if (desc_ptr)
desc_ptr += len;

if (addl_desc_ptr)
addl_desc_ptr += addl_desc_ptr[1] + 2;

}
}
kfree(buf);
kfree(hdr_buf);
}

static void ses_match_to_enclosure(struct enclosure_device *edev,
struct scsi_device *sdev)
{
Expand All @@ -361,6 +452,8 @@ static void ses_match_to_enclosure(struct enclosure_device *edev,
if (!buf)
return;

ses_enclosure_data_process(edev, to_scsi_device(edev->edev.parent), 0);

vpd_len = ((buf[2] << 8) | buf[3]) + 4;

desc = buf + 4;
Expand Down Expand Up @@ -395,18 +488,15 @@ static void ses_match_to_enclosure(struct enclosure_device *edev,
kfree(buf);
}

#define INIT_ALLOC_SIZE 32

static int ses_intf_add(struct device *cdev,
struct class_interface *intf)
{
struct scsi_device *sdev = to_scsi_device(cdev->parent);
struct scsi_device *tmp_sdev;
unsigned char *buf = NULL, *hdr_buf, *type_ptr, *desc_ptr = NULL,
*addl_desc_ptr = NULL;
unsigned char *buf = NULL, *hdr_buf, *type_ptr;
struct ses_device *ses_dev;
u32 result;
int i, j, types, len, page7_len = 0, components = 0;
int i, types, len, components = 0;
int err = -ENOMEM;
struct enclosure_device *edev;
struct ses_component *scomp = NULL;
Expand Down Expand Up @@ -501,6 +591,7 @@ static int ses_intf_add(struct device *cdev,
ses_dev->page10_len = len;
buf = NULL;
}
kfree(hdr_buf);

scomp = kzalloc(sizeof(struct ses_component) * components, GFP_KERNEL);
if (!scomp)
Expand All @@ -517,72 +608,7 @@ static int ses_intf_add(struct device *cdev,
for (i = 0; i < components; i++)
edev->component[i].scratch = scomp + i;

/* Page 7 for the descriptors is optional */
result = ses_recv_diag(sdev, 7, hdr_buf, INIT_ALLOC_SIZE);
if (result)
goto simple_populate;

page7_len = len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
/* add 1 for trailing '\0' we'll use */
buf = kzalloc(len + 1, GFP_KERNEL);
if (!buf)
goto simple_populate;
result = ses_recv_diag(sdev, 7, buf, len);
if (result) {
simple_populate:
kfree(buf);
buf = NULL;
desc_ptr = NULL;
addl_desc_ptr = NULL;
} else {
desc_ptr = buf + 8;
len = (desc_ptr[2] << 8) + desc_ptr[3];
/* skip past overall descriptor */
desc_ptr += len + 4;
if (ses_dev->page10)
addl_desc_ptr = ses_dev->page10 + 8;
}
type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
components = 0;
for (i = 0; i < types; i++, type_ptr += 4) {
for (j = 0; j < type_ptr[1]; j++) {
char *name = NULL;
struct enclosure_component *ecomp;

if (desc_ptr) {
if (desc_ptr >= buf + page7_len) {
desc_ptr = NULL;
} else {
len = (desc_ptr[2] << 8) + desc_ptr[3];
desc_ptr += 4;
/* Add trailing zero - pushes into
* reserved space */
desc_ptr[len] = '\0';
name = desc_ptr;
}
}
if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE) {

ecomp = enclosure_component_register(edev,
components++,
type_ptr[0],
name);

if (!IS_ERR(ecomp) && addl_desc_ptr)
ses_process_descriptor(ecomp,
addl_desc_ptr);
}
if (desc_ptr)
desc_ptr += len;

if (addl_desc_ptr)
addl_desc_ptr += addl_desc_ptr[1] + 2;

}
}
kfree(buf);
kfree(hdr_buf);
ses_enclosure_data_process(edev, sdev, 1);

/* see if there are any devices matching before
* we found the enclosure */
Expand Down

0 comments on commit 94158b8

Please sign in to comment.