mpt3sas, mpt2sas: fix scsi_add_host error handling problems in _scsih_probe
[deliverable/linux.git] / drivers / scsi / mpt3sas / mpt3sas_scsih.c
index 135f12c20ecf09ccab6106a2796117d8cfadafe7..857276b8880f4b94e8578bdc237cc9683d180c29 100644 (file)
@@ -2,7 +2,7 @@
  * Scsi Host Layer for MPT (Message Passing Technology) based controllers
  *
  * This code is based on drivers/scsi/mpt3sas/mpt3sas_scsih.c
- * Copyright (C) 2012-2013  LSI Corporation
+ * Copyright (C) 2012-2014  LSI Corporation
  *  (mailto:DL-MPTFusionLinux@lsi.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -159,7 +159,7 @@ struct sense_info {
 };
 
 #define MPT3SAS_PROCESS_TRIGGER_DIAG (0xFFFB)
-#define MPT3SAS_TURN_ON_FAULT_LED (0xFFFC)
+#define MPT3SAS_TURN_ON_PFA_LED (0xFFFC)
 #define MPT3SAS_PORT_ENABLE_COMPLETE (0xFFFD)
 #define MPT3SAS_ABRT_TASK_SET (0xFFFE)
 #define MPT3SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF)
@@ -3885,7 +3885,7 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
 #endif
 
 /**
- * _scsih_turn_on_fault_led - illuminate Fault LED
+ * _scsih_turn_on_pfa_led - illuminate PFA LED
  * @ioc: per adapter object
  * @handle: device handle
  * Context: process
@@ -3893,10 +3893,15 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
  * Return nothing.
  */
 static void
-_scsih_turn_on_fault_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+_scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 {
        Mpi2SepReply_t mpi_reply;
        Mpi2SepRequest_t mpi_request;
+       struct _sas_device *sas_device;
+
+       sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+       if (!sas_device)
+               return;
 
        memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
        mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
@@ -3911,6 +3916,7 @@ _scsih_turn_on_fault_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
                __FILE__, __LINE__, __func__);
                return;
        }
+       sas_device->pfa_led_on = 1;
 
        if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
                dewtprintk(ioc, pr_info(MPT3SAS_FMT
@@ -3920,9 +3926,46 @@ _scsih_turn_on_fault_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
                return;
        }
 }
+/**
+ * _scsih_turn_off_pfa_led - turn off Fault LED
+ * @ioc: per adapter object
+ * @sas_device: sas device whose PFA LED has to turned off
+ * Context: process
+ *
+ * Return nothing.
+ */
+static void
+_scsih_turn_off_pfa_led(struct MPT3SAS_ADAPTER *ioc,
+       struct _sas_device *sas_device)
+{
+       Mpi2SepReply_t mpi_reply;
+       Mpi2SepRequest_t mpi_request;
 
+       memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
+       mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
+       mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
+       mpi_request.SlotStatus = 0;
+       mpi_request.Slot = cpu_to_le16(sas_device->slot);
+       mpi_request.DevHandle = 0;
+       mpi_request.EnclosureHandle = cpu_to_le16(sas_device->enclosure_handle);
+       mpi_request.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
+       if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
+               &mpi_request)) != 0) {
+               printk(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
+               __FILE__, __LINE__, __func__);
+               return;
+       }
+
+       if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
+               dewtprintk(ioc, printk(MPT3SAS_FMT
+                "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
+                ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
+                le32_to_cpu(mpi_reply.IOCLogInfo)));
+               return;
+       }
+}
 /**
- * _scsih_send_event_to_turn_on_fault_led - fire delayed event
+ * _scsih_send_event_to_turn_on_pfa_led - fire delayed event
  * @ioc: per adapter object
  * @handle: device handle
  * Context: interrupt.
@@ -3930,14 +3973,14 @@ _scsih_turn_on_fault_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
  * Return nothing.
  */
 static void
-_scsih_send_event_to_turn_on_fault_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+_scsih_send_event_to_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
 {
        struct fw_event_work *fw_event;
 
        fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
        if (!fw_event)
                return;
-       fw_event->event = MPT3SAS_TURN_ON_FAULT_LED;
+       fw_event->event = MPT3SAS_TURN_ON_PFA_LED;
        fw_event->device_handle = handle;
        fw_event->ioc = ioc;
        _scsih_fw_event_add(ioc, fw_event);
@@ -3981,7 +4024,7 @@ _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
        if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
-               _scsih_send_event_to_turn_on_fault_led(ioc, handle);
+               _scsih_send_event_to_turn_on_pfa_led(ioc, handle);
 
        /* insert into event log */
        sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
@@ -4911,7 +4954,11 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
 {
        struct MPT3SAS_TARGET *sas_target_priv_data;
 
-
+       if ((ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) &&
+            (sas_device->pfa_led_on)) {
+               _scsih_turn_off_pfa_led(ioc, sas_device);
+               sas_device->pfa_led_on = 0;
+       }
        dewtprintk(ioc, pr_info(MPT3SAS_FMT
                "%s: enter: handle(0x%04x), sas_addr(0x%016llx)\n",
                ioc->name, __func__,
@@ -7065,8 +7112,8 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
                        "port enable: complete from worker thread\n",
                        ioc->name));
                break;
-       case MPT3SAS_TURN_ON_FAULT_LED:
-               _scsih_turn_on_fault_led(ioc, fw_event->device_handle);
+       case MPT3SAS_TURN_ON_PFA_LED:
+               _scsih_turn_on_pfa_led(ioc, fw_event->device_handle);
                break;
        case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
                _scsih_sas_topology_change_event(ioc, fw_event);
@@ -7734,6 +7781,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct MPT3SAS_ADAPTER *ioc;
        struct Scsi_Host *shost;
+       int rv;
 
        shost = scsi_host_alloc(&scsih_driver_template,
            sizeof(struct MPT3SAS_ADAPTER));
@@ -7826,6 +7874,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (!ioc->firmware_event_thread) {
                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
                    ioc->name, __FILE__, __LINE__, __func__);
+               rv = -ENODEV;
                goto out_thread_fail;
        }
 
@@ -7833,12 +7882,13 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if ((mpt3sas_base_attach(ioc))) {
                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
                    ioc->name, __FILE__, __LINE__, __func__);
+               rv = -ENODEV;
                goto out_attach_fail;
        }
-       if ((scsi_add_host(shost, &pdev->dev))) {
+       rv = scsi_add_host(shost, &pdev->dev);
+       if (rv) {
                pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
                    ioc->name, __FILE__, __LINE__, __func__);
-               list_del(&ioc->list);
                goto out_add_shost_fail;
        }
 
@@ -7851,7 +7901,7 @@ out_add_shost_fail:
  out_thread_fail:
        list_del(&ioc->list);
        scsi_host_put(shost);
-       return -ENODEV;
+       return rv;
 }
 
 #ifdef CONFIG_PM
This page took 0.030011 seconds and 5 git commands to generate.