1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Aic94xx SAS/SATA DDB management 4 * 5 * Copyright (C) 2005 Adaptec, Inc. All rights reserved. 6 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com> 7 * 8 * $Id: //depot/aic94xx/aic94xx_dev.c#21 $ 9 */ 10 11 #include "aic94xx.h" 12 #include "aic94xx_hwi.h" 13 #include "aic94xx_reg.h" 14 #include "aic94xx_sas.h" 15 16 #define FIND_FREE_DDB(_ha) find_first_zero_bit((_ha)->hw_prof.ddb_bitmap, \ 17 (_ha)->hw_prof.max_ddbs) 18 #define SET_DDB(_ddb, _ha) set_bit(_ddb, (_ha)->hw_prof.ddb_bitmap) 19 #define CLEAR_DDB(_ddb, _ha) clear_bit(_ddb, (_ha)->hw_prof.ddb_bitmap) 20 21 static int asd_get_ddb(struct asd_ha_struct *asd_ha) 22 { 23 int ddb, i; 24 25 ddb = FIND_FREE_DDB(asd_ha); 26 if (ddb >= asd_ha->hw_prof.max_ddbs) { 27 ddb = -ENOMEM; 28 goto out; 29 } 30 SET_DDB(ddb, asd_ha); 31 32 for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4) 33 asd_ddbsite_write_dword(asd_ha, ddb, i, 0); 34 out: 35 return ddb; 36 } 37 38 #define INIT_CONN_TAG offsetof(struct asd_ddb_ssp_smp_target_port, init_conn_tag) 39 #define DEST_SAS_ADDR offsetof(struct asd_ddb_ssp_smp_target_port, dest_sas_addr) 40 #define SEND_QUEUE_HEAD offsetof(struct asd_ddb_ssp_smp_target_port, send_queue_head) 41 #define DDB_TYPE offsetof(struct asd_ddb_ssp_smp_target_port, ddb_type) 42 #define CONN_MASK offsetof(struct asd_ddb_ssp_smp_target_port, conn_mask) 43 #define DDB_TARG_FLAGS offsetof(struct asd_ddb_ssp_smp_target_port, flags) 44 #define DDB_TARG_FLAGS2 offsetof(struct asd_ddb_stp_sata_target_port, flags2) 45 #define EXEC_QUEUE_TAIL offsetof(struct asd_ddb_ssp_smp_target_port, exec_queue_tail) 46 #define SEND_QUEUE_TAIL offsetof(struct asd_ddb_ssp_smp_target_port, send_queue_tail) 47 #define SISTER_DDB offsetof(struct asd_ddb_ssp_smp_target_port, sister_ddb) 48 #define MAX_CCONN offsetof(struct asd_ddb_ssp_smp_target_port, max_concurrent_conn) 49 #define NUM_CTX offsetof(struct asd_ddb_ssp_smp_target_port, num_contexts) 50 #define ATA_CMD_SCBPTR offsetof(struct asd_ddb_stp_sata_target_port, ata_cmd_scbptr) 51 #define SATA_TAG_ALLOC_MASK offsetof(struct asd_ddb_stp_sata_target_port, sata_tag_alloc_mask) 52 #define NUM_SATA_TAGS offsetof(struct asd_ddb_stp_sata_target_port, num_sata_tags) 53 #define SATA_STATUS offsetof(struct asd_ddb_stp_sata_target_port, sata_status) 54 #define NCQ_DATA_SCB_PTR offsetof(struct asd_ddb_stp_sata_target_port, ncq_data_scb_ptr) 55 #define ITNL_TIMEOUT offsetof(struct asd_ddb_ssp_smp_target_port, itnl_timeout) 56 57 static void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb) 58 { 59 if (!ddb || ddb >= 0xFFFF) 60 return; 61 asd_ddbsite_write_byte(asd_ha, ddb, DDB_TYPE, DDB_TYPE_UNUSED); 62 CLEAR_DDB(ddb, asd_ha); 63 } 64 65 static void asd_set_ddb_type(struct domain_device *dev) 66 { 67 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 68 int ddb = (int) (unsigned long) dev->lldd_dev; 69 70 if (dev->dev_type == SAS_SATA_PM_PORT) 71 asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_PM_PORT); 72 else if (dev->tproto) 73 asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_TARGET); 74 else 75 asd_ddbsite_write_byte(asd_ha,ddb,DDB_TYPE,DDB_TYPE_INITIATOR); 76 } 77 78 static int asd_init_sata_tag_ddb(struct domain_device *dev) 79 { 80 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 81 int ddb, i; 82 83 ddb = asd_get_ddb(asd_ha); 84 if (ddb < 0) 85 return ddb; 86 87 for (i = 0; i < sizeof(struct asd_ddb_sata_tag); i += 2) 88 asd_ddbsite_write_word(asd_ha, ddb, i, 0xFFFF); 89 90 asd_ddbsite_write_word(asd_ha, (int) (unsigned long) dev->lldd_dev, 91 SISTER_DDB, ddb); 92 return 0; 93 } 94 95 void asd_set_dmamode(struct domain_device *dev) 96 { 97 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 98 struct ata_device *ata_dev = sas_to_ata_dev(dev); 99 int ddb = (int) (unsigned long) dev->lldd_dev; 100 u32 qdepth = 0; 101 102 if (dev->dev_type == SAS_SATA_DEV || dev->dev_type == SAS_SATA_PM_PORT) { 103 if (ata_id_has_ncq(ata_dev->id)) 104 qdepth = ata_id_queue_depth(ata_dev->id); 105 asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK, 106 (1ULL<<qdepth)-1); 107 asd_ddbsite_write_byte(asd_ha, ddb, NUM_SATA_TAGS, qdepth); 108 } 109 110 if (qdepth > 0) 111 if (asd_init_sata_tag_ddb(dev) != 0) { 112 unsigned long flags; 113 114 spin_lock_irqsave(dev->sata_dev.ap->lock, flags); 115 ata_dev->flags |= ATA_DFLAG_NCQ_OFF; 116 spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags); 117 } 118 } 119 120 static int asd_init_sata(struct domain_device *dev) 121 { 122 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 123 int ddb = (int) (unsigned long) dev->lldd_dev; 124 125 asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF); 126 if (dev->dev_type == SAS_SATA_DEV || dev->dev_type == SAS_SATA_PM || 127 dev->dev_type == SAS_SATA_PM_PORT) { 128 struct dev_to_host_fis *fis = (struct dev_to_host_fis *) 129 dev->frame_rcvd; 130 asd_ddbsite_write_byte(asd_ha, ddb, SATA_STATUS, fis->status); 131 } 132 asd_ddbsite_write_word(asd_ha, ddb, NCQ_DATA_SCB_PTR, 0xFFFF); 133 134 return 0; 135 } 136 137 static int asd_init_target_ddb(struct domain_device *dev) 138 { 139 int ddb, i; 140 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 141 u8 flags = 0; 142 143 ddb = asd_get_ddb(asd_ha); 144 if (ddb < 0) 145 return ddb; 146 147 dev->lldd_dev = (void *) (unsigned long) ddb; 148 149 asd_ddbsite_write_byte(asd_ha, ddb, 0, DDB_TP_CONN_TYPE); 150 asd_ddbsite_write_byte(asd_ha, ddb, 1, 0); 151 asd_ddbsite_write_word(asd_ha, ddb, INIT_CONN_TAG, 0xFFFF); 152 for (i = 0; i < SAS_ADDR_SIZE; i++) 153 asd_ddbsite_write_byte(asd_ha, ddb, DEST_SAS_ADDR+i, 154 dev->sas_addr[i]); 155 asd_ddbsite_write_word(asd_ha, ddb, SEND_QUEUE_HEAD, 0xFFFF); 156 asd_set_ddb_type(dev); 157 asd_ddbsite_write_byte(asd_ha, ddb, CONN_MASK, dev->port->phy_mask); 158 if (dev->port->oob_mode != SATA_OOB_MODE) { 159 flags |= OPEN_REQUIRED; 160 if ((dev->dev_type == SAS_SATA_DEV) || 161 (dev->tproto & SAS_PROTOCOL_STP)) { 162 struct smp_resp *rps_resp = &dev->sata_dev.rps_resp; 163 if (rps_resp->frame_type == SMP_RESPONSE && 164 rps_resp->function == SMP_REPORT_PHY_SATA && 165 rps_resp->result == SMP_RESP_FUNC_ACC) { 166 if (rps_resp->rps.affil_valid) 167 flags |= STP_AFFIL_POL; 168 if (rps_resp->rps.affil_supp) 169 flags |= SUPPORTS_AFFIL; 170 } 171 } else { 172 flags |= CONCURRENT_CONN_SUPP; 173 if (!dev->parent && 174 (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || 175 dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE)) 176 asd_ddbsite_write_byte(asd_ha, ddb, MAX_CCONN, 177 4); 178 else 179 asd_ddbsite_write_byte(asd_ha, ddb, MAX_CCONN, 180 dev->pathways); 181 asd_ddbsite_write_byte(asd_ha, ddb, NUM_CTX, 1); 182 } 183 } 184 if (dev->dev_type == SAS_SATA_PM) 185 flags |= SATA_MULTIPORT; 186 asd_ddbsite_write_byte(asd_ha, ddb, DDB_TARG_FLAGS, flags); 187 188 flags = 0; 189 if (dev->tproto & SAS_PROTOCOL_STP) 190 flags |= STP_CL_POL_NO_TX; 191 asd_ddbsite_write_byte(asd_ha, ddb, DDB_TARG_FLAGS2, flags); 192 193 asd_ddbsite_write_word(asd_ha, ddb, EXEC_QUEUE_TAIL, 0xFFFF); 194 asd_ddbsite_write_word(asd_ha, ddb, SEND_QUEUE_TAIL, 0xFFFF); 195 asd_ddbsite_write_word(asd_ha, ddb, SISTER_DDB, 0xFFFF); 196 197 if (dev->dev_type == SAS_SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { 198 i = asd_init_sata(dev); 199 if (i < 0) { 200 asd_free_ddb(asd_ha, ddb); 201 return i; 202 } 203 } 204 205 if (dev->dev_type == SAS_END_DEVICE) { 206 struct sas_end_device *rdev = rphy_to_end_device(dev->rphy); 207 if (rdev->I_T_nexus_loss_timeout > 0) 208 asd_ddbsite_write_word(asd_ha, ddb, ITNL_TIMEOUT, 209 min(rdev->I_T_nexus_loss_timeout, 210 (u16)ITNL_TIMEOUT_CONST)); 211 else 212 asd_ddbsite_write_word(asd_ha, ddb, ITNL_TIMEOUT, 213 (u16)ITNL_TIMEOUT_CONST); 214 } 215 return 0; 216 } 217 218 static int asd_init_sata_pm_table_ddb(struct domain_device *dev) 219 { 220 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 221 int ddb, i; 222 223 ddb = asd_get_ddb(asd_ha); 224 if (ddb < 0) 225 return ddb; 226 227 for (i = 0; i < 32; i += 2) 228 asd_ddbsite_write_word(asd_ha, ddb, i, 0xFFFF); 229 230 asd_ddbsite_write_word(asd_ha, (int) (unsigned long) dev->lldd_dev, 231 SISTER_DDB, ddb); 232 233 return 0; 234 } 235 236 #define PM_PORT_FLAGS offsetof(struct asd_ddb_sata_pm_port, pm_port_flags) 237 #define PARENT_DDB offsetof(struct asd_ddb_sata_pm_port, parent_ddb) 238 239 /** 240 * asd_init_sata_pm_port_ddb -- SATA Port Multiplier Port 241 * dev: pointer to domain device 242 * 243 * For SATA Port Multiplier Ports we need to allocate one SATA Port 244 * Multiplier Port DDB and depending on whether the target on it 245 * supports SATA II NCQ, one SATA Tag DDB. 246 */ 247 static int asd_init_sata_pm_port_ddb(struct domain_device *dev) 248 { 249 int ddb, i, parent_ddb, pmtable_ddb; 250 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 251 u8 flags; 252 253 ddb = asd_get_ddb(asd_ha); 254 if (ddb < 0) 255 return ddb; 256 257 asd_set_ddb_type(dev); 258 flags = (dev->sata_dev.port_no << 4) | PM_PORT_SET; 259 asd_ddbsite_write_byte(asd_ha, ddb, PM_PORT_FLAGS, flags); 260 asd_ddbsite_write_word(asd_ha, ddb, SISTER_DDB, 0xFFFF); 261 asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF); 262 asd_init_sata(dev); 263 264 parent_ddb = (int) (unsigned long) dev->parent->lldd_dev; 265 asd_ddbsite_write_word(asd_ha, ddb, PARENT_DDB, parent_ddb); 266 pmtable_ddb = asd_ddbsite_read_word(asd_ha, parent_ddb, SISTER_DDB); 267 asd_ddbsite_write_word(asd_ha, pmtable_ddb, dev->sata_dev.port_no,ddb); 268 269 if (asd_ddbsite_read_byte(asd_ha, ddb, NUM_SATA_TAGS) > 0) { 270 i = asd_init_sata_tag_ddb(dev); 271 if (i < 0) { 272 asd_free_ddb(asd_ha, ddb); 273 return i; 274 } 275 } 276 return 0; 277 } 278 279 static int asd_init_initiator_ddb(struct domain_device *dev) 280 { 281 return -ENODEV; 282 } 283 284 /** 285 * asd_init_sata_pm_ddb -- SATA Port Multiplier 286 * dev: pointer to domain device 287 * 288 * For STP and direct-attached SATA Port Multipliers we need 289 * one target port DDB entry and one SATA PM table DDB entry. 290 */ 291 static int asd_init_sata_pm_ddb(struct domain_device *dev) 292 { 293 int res = 0; 294 295 res = asd_init_target_ddb(dev); 296 if (res) 297 goto out; 298 res = asd_init_sata_pm_table_ddb(dev); 299 if (res) 300 asd_free_ddb(dev->port->ha->lldd_ha, 301 (int) (unsigned long) dev->lldd_dev); 302 out: 303 return res; 304 } 305 306 int asd_dev_found(struct domain_device *dev) 307 { 308 unsigned long flags; 309 int res = 0; 310 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 311 312 spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); 313 switch (dev->dev_type) { 314 case SAS_SATA_PM: 315 res = asd_init_sata_pm_ddb(dev); 316 break; 317 case SAS_SATA_PM_PORT: 318 res = asd_init_sata_pm_port_ddb(dev); 319 break; 320 default: 321 if (dev->tproto) 322 res = asd_init_target_ddb(dev); 323 else 324 res = asd_init_initiator_ddb(dev); 325 } 326 spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); 327 328 return res; 329 } 330 331 void asd_dev_gone(struct domain_device *dev) 332 { 333 int ddb, sister_ddb; 334 unsigned long flags; 335 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 336 337 spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); 338 ddb = (int) (unsigned long) dev->lldd_dev; 339 sister_ddb = asd_ddbsite_read_word(asd_ha, ddb, SISTER_DDB); 340 341 if (sister_ddb != 0xFFFF) 342 asd_free_ddb(asd_ha, sister_ddb); 343 asd_free_ddb(asd_ha, ddb); 344 dev->lldd_dev = NULL; 345 spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); 346 } 347