162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Aic94xx SAS/SATA DDB management 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2005 Adaptec, Inc. All rights reserved. 662306a36Sopenharmony_ci * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * $Id: //depot/aic94xx/aic94xx_dev.c#21 $ 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "aic94xx.h" 1262306a36Sopenharmony_ci#include "aic94xx_hwi.h" 1362306a36Sopenharmony_ci#include "aic94xx_reg.h" 1462306a36Sopenharmony_ci#include "aic94xx_sas.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define FIND_FREE_DDB(_ha) find_first_zero_bit((_ha)->hw_prof.ddb_bitmap, \ 1762306a36Sopenharmony_ci (_ha)->hw_prof.max_ddbs) 1862306a36Sopenharmony_ci#define SET_DDB(_ddb, _ha) set_bit(_ddb, (_ha)->hw_prof.ddb_bitmap) 1962306a36Sopenharmony_ci#define CLEAR_DDB(_ddb, _ha) clear_bit(_ddb, (_ha)->hw_prof.ddb_bitmap) 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic int asd_get_ddb(struct asd_ha_struct *asd_ha) 2262306a36Sopenharmony_ci{ 2362306a36Sopenharmony_ci int ddb, i; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci ddb = FIND_FREE_DDB(asd_ha); 2662306a36Sopenharmony_ci if (ddb >= asd_ha->hw_prof.max_ddbs) { 2762306a36Sopenharmony_ci ddb = -ENOMEM; 2862306a36Sopenharmony_ci goto out; 2962306a36Sopenharmony_ci } 3062306a36Sopenharmony_ci SET_DDB(ddb, asd_ha); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4) 3362306a36Sopenharmony_ci asd_ddbsite_write_dword(asd_ha, ddb, i, 0); 3462306a36Sopenharmony_ciout: 3562306a36Sopenharmony_ci return ddb; 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define INIT_CONN_TAG offsetof(struct asd_ddb_ssp_smp_target_port, init_conn_tag) 3962306a36Sopenharmony_ci#define DEST_SAS_ADDR offsetof(struct asd_ddb_ssp_smp_target_port, dest_sas_addr) 4062306a36Sopenharmony_ci#define SEND_QUEUE_HEAD offsetof(struct asd_ddb_ssp_smp_target_port, send_queue_head) 4162306a36Sopenharmony_ci#define DDB_TYPE offsetof(struct asd_ddb_ssp_smp_target_port, ddb_type) 4262306a36Sopenharmony_ci#define CONN_MASK offsetof(struct asd_ddb_ssp_smp_target_port, conn_mask) 4362306a36Sopenharmony_ci#define DDB_TARG_FLAGS offsetof(struct asd_ddb_ssp_smp_target_port, flags) 4462306a36Sopenharmony_ci#define DDB_TARG_FLAGS2 offsetof(struct asd_ddb_stp_sata_target_port, flags2) 4562306a36Sopenharmony_ci#define EXEC_QUEUE_TAIL offsetof(struct asd_ddb_ssp_smp_target_port, exec_queue_tail) 4662306a36Sopenharmony_ci#define SEND_QUEUE_TAIL offsetof(struct asd_ddb_ssp_smp_target_port, send_queue_tail) 4762306a36Sopenharmony_ci#define SISTER_DDB offsetof(struct asd_ddb_ssp_smp_target_port, sister_ddb) 4862306a36Sopenharmony_ci#define MAX_CCONN offsetof(struct asd_ddb_ssp_smp_target_port, max_concurrent_conn) 4962306a36Sopenharmony_ci#define NUM_CTX offsetof(struct asd_ddb_ssp_smp_target_port, num_contexts) 5062306a36Sopenharmony_ci#define ATA_CMD_SCBPTR offsetof(struct asd_ddb_stp_sata_target_port, ata_cmd_scbptr) 5162306a36Sopenharmony_ci#define SATA_TAG_ALLOC_MASK offsetof(struct asd_ddb_stp_sata_target_port, sata_tag_alloc_mask) 5262306a36Sopenharmony_ci#define NUM_SATA_TAGS offsetof(struct asd_ddb_stp_sata_target_port, num_sata_tags) 5362306a36Sopenharmony_ci#define SATA_STATUS offsetof(struct asd_ddb_stp_sata_target_port, sata_status) 5462306a36Sopenharmony_ci#define NCQ_DATA_SCB_PTR offsetof(struct asd_ddb_stp_sata_target_port, ncq_data_scb_ptr) 5562306a36Sopenharmony_ci#define ITNL_TIMEOUT offsetof(struct asd_ddb_ssp_smp_target_port, itnl_timeout) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci if (!ddb || ddb >= 0xFFFF) 6062306a36Sopenharmony_ci return; 6162306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, ddb, DDB_TYPE, DDB_TYPE_UNUSED); 6262306a36Sopenharmony_ci CLEAR_DDB(ddb, asd_ha); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic void asd_set_ddb_type(struct domain_device *dev) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 6862306a36Sopenharmony_ci int ddb = (int) (unsigned long) dev->lldd_dev; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci if (dev->dev_type == SAS_SATA_PM_PORT) 7162306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_PM_PORT); 7262306a36Sopenharmony_ci else if (dev->tproto) 7362306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_TARGET); 7462306a36Sopenharmony_ci else 7562306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha,ddb,DDB_TYPE,DDB_TYPE_INITIATOR); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic int asd_init_sata_tag_ddb(struct domain_device *dev) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 8162306a36Sopenharmony_ci int ddb, i; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci ddb = asd_get_ddb(asd_ha); 8462306a36Sopenharmony_ci if (ddb < 0) 8562306a36Sopenharmony_ci return ddb; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci for (i = 0; i < sizeof(struct asd_ddb_sata_tag); i += 2) 8862306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, i, 0xFFFF); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, (int) (unsigned long) dev->lldd_dev, 9162306a36Sopenharmony_ci SISTER_DDB, ddb); 9262306a36Sopenharmony_ci return 0; 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_civoid asd_set_dmamode(struct domain_device *dev) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 9862306a36Sopenharmony_ci struct ata_device *ata_dev = sas_to_ata_dev(dev); 9962306a36Sopenharmony_ci int ddb = (int) (unsigned long) dev->lldd_dev; 10062306a36Sopenharmony_ci u32 qdepth = 0; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci if (dev->dev_type == SAS_SATA_DEV || dev->dev_type == SAS_SATA_PM_PORT) { 10362306a36Sopenharmony_ci if (ata_id_has_ncq(ata_dev->id)) 10462306a36Sopenharmony_ci qdepth = ata_id_queue_depth(ata_dev->id); 10562306a36Sopenharmony_ci asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK, 10662306a36Sopenharmony_ci (1ULL<<qdepth)-1); 10762306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, ddb, NUM_SATA_TAGS, qdepth); 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci if (qdepth > 0) 11162306a36Sopenharmony_ci if (asd_init_sata_tag_ddb(dev) != 0) { 11262306a36Sopenharmony_ci unsigned long flags; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci spin_lock_irqsave(dev->sata_dev.ap->lock, flags); 11562306a36Sopenharmony_ci ata_dev->flags |= ATA_DFLAG_NCQ_OFF; 11662306a36Sopenharmony_ci spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags); 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic int asd_init_sata(struct domain_device *dev) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 12362306a36Sopenharmony_ci int ddb = (int) (unsigned long) dev->lldd_dev; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF); 12662306a36Sopenharmony_ci if (dev->dev_type == SAS_SATA_DEV || dev->dev_type == SAS_SATA_PM || 12762306a36Sopenharmony_ci dev->dev_type == SAS_SATA_PM_PORT) { 12862306a36Sopenharmony_ci struct dev_to_host_fis *fis = (struct dev_to_host_fis *) 12962306a36Sopenharmony_ci dev->frame_rcvd; 13062306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, ddb, SATA_STATUS, fis->status); 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, NCQ_DATA_SCB_PTR, 0xFFFF); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci return 0; 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic int asd_init_target_ddb(struct domain_device *dev) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci int ddb, i; 14062306a36Sopenharmony_ci struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 14162306a36Sopenharmony_ci u8 flags = 0; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci ddb = asd_get_ddb(asd_ha); 14462306a36Sopenharmony_ci if (ddb < 0) 14562306a36Sopenharmony_ci return ddb; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci dev->lldd_dev = (void *) (unsigned long) ddb; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, ddb, 0, DDB_TP_CONN_TYPE); 15062306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, ddb, 1, 0); 15162306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, INIT_CONN_TAG, 0xFFFF); 15262306a36Sopenharmony_ci for (i = 0; i < SAS_ADDR_SIZE; i++) 15362306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, ddb, DEST_SAS_ADDR+i, 15462306a36Sopenharmony_ci dev->sas_addr[i]); 15562306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, SEND_QUEUE_HEAD, 0xFFFF); 15662306a36Sopenharmony_ci asd_set_ddb_type(dev); 15762306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, ddb, CONN_MASK, dev->port->phy_mask); 15862306a36Sopenharmony_ci if (dev->port->oob_mode != SATA_OOB_MODE) { 15962306a36Sopenharmony_ci flags |= OPEN_REQUIRED; 16062306a36Sopenharmony_ci if ((dev->dev_type == SAS_SATA_DEV) || 16162306a36Sopenharmony_ci (dev->tproto & SAS_PROTOCOL_STP)) { 16262306a36Sopenharmony_ci struct smp_rps_resp *rps_resp = &dev->sata_dev.rps_resp; 16362306a36Sopenharmony_ci if (rps_resp->frame_type == SMP_RESPONSE && 16462306a36Sopenharmony_ci rps_resp->function == SMP_REPORT_PHY_SATA && 16562306a36Sopenharmony_ci rps_resp->result == SMP_RESP_FUNC_ACC) { 16662306a36Sopenharmony_ci if (rps_resp->rps.affil_valid) 16762306a36Sopenharmony_ci flags |= STP_AFFIL_POL; 16862306a36Sopenharmony_ci if (rps_resp->rps.affil_supp) 16962306a36Sopenharmony_ci flags |= SUPPORTS_AFFIL; 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci } else { 17262306a36Sopenharmony_ci flags |= CONCURRENT_CONN_SUPP; 17362306a36Sopenharmony_ci if (!dev->parent && dev_is_expander(dev->dev_type)) 17462306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, ddb, MAX_CCONN, 17562306a36Sopenharmony_ci 4); 17662306a36Sopenharmony_ci else 17762306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, ddb, MAX_CCONN, 17862306a36Sopenharmony_ci dev->pathways); 17962306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, ddb, NUM_CTX, 1); 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci if (dev->dev_type == SAS_SATA_PM) 18362306a36Sopenharmony_ci flags |= SATA_MULTIPORT; 18462306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, ddb, DDB_TARG_FLAGS, flags); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci flags = 0; 18762306a36Sopenharmony_ci if (dev->tproto & SAS_PROTOCOL_STP) 18862306a36Sopenharmony_ci flags |= STP_CL_POL_NO_TX; 18962306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, ddb, DDB_TARG_FLAGS2, flags); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, EXEC_QUEUE_TAIL, 0xFFFF); 19262306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, SEND_QUEUE_TAIL, 0xFFFF); 19362306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, SISTER_DDB, 0xFFFF); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci if (dev->dev_type == SAS_SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { 19662306a36Sopenharmony_ci i = asd_init_sata(dev); 19762306a36Sopenharmony_ci if (i < 0) { 19862306a36Sopenharmony_ci asd_free_ddb(asd_ha, ddb); 19962306a36Sopenharmony_ci return i; 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (dev->dev_type == SAS_END_DEVICE) { 20462306a36Sopenharmony_ci struct sas_end_device *rdev = rphy_to_end_device(dev->rphy); 20562306a36Sopenharmony_ci if (rdev->I_T_nexus_loss_timeout > 0) 20662306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, ITNL_TIMEOUT, 20762306a36Sopenharmony_ci min(rdev->I_T_nexus_loss_timeout, 20862306a36Sopenharmony_ci (u16)ITNL_TIMEOUT_CONST)); 20962306a36Sopenharmony_ci else 21062306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, ITNL_TIMEOUT, 21162306a36Sopenharmony_ci (u16)ITNL_TIMEOUT_CONST); 21262306a36Sopenharmony_ci } 21362306a36Sopenharmony_ci return 0; 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic int asd_init_sata_pm_table_ddb(struct domain_device *dev) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 21962306a36Sopenharmony_ci int ddb, i; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci ddb = asd_get_ddb(asd_ha); 22262306a36Sopenharmony_ci if (ddb < 0) 22362306a36Sopenharmony_ci return ddb; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci for (i = 0; i < 32; i += 2) 22662306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, i, 0xFFFF); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, (int) (unsigned long) dev->lldd_dev, 22962306a36Sopenharmony_ci SISTER_DDB, ddb); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci return 0; 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci#define PM_PORT_FLAGS offsetof(struct asd_ddb_sata_pm_port, pm_port_flags) 23562306a36Sopenharmony_ci#define PARENT_DDB offsetof(struct asd_ddb_sata_pm_port, parent_ddb) 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/** 23862306a36Sopenharmony_ci * asd_init_sata_pm_port_ddb -- SATA Port Multiplier Port 23962306a36Sopenharmony_ci * @dev: pointer to domain device 24062306a36Sopenharmony_ci * 24162306a36Sopenharmony_ci * For SATA Port Multiplier Ports we need to allocate one SATA Port 24262306a36Sopenharmony_ci * Multiplier Port DDB and depending on whether the target on it 24362306a36Sopenharmony_ci * supports SATA II NCQ, one SATA Tag DDB. 24462306a36Sopenharmony_ci */ 24562306a36Sopenharmony_cistatic int asd_init_sata_pm_port_ddb(struct domain_device *dev) 24662306a36Sopenharmony_ci{ 24762306a36Sopenharmony_ci int ddb, i, parent_ddb, pmtable_ddb; 24862306a36Sopenharmony_ci struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 24962306a36Sopenharmony_ci u8 flags; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci ddb = asd_get_ddb(asd_ha); 25262306a36Sopenharmony_ci if (ddb < 0) 25362306a36Sopenharmony_ci return ddb; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci asd_set_ddb_type(dev); 25662306a36Sopenharmony_ci flags = (dev->sata_dev.port_no << 4) | PM_PORT_SET; 25762306a36Sopenharmony_ci asd_ddbsite_write_byte(asd_ha, ddb, PM_PORT_FLAGS, flags); 25862306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, SISTER_DDB, 0xFFFF); 25962306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF); 26062306a36Sopenharmony_ci asd_init_sata(dev); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci parent_ddb = (int) (unsigned long) dev->parent->lldd_dev; 26362306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, ddb, PARENT_DDB, parent_ddb); 26462306a36Sopenharmony_ci pmtable_ddb = asd_ddbsite_read_word(asd_ha, parent_ddb, SISTER_DDB); 26562306a36Sopenharmony_ci asd_ddbsite_write_word(asd_ha, pmtable_ddb, dev->sata_dev.port_no,ddb); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci if (asd_ddbsite_read_byte(asd_ha, ddb, NUM_SATA_TAGS) > 0) { 26862306a36Sopenharmony_ci i = asd_init_sata_tag_ddb(dev); 26962306a36Sopenharmony_ci if (i < 0) { 27062306a36Sopenharmony_ci asd_free_ddb(asd_ha, ddb); 27162306a36Sopenharmony_ci return i; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci return 0; 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cistatic int asd_init_initiator_ddb(struct domain_device *dev) 27862306a36Sopenharmony_ci{ 27962306a36Sopenharmony_ci return -ENODEV; 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci/** 28362306a36Sopenharmony_ci * asd_init_sata_pm_ddb -- SATA Port Multiplier 28462306a36Sopenharmony_ci * @dev: pointer to domain device 28562306a36Sopenharmony_ci * 28662306a36Sopenharmony_ci * For STP and direct-attached SATA Port Multipliers we need 28762306a36Sopenharmony_ci * one target port DDB entry and one SATA PM table DDB entry. 28862306a36Sopenharmony_ci */ 28962306a36Sopenharmony_cistatic int asd_init_sata_pm_ddb(struct domain_device *dev) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci int res = 0; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci res = asd_init_target_ddb(dev); 29462306a36Sopenharmony_ci if (res) 29562306a36Sopenharmony_ci goto out; 29662306a36Sopenharmony_ci res = asd_init_sata_pm_table_ddb(dev); 29762306a36Sopenharmony_ci if (res) 29862306a36Sopenharmony_ci asd_free_ddb(dev->port->ha->lldd_ha, 29962306a36Sopenharmony_ci (int) (unsigned long) dev->lldd_dev); 30062306a36Sopenharmony_ciout: 30162306a36Sopenharmony_ci return res; 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ciint asd_dev_found(struct domain_device *dev) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci unsigned long flags; 30762306a36Sopenharmony_ci int res = 0; 30862306a36Sopenharmony_ci struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); 31162306a36Sopenharmony_ci switch (dev->dev_type) { 31262306a36Sopenharmony_ci case SAS_SATA_PM: 31362306a36Sopenharmony_ci res = asd_init_sata_pm_ddb(dev); 31462306a36Sopenharmony_ci break; 31562306a36Sopenharmony_ci case SAS_SATA_PM_PORT: 31662306a36Sopenharmony_ci res = asd_init_sata_pm_port_ddb(dev); 31762306a36Sopenharmony_ci break; 31862306a36Sopenharmony_ci default: 31962306a36Sopenharmony_ci if (dev->tproto) 32062306a36Sopenharmony_ci res = asd_init_target_ddb(dev); 32162306a36Sopenharmony_ci else 32262306a36Sopenharmony_ci res = asd_init_initiator_ddb(dev); 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci return res; 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_civoid asd_dev_gone(struct domain_device *dev) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci int ddb, sister_ddb; 33262306a36Sopenharmony_ci unsigned long flags; 33362306a36Sopenharmony_ci struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); 33662306a36Sopenharmony_ci ddb = (int) (unsigned long) dev->lldd_dev; 33762306a36Sopenharmony_ci sister_ddb = asd_ddbsite_read_word(asd_ha, ddb, SISTER_DDB); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci if (sister_ddb != 0xFFFF) 34062306a36Sopenharmony_ci asd_free_ddb(asd_ha, sister_ddb); 34162306a36Sopenharmony_ci asd_free_ddb(asd_ha, ddb); 34262306a36Sopenharmony_ci dev->lldd_dev = NULL; 34362306a36Sopenharmony_ci spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); 34462306a36Sopenharmony_ci} 345