aic94xx_dev.c 10 KB

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