summaryrefslogtreecommitdiff
path: root/drivers/scsi/libsas/sas_event.c
diff options
context:
space:
mode:
authorJohannes Thumshirn <jthumshirn@suse.de>2017-06-14 14:52:43 +0300
committerMartin K. Petersen <martin.petersen@oracle.com>2017-06-28 04:28:04 +0300
commit6d311fa7d2c18659d040b9beba5e41fe24c2a6f5 (patch)
treeb5bbaaeaa6bb080b2687787f05dd057f574d91bc /drivers/scsi/libsas/sas_event.c
parentd06c587dd723882cd99c89d335b89c535079cdb1 (diff)
downloadlinux-6d311fa7d2c18659d040b9beba5e41fe24c2a6f5.tar.xz
scsi: sas: scsi_queue_work can fail, so make callers aware
libsas uses scsi_queue_work() to queue its internal event notifications. scsi_queue_work() can return -EINVAL if the work queue doesn't exist and it does call queue_work() which can return false if the work is already queued. Make the SAS event code capable of returning errors up to the caller, which is handy when changing to dynamically allocated work in libsas as well, as discussed here: https://lkml.org/lkml/2017/6/14/121. [mkp: fixed typo] Signed-off-by: Johannes Thumshirn <jthumshirn@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/libsas/sas_event.c')
-rw-r--r--drivers/scsi/libsas/sas_event.c36
1 files changed, 22 insertions, 14 deletions
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index aadbd5314c5c..c0d0d979b76d 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -27,30 +27,38 @@
#include "sas_internal.h"
#include "sas_dump.h"
-void sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw)
+int sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw)
{
+ int rc = 0;
+
if (!test_bit(SAS_HA_REGISTERED, &ha->state))
- return;
+ return 0;
if (test_bit(SAS_HA_DRAINING, &ha->state)) {
/* add it to the defer list, if not already pending */
if (list_empty(&sw->drain_node))
list_add(&sw->drain_node, &ha->defer_q);
} else
- scsi_queue_work(ha->core.shost, &sw->work);
+ rc = scsi_queue_work(ha->core.shost, &sw->work);
+
+ return rc;
}
-static void sas_queue_event(int event, unsigned long *pending,
+static int sas_queue_event(int event, unsigned long *pending,
struct sas_work *work,
struct sas_ha_struct *ha)
{
+ int rc = 0;
+
if (!test_and_set_bit(event, pending)) {
unsigned long flags;
spin_lock_irqsave(&ha->lock, flags);
- sas_queue_work(ha, work);
+ rc = sas_queue_work(ha, work);
spin_unlock_irqrestore(&ha->lock, flags);
}
+
+ return rc;
}
@@ -116,32 +124,32 @@ void sas_enable_revalidation(struct sas_ha_struct *ha)
mutex_unlock(&ha->disco_mutex);
}
-static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event)
+static int notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event)
{
BUG_ON(event >= HA_NUM_EVENTS);
- sas_queue_event(event, &sas_ha->pending,
- &sas_ha->ha_events[event].work, sas_ha);
+ return sas_queue_event(event, &sas_ha->pending,
+ &sas_ha->ha_events[event].work, sas_ha);
}
-static void notify_port_event(struct asd_sas_phy *phy, enum port_event event)
+static int notify_port_event(struct asd_sas_phy *phy, enum port_event event)
{
struct sas_ha_struct *ha = phy->ha;
BUG_ON(event >= PORT_NUM_EVENTS);
- sas_queue_event(event, &phy->port_events_pending,
- &phy->port_events[event].work, ha);
+ return sas_queue_event(event, &phy->port_events_pending,
+ &phy->port_events[event].work, ha);
}
-void sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
+int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
{
struct sas_ha_struct *ha = phy->ha;
BUG_ON(event >= PHY_NUM_EVENTS);
- sas_queue_event(event, &phy->phy_events_pending,
- &phy->phy_events[event].work, ha);
+ return sas_queue_event(event, &phy->phy_events_pending,
+ &phy->phy_events[event].work, ha);
}
int sas_init_events(struct sas_ha_struct *sas_ha)