diff options
Diffstat (limited to 'drivers/scsi/ses.c')
-rw-r--r-- | drivers/scsi/ses.c | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index 8927f9f54ad9..11826c5c2dd4 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -51,6 +51,13 @@ struct ses_component { u64 addr; }; +static bool ses_page2_supported(struct enclosure_device *edev) +{ + struct ses_device *ses_dev = edev->scratch; + + return (ses_dev->page2 != NULL); +} + static int ses_probe(struct device *dev) { struct scsi_device *sdev = to_scsi_device(dev); @@ -179,7 +186,8 @@ static unsigned char *ses_get_page2_descriptor(struct enclosure_device *edev, unsigned char *type_ptr = ses_dev->page1_types; unsigned char *desc_ptr = ses_dev->page2 + 8; - ses_recv_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len); + if (ses_recv_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len) < 0) + return NULL; for (i = 0; i < ses_dev->page1_num_types; i++, type_ptr += 4) { for (j = 0; j < type_ptr[1]; j++) { @@ -203,6 +211,10 @@ static void ses_get_fault(struct enclosure_device *edev, { unsigned char *desc; + if (!ses_page2_supported(edev)) { + ecomp->fault = 0; + return; + } desc = ses_get_page2_descriptor(edev, ecomp); if (desc) ecomp->fault = (desc[3] & 0x60) >> 4; @@ -215,6 +227,9 @@ static int ses_set_fault(struct enclosure_device *edev, unsigned char desc[4]; unsigned char *desc_ptr; + if (!ses_page2_supported(edev)) + return -EINVAL; + desc_ptr = ses_get_page2_descriptor(edev, ecomp); if (!desc_ptr) @@ -242,6 +257,10 @@ static void ses_get_status(struct enclosure_device *edev, { unsigned char *desc; + if (!ses_page2_supported(edev)) { + ecomp->status = 0; + return; + } desc = ses_get_page2_descriptor(edev, ecomp); if (desc) ecomp->status = (desc[0] & 0x0f); @@ -252,6 +271,10 @@ static void ses_get_locate(struct enclosure_device *edev, { unsigned char *desc; + if (!ses_page2_supported(edev)) { + ecomp->locate = 0; + return; + } desc = ses_get_page2_descriptor(edev, ecomp); if (desc) ecomp->locate = (desc[2] & 0x02) ? 1 : 0; @@ -264,6 +287,9 @@ static int ses_set_locate(struct enclosure_device *edev, unsigned char desc[4]; unsigned char *desc_ptr; + if (!ses_page2_supported(edev)) + return -EINVAL; + desc_ptr = ses_get_page2_descriptor(edev, ecomp); if (!desc_ptr) @@ -292,6 +318,9 @@ static int ses_set_active(struct enclosure_device *edev, unsigned char desc[4]; unsigned char *desc_ptr; + if (!ses_page2_supported(edev)) + return -EINVAL; + desc_ptr = ses_get_page2_descriptor(edev, ecomp); if (!desc_ptr) @@ -328,6 +357,11 @@ static void ses_get_power_status(struct enclosure_device *edev, { unsigned char *desc; + if (!ses_page2_supported(edev)) { + ecomp->power_status = 0; + return; + } + desc = ses_get_page2_descriptor(edev, ecomp); if (desc) ecomp->power_status = (desc[3] & 0x10) ? 0 : 1; @@ -340,6 +374,9 @@ static int ses_set_power_status(struct enclosure_device *edev, unsigned char desc[4]; unsigned char *desc_ptr; + if (!ses_page2_supported(edev)) + return -EINVAL; + desc_ptr = ses_get_page2_descriptor(edev, ecomp); if (!desc_ptr) @@ -601,7 +638,7 @@ static int ses_intf_add(struct device *cdev, { struct scsi_device *sdev = to_scsi_device(cdev->parent); struct scsi_device *tmp_sdev; - unsigned char *buf = NULL, *hdr_buf, *type_ptr; + unsigned char *buf = NULL, *hdr_buf, *type_ptr, page; struct ses_device *ses_dev; u32 result; int i, types, len, components = 0; @@ -630,7 +667,8 @@ static int ses_intf_add(struct device *cdev, if (!hdr_buf || !ses_dev) goto err_init_free; - result = ses_recv_diag(sdev, 1, hdr_buf, INIT_ALLOC_SIZE); + page = 1; + result = ses_recv_diag(sdev, page, hdr_buf, INIT_ALLOC_SIZE); if (result) goto recv_failed; @@ -639,7 +677,7 @@ static int ses_intf_add(struct device *cdev, if (!buf) goto err_free; - result = ses_recv_diag(sdev, 1, buf, len); + result = ses_recv_diag(sdev, page, buf, len); if (result) goto recv_failed; @@ -669,9 +707,10 @@ static int ses_intf_add(struct device *cdev, ses_dev->page1_len = len; buf = NULL; - result = ses_recv_diag(sdev, 2, hdr_buf, INIT_ALLOC_SIZE); + page = 2; + result = ses_recv_diag(sdev, page, hdr_buf, INIT_ALLOC_SIZE); if (result) - goto recv_failed; + goto page2_not_supported; len = (hdr_buf[2] << 8) + hdr_buf[3] + 4; buf = kzalloc(len, GFP_KERNEL); @@ -688,7 +727,8 @@ static int ses_intf_add(struct device *cdev, /* The additional information page --- allows us * to match up the devices */ - result = ses_recv_diag(sdev, 10, hdr_buf, INIT_ALLOC_SIZE); + page = 10; + result = ses_recv_diag(sdev, page, hdr_buf, INIT_ALLOC_SIZE); if (!result) { len = (hdr_buf[2] << 8) + hdr_buf[3] + 4; @@ -696,13 +736,14 @@ static int ses_intf_add(struct device *cdev, if (!buf) goto err_free; - result = ses_recv_diag(sdev, 10, buf, len); + result = ses_recv_diag(sdev, page, buf, len); if (result) goto recv_failed; ses_dev->page10 = buf; ses_dev->page10_len = len; buf = NULL; } +page2_not_supported: scomp = kzalloc(sizeof(struct ses_component) * components, GFP_KERNEL); if (!scomp) goto err_free; @@ -734,7 +775,7 @@ static int ses_intf_add(struct device *cdev, recv_failed: sdev_printk(KERN_ERR, sdev, "Failed to get diagnostic page 0x%x\n", - result); + page); err = -ENODEV; err_free: kfree(buf); @@ -777,8 +818,6 @@ static void ses_intf_remove_enclosure(struct scsi_device *sdev) if (!edev) return; - enclosure_unregister(edev); - ses_dev = edev->scratch; edev->scratch = NULL; @@ -790,6 +829,7 @@ static void ses_intf_remove_enclosure(struct scsi_device *sdev) kfree(edev->component[0].scratch); put_device(&edev->edev); + enclosure_unregister(edev); } static void ses_intf_remove(struct device *cdev, |