aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_init.c
diff options
context:
space:
mode:
authorJason Yan <yanaijie@huawei.com>2017-12-08 04:42:05 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2018-01-08 21:59:28 -0500
commitf12486e06ae87453530f00a6cb49b60ae3fe4551 (patch)
tree831a4dd957ced9acdff2349e03ae84fcaacad88e /drivers/scsi/libsas/sas_init.c
parent1c393b970e0f4070e4376d45f89a2d19a5c895d0 (diff)
scsi: libsas: shut down the PHY if events reached the threshold
If the PHY burst too many events, we will alloc a lot of events for the worker. This may leads to memory exhaustion. Dan Williams suggested to shut down the PHY if the events reached the threshold, because in this case the PHY may have gone into some erroneous state. Users can re-enable the PHY by sysfs if they want. We cannot use the fixed memory pool because if we run out of events, the shut down event and loss of signal event will lost too. The events still need to be allocated and processed in this case. Suggested-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Jason Yan <yanaijie@huawei.com> CC: John Garry <john.garry@huawei.com> CC: Johannes Thumshirn <jthumshirn@suse.de> CC: Ewan Milne <emilne@redhat.com> CC: Christoph Hellwig <hch@lst.de> CC: Tomas Henzl <thenzl@redhat.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/libsas/sas_init.c')
-rw-r--r--drivers/scsi/libsas/sas_init.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index e04f6d6f5aff..22bfc025ae81 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -123,6 +123,8 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
123 INIT_LIST_HEAD(&sas_ha->defer_q); 123 INIT_LIST_HEAD(&sas_ha->defer_q);
124 INIT_LIST_HEAD(&sas_ha->eh_dev_q); 124 INIT_LIST_HEAD(&sas_ha->eh_dev_q);
125 125
126 sas_ha->event_thres = SAS_PHY_SHUTDOWN_THRES;
127
126 error = sas_register_phys(sas_ha); 128 error = sas_register_phys(sas_ha);
127 if (error) { 129 if (error) {
128 printk(KERN_NOTICE "couldn't register sas phys:%d\n", error); 130 printk(KERN_NOTICE "couldn't register sas phys:%d\n", error);
@@ -557,14 +559,43 @@ EXPORT_SYMBOL_GPL(sas_domain_attach_transport);
557 559
558struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy) 560struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy)
559{ 561{
562 struct asd_sas_event *event;
560 gfp_t flags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; 563 gfp_t flags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
564 struct sas_ha_struct *sas_ha = phy->ha;
565 struct sas_internal *i =
566 to_sas_internal(sas_ha->core.shost->transportt);
567
568 event = kmem_cache_zalloc(sas_event_cache, flags);
569 if (!event)
570 return NULL;
561 571
562 return kmem_cache_zalloc(sas_event_cache, flags); 572 atomic_inc(&phy->event_nr);
573
574 if (atomic_read(&phy->event_nr) > phy->ha->event_thres) {
575 if (i->dft->lldd_control_phy) {
576 if (cmpxchg(&phy->in_shutdown, 0, 1) == 0) {
577 sas_printk("The phy%02d bursting events, shut it down.\n",
578 phy->id);
579 sas_notify_phy_event(phy, PHYE_SHUTDOWN);
580 }
581 } else {
582 /* Do not support PHY control, stop allocating events */
583 WARN_ONCE(1, "PHY control not supported.\n");
584 kmem_cache_free(sas_event_cache, event);
585 atomic_dec(&phy->event_nr);
586 event = NULL;
587 }
588 }
589
590 return event;
563} 591}
564 592
565void sas_free_event(struct asd_sas_event *event) 593void sas_free_event(struct asd_sas_event *event)
566{ 594{
595 struct asd_sas_phy *phy = event->phy;
596
567 kmem_cache_free(sas_event_cache, event); 597 kmem_cache_free(sas_event_cache, event);
598 atomic_dec(&phy->event_nr);
568} 599}
569 600
570/* ---------- SAS Class register/unregister ---------- */ 601/* ---------- SAS Class register/unregister ---------- */