summaryrefslogtreecommitdiff
path: root/drivers/scsi/ses.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-09-07 21:11:05 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-07 21:11:05 -0700
commit572c01ba19ef150e98aea0b45ca17d43356521b5 (patch)
tree289381d051dfc34a86be988700ee11cb9ad0cd5b /drivers/scsi/ses.c
parentcef5d0f952a03d42051141742632078d488b0c6b (diff)
parent2441500a41a9b17ff657626eb81972f62bc8cc5a (diff)
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley: "This is mostly updates of the usual suspects: lpfc, qla2xxx, hisi_sas, megaraid_sas, zfcp and a host of minor updates. The major driver change here is the elimination of the block based cciss driver in favour of the SCSI based hpsa driver (which now drives all the legacy cases cciss used to be required for). Plus a reset handler clean up and the redo of the SAS SMP handler to use bsg lib" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (279 commits) scsi: scsi-mq: Always unprepare before requeuing a request scsi: Show .retries and .jiffies_at_alloc in debugfs scsi: Improve requeuing behavior scsi: Call scsi_initialize_rq() for filesystem requests scsi: qla2xxx: Reset the logo flag, after target re-login. scsi: qla2xxx: Fix slow mem alloc behind lock scsi: qla2xxx: Clear fc4f_nvme flag scsi: qla2xxx: add missing includes for qla_isr scsi: qla2xxx: Fix an integer overflow in sysfs code scsi: aacraid: report -ENOMEM to upper layer from aac_convert_sgraw2() scsi: aacraid: get rid of one level of indentation scsi: aacraid: fix indentation errors scsi: storvsc: fix memory leak on ring buffer busy scsi: scsi_transport_sas: switch to bsg-lib for SMP passthrough scsi: smartpqi: remove the smp_handler stub scsi: hpsa: remove the smp_handler stub scsi: bsg-lib: pass the release callback through bsg_setup_queue scsi: Rework handling of scsi_device.vpd_pg8[03] scsi: Rework the code for caching Vital Product Data (VPD) scsi: rcu: Introduce rcu_swap_protected() ...
Diffstat (limited to 'drivers/scsi/ses.c')
-rw-r--r--drivers/scsi/ses.c62
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,