cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sas_init.c (17578B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Serial Attached SCSI (SAS) Transport Layer initialization
      4 *
      5 * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
      6 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/slab.h>
     11#include <linux/init.h>
     12#include <linux/device.h>
     13#include <linux/spinlock.h>
     14#include <scsi/sas_ata.h>
     15#include <scsi/scsi_host.h>
     16#include <scsi/scsi_device.h>
     17#include <scsi/scsi_transport.h>
     18#include <scsi/scsi_transport_sas.h>
     19
     20#include "sas_internal.h"
     21
     22#include "scsi_sas_internal.h"
     23
     24static struct kmem_cache *sas_task_cache;
     25static struct kmem_cache *sas_event_cache;
     26
     27struct sas_task *sas_alloc_task(gfp_t flags)
     28{
     29	struct sas_task *task = kmem_cache_zalloc(sas_task_cache, flags);
     30
     31	if (task) {
     32		spin_lock_init(&task->task_state_lock);
     33		task->task_state_flags = SAS_TASK_STATE_PENDING;
     34	}
     35
     36	return task;
     37}
     38EXPORT_SYMBOL_GPL(sas_alloc_task);
     39
     40struct sas_task *sas_alloc_slow_task(gfp_t flags)
     41{
     42	struct sas_task *task = sas_alloc_task(flags);
     43	struct sas_task_slow *slow = kmalloc(sizeof(*slow), flags);
     44
     45	if (!task || !slow) {
     46		if (task)
     47			kmem_cache_free(sas_task_cache, task);
     48		kfree(slow);
     49		return NULL;
     50	}
     51
     52	task->slow_task = slow;
     53	slow->task = task;
     54	timer_setup(&slow->timer, NULL, 0);
     55	init_completion(&slow->completion);
     56
     57	return task;
     58}
     59EXPORT_SYMBOL_GPL(sas_alloc_slow_task);
     60
     61void sas_free_task(struct sas_task *task)
     62{
     63	if (task) {
     64		kfree(task->slow_task);
     65		kmem_cache_free(sas_task_cache, task);
     66	}
     67}
     68EXPORT_SYMBOL_GPL(sas_free_task);
     69
     70/*------------ SAS addr hash -----------*/
     71void sas_hash_addr(u8 *hashed, const u8 *sas_addr)
     72{
     73	const u32 poly = 0x00DB2777;
     74	u32 r = 0;
     75	int i;
     76
     77	for (i = 0; i < SAS_ADDR_SIZE; i++) {
     78		int b;
     79
     80		for (b = (SAS_ADDR_SIZE - 1); b >= 0; b--) {
     81			r <<= 1;
     82			if ((1 << b) & sas_addr[i]) {
     83				if (!(r & 0x01000000))
     84					r ^= poly;
     85			} else if (r & 0x01000000) {
     86				r ^= poly;
     87			}
     88		}
     89	}
     90
     91	hashed[0] = (r >> 16) & 0xFF;
     92	hashed[1] = (r >> 8) & 0xFF;
     93	hashed[2] = r & 0xFF;
     94}
     95
     96int sas_register_ha(struct sas_ha_struct *sas_ha)
     97{
     98	char name[64];
     99	int error = 0;
    100
    101	mutex_init(&sas_ha->disco_mutex);
    102	spin_lock_init(&sas_ha->phy_port_lock);
    103	sas_hash_addr(sas_ha->hashed_sas_addr, sas_ha->sas_addr);
    104
    105	set_bit(SAS_HA_REGISTERED, &sas_ha->state);
    106	spin_lock_init(&sas_ha->lock);
    107	mutex_init(&sas_ha->drain_mutex);
    108	init_waitqueue_head(&sas_ha->eh_wait_q);
    109	INIT_LIST_HEAD(&sas_ha->defer_q);
    110	INIT_LIST_HEAD(&sas_ha->eh_dev_q);
    111
    112	sas_ha->event_thres = SAS_PHY_SHUTDOWN_THRES;
    113
    114	error = sas_register_phys(sas_ha);
    115	if (error) {
    116		pr_notice("couldn't register sas phys:%d\n", error);
    117		return error;
    118	}
    119
    120	error = sas_register_ports(sas_ha);
    121	if (error) {
    122		pr_notice("couldn't register sas ports:%d\n", error);
    123		goto Undo_phys;
    124	}
    125
    126	error = -ENOMEM;
    127	snprintf(name, sizeof(name), "%s_event_q", dev_name(sas_ha->dev));
    128	sas_ha->event_q = create_singlethread_workqueue(name);
    129	if (!sas_ha->event_q)
    130		goto Undo_ports;
    131
    132	snprintf(name, sizeof(name), "%s_disco_q", dev_name(sas_ha->dev));
    133	sas_ha->disco_q = create_singlethread_workqueue(name);
    134	if (!sas_ha->disco_q)
    135		goto Undo_event_q;
    136
    137	INIT_LIST_HEAD(&sas_ha->eh_done_q);
    138	INIT_LIST_HEAD(&sas_ha->eh_ata_q);
    139
    140	return 0;
    141
    142Undo_event_q:
    143	destroy_workqueue(sas_ha->event_q);
    144Undo_ports:
    145	sas_unregister_ports(sas_ha);
    146Undo_phys:
    147
    148	return error;
    149}
    150EXPORT_SYMBOL_GPL(sas_register_ha);
    151
    152static void sas_disable_events(struct sas_ha_struct *sas_ha)
    153{
    154	/* Set the state to unregistered to avoid further unchained
    155	 * events to be queued, and flush any in-progress drainers
    156	 */
    157	mutex_lock(&sas_ha->drain_mutex);
    158	spin_lock_irq(&sas_ha->lock);
    159	clear_bit(SAS_HA_REGISTERED, &sas_ha->state);
    160	spin_unlock_irq(&sas_ha->lock);
    161	__sas_drain_work(sas_ha);
    162	mutex_unlock(&sas_ha->drain_mutex);
    163}
    164
    165int sas_unregister_ha(struct sas_ha_struct *sas_ha)
    166{
    167	sas_disable_events(sas_ha);
    168	sas_unregister_ports(sas_ha);
    169
    170	/* flush unregistration work */
    171	mutex_lock(&sas_ha->drain_mutex);
    172	__sas_drain_work(sas_ha);
    173	mutex_unlock(&sas_ha->drain_mutex);
    174
    175	destroy_workqueue(sas_ha->disco_q);
    176	destroy_workqueue(sas_ha->event_q);
    177
    178	return 0;
    179}
    180EXPORT_SYMBOL_GPL(sas_unregister_ha);
    181
    182static int sas_get_linkerrors(struct sas_phy *phy)
    183{
    184	if (scsi_is_sas_phy_local(phy)) {
    185		struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
    186		struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
    187		struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
    188		struct sas_internal *i =
    189			to_sas_internal(sas_ha->core.shost->transportt);
    190
    191		return i->dft->lldd_control_phy(asd_phy, PHY_FUNC_GET_EVENTS, NULL);
    192	}
    193
    194	return sas_smp_get_phy_events(phy);
    195}
    196
    197int sas_try_ata_reset(struct asd_sas_phy *asd_phy)
    198{
    199	struct domain_device *dev = NULL;
    200
    201	/* try to route user requested link resets through libata */
    202	if (asd_phy->port)
    203		dev = asd_phy->port->port_dev;
    204
    205	/* validate that dev has been probed */
    206	if (dev)
    207		dev = sas_find_dev_by_rphy(dev->rphy);
    208
    209	if (dev && dev_is_sata(dev)) {
    210		sas_ata_schedule_reset(dev);
    211		sas_ata_wait_eh(dev);
    212		return 0;
    213	}
    214
    215	return -ENODEV;
    216}
    217
    218/*
    219 * transport_sas_phy_reset - reset a phy and permit libata to manage the link
    220 *
    221 * phy reset request via sysfs in host workqueue context so we know we
    222 * can block on eh and safely traverse the domain_device topology
    223 */
    224static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset)
    225{
    226	enum phy_func reset_type;
    227
    228	if (hard_reset)
    229		reset_type = PHY_FUNC_HARD_RESET;
    230	else
    231		reset_type = PHY_FUNC_LINK_RESET;
    232
    233	if (scsi_is_sas_phy_local(phy)) {
    234		struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
    235		struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
    236		struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
    237		struct sas_internal *i =
    238			to_sas_internal(sas_ha->core.shost->transportt);
    239
    240		if (!hard_reset && sas_try_ata_reset(asd_phy) == 0)
    241			return 0;
    242		return i->dft->lldd_control_phy(asd_phy, reset_type, NULL);
    243	} else {
    244		struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
    245		struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
    246		struct domain_device *ata_dev = sas_ex_to_ata(ddev, phy->number);
    247
    248		if (ata_dev && !hard_reset) {
    249			sas_ata_schedule_reset(ata_dev);
    250			sas_ata_wait_eh(ata_dev);
    251			return 0;
    252		} else
    253			return sas_smp_phy_control(ddev, phy->number, reset_type, NULL);
    254	}
    255}
    256
    257int sas_phy_enable(struct sas_phy *phy, int enable)
    258{
    259	int ret;
    260	enum phy_func cmd;
    261
    262	if (enable)
    263		cmd = PHY_FUNC_LINK_RESET;
    264	else
    265		cmd = PHY_FUNC_DISABLE;
    266
    267	if (scsi_is_sas_phy_local(phy)) {
    268		struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
    269		struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
    270		struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
    271		struct sas_internal *i =
    272			to_sas_internal(sas_ha->core.shost->transportt);
    273
    274		if (enable)
    275			ret = transport_sas_phy_reset(phy, 0);
    276		else
    277			ret = i->dft->lldd_control_phy(asd_phy, cmd, NULL);
    278	} else {
    279		struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
    280		struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
    281
    282		if (enable)
    283			ret = transport_sas_phy_reset(phy, 0);
    284		else
    285			ret = sas_smp_phy_control(ddev, phy->number, cmd, NULL);
    286	}
    287	return ret;
    288}
    289EXPORT_SYMBOL_GPL(sas_phy_enable);
    290
    291int sas_phy_reset(struct sas_phy *phy, int hard_reset)
    292{
    293	int ret;
    294	enum phy_func reset_type;
    295
    296	if (!phy->enabled)
    297		return -ENODEV;
    298
    299	if (hard_reset)
    300		reset_type = PHY_FUNC_HARD_RESET;
    301	else
    302		reset_type = PHY_FUNC_LINK_RESET;
    303
    304	if (scsi_is_sas_phy_local(phy)) {
    305		struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
    306		struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
    307		struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
    308		struct sas_internal *i =
    309			to_sas_internal(sas_ha->core.shost->transportt);
    310
    311		ret = i->dft->lldd_control_phy(asd_phy, reset_type, NULL);
    312	} else {
    313		struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
    314		struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
    315		ret = sas_smp_phy_control(ddev, phy->number, reset_type, NULL);
    316	}
    317	return ret;
    318}
    319EXPORT_SYMBOL_GPL(sas_phy_reset);
    320
    321int sas_set_phy_speed(struct sas_phy *phy,
    322		      struct sas_phy_linkrates *rates)
    323{
    324	int ret;
    325
    326	if ((rates->minimum_linkrate &&
    327	     rates->minimum_linkrate > phy->maximum_linkrate) ||
    328	    (rates->maximum_linkrate &&
    329	     rates->maximum_linkrate < phy->minimum_linkrate))
    330		return -EINVAL;
    331
    332	if (rates->minimum_linkrate &&
    333	    rates->minimum_linkrate < phy->minimum_linkrate_hw)
    334		rates->minimum_linkrate = phy->minimum_linkrate_hw;
    335
    336	if (rates->maximum_linkrate &&
    337	    rates->maximum_linkrate > phy->maximum_linkrate_hw)
    338		rates->maximum_linkrate = phy->maximum_linkrate_hw;
    339
    340	if (scsi_is_sas_phy_local(phy)) {
    341		struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
    342		struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
    343		struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
    344		struct sas_internal *i =
    345			to_sas_internal(sas_ha->core.shost->transportt);
    346
    347		ret = i->dft->lldd_control_phy(asd_phy, PHY_FUNC_SET_LINK_RATE,
    348					       rates);
    349	} else {
    350		struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
    351		struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
    352		ret = sas_smp_phy_control(ddev, phy->number,
    353					  PHY_FUNC_LINK_RESET, rates);
    354
    355	}
    356
    357	return ret;
    358}
    359
    360void sas_prep_resume_ha(struct sas_ha_struct *ha)
    361{
    362	int i;
    363
    364	set_bit(SAS_HA_REGISTERED, &ha->state);
    365	set_bit(SAS_HA_RESUMING, &ha->state);
    366
    367	/* clear out any stale link events/data from the suspension path */
    368	for (i = 0; i < ha->num_phys; i++) {
    369		struct asd_sas_phy *phy = ha->sas_phy[i];
    370
    371		memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
    372		phy->frame_rcvd_size = 0;
    373	}
    374}
    375EXPORT_SYMBOL(sas_prep_resume_ha);
    376
    377static int phys_suspended(struct sas_ha_struct *ha)
    378{
    379	int i, rc = 0;
    380
    381	for (i = 0; i < ha->num_phys; i++) {
    382		struct asd_sas_phy *phy = ha->sas_phy[i];
    383
    384		if (phy->suspended)
    385			rc++;
    386	}
    387
    388	return rc;
    389}
    390
    391static void sas_resume_insert_broadcast_ha(struct sas_ha_struct *ha)
    392{
    393	int i;
    394
    395	for (i = 0; i < ha->num_phys; i++) {
    396		struct asd_sas_port *port = ha->sas_port[i];
    397		struct domain_device *dev = port->port_dev;
    398
    399		if (dev && dev_is_expander(dev->dev_type)) {
    400			struct asd_sas_phy *first_phy;
    401
    402			spin_lock(&port->phy_list_lock);
    403			first_phy = list_first_entry_or_null(
    404				&port->phy_list, struct asd_sas_phy,
    405				port_phy_el);
    406			spin_unlock(&port->phy_list_lock);
    407
    408			if (first_phy)
    409				sas_notify_port_event(first_phy,
    410					PORTE_BROADCAST_RCVD, GFP_KERNEL);
    411		}
    412	}
    413}
    414
    415static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain)
    416{
    417	const unsigned long tmo = msecs_to_jiffies(25000);
    418	int i;
    419
    420	/* deform ports on phys that did not resume
    421	 * at this point we may be racing the phy coming back (as posted
    422	 * by the lldd).  So we post the event and once we are in the
    423	 * libsas context check that the phy remains suspended before
    424	 * tearing it down.
    425	 */
    426	i = phys_suspended(ha);
    427	if (i)
    428		dev_info(ha->dev, "waiting up to 25 seconds for %d phy%s to resume\n",
    429			 i, i > 1 ? "s" : "");
    430	wait_event_timeout(ha->eh_wait_q, phys_suspended(ha) == 0, tmo);
    431	for (i = 0; i < ha->num_phys; i++) {
    432		struct asd_sas_phy *phy = ha->sas_phy[i];
    433
    434		if (phy->suspended) {
    435			dev_warn(&phy->phy->dev, "resume timeout\n");
    436			sas_notify_phy_event(phy, PHYE_RESUME_TIMEOUT,
    437					     GFP_KERNEL);
    438		}
    439	}
    440
    441	/* all phys are back up or timed out, turn on i/o so we can
    442	 * flush out disks that did not return
    443	 */
    444	scsi_unblock_requests(ha->core.shost);
    445	if (drain)
    446		sas_drain_work(ha);
    447	clear_bit(SAS_HA_RESUMING, &ha->state);
    448
    449	sas_queue_deferred_work(ha);
    450	/* send event PORTE_BROADCAST_RCVD to identify some new inserted
    451	 * disks for expander
    452	 */
    453	sas_resume_insert_broadcast_ha(ha);
    454}
    455
    456void sas_resume_ha(struct sas_ha_struct *ha)
    457{
    458	_sas_resume_ha(ha, true);
    459}
    460EXPORT_SYMBOL(sas_resume_ha);
    461
    462/* A no-sync variant, which does not call sas_drain_ha(). */
    463void sas_resume_ha_no_sync(struct sas_ha_struct *ha)
    464{
    465	_sas_resume_ha(ha, false);
    466}
    467EXPORT_SYMBOL(sas_resume_ha_no_sync);
    468
    469void sas_suspend_ha(struct sas_ha_struct *ha)
    470{
    471	int i;
    472
    473	sas_disable_events(ha);
    474	scsi_block_requests(ha->core.shost);
    475	for (i = 0; i < ha->num_phys; i++) {
    476		struct asd_sas_port *port = ha->sas_port[i];
    477
    478		sas_discover_event(port, DISCE_SUSPEND);
    479	}
    480
    481	/* flush suspend events while unregistered */
    482	mutex_lock(&ha->drain_mutex);
    483	__sas_drain_work(ha);
    484	mutex_unlock(&ha->drain_mutex);
    485}
    486EXPORT_SYMBOL(sas_suspend_ha);
    487
    488static void sas_phy_release(struct sas_phy *phy)
    489{
    490	kfree(phy->hostdata);
    491	phy->hostdata = NULL;
    492}
    493
    494static void phy_reset_work(struct work_struct *work)
    495{
    496	struct sas_phy_data *d = container_of(work, typeof(*d), reset_work.work);
    497
    498	d->reset_result = transport_sas_phy_reset(d->phy, d->hard_reset);
    499}
    500
    501static void phy_enable_work(struct work_struct *work)
    502{
    503	struct sas_phy_data *d = container_of(work, typeof(*d), enable_work.work);
    504
    505	d->enable_result = sas_phy_enable(d->phy, d->enable);
    506}
    507
    508static int sas_phy_setup(struct sas_phy *phy)
    509{
    510	struct sas_phy_data *d = kzalloc(sizeof(*d), GFP_KERNEL);
    511
    512	if (!d)
    513		return -ENOMEM;
    514
    515	mutex_init(&d->event_lock);
    516	INIT_SAS_WORK(&d->reset_work, phy_reset_work);
    517	INIT_SAS_WORK(&d->enable_work, phy_enable_work);
    518	d->phy = phy;
    519	phy->hostdata = d;
    520
    521	return 0;
    522}
    523
    524static int queue_phy_reset(struct sas_phy *phy, int hard_reset)
    525{
    526	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
    527	struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
    528	struct sas_phy_data *d = phy->hostdata;
    529	int rc;
    530
    531	if (!d)
    532		return -ENOMEM;
    533
    534	/* libsas workqueue coordinates ata-eh reset with discovery */
    535	mutex_lock(&d->event_lock);
    536	d->reset_result = 0;
    537	d->hard_reset = hard_reset;
    538
    539	spin_lock_irq(&ha->lock);
    540	sas_queue_work(ha, &d->reset_work);
    541	spin_unlock_irq(&ha->lock);
    542
    543	rc = sas_drain_work(ha);
    544	if (rc == 0)
    545		rc = d->reset_result;
    546	mutex_unlock(&d->event_lock);
    547
    548	return rc;
    549}
    550
    551static int queue_phy_enable(struct sas_phy *phy, int enable)
    552{
    553	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
    554	struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
    555	struct sas_phy_data *d = phy->hostdata;
    556	int rc;
    557
    558	if (!d)
    559		return -ENOMEM;
    560
    561	/* libsas workqueue coordinates ata-eh reset with discovery */
    562	mutex_lock(&d->event_lock);
    563	d->enable_result = 0;
    564	d->enable = enable;
    565
    566	spin_lock_irq(&ha->lock);
    567	sas_queue_work(ha, &d->enable_work);
    568	spin_unlock_irq(&ha->lock);
    569
    570	rc = sas_drain_work(ha);
    571	if (rc == 0)
    572		rc = d->enable_result;
    573	mutex_unlock(&d->event_lock);
    574
    575	return rc;
    576}
    577
    578static struct sas_function_template sft = {
    579	.phy_enable = queue_phy_enable,
    580	.phy_reset = queue_phy_reset,
    581	.phy_setup = sas_phy_setup,
    582	.phy_release = sas_phy_release,
    583	.set_phy_speed = sas_set_phy_speed,
    584	.get_linkerrors = sas_get_linkerrors,
    585	.smp_handler = sas_smp_handler,
    586};
    587
    588static inline ssize_t phy_event_threshold_show(struct device *dev,
    589			struct device_attribute *attr, char *buf)
    590{
    591	struct Scsi_Host *shost = class_to_shost(dev);
    592	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
    593
    594	return scnprintf(buf, PAGE_SIZE, "%u\n", sha->event_thres);
    595}
    596
    597static inline ssize_t phy_event_threshold_store(struct device *dev,
    598			struct device_attribute *attr,
    599			const char *buf, size_t count)
    600{
    601	struct Scsi_Host *shost = class_to_shost(dev);
    602	struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
    603
    604	sha->event_thres = simple_strtol(buf, NULL, 10);
    605
    606	/* threshold cannot be set too small */
    607	if (sha->event_thres < 32)
    608		sha->event_thres = 32;
    609
    610	return count;
    611}
    612
    613DEVICE_ATTR(phy_event_threshold,
    614	S_IRUGO|S_IWUSR,
    615	phy_event_threshold_show,
    616	phy_event_threshold_store);
    617EXPORT_SYMBOL_GPL(dev_attr_phy_event_threshold);
    618
    619struct scsi_transport_template *
    620sas_domain_attach_transport(struct sas_domain_function_template *dft)
    621{
    622	struct scsi_transport_template *stt = sas_attach_transport(&sft);
    623	struct sas_internal *i;
    624
    625	if (!stt)
    626		return stt;
    627
    628	i = to_sas_internal(stt);
    629	i->dft = dft;
    630	stt->create_work_queue = 1;
    631	stt->eh_strategy_handler = sas_scsi_recover_host;
    632
    633	return stt;
    634}
    635EXPORT_SYMBOL_GPL(sas_domain_attach_transport);
    636
    637struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy,
    638				      gfp_t gfp_flags)
    639{
    640	struct asd_sas_event *event;
    641	struct sas_ha_struct *sas_ha = phy->ha;
    642	struct sas_internal *i =
    643		to_sas_internal(sas_ha->core.shost->transportt);
    644
    645	event = kmem_cache_zalloc(sas_event_cache, gfp_flags);
    646	if (!event)
    647		return NULL;
    648
    649	atomic_inc(&phy->event_nr);
    650
    651	if (atomic_read(&phy->event_nr) > phy->ha->event_thres) {
    652		if (i->dft->lldd_control_phy) {
    653			if (cmpxchg(&phy->in_shutdown, 0, 1) == 0) {
    654				pr_notice("The phy%d bursting events, shut it down.\n",
    655					  phy->id);
    656				sas_notify_phy_event(phy, PHYE_SHUTDOWN,
    657						     gfp_flags);
    658			}
    659		} else {
    660			/* Do not support PHY control, stop allocating events */
    661			WARN_ONCE(1, "PHY control not supported.\n");
    662			kmem_cache_free(sas_event_cache, event);
    663			atomic_dec(&phy->event_nr);
    664			event = NULL;
    665		}
    666	}
    667
    668	return event;
    669}
    670
    671void sas_free_event(struct asd_sas_event *event)
    672{
    673	struct asd_sas_phy *phy = event->phy;
    674
    675	kmem_cache_free(sas_event_cache, event);
    676	atomic_dec(&phy->event_nr);
    677}
    678
    679/* ---------- SAS Class register/unregister ---------- */
    680
    681static int __init sas_class_init(void)
    682{
    683	sas_task_cache = KMEM_CACHE(sas_task, SLAB_HWCACHE_ALIGN);
    684	if (!sas_task_cache)
    685		goto out;
    686
    687	sas_event_cache = KMEM_CACHE(asd_sas_event, SLAB_HWCACHE_ALIGN);
    688	if (!sas_event_cache)
    689		goto free_task_kmem;
    690
    691	return 0;
    692free_task_kmem:
    693	kmem_cache_destroy(sas_task_cache);
    694out:
    695	return -ENOMEM;
    696}
    697
    698static void __exit sas_class_exit(void)
    699{
    700	kmem_cache_destroy(sas_task_cache);
    701	kmem_cache_destroy(sas_event_cache);
    702}
    703
    704MODULE_AUTHOR("Luben Tuikov <luben_tuikov@adaptec.com>");
    705MODULE_DESCRIPTION("SAS Transport Layer");
    706MODULE_LICENSE("GPL v2");
    707
    708module_init(sas_class_init);
    709module_exit(sas_class_exit);
    710