hisi_sas_main.c 91.2 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
2 3 4 5 6 7 8 9
/*
 * Copyright (c) 2015 Linaro Ltd.
 * Copyright (c) 2015 Hisilicon Limited.
 */

#include "hisi_sas.h"
#define DRV_NAME "hisi_sas"

J
John Garry 已提交
10 11 12
#define DEV_IS_GONE(dev) \
	((!dev) || (dev->dev_type == SAS_PHY_UNUSED))

J
John Garry 已提交
13 14
static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device,
				u8 *lun, struct hisi_sas_tmf_task *tmf);
15 16 17 18
static int
hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
			     struct domain_device *device,
			     int abort_flag, int tag);
19
static int hisi_sas_softreset_ata_disk(struct domain_device *device);
20 21
static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
				void *funcdata);
22 23 24
static void hisi_sas_release_task(struct hisi_hba *hisi_hba,
				  struct domain_device *device);
static void hisi_sas_dev_gone(struct domain_device *device);
J
John Garry 已提交
25

26
u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
27
{
28
	switch (fis->command) {
29 30 31 32 33
	case ATA_CMD_FPDMA_WRITE:
	case ATA_CMD_FPDMA_READ:
	case ATA_CMD_FPDMA_RECV:
	case ATA_CMD_FPDMA_SEND:
	case ATA_CMD_NCQ_NON_DATA:
34
		return HISI_SAS_SATA_PROTOCOL_FPDMA;
35 36 37 38 39 40 41 42 43 44 45

	case ATA_CMD_DOWNLOAD_MICRO:
	case ATA_CMD_ID_ATA:
	case ATA_CMD_PMP_READ:
	case ATA_CMD_READ_LOG_EXT:
	case ATA_CMD_PIO_READ:
	case ATA_CMD_PIO_READ_EXT:
	case ATA_CMD_PMP_WRITE:
	case ATA_CMD_WRITE_LOG_EXT:
	case ATA_CMD_PIO_WRITE:
	case ATA_CMD_PIO_WRITE_EXT:
46
		return HISI_SAS_SATA_PROTOCOL_PIO;
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

	case ATA_CMD_DSM:
	case ATA_CMD_DOWNLOAD_MICRO_DMA:
	case ATA_CMD_PMP_READ_DMA:
	case ATA_CMD_PMP_WRITE_DMA:
	case ATA_CMD_READ:
	case ATA_CMD_READ_EXT:
	case ATA_CMD_READ_LOG_DMA_EXT:
	case ATA_CMD_READ_STREAM_DMA_EXT:
	case ATA_CMD_TRUSTED_RCV_DMA:
	case ATA_CMD_TRUSTED_SND_DMA:
	case ATA_CMD_WRITE:
	case ATA_CMD_WRITE_EXT:
	case ATA_CMD_WRITE_FUA_EXT:
	case ATA_CMD_WRITE_QUEUED:
	case ATA_CMD_WRITE_LOG_DMA_EXT:
	case ATA_CMD_WRITE_STREAM_DMA_EXT:
64
	case ATA_CMD_ZAC_MGMT_IN:
65
		return HISI_SAS_SATA_PROTOCOL_DMA;
66 67 68 69 70 71 72 73 74 75 76

	case ATA_CMD_CHK_POWER:
	case ATA_CMD_DEV_RESET:
	case ATA_CMD_EDD:
	case ATA_CMD_FLUSH:
	case ATA_CMD_FLUSH_EXT:
	case ATA_CMD_VERIFY:
	case ATA_CMD_VERIFY_EXT:
	case ATA_CMD_SET_FEATURES:
	case ATA_CMD_STANDBY:
	case ATA_CMD_STANDBYNOW1:
77
	case ATA_CMD_ZAC_MGMT_OUT:
78
		return HISI_SAS_SATA_PROTOCOL_NONDATA;
79

80 81 82 83 84
	case ATA_CMD_SET_MAX:
		switch (fis->features) {
		case ATA_SET_MAX_PASSWD:
		case ATA_SET_MAX_LOCK:
			return HISI_SAS_SATA_PROTOCOL_PIO;
85

86 87 88 89 90 91
		case ATA_SET_MAX_PASSWD_DMA:
		case ATA_SET_MAX_UNLOCK_DMA:
			return HISI_SAS_SATA_PROTOCOL_DMA;

		default:
			return HISI_SAS_SATA_PROTOCOL_NONDATA;
92
		}
93 94 95

	default:
	{
96 97 98 99
		if (direction == DMA_NONE)
			return HISI_SAS_SATA_PROTOCOL_NONDATA;
		return HISI_SAS_SATA_PROTOCOL_PIO;
	}
100
	}
101 102 103
}
EXPORT_SYMBOL_GPL(hisi_sas_get_ata_protocol);

104 105 106 107 108
void hisi_sas_sata_done(struct sas_task *task,
			    struct hisi_sas_slot *slot)
{
	struct task_status_struct *ts = &task->task_status;
	struct ata_task_resp *resp = (struct ata_task_resp *)ts->buf;
109 110 111 112
	struct hisi_sas_status_buffer *status_buf =
			hisi_sas_status_buf_addr_mem(slot);
	u8 *iu = &status_buf->iu[0];
	struct dev_to_host_fis *d2h =  (struct dev_to_host_fis *)iu;
113 114 115 116 117 118 119 120

	resp->frame_len = sizeof(struct dev_to_host_fis);
	memcpy(&resp->ending_fis[0], d2h, sizeof(struct dev_to_host_fis));

	ts->buf_valid_size = sizeof(*resp);
}
EXPORT_SYMBOL_GPL(hisi_sas_sata_done);

121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
int hisi_sas_get_ncq_tag(struct sas_task *task, u32 *tag)
{
	struct ata_queued_cmd *qc = task->uldd_task;

	if (qc) {
		if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
			qc->tf.command == ATA_CMD_FPDMA_READ) {
			*tag = qc->tag;
			return 1;
		}
	}
	return 0;
}
EXPORT_SYMBOL_GPL(hisi_sas_get_ncq_tag);

136 137 138 139 140 141
/*
 * This function assumes linkrate mask fits in 8 bits, which it
 * does for all HW versions supported.
 */
u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max)
{
142
	u8 rate = 0;
143 144 145 146 147 148 149 150 151
	int i;

	max -= SAS_LINK_RATE_1_5_GBPS;
	for (i = 0; i <= max; i++)
		rate |= 1 << (i * 2);
	return rate;
}
EXPORT_SYMBOL_GPL(hisi_sas_get_prog_phy_linkrate_mask);

J
John Garry 已提交
152 153 154 155 156
static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
{
	return device->port->ha->lldd_ha;
}

157 158 159 160 161 162
struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port)
{
	return container_of(sas_port, struct hisi_sas_port, sas_port);
}
EXPORT_SYMBOL_GPL(to_hisi_sas_port);

163 164 165 166 167
void hisi_sas_stop_phys(struct hisi_hba *hisi_hba)
{
	int phy_no;

	for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++)
168
		hisi_sas_phy_enable(hisi_hba, phy_no, 0);
169 170 171
}
EXPORT_SYMBOL_GPL(hisi_sas_stop_phys);

J
John Garry 已提交
172 173 174 175 176 177 178
static void hisi_sas_slot_index_clear(struct hisi_hba *hisi_hba, int slot_idx)
{
	void *bitmap = hisi_hba->slot_index_tags;

	clear_bit(slot_idx, bitmap);
}

J
John Garry 已提交
179 180
static void hisi_sas_slot_index_free(struct hisi_hba *hisi_hba, int slot_idx)
{
181 182
	unsigned long flags;

183 184
	if (hisi_hba->hw->slot_index_alloc ||
	    slot_idx >= HISI_SAS_UNRESERVED_IPTT) {
185 186 187 188
		spin_lock_irqsave(&hisi_hba->lock, flags);
		hisi_sas_slot_index_clear(hisi_hba, slot_idx);
		spin_unlock_irqrestore(&hisi_hba->lock, flags);
	}
J
John Garry 已提交
189 190 191 192 193 194 195 196 197
}

static void hisi_sas_slot_index_set(struct hisi_hba *hisi_hba, int slot_idx)
{
	void *bitmap = hisi_hba->slot_index_tags;

	set_bit(slot_idx, bitmap);
}

198 199
static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba,
				     struct scsi_cmnd *scsi_cmnd)
J
John Garry 已提交
200
{
201
	int index;
J
John Garry 已提交
202
	void *bitmap = hisi_hba->slot_index_tags;
203
	unsigned long flags;
J
John Garry 已提交
204

205 206 207 208
	if (scsi_cmnd)
		return scsi_cmnd->request->tag;

	spin_lock_irqsave(&hisi_hba->lock, flags);
209
	index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count,
210
				   hisi_hba->last_slot_index + 1);
211
	if (index >= hisi_hba->slot_index_count) {
212 213
		index = find_next_zero_bit(bitmap,
				hisi_hba->slot_index_count,
214
				HISI_SAS_UNRESERVED_IPTT);
215 216
		if (index >= hisi_hba->slot_index_count) {
			spin_unlock_irqrestore(&hisi_hba->lock, flags);
217
			return -SAS_QUEUE_FULL;
218
		}
219
	}
J
John Garry 已提交
220
	hisi_sas_slot_index_set(hisi_hba, index);
221
	hisi_hba->last_slot_index = index;
222
	spin_unlock_irqrestore(&hisi_hba->lock, flags);
223

224
	return index;
J
John Garry 已提交
225 226
}

J
John Garry 已提交
227 228 229 230 231 232 233
static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba)
{
	int i;

	for (i = 0; i < hisi_hba->slot_index_count; ++i)
		hisi_sas_slot_index_clear(hisi_hba, i);
}
J
John Garry 已提交
234 235 236 237

void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
			     struct hisi_sas_slot *slot)
{
238
	unsigned long flags;
239 240
	int device_id = slot->device_id;
	struct hisi_sas_device *sas_dev = &hisi_hba->devices[device_id];
J
John Garry 已提交
241

242
	if (task) {
243
		struct device *dev = hisi_hba->dev;
J
John Garry 已提交
244

245 246 247 248 249
		if (!task->lldd_task)
			return;

		task->lldd_task = NULL;

250 251 252 253
		if (!sas_protocol_ata(task->task_proto)) {
			struct sas_ssp_task *ssp_task = &task->ssp_task;
			struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;

254
			if (slot->n_elem)
255 256
				dma_unmap_sg(dev, task->scatter,
					     task->num_scatter,
257
					     task->data_dir);
258 259 260 261 262
			if (slot->n_elem_dif)
				dma_unmap_sg(dev, scsi_prot_sglist(scsi_cmnd),
					     scsi_prot_sg_count(scsi_cmnd),
					     task->data_dir);
		}
263
	}
J
John Garry 已提交
264

265
	spin_lock_irqsave(&sas_dev->lock, flags);
J
John Garry 已提交
266
	list_del_init(&slot->entry);
267
	spin_unlock_irqrestore(&sas_dev->lock, flags);
268 269 270

	memset(slot, 0, offsetof(struct hisi_sas_slot, buf));

J
John Garry 已提交
271 272 273 274
	hisi_sas_slot_index_free(hisi_hba, slot->idx);
}
EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free);

275
static void hisi_sas_task_prep_smp(struct hisi_hba *hisi_hba,
J
John Garry 已提交
276 277
				  struct hisi_sas_slot *slot)
{
278
	hisi_hba->hw->prep_smp(hisi_hba, slot);
J
John Garry 已提交
279 280
}

281
static void hisi_sas_task_prep_ssp(struct hisi_hba *hisi_hba,
282
				  struct hisi_sas_slot *slot)
J
John Garry 已提交
283
{
284
	hisi_hba->hw->prep_ssp(hisi_hba, slot);
J
John Garry 已提交
285 286
}

287
static void hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba,
288 289
				  struct hisi_sas_slot *slot)
{
290
	hisi_hba->hw->prep_stp(hisi_hba, slot);
291 292
}

293
static void hisi_sas_task_prep_abort(struct hisi_hba *hisi_hba,
294 295 296
		struct hisi_sas_slot *slot,
		int device_id, int abort_flag, int tag_to_abort)
{
297
	hisi_hba->hw->prep_abort(hisi_hba, slot,
298 299 300
			device_id, abort_flag, tag_to_abort);
}

301 302
static void hisi_sas_dma_unmap(struct hisi_hba *hisi_hba,
			       struct sas_task *task, int n_elem,
303
			       int n_elem_req)
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
{
	struct device *dev = hisi_hba->dev;

	if (!sas_protocol_ata(task->task_proto)) {
		if (task->num_scatter) {
			if (n_elem)
				dma_unmap_sg(dev, task->scatter,
					     task->num_scatter,
					     task->data_dir);
		} else if (task->task_proto & SAS_PROTOCOL_SMP) {
			if (n_elem_req)
				dma_unmap_sg(dev, &task->smp_task.smp_req,
					     1, DMA_TO_DEVICE);
		}
	}
}

static int hisi_sas_dma_map(struct hisi_hba *hisi_hba,
			    struct sas_task *task, int *n_elem,
323
			    int *n_elem_req)
324 325 326 327 328 329 330
{
	struct device *dev = hisi_hba->dev;
	int rc;

	if (sas_protocol_ata(task->task_proto)) {
		*n_elem = task->num_scatter;
	} else {
331
		unsigned int req_len;
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365

		if (task->num_scatter) {
			*n_elem = dma_map_sg(dev, task->scatter,
					     task->num_scatter, task->data_dir);
			if (!*n_elem) {
				rc = -ENOMEM;
				goto prep_out;
			}
		} else if (task->task_proto & SAS_PROTOCOL_SMP) {
			*n_elem_req = dma_map_sg(dev, &task->smp_task.smp_req,
						 1, DMA_TO_DEVICE);
			if (!*n_elem_req) {
				rc = -ENOMEM;
				goto prep_out;
			}
			req_len = sg_dma_len(&task->smp_task.smp_req);
			if (req_len & 0x3) {
				rc = -EINVAL;
				goto err_out_dma_unmap;
			}
		}
	}

	if (*n_elem > HISI_SAS_SGE_PAGE_CNT) {
		dev_err(dev, "task prep: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT",
			*n_elem);
		rc = -EINVAL;
		goto err_out_dma_unmap;
	}
	return 0;

err_out_dma_unmap:
	/* It would be better to call dma_unmap_sg() here, but it's messy */
	hisi_sas_dma_unmap(hisi_hba, task, *n_elem,
366
			   *n_elem_req);
367 368 369 370
prep_out:
	return rc;
}

371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
static void hisi_sas_dif_dma_unmap(struct hisi_hba *hisi_hba,
				   struct sas_task *task, int n_elem_dif)
{
	struct device *dev = hisi_hba->dev;

	if (n_elem_dif) {
		struct sas_ssp_task *ssp_task = &task->ssp_task;
		struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;

		dma_unmap_sg(dev, scsi_prot_sglist(scsi_cmnd),
			     scsi_prot_sg_count(scsi_cmnd),
			     task->data_dir);
	}
}

static int hisi_sas_dif_dma_map(struct hisi_hba *hisi_hba,
				int *n_elem_dif, struct sas_task *task)
{
	struct device *dev = hisi_hba->dev;
	struct sas_ssp_task *ssp_task;
	struct scsi_cmnd *scsi_cmnd;
	int rc;

	if (task->num_scatter) {
		ssp_task = &task->ssp_task;
		scsi_cmnd = ssp_task->cmd;

		if (scsi_prot_sg_count(scsi_cmnd)) {
			*n_elem_dif = dma_map_sg(dev,
						 scsi_prot_sglist(scsi_cmnd),
						 scsi_prot_sg_count(scsi_cmnd),
						 task->data_dir);

			if (!*n_elem_dif)
				return -ENOMEM;

			if (*n_elem_dif > HISI_SAS_SGE_DIF_PAGE_CNT) {
				dev_err(dev, "task prep: n_elem_dif(%d) too large\n",
					*n_elem_dif);
				rc = -EINVAL;
				goto err_out_dif_dma_unmap;
			}
		}
	}

	return 0;

err_out_dif_dma_unmap:
	dma_unmap_sg(dev, scsi_prot_sglist(scsi_cmnd),
		     scsi_prot_sg_count(scsi_cmnd), task->data_dir);
	return rc;
}

424 425
static int hisi_sas_task_prep(struct sas_task *task,
			      struct hisi_sas_dq **dq_pointer,
426
			      bool is_tmf, struct hisi_sas_tmf_task *tmf,
427
			      int *pass)
J
John Garry 已提交
428 429
{
	struct domain_device *device = task->dev;
430
	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
J
John Garry 已提交
431 432 433 434
	struct hisi_sas_device *sas_dev = device->lldd_dev;
	struct hisi_sas_port *port;
	struct hisi_sas_slot *slot;
	struct hisi_sas_cmd_hdr	*cmd_hdr_base;
435
	struct asd_sas_port *sas_port = device->port;
436
	struct device *dev = hisi_hba->dev;
X
Xiang Chen 已提交
437
	int dlvry_queue_slot, dlvry_queue, rc, slot_idx;
438
	int n_elem = 0, n_elem_dif = 0, n_elem_req = 0;
439
	struct hisi_sas_dq *dq;
440
	unsigned long flags;
441
	int wr_q_index;
J
John Garry 已提交
442 443 444

	if (DEV_IS_GONE(sas_dev)) {
		if (sas_dev)
445
			dev_info(dev, "task prep: device %d not ready\n",
J
John Garry 已提交
446 447 448 449 450
				 sas_dev->device_id);
		else
			dev_info(dev, "task prep: device %016llx not ready\n",
				 SAS_ADDR(device->sas_addr));

451
		return -ECOMM;
J
John Garry 已提交
452
	}
453

454 455 456 457 458 459 460 461
	if (hisi_hba->reply_map) {
		int cpu = raw_smp_processor_id();
		unsigned int dq_index = hisi_hba->reply_map[cpu];

		*dq_pointer = dq = &hisi_hba->dq[dq_index];
	} else {
		*dq_pointer = dq = sas_dev->dq;
	}
462

463
	port = to_hisi_sas_port(sas_port);
464
	if (port && !port->port_attached) {
465
		dev_info(dev, "task prep: %s port%d not attach device\n",
466
			 (dev_is_sata(device)) ?
467 468 469
			 "SATA/STP" : "SAS",
			 device->port->id);

470
		return -ECOMM;
J
John Garry 已提交
471 472
	}

473
	rc = hisi_sas_dma_map(hisi_hba, task, &n_elem,
474
			      &n_elem_req);
475 476
	if (rc < 0)
		goto prep_out;
477

478 479 480 481 482 483
	if (!sas_protocol_ata(task->task_proto)) {
		rc = hisi_sas_dif_dma_map(hisi_hba, &n_elem_dif, task);
		if (rc < 0)
			goto err_out_dma_unmap;
	}

484
	if (hisi_hba->hw->slot_index_alloc)
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
		rc = hisi_hba->hw->slot_index_alloc(hisi_hba, device);
	else {
		struct scsi_cmnd *scsi_cmnd = NULL;

		if (task->uldd_task) {
			struct ata_queued_cmd *qc;

			if (dev_is_sata(device)) {
				qc = task->uldd_task;
				scsi_cmnd = qc->scsicmd;
			} else {
				scsi_cmnd = task->uldd_task;
			}
		}
		rc  = hisi_sas_slot_index_alloc(hisi_hba, scsi_cmnd);
	}
	if (rc < 0)
502
		goto err_out_dif_dma_unmap;
503

504
	slot_idx = rc;
505 506
	slot = &hisi_hba->slot_info[slot_idx];

507
	spin_lock_irqsave(&dq->lock, flags);
508 509
	wr_q_index = dq->wr_point;
	dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS;
510
	list_add_tail(&slot->delivery, &dq->list);
511
	spin_unlock_irqrestore(&dq->lock, flags);
512 513 514
	spin_lock_irqsave(&sas_dev->lock, flags);
	list_add_tail(&slot->entry, &sas_dev->list);
	spin_unlock_irqrestore(&sas_dev->lock, flags);
J
John Garry 已提交
515

516
	dlvry_queue = dq->id;
517
	dlvry_queue_slot = wr_q_index;
J
John Garry 已提交
518

519
	slot->device_id = sas_dev->device_id;
J
John Garry 已提交
520
	slot->n_elem = n_elem;
521
	slot->n_elem_dif = n_elem_dif;
J
John Garry 已提交
522 523 524 525 526 527
	slot->dlvry_queue = dlvry_queue;
	slot->dlvry_queue_slot = dlvry_queue_slot;
	cmd_hdr_base = hisi_hba->cmd_hdr[dlvry_queue];
	slot->cmd_hdr = &cmd_hdr_base[dlvry_queue_slot];
	slot->task = task;
	slot->port = port;
528 529
	slot->tmf = tmf;
	slot->is_internal = is_tmf;
J
John Garry 已提交
530 531 532
	task->lldd_task = slot;

	memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr));
533
	memset(hisi_sas_cmd_hdr_addr_mem(slot), 0, HISI_SAS_COMMAND_TABLE_SZ);
534 535
	memset(hisi_sas_status_buf_addr_mem(slot), 0,
	       sizeof(struct hisi_sas_err_record));
J
John Garry 已提交
536 537

	switch (task->task_proto) {
J
John Garry 已提交
538
	case SAS_PROTOCOL_SMP:
539
		hisi_sas_task_prep_smp(hisi_hba, slot);
J
John Garry 已提交
540
		break;
J
John Garry 已提交
541
	case SAS_PROTOCOL_SSP:
542
		hisi_sas_task_prep_ssp(hisi_hba, slot);
J
John Garry 已提交
543 544 545 546
		break;
	case SAS_PROTOCOL_SATA:
	case SAS_PROTOCOL_STP:
	case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
547
		hisi_sas_task_prep_ata(hisi_hba, slot);
548
		break;
J
John Garry 已提交
549 550 551 552 553 554
	default:
		dev_err(dev, "task prep: unknown/unsupported proto (0x%x)\n",
			task->task_proto);
		break;
	}

555
	spin_lock_irqsave(&task->task_state_lock, flags);
J
John Garry 已提交
556
	task->task_state_flags |= SAS_TASK_AT_INITIATOR;
557
	spin_unlock_irqrestore(&task->task_state_lock, flags);
J
John Garry 已提交
558 559

	++(*pass);
560
	WRITE_ONCE(slot->ready, 1);
J
John Garry 已提交
561

562
	return 0;
J
John Garry 已提交
563

564 565 566
err_out_dif_dma_unmap:
	if (!sas_protocol_ata(task->task_proto))
		hisi_sas_dif_dma_unmap(hisi_hba, task, n_elem_dif);
X
Xiang Chen 已提交
567
err_out_dma_unmap:
568
	hisi_sas_dma_unmap(hisi_hba, task, n_elem,
569
			   n_elem_req);
J
John Garry 已提交
570
prep_out:
X
Xiang Chen 已提交
571
	dev_err(dev, "task prep: failed[%d]!\n", rc);
J
John Garry 已提交
572 573 574 575
	return rc;
}

static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags,
576
			      bool is_tmf, struct hisi_sas_tmf_task *tmf)
J
John Garry 已提交
577 578 579 580
{
	u32 rc;
	u32 pass = 0;
	unsigned long flags;
581 582 583 584
	struct hisi_hba *hisi_hba;
	struct device *dev;
	struct domain_device *device = task->dev;
	struct asd_sas_port *sas_port = device->port;
585
	struct hisi_sas_dq *dq = NULL;
J
John Garry 已提交
586

587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
	if (!sas_port) {
		struct task_status_struct *ts = &task->task_status;

		ts->resp = SAS_TASK_UNDELIVERED;
		ts->stat = SAS_PHY_DOWN;
		/*
		 * libsas will use dev->port, should
		 * not call task_done for sata
		 */
		if (device->dev_type != SAS_SATA_DEV)
			task->task_done(task);
		return -ECOMM;
	}

	hisi_hba = dev_to_hisi_hba(device);
	dev = hisi_hba->dev;

604 605 606 607 608 609 610
	if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) {
		if (in_softirq())
			return -EINVAL;

		down(&hisi_hba->sem);
		up(&hisi_hba->sem);
	}
611

J
John Garry 已提交
612
	/* protect task_prep and start_delivery sequence */
613
	rc = hisi_sas_task_prep(task, &dq, is_tmf, tmf, &pass);
J
John Garry 已提交
614 615 616
	if (rc)
		dev_err(dev, "task exec: failed[%d]!\n", rc);

617 618
	if (likely(pass)) {
		spin_lock_irqsave(&dq->lock, flags);
619
		hisi_hba->hw->start_delivery(dq);
620 621
		spin_unlock_irqrestore(&dq->lock, flags);
	}
J
John Garry 已提交
622 623 624

	return rc;
}
J
John Garry 已提交
625

626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no)
{
	struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
	struct asd_sas_phy *sas_phy = &phy->sas_phy;
	struct sas_ha_struct *sas_ha;

	if (!phy->phy_attached)
		return;

	sas_ha = &hisi_hba->sha;
	sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE);

	if (sas_phy->phy) {
		struct sas_phy *sphy = sas_phy->phy;

		sphy->negotiated_linkrate = sas_phy->linkrate;
		sphy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
643 644 645 646 647 648 649
		sphy->maximum_linkrate_hw =
			hisi_hba->hw->phy_get_max_linkrate();
		if (sphy->minimum_linkrate == SAS_LINK_RATE_UNKNOWN)
			sphy->minimum_linkrate = phy->minimum_linkrate;

		if (sphy->maximum_linkrate == SAS_LINK_RATE_UNKNOWN)
			sphy->maximum_linkrate = phy->maximum_linkrate;
650 651 652 653 654 655 656 657 658 659
	}

	if (phy->phy_type & PORT_TYPE_SAS) {
		struct sas_identify_frame *id;

		id = (struct sas_identify_frame *)phy->frame_rcvd;
		id->dev_type = phy->identify.device_type;
		id->initiator_bits = SAS_PROTOCOL_ALL;
		id->target_bits = phy->identify.target_port_protocols;
	} else if (phy->phy_type & PORT_TYPE_SATA) {
X
Xiang Chen 已提交
660
		/* Nothing */
661 662 663 664 665 666
	}

	sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
	sas_ha->notify_port_event(sas_phy, PORTE_BYTES_DMAED);
}

J
John Garry 已提交
667 668 669 670
static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
{
	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
	struct hisi_sas_device *sas_dev = NULL;
671
	unsigned long flags;
672 673
	int last = hisi_hba->last_dev_id;
	int first = (hisi_hba->last_dev_id + 1) % HISI_SAS_MAX_DEVICES;
J
John Garry 已提交
674 675
	int i;

676
	spin_lock_irqsave(&hisi_hba->lock, flags);
677
	for (i = first; i != last; i %= HISI_SAS_MAX_DEVICES) {
J
John Garry 已提交
678
		if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) {
679 680 681
			int queue = i % hisi_hba->queue_count;
			struct hisi_sas_dq *dq = &hisi_hba->dq[queue];

J
John Garry 已提交
682 683
			hisi_hba->devices[i].device_id = i;
			sas_dev = &hisi_hba->devices[i];
684
			sas_dev->dev_status = HISI_SAS_DEV_INIT;
J
John Garry 已提交
685 686 687
			sas_dev->dev_type = device->dev_type;
			sas_dev->hisi_hba = hisi_hba;
			sas_dev->sas_device = device;
688
			sas_dev->dq = dq;
689
			spin_lock_init(&sas_dev->lock);
690
			INIT_LIST_HEAD(&hisi_hba->devices[i].list);
J
John Garry 已提交
691 692
			break;
		}
693
		i++;
J
John Garry 已提交
694
	}
695
	hisi_hba->last_dev_id = i;
696
	spin_unlock_irqrestore(&hisi_hba->lock, flags);
J
John Garry 已提交
697 698 699 700

	return sas_dev;
}

701 702 703 704 705 706 707 708
#define HISI_SAS_SRST_ATA_DISK_CNT 3
static int hisi_sas_init_device(struct domain_device *device)
{
	int rc = TMF_RESP_FUNC_COMPLETE;
	struct scsi_lun lun;
	struct hisi_sas_tmf_task tmf_task;
	int retry = HISI_SAS_SRST_ATA_DISK_CNT;
	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
709 710
	struct device *dev = hisi_hba->dev;
	struct sas_phy *local_phy;
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725

	switch (device->dev_type) {
	case SAS_END_DEVICE:
		int_to_scsilun(0, &lun);

		tmf_task.tmf = TMF_CLEAR_TASK_SET;
		rc = hisi_sas_debug_issue_ssp_tmf(device, lun.scsi_lun,
						  &tmf_task);
		if (rc == TMF_RESP_FUNC_COMPLETE)
			hisi_sas_release_task(hisi_hba, device);
		break;
	case SAS_SATA_DEV:
	case SAS_SATA_PM:
	case SAS_SATA_PM_PORT:
	case SAS_SATA_PENDING:
726 727 728 729 730
		/*
		 * send HARD RESET to clear previous affiliation of
		 * STP target port
		 */
		local_phy = sas_get_local_phy(device);
731 732
		if (!scsi_is_sas_phy_local(local_phy) &&
		    !test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) {
733 734 735 736 737 738 739 740 741 742 743 744 745 746
			unsigned long deadline = ata_deadline(jiffies, 20000);
			struct sata_device *sata_dev = &device->sata_dev;
			struct ata_host *ata_host = sata_dev->ata_host;
			struct ata_port_operations *ops = ata_host->ops;
			struct ata_port *ap = sata_dev->ap;
			struct ata_link *link;
			unsigned int classes;

			ata_for_each_link(link, ap, EDGE)
				rc = ops->hardreset(link, &classes,
						    deadline);
		}
		sas_put_local_phy(local_phy);
		if (rc) {
747
			dev_warn(dev, "SATA disk hardreset fail: %d\n", rc);
748 749 750
			return rc;
		}

751 752 753 754 755 756 757 758 759 760 761 762 763
		while (retry-- > 0) {
			rc = hisi_sas_softreset_ata_disk(device);
			if (!rc)
				break;
		}
		break;
	default:
		break;
	}

	return rc;
}

J
John Garry 已提交
764 765 766 767 768
static int hisi_sas_dev_found(struct domain_device *device)
{
	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
	struct domain_device *parent_dev = device->parent;
	struct hisi_sas_device *sas_dev;
769
	struct device *dev = hisi_hba->dev;
770
	int rc;
J
John Garry 已提交
771

772 773 774 775
	if (hisi_hba->hw->alloc_dev)
		sas_dev = hisi_hba->hw->alloc_dev(device);
	else
		sas_dev = hisi_sas_alloc_dev(device);
J
John Garry 已提交
776 777 778 779 780 781 782 783 784
	if (!sas_dev) {
		dev_err(dev, "fail alloc dev: max support %d devices\n",
			HISI_SAS_MAX_DEVICES);
		return -EINVAL;
	}

	device->lldd_dev = sas_dev;
	hisi_hba->hw->setup_itct(hisi_hba, sas_dev);

785
	if (parent_dev && dev_is_expander(parent_dev->dev_type)) {
J
John Garry 已提交
786 787 788 789 790 791 792
		int phy_no;
		u8 phy_num = parent_dev->ex_dev.num_phys;
		struct ex_phy *phy;

		for (phy_no = 0; phy_no < phy_num; phy_no++) {
			phy = &parent_dev->ex_dev.ex_phy[phy_no];
			if (SAS_ADDR(phy->attached_sas_addr) ==
793
				SAS_ADDR(device->sas_addr))
J
John Garry 已提交
794 795 796 797 798 799 800 801
				break;
		}

		if (phy_no == phy_num) {
			dev_info(dev, "dev found: no attached "
				 "dev:%016llx at ex:%016llx\n",
				 SAS_ADDR(device->sas_addr),
				 SAS_ADDR(parent_dev->sas_addr));
802 803
			rc = -EINVAL;
			goto err_out;
J
John Garry 已提交
804 805 806
		}
	}

807 808 809
	dev_info(dev, "dev[%d:%x] found\n",
		sas_dev->device_id, sas_dev->dev_type);

810 811 812
	rc = hisi_sas_init_device(device);
	if (rc)
		goto err_out;
813
	sas_dev->dev_status = HISI_SAS_DEV_NORMAL;
J
John Garry 已提交
814
	return 0;
815 816 817 818

err_out:
	hisi_sas_dev_gone(device);
	return rc;
J
John Garry 已提交
819 820
}

821
int hisi_sas_slave_configure(struct scsi_device *sdev)
822 823 824 825 826 827 828 829 830 831 832
{
	struct domain_device *dev = sdev_to_domain_dev(sdev);
	int ret = sas_slave_configure(sdev);

	if (ret)
		return ret;
	if (!dev_is_sata(dev))
		sas_change_queue_depth(sdev, 64);

	return 0;
}
833
EXPORT_SYMBOL_GPL(hisi_sas_slave_configure);
834

835
void hisi_sas_scan_start(struct Scsi_Host *shost)
J
John Garry 已提交
836 837 838
{
	struct hisi_hba *hisi_hba = shost_priv(shost);

839
	hisi_hba->hw->phys_init(hisi_hba);
J
John Garry 已提交
840
}
841
EXPORT_SYMBOL_GPL(hisi_sas_scan_start);
J
John Garry 已提交
842

843
int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
J
John Garry 已提交
844 845 846 847
{
	struct hisi_hba *hisi_hba = shost_priv(shost);
	struct sas_ha_struct *sha = &hisi_hba->sha;

848 849
	/* Wait for PHY up interrupt to occur */
	if (time < HZ)
J
John Garry 已提交
850 851 852 853 854
		return 0;

	sas_drain_work(sha);
	return 1;
}
855
EXPORT_SYMBOL_GPL(hisi_sas_scan_finished);
J
John Garry 已提交
856

857 858 859
static void hisi_sas_phyup_work(struct work_struct *work)
{
	struct hisi_sas_phy *phy =
860
		container_of(work, typeof(*phy), works[HISI_PHYE_PHY_UP]);
861 862 863 864
	struct hisi_hba *hisi_hba = phy->hisi_hba;
	struct asd_sas_phy *sas_phy = &phy->sas_phy;
	int phy_no = sas_phy->id;

865 866
	if (phy->identify.target_port_protocols == SAS_PROTOCOL_SSP)
		hisi_hba->hw->sl_notify_ssp(hisi_hba, phy_no);
867 868
	hisi_sas_bytes_dmaed(hisi_hba, phy_no);
}
J
John Garry 已提交
869

870 871 872 873 874 875 876 877 878
static void hisi_sas_linkreset_work(struct work_struct *work)
{
	struct hisi_sas_phy *phy =
		container_of(work, typeof(*phy), works[HISI_PHYE_LINK_RESET]);
	struct asd_sas_phy *sas_phy = &phy->sas_phy;

	hisi_sas_control_phy(sas_phy, PHY_FUNC_LINK_RESET, NULL);
}

879 880
static const work_func_t hisi_sas_phye_fns[HISI_PHYES_NUM] = {
	[HISI_PHYE_PHY_UP] = hisi_sas_phyup_work,
881
	[HISI_PHYE_LINK_RESET] = hisi_sas_linkreset_work,
882 883 884 885 886 887 888 889 890 891 892 893 894 895
};

bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy,
				enum hisi_sas_phy_event event)
{
	struct hisi_hba *hisi_hba = phy->hisi_hba;

	if (WARN_ON(event >= HISI_PHYES_NUM))
		return false;

	return queue_work(hisi_hba->wq, &phy->works[event]);
}
EXPORT_SYMBOL_GPL(hisi_sas_notify_phy_event);

896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
static void hisi_sas_wait_phyup_timedout(struct timer_list *t)
{
	struct hisi_sas_phy *phy = from_timer(phy, t, timer);
	struct hisi_hba *hisi_hba = phy->hisi_hba;
	struct device *dev = hisi_hba->dev;
	int phy_no = phy->sas_phy.id;

	dev_warn(dev, "phy%d wait phyup timeout, issuing link reset\n", phy_no);
	hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET);
}

void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no)
{
	struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
	struct device *dev = hisi_hba->dev;

	if (!timer_pending(&phy->timer)) {
		dev_dbg(dev, "phy%d OOB ready\n", phy_no);
		phy->timer.expires = jiffies + HISI_SAS_WAIT_PHYUP_TIMEOUT * HZ;
		add_timer(&phy->timer);
	}
}
EXPORT_SYMBOL_GPL(hisi_sas_phy_oob_ready);

J
John Garry 已提交
920 921 922 923
static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no)
{
	struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
	struct asd_sas_phy *sas_phy = &phy->sas_phy;
924
	int i;
J
John Garry 已提交
925 926 927

	phy->hisi_hba = hisi_hba;
	phy->port = NULL;
928 929
	phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
	phy->maximum_linkrate = hisi_hba->hw->phy_get_max_linkrate();
J
John Garry 已提交
930 931 932 933 934 935 936 937 938 939 940 941 942
	sas_phy->enabled = (phy_no < hisi_hba->n_phy) ? 1 : 0;
	sas_phy->class = SAS;
	sas_phy->iproto = SAS_PROTOCOL_ALL;
	sas_phy->tproto = 0;
	sas_phy->type = PHY_TYPE_PHYSICAL;
	sas_phy->role = PHY_ROLE_INITIATOR;
	sas_phy->oob_mode = OOB_NOT_CONNECTED;
	sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
	sas_phy->id = phy_no;
	sas_phy->sas_addr = &hisi_hba->sas_addr[0];
	sas_phy->frame_rcvd = &phy->frame_rcvd[0];
	sas_phy->ha = (struct sas_ha_struct *)hisi_hba->shost->hostdata;
	sas_phy->lldd_phy = phy;
943

944 945
	for (i = 0; i < HISI_PHYES_NUM; i++)
		INIT_WORK(&phy->works[i], hisi_sas_phye_fns[i]);
946 947

	spin_lock_init(&phy->lock);
948 949

	timer_setup(&phy->timer, hisi_sas_wait_phyup_timedout, 0);
J
John Garry 已提交
950 951
}

952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975
/* Wrapper to ensure we track hisi_sas_phy.enable properly */
void hisi_sas_phy_enable(struct hisi_hba *hisi_hba, int phy_no, int enable)
{
	struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
	struct asd_sas_phy *aphy = &phy->sas_phy;
	struct sas_phy *sphy = aphy->phy;
	unsigned long flags;

	spin_lock_irqsave(&phy->lock, flags);

	if (enable) {
		/* We may have been enabled already; if so, don't touch */
		if (!phy->enable)
			sphy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
		hisi_hba->hw->phy_start(hisi_hba, phy_no);
	} else {
		sphy->negotiated_linkrate = SAS_PHY_DISABLED;
		hisi_hba->hw->phy_disable(hisi_hba, phy_no);
	}
	phy->enable = enable;
	spin_unlock_irqrestore(&phy->lock, flags);
}
EXPORT_SYMBOL_GPL(hisi_sas_phy_enable);

J
John Garry 已提交
976 977 978 979 980 981
static void hisi_sas_port_notify_formed(struct asd_sas_phy *sas_phy)
{
	struct sas_ha_struct *sas_ha = sas_phy->ha;
	struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
	struct hisi_sas_phy *phy = sas_phy->lldd_phy;
	struct asd_sas_port *sas_port = sas_phy->port;
982
	struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
J
John Garry 已提交
983 984 985 986 987 988 989 990 991 992 993 994 995
	unsigned long flags;

	if (!sas_port)
		return;

	spin_lock_irqsave(&hisi_hba->lock, flags);
	port->port_attached = 1;
	port->id = phy->port_id;
	phy->port = port;
	sas_port->lldd_port = port;
	spin_unlock_irqrestore(&hisi_hba->lock, flags);
}

996
static void hisi_sas_do_release_task(struct hisi_hba *hisi_hba, struct sas_task *task,
997
				     struct hisi_sas_slot *slot)
J
John Garry 已提交
998
{
999 1000 1001
	if (task) {
		unsigned long flags;
		struct task_status_struct *ts;
J
John Garry 已提交
1002

1003
		ts = &task->task_status;
J
John Garry 已提交
1004

1005 1006 1007 1008 1009
		ts->resp = SAS_TASK_COMPLETE;
		ts->stat = SAS_ABORTED_TASK;
		spin_lock_irqsave(&task->task_state_lock, flags);
		task->task_state_flags &=
			~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
1010 1011
		if (!slot->is_internal && task->task_proto != SAS_PROTOCOL_SMP)
			task->task_state_flags |= SAS_TASK_STATE_DONE;
1012 1013
		spin_unlock_irqrestore(&task->task_state_lock, flags);
	}
J
John Garry 已提交
1014

1015
	hisi_sas_slot_task_free(hisi_hba, task, slot);
J
John Garry 已提交
1016 1017 1018 1019 1020
}

static void hisi_sas_release_task(struct hisi_hba *hisi_hba,
			struct domain_device *device)
{
1021 1022
	struct hisi_sas_slot *slot, *slot2;
	struct hisi_sas_device *sas_dev = device->lldd_dev;
J
John Garry 已提交
1023

1024 1025
	list_for_each_entry_safe(slot, slot2, &sas_dev->list, entry)
		hisi_sas_do_release_task(hisi_hba, slot->task, slot);
J
John Garry 已提交
1026 1027
}

1028
void hisi_sas_release_tasks(struct hisi_hba *hisi_hba)
1029
{
1030 1031
	struct hisi_sas_device *sas_dev;
	struct domain_device *device;
1032 1033
	int i;

1034 1035 1036
	for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
		sas_dev = &hisi_hba->devices[i];
		device = sas_dev->sas_device;
1037

1038 1039
		if ((sas_dev->dev_type == SAS_PHY_UNUSED) ||
		    !device)
1040
			continue;
1041 1042

		hisi_sas_release_task(hisi_hba, device);
1043 1044
	}
}
1045
EXPORT_SYMBOL_GPL(hisi_sas_release_tasks);
1046

1047 1048 1049 1050 1051 1052 1053
static void hisi_sas_dereg_device(struct hisi_hba *hisi_hba,
				struct domain_device *device)
{
	if (hisi_hba->hw->dereg_device)
		hisi_hba->hw->dereg_device(hisi_hba, device);
}

J
John Garry 已提交
1054 1055 1056 1057
static void hisi_sas_dev_gone(struct domain_device *device)
{
	struct hisi_sas_device *sas_dev = device->lldd_dev;
	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
1058
	struct device *dev = hisi_hba->dev;
J
John Garry 已提交
1059

1060
	dev_info(dev, "dev[%d:%x] is gone\n",
J
John Garry 已提交
1061 1062
		 sas_dev->device_id, sas_dev->dev_type);

1063 1064
	if (!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) {
		hisi_sas_internal_task_abort(hisi_hba, device,
1065
					     HISI_SAS_INT_ABT_DEV, 0);
1066

1067 1068
		hisi_sas_dereg_device(hisi_hba, device);

1069
		down(&hisi_hba->sem);
1070
		hisi_hba->hw->clear_itct(hisi_hba, sas_dev);
1071
		up(&hisi_hba->sem);
1072 1073
		device->lldd_dev = NULL;
	}
1074

1075 1076
	if (hisi_hba->hw->free_device)
		hisi_hba->hw->free_device(sas_dev);
J
John Garry 已提交
1077 1078
	sas_dev->dev_type = SAS_PHY_UNUSED;
}
J
John Garry 已提交
1079 1080 1081 1082 1083 1084

static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags)
{
	return hisi_sas_task_exec(task, gfp_flags, 0, NULL);
}

1085
static int hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no,
1086 1087 1088 1089 1090 1091 1092 1093
			struct sas_phy_linkrates *r)
{
	struct sas_phy_linkrates _r;

	struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
	struct asd_sas_phy *sas_phy = &phy->sas_phy;
	enum sas_linkrate min, max;

1094 1095 1096
	if (r->minimum_linkrate > SAS_LINK_RATE_1_5_GBPS)
		return -EINVAL;

1097 1098 1099 1100 1101 1102 1103
	if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) {
		max = sas_phy->phy->maximum_linkrate;
		min = r->minimum_linkrate;
	} else if (r->minimum_linkrate == SAS_LINK_RATE_UNKNOWN) {
		max = r->maximum_linkrate;
		min = sas_phy->phy->minimum_linkrate;
	} else
1104
		return -EINVAL;
1105 1106 1107 1108

	_r.maximum_linkrate = max;
	_r.minimum_linkrate = min;

1109 1110 1111
	sas_phy->phy->maximum_linkrate = max;
	sas_phy->phy->minimum_linkrate = min;

1112
	hisi_sas_phy_enable(hisi_hba, phy_no, 0);
1113 1114
	msleep(100);
	hisi_hba->hw->phy_set_linkrate(hisi_hba, phy_no, &_r);
1115
	hisi_sas_phy_enable(hisi_hba, phy_no, 1);
1116 1117

	return 0;
1118 1119
}

J
John Garry 已提交
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
				void *funcdata)
{
	struct sas_ha_struct *sas_ha = sas_phy->ha;
	struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
	int phy_no = sas_phy->id;

	switch (func) {
	case PHY_FUNC_HARD_RESET:
		hisi_hba->hw->phy_hard_reset(hisi_hba, phy_no);
		break;

	case PHY_FUNC_LINK_RESET:
1133
		hisi_sas_phy_enable(hisi_hba, phy_no, 0);
1134
		msleep(100);
1135
		hisi_sas_phy_enable(hisi_hba, phy_no, 1);
J
John Garry 已提交
1136 1137 1138
		break;

	case PHY_FUNC_DISABLE:
1139
		hisi_sas_phy_enable(hisi_hba, phy_no, 0);
J
John Garry 已提交
1140 1141 1142
		break;

	case PHY_FUNC_SET_LINK_RATE:
1143
		return hisi_sas_phy_set_linkrate(hisi_hba, phy_no, funcdata);
1144 1145 1146 1147 1148 1149
	case PHY_FUNC_GET_EVENTS:
		if (hisi_hba->hw->get_events) {
			hisi_hba->hw->get_events(hisi_hba, phy_no);
			break;
		}
		/* fallthru */
J
John Garry 已提交
1150 1151 1152 1153 1154 1155
	case PHY_FUNC_RELEASE_SPINUP_HOLD:
	default:
		return -EOPNOTSUPP;
	}
	return 0;
}
J
John Garry 已提交
1156

J
John Garry 已提交
1157 1158
static void hisi_sas_task_done(struct sas_task *task)
{
1159
	del_timer(&task->slow_task->timer);
J
John Garry 已提交
1160 1161 1162
	complete(&task->slow_task->completion);
}

1163
static void hisi_sas_tmf_timedout(struct timer_list *t)
J
John Garry 已提交
1164
{
1165 1166
	struct sas_task_slow *slow = from_timer(slow, t, timer);
	struct sas_task *task = slow->task;
1167
	unsigned long flags;
1168
	bool is_completed = true;
1169 1170

	spin_lock_irqsave(&task->task_state_lock, flags);
1171
	if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
1172
		task->task_state_flags |= SAS_TASK_STATE_ABORTED;
1173 1174
		is_completed = false;
	}
1175
	spin_unlock_irqrestore(&task->task_state_lock, flags);
J
John Garry 已提交
1176

1177 1178
	if (!is_completed)
		complete(&task->slow_task->completion);
J
John Garry 已提交
1179 1180 1181 1182
}

#define TASK_TIMEOUT 20
#define TASK_RETRY 3
1183
#define INTERNAL_ABORT_TIMEOUT 6
J
John Garry 已提交
1184 1185 1186 1187 1188 1189
static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
					   void *parameter, u32 para_len,
					   struct hisi_sas_tmf_task *tmf)
{
	struct hisi_sas_device *sas_dev = device->lldd_dev;
	struct hisi_hba *hisi_hba = sas_dev->hisi_hba;
1190
	struct device *dev = hisi_hba->dev;
J
John Garry 已提交
1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201
	struct sas_task *task;
	int res, retry;

	for (retry = 0; retry < TASK_RETRY; retry++) {
		task = sas_alloc_slow_task(GFP_KERNEL);
		if (!task)
			return -ENOMEM;

		task->dev = device;
		task->task_proto = device->tproto;

1202 1203 1204 1205 1206 1207
		if (dev_is_sata(device)) {
			task->ata_task.device_control_reg_update = 1;
			memcpy(&task->ata_task.fis, parameter, para_len);
		} else {
			memcpy(&task->ssp_task, parameter, para_len);
		}
J
John Garry 已提交
1208 1209
		task->task_done = hisi_sas_task_done;

1210
		task->slow_task->timer.function = hisi_sas_tmf_timedout;
1211
		task->slow_task->timer.expires = jiffies + TASK_TIMEOUT * HZ;
J
John Garry 已提交
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
		add_timer(&task->slow_task->timer);

		res = hisi_sas_task_exec(task, GFP_KERNEL, 1, tmf);

		if (res) {
			del_timer(&task->slow_task->timer);
			dev_err(dev, "abort tmf: executing internal task failed: %d\n",
				res);
			goto ex_err;
		}

		wait_for_completion(&task->slow_task->completion);
		res = TMF_RESP_FUNC_FAILED;
		/* Even TMF timed out, return direct. */
		if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
			if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
1228 1229
				struct hisi_sas_slot *slot = task->lldd_task;

1230
				dev_err(dev, "abort tmf: TMF task timeout and not done\n");
1231
				if (slot) {
1232 1233
					struct hisi_sas_cq *cq =
					       &hisi_hba->cq[slot->dlvry_queue];
1234 1235 1236 1237 1238
					/*
					 * flush tasklet to avoid free'ing task
					 * before using task in IO completion
					 */
					tasklet_kill(&cq->tasklet);
1239
					slot->task = NULL;
1240
				}
1241

J
John Garry 已提交
1242
				goto ex_err;
1243 1244
			} else
				dev_err(dev, "abort tmf: TMF task timeout\n");
J
John Garry 已提交
1245 1246 1247
		}

		if (task->task_status.resp == SAS_TASK_COMPLETE &&
1248
		     task->task_status.stat == TMF_RESP_FUNC_COMPLETE) {
J
John Garry 已提交
1249 1250 1251 1252
			res = TMF_RESP_FUNC_COMPLETE;
			break;
		}

1253 1254 1255 1256 1257 1258
		if (task->task_status.resp == SAS_TASK_COMPLETE &&
			task->task_status.stat == TMF_RESP_FUNC_SUCC) {
			res = TMF_RESP_FUNC_SUCC;
			break;
		}

J
John Garry 已提交
1259 1260 1261 1262 1263
		if (task->task_status.resp == SAS_TASK_COMPLETE &&
		      task->task_status.stat == SAS_DATA_UNDERRUN) {
			/* no error, but return the number of bytes of
			 * underrun
			 */
1264
			dev_warn(dev, "abort tmf: task to dev %016llx resp: 0x%x sts 0x%x underrun\n",
J
John Garry 已提交
1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278
				 SAS_ADDR(device->sas_addr),
				 task->task_status.resp,
				 task->task_status.stat);
			res = task->task_status.residual;
			break;
		}

		if (task->task_status.resp == SAS_TASK_COMPLETE &&
			task->task_status.stat == SAS_DATA_OVERRUN) {
			dev_warn(dev, "abort tmf: blocked task error\n");
			res = -EMSGSIZE;
			break;
		}

1279 1280 1281 1282 1283 1284 1285 1286 1287 1288
		if (task->task_status.resp == SAS_TASK_COMPLETE &&
		    task->task_status.stat == SAS_OPEN_REJECT) {
			dev_warn(dev, "abort tmf: open reject failed\n");
			res = -EIO;
		} else {
			dev_warn(dev, "abort tmf: task to dev %016llx resp: 0x%x status 0x%x\n",
				 SAS_ADDR(device->sas_addr),
				 task->task_status.resp,
				 task->task_status.stat);
		}
J
John Garry 已提交
1289 1290 1291 1292
		sas_free_task(task);
		task = NULL;
	}
ex_err:
1293 1294
	if (retry == TASK_RETRY)
		dev_warn(dev, "abort tmf: executing internal task failed!\n");
J
John Garry 已提交
1295 1296 1297 1298
	sas_free_task(task);
	return res;
}

1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319
static void hisi_sas_fill_ata_reset_cmd(struct ata_device *dev,
		bool reset, int pmp, u8 *fis)
{
	struct ata_taskfile tf;

	ata_tf_init(dev, &tf);
	if (reset)
		tf.ctl |= ATA_SRST;
	else
		tf.ctl &= ~ATA_SRST;
	tf.command = ATA_CMD_DEV_RESET;
	ata_tf_to_fis(&tf, pmp, 0, fis);
}

static int hisi_sas_softreset_ata_disk(struct domain_device *device)
{
	u8 fis[20] = {0};
	struct ata_port *ap = device->sata_dev.ap;
	struct ata_link *link;
	int rc = TMF_RESP_FUNC_FAILED;
	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
1320
	struct device *dev = hisi_hba->dev;
1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345
	int s = sizeof(struct host_to_dev_fis);

	ata_for_each_link(link, ap, EDGE) {
		int pmp = sata_srst_pmp(link);

		hisi_sas_fill_ata_reset_cmd(link->device, 1, pmp, fis);
		rc = hisi_sas_exec_internal_tmf_task(device, fis, s, NULL);
		if (rc != TMF_RESP_FUNC_COMPLETE)
			break;
	}

	if (rc == TMF_RESP_FUNC_COMPLETE) {
		ata_for_each_link(link, ap, EDGE) {
			int pmp = sata_srst_pmp(link);

			hisi_sas_fill_ata_reset_cmd(link->device, 0, pmp, fis);
			rc = hisi_sas_exec_internal_tmf_task(device, fis,
							     s, NULL);
			if (rc != TMF_RESP_FUNC_COMPLETE)
				dev_err(dev, "ata disk de-reset failed\n");
		}
	} else {
		dev_err(dev, "ata disk reset failed\n");
	}

1346
	if (rc == TMF_RESP_FUNC_COMPLETE)
1347 1348 1349 1350 1351
		hisi_sas_release_task(hisi_hba, device);

	return rc;
}

J
John Garry 已提交
1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device,
				u8 *lun, struct hisi_sas_tmf_task *tmf)
{
	struct sas_ssp_task ssp_task;

	if (!(device->tproto & SAS_PROTOCOL_SSP))
		return TMF_RESP_FUNC_ESUPP;

	memcpy(ssp_task.LUN, lun, 8);

	return hisi_sas_exec_internal_tmf_task(device, &ssp_task,
				sizeof(ssp_task), tmf);
}

1366
static void hisi_sas_refresh_port_id(struct hisi_hba *hisi_hba)
1367
{
1368
	u32 state = hisi_hba->hw->get_phys_state(hisi_hba);
1369 1370 1371
	int i;

	for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
1372 1373 1374 1375 1376 1377 1378
		struct hisi_sas_device *sas_dev = &hisi_hba->devices[i];
		struct domain_device *device = sas_dev->sas_device;
		struct asd_sas_port *sas_port;
		struct hisi_sas_port *port;
		struct hisi_sas_phy *phy = NULL;
		struct asd_sas_phy *sas_phy;

1379
		if ((sas_dev->dev_type == SAS_PHY_UNUSED)
1380
				|| !device || !device->port)
1381 1382
			continue;

1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393
		sas_port = device->port;
		port = to_hisi_sas_port(sas_port);

		list_for_each_entry(sas_phy, &sas_port->phy_list, port_phy_el)
			if (state & BIT(sas_phy->id)) {
				phy = sas_phy->lldd_phy;
				break;
			}

		if (phy) {
			port->id = phy->port_id;
1394

1395 1396 1397
			/* Update linkrate of directly attached device. */
			if (!device->parent)
				device->linkrate = phy->sas_phy.linkrate;
1398

1399 1400 1401
			hisi_hba->hw->setup_itct(hisi_hba, sas_dev);
		} else
			port->id = 0xff;
1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
	}
}

static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 old_state,
			      u32 state)
{
	struct sas_ha_struct *sas_ha = &hisi_hba->sha;
	struct asd_sas_port *_sas_port = NULL;
	int phy_no;

	for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
		struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
		struct asd_sas_phy *sas_phy = &phy->sas_phy;
		struct asd_sas_port *sas_port = sas_phy->port;
		bool do_port_check = !!(_sas_port != sas_port);

		if (!sas_phy->phy->enabled)
			continue;

		/* Report PHY state change to libsas */
1422 1423
		if (state & BIT(phy_no)) {
			if (do_port_check && sas_port && sas_port->port_dev) {
1424 1425 1426 1427
				struct domain_device *dev = sas_port->port_dev;

				_sas_port = sas_port;

1428
				if (dev_is_expander(dev->dev_type))
1429 1430 1431
					sas_ha->notify_port_event(sas_phy,
							PORTE_BROADCAST_RCVD);
			}
1432
		} else {
1433
			hisi_sas_phy_down(hisi_hba, phy_no, 0);
1434
		}
1435 1436 1437 1438

	}
}

1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455
static void hisi_sas_reset_init_all_devices(struct hisi_hba *hisi_hba)
{
	struct hisi_sas_device *sas_dev;
	struct domain_device *device;
	int i;

	for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
		sas_dev = &hisi_hba->devices[i];
		device = sas_dev->sas_device;

		if ((sas_dev->dev_type == SAS_PHY_UNUSED) || !device)
			continue;

		hisi_sas_init_device(device);
	}
}

1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514
static void hisi_sas_send_ata_reset_each_phy(struct hisi_hba *hisi_hba,
					     struct asd_sas_port *sas_port,
					     struct domain_device *device)
{
	struct hisi_sas_tmf_task tmf_task = { .force_phy = 1 };
	struct ata_port *ap = device->sata_dev.ap;
	struct device *dev = hisi_hba->dev;
	int s = sizeof(struct host_to_dev_fis);
	int rc = TMF_RESP_FUNC_FAILED;
	struct asd_sas_phy *sas_phy;
	struct ata_link *link;
	u8 fis[20] = {0};
	u32 state;

	state = hisi_hba->hw->get_phys_state(hisi_hba);
	list_for_each_entry(sas_phy, &sas_port->phy_list, port_phy_el) {
		if (!(state & BIT(sas_phy->id)))
			continue;

		ata_for_each_link(link, ap, EDGE) {
			int pmp = sata_srst_pmp(link);

			tmf_task.phy_id = sas_phy->id;
			hisi_sas_fill_ata_reset_cmd(link->device, 1, pmp, fis);
			rc = hisi_sas_exec_internal_tmf_task(device, fis, s,
							     &tmf_task);
			if (rc != TMF_RESP_FUNC_COMPLETE) {
				dev_err(dev, "phy%d ata reset failed rc=%d\n",
					sas_phy->id, rc);
				break;
			}
		}
	}
}

static void hisi_sas_terminate_stp_reject(struct hisi_hba *hisi_hba)
{
	struct device *dev = hisi_hba->dev;
	int port_no, rc, i;

	for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
		struct hisi_sas_device *sas_dev = &hisi_hba->devices[i];
		struct domain_device *device = sas_dev->sas_device;

		if ((sas_dev->dev_type == SAS_PHY_UNUSED) || !device)
			continue;

		rc = hisi_sas_internal_task_abort(hisi_hba, device,
						  HISI_SAS_INT_ABT_DEV, 0);
		if (rc < 0)
			dev_err(dev, "STP reject: abort dev failed %d\n", rc);
	}

	for (port_no = 0; port_no < hisi_hba->n_phy; port_no++) {
		struct hisi_sas_port *port = &hisi_hba->port[port_no];
		struct asd_sas_port *sas_port = &port->sas_port;
		struct domain_device *port_dev = sas_port->port_dev;
		struct domain_device *device;

1515
		if (!port_dev || !dev_is_expander(port_dev->dev_type))
1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530
			continue;

		/* Try to find a SATA device */
		list_for_each_entry(device, &sas_port->dev_list,
				    dev_list_node) {
			if (dev_is_sata(device)) {
				hisi_sas_send_ata_reset_each_phy(hisi_hba,
								 sas_port,
								 device);
				break;
			}
		}
	}
}

1531
void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba)
1532
{
1533
	struct Scsi_Host *shost = hisi_hba->shost;
1534

1535
	down(&hisi_hba->sem);
1536
	hisi_hba->phy_state = hisi_hba->hw->get_phys_state(hisi_hba);
1537

1538
	scsi_block_requests(shost);
1539 1540
	hisi_hba->hw->wait_cmds_complete_timeout(hisi_hba, 100, 5000);

1541 1542 1543
	if (timer_pending(&hisi_hba->timer))
		del_timer_sync(&hisi_hba->timer);

1544
	set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
1545 1546 1547 1548 1549 1550 1551
}
EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_prepare);

void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba)
{
	struct Scsi_Host *shost = hisi_hba->shost;
	u32 state;
1552 1553 1554 1555

	/* Init and wait for PHYs to come up and all libsas event finished. */
	hisi_hba->hw->phys_init(hisi_hba);
	msleep(1000);
1556
	hisi_sas_refresh_port_id(hisi_hba);
1557
	clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
1558
	up(&hisi_hba->sem);
1559 1560 1561

	if (hisi_hba->reject_stp_links_msk)
		hisi_sas_terminate_stp_reject(hisi_hba);
1562
	hisi_sas_reset_init_all_devices(hisi_hba);
1563
	scsi_unblock_requests(shost);
1564
	clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
1565 1566

	state = hisi_hba->hw->get_phys_state(hisi_hba);
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576
	hisi_sas_rescan_topology(hisi_hba, hisi_hba->phy_state, state);
}
EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_done);

static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
{
	struct device *dev = hisi_hba->dev;
	struct Scsi_Host *shost = hisi_hba->shost;
	int rc;

1577
	if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct)
1578 1579
		queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);

1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599
	if (!hisi_hba->hw->soft_reset)
		return -1;

	if (test_and_set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags))
		return -1;

	dev_info(dev, "controller resetting...\n");
	hisi_sas_controller_reset_prepare(hisi_hba);

	rc = hisi_hba->hw->soft_reset(hisi_hba);
	if (rc) {
		dev_warn(dev, "controller reset failed (%d)\n", rc);
		clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
		up(&hisi_hba->sem);
		scsi_unblock_requests(shost);
		clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
		return rc;
	}

	hisi_sas_controller_reset_done(hisi_hba);
1600
	dev_info(dev, "controller reset complete\n");
1601

1602
	return 0;
1603 1604
}

J
John Garry 已提交
1605 1606 1607 1608 1609 1610
static int hisi_sas_abort_task(struct sas_task *task)
{
	struct scsi_lun lun;
	struct hisi_sas_tmf_task tmf_task;
	struct domain_device *device = task->dev;
	struct hisi_sas_device *sas_dev = device->lldd_dev;
1611 1612
	struct hisi_hba *hisi_hba;
	struct device *dev;
J
John Garry 已提交
1613 1614 1615
	int rc = TMF_RESP_FUNC_FAILED;
	unsigned long flags;

1616
	if (!sas_dev)
J
John Garry 已提交
1617
		return TMF_RESP_FUNC_FAILED;
1618 1619 1620

	hisi_hba = dev_to_hisi_hba(task->dev);
	dev = hisi_hba->dev;
J
John Garry 已提交
1621

1622
	spin_lock_irqsave(&task->task_state_lock, flags);
J
John Garry 已提交
1623
	if (task->task_state_flags & SAS_TASK_STATE_DONE) {
1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
		struct hisi_sas_slot *slot = task->lldd_task;
		struct hisi_sas_cq *cq;

		if (slot) {
			/*
			 * flush tasklet to avoid free'ing task
			 * before using task in IO completion
			 */
			cq = &hisi_hba->cq[slot->dlvry_queue];
			tasklet_kill(&cq->tasklet);
		}
1635
		spin_unlock_irqrestore(&task->task_state_lock, flags);
J
John Garry 已提交
1636 1637 1638
		rc = TMF_RESP_FUNC_COMPLETE;
		goto out;
	}
1639 1640
	task->task_state_flags |= SAS_TASK_STATE_ABORTED;
	spin_unlock_irqrestore(&task->task_state_lock, flags);
J
John Garry 已提交
1641 1642 1643 1644

	if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
		struct scsi_cmnd *cmnd = task->uldd_task;
		struct hisi_sas_slot *slot = task->lldd_task;
1645
		u16 tag = slot->idx;
1646
		int rc2;
J
John Garry 已提交
1647 1648 1649

		int_to_scsilun(cmnd->device->lun, &lun);
		tmf_task.tmf = TMF_ABORT_TASK;
1650
		tmf_task.tag_of_task_to_be_managed = tag;
J
John Garry 已提交
1651 1652 1653 1654

		rc = hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun,
						  &tmf_task);

1655 1656
		rc2 = hisi_sas_internal_task_abort(hisi_hba, device,
						   HISI_SAS_INT_ABT_CMD, tag);
1657 1658 1659 1660 1661
		if (rc2 < 0) {
			dev_err(dev, "abort task: internal abort (%d)\n", rc2);
			return TMF_RESP_FUNC_FAILED;
		}

1662 1663 1664 1665 1666 1667 1668 1669
		/*
		 * If the TMF finds that the IO is not in the device and also
		 * the internal abort does not succeed, then it is safe to
		 * free the slot.
		 * Note: if the internal abort succeeds then the slot
		 * will have already been completed
		 */
		if (rc == TMF_RESP_FUNC_COMPLETE && rc2 != TMF_RESP_FUNC_SUCC) {
1670
			if (task->lldd_task)
1671
				hisi_sas_do_release_task(hisi_hba, task, slot);
J
John Garry 已提交
1672 1673 1674 1675
		}
	} else if (task->task_proto & SAS_PROTOCOL_SATA ||
		task->task_proto & SAS_PROTOCOL_STP) {
		if (task->dev->dev_type == SAS_SATA_DEV) {
1676
			rc = hisi_sas_internal_task_abort(hisi_hba, device,
1677 1678
							  HISI_SAS_INT_ABT_DEV,
							  0);
1679 1680 1681 1682
			if (rc < 0) {
				dev_err(dev, "abort task: internal abort failed\n");
				goto out;
			}
1683
			hisi_sas_dereg_device(hisi_hba, device);
1684
			rc = hisi_sas_softreset_ata_disk(device);
J
John Garry 已提交
1685
		}
1686
	} else if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SMP) {
1687 1688 1689
		/* SMP */
		struct hisi_sas_slot *slot = task->lldd_task;
		u32 tag = slot->idx;
1690
		struct hisi_sas_cq *cq = &hisi_hba->cq[slot->dlvry_queue];
J
John Garry 已提交
1691

1692
		rc = hisi_sas_internal_task_abort(hisi_hba, device,
1693
						  HISI_SAS_INT_ABT_CMD, tag);
1694
		if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) &&
1695 1696 1697 1698 1699 1700 1701 1702
					task->lldd_task) {
			/*
			 * flush tasklet to avoid free'ing task
			 * before using task in IO completion
			 */
			tasklet_kill(&cq->tasklet);
			slot->task = NULL;
		}
J
John Garry 已提交
1703 1704 1705 1706 1707 1708 1709 1710 1711 1712
	}

out:
	if (rc != TMF_RESP_FUNC_COMPLETE)
		dev_notice(dev, "abort task: rc=%d\n", rc);
	return rc;
}

static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun)
{
1713 1714
	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
	struct device *dev = hisi_hba->dev;
J
John Garry 已提交
1715
	struct hisi_sas_tmf_task tmf_task;
X
Xiang Chen 已提交
1716
	int rc;
1717 1718

	rc = hisi_sas_internal_task_abort(hisi_hba, device,
1719
					  HISI_SAS_INT_ABT_DEV, 0);
1720 1721 1722 1723 1724
	if (rc < 0) {
		dev_err(dev, "abort task set: internal abort rc=%d\n", rc);
		return TMF_RESP_FUNC_FAILED;
	}
	hisi_sas_dereg_device(hisi_hba, device);
J
John Garry 已提交
1725 1726 1727 1728

	tmf_task.tmf = TMF_ABORT_TASK_SET;
	rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task);

1729
	if (rc == TMF_RESP_FUNC_COMPLETE)
1730 1731
		hisi_sas_release_task(hisi_hba, device);

J
John Garry 已提交
1732 1733 1734 1735 1736 1737
	return rc;
}

static int hisi_sas_clear_aca(struct domain_device *device, u8 *lun)
{
	struct hisi_sas_tmf_task tmf_task;
1738
	int rc;
J
John Garry 已提交
1739 1740 1741 1742 1743 1744 1745 1746 1747

	tmf_task.tmf = TMF_CLEAR_ACA;
	rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task);

	return rc;
}

static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
{
1748
	struct sas_phy *local_phy = sas_get_local_phy(device);
1749
	struct hisi_sas_device *sas_dev = device->lldd_dev;
1750 1751 1752
	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
	struct sas_ha_struct *sas_ha = &hisi_hba->sha;
	DECLARE_COMPLETION_ONSTACK(phyreset);
1753
	int rc, reset_type;
1754

1755 1756 1757 1758 1759
	if (!local_phy->enabled) {
		sas_put_local_phy(local_phy);
		return -ENODEV;
	}

1760
	if (scsi_is_sas_phy_local(local_phy)) {
1761 1762 1763 1764
		struct asd_sas_phy *sas_phy =
			sas_ha->sas_phy[local_phy->number];
		struct hisi_sas_phy *phy =
			container_of(sas_phy, struct hisi_sas_phy, sas_phy);
1765 1766 1767 1768
		phy->in_reset = 1;
		phy->reset_completion = &phyreset;
	}

1769
	reset_type = (sas_dev->dev_status == HISI_SAS_DEV_INIT ||
1770
		      !dev_is_sata(device)) ? true : false;
1771

1772 1773 1774 1775
	rc = sas_phy_reset(local_phy, reset_type);
	sas_put_local_phy(local_phy);

	if (scsi_is_sas_phy_local(local_phy)) {
1776 1777 1778 1779
		struct asd_sas_phy *sas_phy =
			sas_ha->sas_phy[local_phy->number];
		struct hisi_sas_phy *phy =
			container_of(sas_phy, struct hisi_sas_phy, sas_phy);
1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790
		int ret = wait_for_completion_timeout(&phyreset, 2 * HZ);
		unsigned long flags;

		spin_lock_irqsave(&phy->lock, flags);
		phy->reset_completion = NULL;
		phy->in_reset = 0;
		spin_unlock_irqrestore(&phy->lock, flags);

		/* report PHY down if timed out */
		if (!ret)
			hisi_sas_phy_down(hisi_hba, sas_phy->id, 0);
1791 1792 1793
	} else if (sas_dev->dev_status != HISI_SAS_DEV_INIT) {
		/*
		 * If in init state, we rely on caller to wait for link to be
1794
		 * ready; otherwise, except phy reset is fail, delay.
1795
		 */
1796 1797
		if (!rc)
			msleep(2000);
1798
	}
1799

J
John Garry 已提交
1800 1801 1802 1803 1804 1805
	return rc;
}

static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
{
	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
1806
	struct device *dev = hisi_hba->dev;
1807
	int rc;
J
John Garry 已提交
1808

1809
	rc = hisi_sas_internal_task_abort(hisi_hba, device,
1810
					  HISI_SAS_INT_ABT_DEV, 0);
1811 1812 1813 1814
	if (rc < 0) {
		dev_err(dev, "I_T nexus reset: internal abort (%d)\n", rc);
		return TMF_RESP_FUNC_FAILED;
	}
1815 1816
	hisi_sas_dereg_device(hisi_hba, device);

1817 1818
	if (dev_is_sata(device)) {
		rc = hisi_sas_softreset_ata_disk(device);
1819
		if (rc == TMF_RESP_FUNC_FAILED)
1820 1821 1822
			return TMF_RESP_FUNC_FAILED;
	}

J
John Garry 已提交
1823 1824
	rc = hisi_sas_debug_I_T_nexus_reset(device);

1825
	if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV))
1826
		hisi_sas_release_task(hisi_hba, device);
1827

1828
	return rc;
J
John Garry 已提交
1829 1830 1831 1832 1833 1834
}

static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
{
	struct hisi_sas_device *sas_dev = device->lldd_dev;
	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
1835
	struct device *dev = hisi_hba->dev;
J
John Garry 已提交
1836 1837
	int rc = TMF_RESP_FUNC_FAILED;

1838 1839 1840 1841 1842 1843 1844 1845 1846
	/* Clear internal IO and then lu reset */
	rc = hisi_sas_internal_task_abort(hisi_hba, device,
					  HISI_SAS_INT_ABT_DEV, 0);
	if (rc < 0) {
		dev_err(dev, "lu_reset: internal abort failed\n");
		goto out;
	}
	hisi_sas_dereg_device(hisi_hba, device);

1847 1848 1849 1850 1851
	if (dev_is_sata(device)) {
		struct sas_phy *phy;

		phy = sas_get_local_phy(device);

1852
		rc = sas_phy_reset(phy, true);
1853

1854
		if (rc == 0)
1855 1856 1857 1858 1859 1860
			hisi_sas_release_task(hisi_hba, device);
		sas_put_local_phy(phy);
	} else {
		struct hisi_sas_tmf_task tmf_task = { .tmf =  TMF_LU_RESET };

		rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task);
1861
		if (rc == TMF_RESP_FUNC_COMPLETE)
1862 1863 1864
			hisi_sas_release_task(hisi_hba, device);
	}
out:
1865
	if (rc != TMF_RESP_FUNC_COMPLETE)
1866
		dev_err(dev, "lu_reset: for device[%d]:rc= %d\n",
1867
			     sas_dev->device_id, rc);
J
John Garry 已提交
1868 1869 1870
	return rc;
}

1871 1872 1873
static int hisi_sas_clear_nexus_ha(struct sas_ha_struct *sas_ha)
{
	struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
1874
	struct device *dev = hisi_hba->dev;
1875
	HISI_SAS_DECLARE_RST_WORK_ON_STACK(r);
1876
	int rc, i;
1877

1878 1879
	queue_work(hisi_hba->wq, &r.work);
	wait_for_completion(r.completion);
1880 1881 1882 1883 1884 1885 1886 1887
	if (!r.done)
		return TMF_RESP_FUNC_FAILED;

	for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
		struct hisi_sas_device *sas_dev = &hisi_hba->devices[i];
		struct domain_device *device = sas_dev->sas_device;

		if ((sas_dev->dev_type == SAS_PHY_UNUSED) || !device ||
1888
		    dev_is_expander(device->dev_type))
1889 1890 1891 1892 1893 1894 1895 1896 1897
			continue;

		rc = hisi_sas_debug_I_T_nexus_reset(device);
		if (rc != TMF_RESP_FUNC_COMPLETE)
			dev_info(dev, "clear nexus ha: for device[%d] rc=%d\n",
				 sas_dev->device_id, rc);
	}

	hisi_sas_release_tasks(hisi_hba);
1898

1899
	return TMF_RESP_FUNC_COMPLETE;
1900 1901
}

J
John Garry 已提交
1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915
static int hisi_sas_query_task(struct sas_task *task)
{
	struct scsi_lun lun;
	struct hisi_sas_tmf_task tmf_task;
	int rc = TMF_RESP_FUNC_FAILED;

	if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
		struct scsi_cmnd *cmnd = task->uldd_task;
		struct domain_device *device = task->dev;
		struct hisi_sas_slot *slot = task->lldd_task;
		u32 tag = slot->idx;

		int_to_scsilun(cmnd->device->lun, &lun);
		tmf_task.tmf = TMF_QUERY_TASK;
1916
		tmf_task.tag_of_task_to_be_managed = tag;
J
John Garry 已提交
1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927

		rc = hisi_sas_debug_issue_ssp_tmf(device,
						  lun.scsi_lun,
						  &tmf_task);
		switch (rc) {
		/* The task is still in Lun, release it then */
		case TMF_RESP_FUNC_SUCC:
		/* The task is not in Lun or failed, reset the phy */
		case TMF_RESP_FUNC_FAILED:
		case TMF_RESP_FUNC_COMPLETE:
			break;
1928 1929 1930
		default:
			rc = TMF_RESP_FUNC_FAILED;
			break;
J
John Garry 已提交
1931 1932 1933 1934 1935
		}
	}
	return rc;
}

1936
static int
1937
hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
1938
				  struct sas_task *task, int abort_flag,
1939
				  int task_tag, struct hisi_sas_dq *dq)
1940 1941 1942
{
	struct domain_device *device = task->dev;
	struct hisi_sas_device *sas_dev = device->lldd_dev;
1943
	struct device *dev = hisi_hba->dev;
1944 1945
	struct hisi_sas_port *port;
	struct hisi_sas_slot *slot;
1946
	struct asd_sas_port *sas_port = device->port;
1947 1948
	struct hisi_sas_cmd_hdr *cmd_hdr_base;
	int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
1949
	unsigned long flags;
1950
	int wr_q_index;
1951

1952
	if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags)))
1953 1954
		return -EINVAL;

1955 1956 1957
	if (!device->port)
		return -1;

1958
	port = to_hisi_sas_port(sas_port);
1959 1960

	/* simply get a slot and send abort command */
1961 1962
	rc = hisi_sas_slot_index_alloc(hisi_hba, NULL);
	if (rc < 0)
1963
		goto err_out;
1964

1965
	slot_idx = rc;
1966
	slot = &hisi_hba->slot_info[slot_idx];
1967

1968 1969 1970
	spin_lock_irqsave(&dq->lock, flags);
	wr_q_index = dq->wr_point;
	dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS;
1971
	list_add_tail(&slot->delivery, &dq->list);
1972
	spin_unlock_irqrestore(&dq->lock, flags);
1973 1974 1975
	spin_lock_irqsave(&sas_dev->lock, flags);
	list_add_tail(&slot->entry, &sas_dev->list);
	spin_unlock_irqrestore(&sas_dev->lock, flags);
1976

1977
	dlvry_queue = dq->id;
1978
	dlvry_queue_slot = wr_q_index;
1979

1980
	slot->device_id = sas_dev->device_id;
1981 1982 1983 1984 1985 1986 1987
	slot->n_elem = n_elem;
	slot->dlvry_queue = dlvry_queue;
	slot->dlvry_queue_slot = dlvry_queue_slot;
	cmd_hdr_base = hisi_hba->cmd_hdr[dlvry_queue];
	slot->cmd_hdr = &cmd_hdr_base[dlvry_queue_slot];
	slot->task = task;
	slot->port = port;
1988
	slot->is_internal = true;
1989 1990 1991
	task->lldd_task = slot;

	memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr));
1992
	memset(hisi_sas_cmd_hdr_addr_mem(slot), 0, HISI_SAS_COMMAND_TABLE_SZ);
1993 1994
	memset(hisi_sas_status_buf_addr_mem(slot), 0,
	       sizeof(struct hisi_sas_err_record));
1995

1996
	hisi_sas_task_prep_abort(hisi_hba, slot, device_id,
1997 1998
				      abort_flag, task_tag);

1999
	spin_lock_irqsave(&task->task_state_lock, flags);
2000
	task->task_state_flags |= SAS_TASK_AT_INITIATOR;
2001
	spin_unlock_irqrestore(&task->task_state_lock, flags);
2002
	WRITE_ONCE(slot->ready, 1);
2003
	/* send abort command to the chip */
2004
	spin_lock_irqsave(&dq->lock, flags);
2005
	hisi_hba->hw->start_delivery(dq);
2006
	spin_unlock_irqrestore(&dq->lock, flags);
2007 2008 2009 2010 2011 2012 2013 2014 2015 2016

	return 0;

err_out:
	dev_err(dev, "internal abort task prep: failed[%d]!\n", rc);

	return rc;
}

/**
2017
 * _hisi_sas_internal_task_abort -- execute an internal
2018 2019 2020 2021 2022 2023
 * abort command for single IO command or a device
 * @hisi_hba: host controller struct
 * @device: domain device
 * @abort_flag: mode of operation, device or single IO
 * @tag: tag of IO to be aborted (only relevant to single
 *       IO mode)
2024
 * @dq: delivery queue for this internal abort command
2025 2026
 */
static int
2027 2028 2029
_hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
			      struct domain_device *device, int abort_flag,
			      int tag, struct hisi_sas_dq *dq)
2030 2031 2032
{
	struct sas_task *task;
	struct hisi_sas_device *sas_dev = device->lldd_dev;
2033
	struct device *dev = hisi_hba->dev;
2034 2035
	int res;

2036 2037 2038 2039 2040 2041
	/*
	 * The interface is not realized means this HW don't support internal
	 * abort, or don't need to do internal abort. Then here, we return
	 * TMF_RESP_FUNC_FAILED and let other steps go on, which depends that
	 * the internal abort has been executed and returned CQ.
	 */
2042
	if (!hisi_hba->hw->prep_abort)
2043
		return TMF_RESP_FUNC_FAILED;
2044 2045 2046 2047 2048 2049 2050 2051

	task = sas_alloc_slow_task(GFP_KERNEL);
	if (!task)
		return -ENOMEM;

	task->dev = device;
	task->task_proto = device->tproto;
	task->task_done = hisi_sas_task_done;
2052
	task->slow_task->timer.function = hisi_sas_tmf_timedout;
2053
	task->slow_task->timer.expires = jiffies + INTERNAL_ABORT_TIMEOUT * HZ;
2054 2055 2056
	add_timer(&task->slow_task->timer);

	res = hisi_sas_internal_abort_task_exec(hisi_hba, sas_dev->device_id,
2057
						task, abort_flag, tag, dq);
2058 2059 2060 2061 2062 2063 2064 2065 2066
	if (res) {
		del_timer(&task->slow_task->timer);
		dev_err(dev, "internal task abort: executing internal task failed: %d\n",
			res);
		goto exit;
	}
	wait_for_completion(&task->slow_task->completion);
	res = TMF_RESP_FUNC_FAILED;

2067 2068
	/* Internal abort timed out */
	if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
2069 2070 2071
		if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct)
			queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);

2072 2073
		if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
			struct hisi_sas_slot *slot = task->lldd_task;
2074 2075

			if (slot) {
2076 2077
				struct hisi_sas_cq *cq =
					&hisi_hba->cq[slot->dlvry_queue];
2078 2079 2080 2081 2082
				/*
				 * flush tasklet to avoid free'ing task
				 * before using task in IO completion
				 */
				tasklet_kill(&cq->tasklet);
2083
				slot->task = NULL;
2084
			}
2085
			dev_err(dev, "internal task abort: timeout and not done.\n");
2086

2087
			res = -EIO;
2088
			goto exit;
2089 2090
		} else
			dev_err(dev, "internal task abort: timeout.\n");
2091 2092
	}

2093 2094 2095 2096 2097 2098
	if (task->task_status.resp == SAS_TASK_COMPLETE &&
		task->task_status.stat == TMF_RESP_FUNC_COMPLETE) {
		res = TMF_RESP_FUNC_COMPLETE;
		goto exit;
	}

2099 2100 2101 2102 2103 2104
	if (task->task_status.resp == SAS_TASK_COMPLETE &&
		task->task_status.stat == TMF_RESP_FUNC_SUCC) {
		res = TMF_RESP_FUNC_SUCC;
		goto exit;
	}

2105
exit:
2106
	dev_dbg(dev, "internal task abort: task to dev %016llx task=%pK resp: 0x%x sts 0x%x\n",
2107
		SAS_ADDR(device->sas_addr), task,
2108 2109 2110 2111 2112 2113 2114
		task->task_status.resp, /* 0 is complete, -1 is undelivered */
		task->task_status.stat);
	sas_free_task(task);

	return res;
}

2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132
static int
hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
			     struct domain_device *device,
			     int abort_flag, int tag)
{
	struct hisi_sas_slot *slot;
	struct device *dev = hisi_hba->dev;
	struct hisi_sas_dq *dq;
	int i, rc;

	switch (abort_flag) {
	case HISI_SAS_INT_ABT_CMD:
		slot = &hisi_hba->slot_info[tag];
		dq = &hisi_hba->dq[slot->dlvry_queue];
		return _hisi_sas_internal_task_abort(hisi_hba, device,
						     abort_flag, tag, dq);
	case HISI_SAS_INT_ABT_DEV:
		for (i = 0; i < hisi_hba->cq_nvecs; i++) {
2133 2134 2135 2136 2137
			struct hisi_sas_cq *cq = &hisi_hba->cq[i];
			const struct cpumask *mask = cq->pci_irq_mask;

			if (mask && !cpumask_intersects(cpu_online_mask, mask))
				continue;
2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154
			dq = &hisi_hba->dq[i];
			rc = _hisi_sas_internal_task_abort(hisi_hba, device,
							   abort_flag, tag,
							   dq);
			if (rc)
				return rc;
		}
		break;
	default:
		dev_err(dev, "Unrecognised internal abort flag (%d)\n",
			abort_flag);
		return -EINVAL;
	}

	return 0;
}

J
John Garry 已提交
2155 2156 2157 2158 2159
static void hisi_sas_port_formed(struct asd_sas_phy *sas_phy)
{
	hisi_sas_port_notify_formed(sas_phy);
}

2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171
static int hisi_sas_write_gpio(struct sas_ha_struct *sha, u8 reg_type,
			u8 reg_index, u8 reg_count, u8 *write_data)
{
	struct hisi_hba *hisi_hba = sha->lldd_ha;

	if (!hisi_hba->hw->write_gpio)
		return -EOPNOTSUPP;

	return hisi_hba->hw->write_gpio(hisi_hba, reg_type,
				reg_index, reg_count, write_data);
}

J
John Garry 已提交
2172 2173
static void hisi_sas_phy_disconnected(struct hisi_sas_phy *phy)
{
2174 2175
	struct asd_sas_phy *sas_phy = &phy->sas_phy;
	struct sas_phy *sphy = sas_phy->phy;
2176
	unsigned long flags;
2177

J
John Garry 已提交
2178 2179 2180
	phy->phy_attached = 0;
	phy->phy_type = 0;
	phy->port = NULL;
2181

2182 2183
	spin_lock_irqsave(&phy->lock, flags);
	if (phy->enable)
2184 2185 2186
		sphy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
	else
		sphy->negotiated_linkrate = SAS_PHY_DISABLED;
2187
	spin_unlock_irqrestore(&phy->lock, flags);
J
John Garry 已提交
2188 2189 2190 2191 2192 2193 2194
}

void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy)
{
	struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
	struct asd_sas_phy *sas_phy = &phy->sas_phy;
	struct sas_ha_struct *sas_ha = &hisi_hba->sha;
2195
	struct device *dev = hisi_hba->dev;
J
John Garry 已提交
2196 2197 2198 2199 2200 2201 2202 2203

	if (rdy) {
		/* Phy down but ready */
		hisi_sas_bytes_dmaed(hisi_hba, phy_no);
		hisi_sas_port_notify_formed(sas_phy);
	} else {
		struct hisi_sas_port *port  = phy->port;

2204 2205
		if (test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags) ||
		    phy->in_reset) {
2206 2207 2208
			dev_info(dev, "ignore flutter phy%d down\n", phy_no);
			return;
		}
J
John Garry 已提交
2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227
		/* Phy down and not ready */
		sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL);
		sas_phy_disconnected(sas_phy);

		if (port) {
			if (phy->phy_type & PORT_TYPE_SAS) {
				int port_id = port->id;

				if (!hisi_hba->hw->get_wideport_bitmap(hisi_hba,
								       port_id))
					port->port_attached = 0;
			} else if (phy->phy_type & PORT_TYPE_SATA)
				port->port_attached = 0;
		}
		hisi_sas_phy_disconnected(phy);
	}
}
EXPORT_SYMBOL_GPL(hisi_sas_phy_down);

2228 2229 2230 2231
void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba)
{
	int i;

2232
	for (i = 0; i < hisi_hba->cq_nvecs; i++) {
2233 2234 2235 2236 2237 2238
		struct hisi_sas_cq *cq = &hisi_hba->cq[i];

		tasklet_kill(&cq->tasklet);
	}
}
EXPORT_SYMBOL_GPL(hisi_sas_kill_tasklets);
2239

2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252
int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type)
{
	struct hisi_hba *hisi_hba = shost_priv(shost);

	if (reset_type != SCSI_ADAPTER_RESET)
		return -EOPNOTSUPP;

	queue_work(hisi_hba->wq, &hisi_hba->rst_work);

	return 0;
}
EXPORT_SYMBOL_GPL(hisi_sas_host_reset);

2253 2254
struct scsi_transport_template *hisi_sas_stt;
EXPORT_SYMBOL_GPL(hisi_sas_stt);
2255 2256

static struct sas_domain_function_template hisi_sas_transport_ops = {
J
John Garry 已提交
2257 2258
	.lldd_dev_found		= hisi_sas_dev_found,
	.lldd_dev_gone		= hisi_sas_dev_gone,
J
John Garry 已提交
2259
	.lldd_execute_task	= hisi_sas_queue_command,
J
John Garry 已提交
2260
	.lldd_control_phy	= hisi_sas_control_phy,
J
John Garry 已提交
2261 2262 2263 2264 2265 2266
	.lldd_abort_task	= hisi_sas_abort_task,
	.lldd_abort_task_set	= hisi_sas_abort_task_set,
	.lldd_clear_aca		= hisi_sas_clear_aca,
	.lldd_I_T_nexus_reset	= hisi_sas_I_T_nexus_reset,
	.lldd_lu_reset		= hisi_sas_lu_reset,
	.lldd_query_task	= hisi_sas_query_task,
2267
	.lldd_clear_nexus_ha	= hisi_sas_clear_nexus_ha,
J
John Garry 已提交
2268
	.lldd_port_formed	= hisi_sas_port_formed,
2269
	.lldd_write_gpio	= hisi_sas_write_gpio,
2270 2271
};

2272 2273
void hisi_sas_init_mem(struct hisi_hba *hisi_hba)
{
2274
	int i, s, j, max_command_entries = HISI_SAS_MAX_COMMANDS;
J
John Garry 已提交
2275
	struct hisi_sas_breakpoint *sata_breakpoint = hisi_hba->sata_breakpoint;
2276 2277 2278 2279

	for (i = 0; i < hisi_hba->queue_count; i++) {
		struct hisi_sas_cq *cq = &hisi_hba->cq[i];
		struct hisi_sas_dq *dq = &hisi_hba->dq[i];
J
John Garry 已提交
2280 2281 2282 2283 2284
		struct hisi_sas_cmd_hdr *cmd_hdr = hisi_hba->cmd_hdr[i];

		s = sizeof(struct hisi_sas_cmd_hdr);
		for (j = 0; j < HISI_SAS_QUEUE_SLOTS; j++)
			memset(&cmd_hdr[j], 0, s);
2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301

		dq->wr_point = 0;

		s = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
		memset(hisi_hba->complete_hdr[i], 0, s);
		cq->rd_point = 0;
	}

	s = sizeof(struct hisi_sas_initial_fis) * hisi_hba->n_phy;
	memset(hisi_hba->initial_fis, 0, s);

	s = max_command_entries * sizeof(struct hisi_sas_iost);
	memset(hisi_hba->iost, 0, s);

	s = max_command_entries * sizeof(struct hisi_sas_breakpoint);
	memset(hisi_hba->breakpoint, 0, s);

J
John Garry 已提交
2302 2303 2304
	s = sizeof(struct hisi_sas_sata_breakpoint);
	for (j = 0; j < HISI_SAS_MAX_ITCT_ENTRIES; j++)
		memset(&sata_breakpoint[j], 0, s);
2305 2306 2307
}
EXPORT_SYMBOL_GPL(hisi_sas_init_mem);

2308
int hisi_sas_alloc(struct hisi_hba *hisi_hba)
2309
{
2310
	struct device *dev = hisi_hba->dev;
2311
	int i, j, s, max_command_entries = HISI_SAS_MAX_COMMANDS;
2312 2313
	int max_command_entries_ru, sz_slot_buf_ru;
	int blk_cnt, slots_per_blk;
2314

2315
	sema_init(&hisi_hba->sem, 1);
J
John Garry 已提交
2316
	spin_lock_init(&hisi_hba->lock);
J
John Garry 已提交
2317 2318 2319 2320 2321 2322
	for (i = 0; i < hisi_hba->n_phy; i++) {
		hisi_sas_phy_init(hisi_hba, i);
		hisi_hba->port[i].port_attached = 0;
		hisi_hba->port[i].id = -1;
	}

J
John Garry 已提交
2323 2324 2325
	for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
		hisi_hba->devices[i].dev_type = SAS_PHY_UNUSED;
		hisi_hba->devices[i].device_id = i;
2326
		hisi_hba->devices[i].dev_status = HISI_SAS_DEV_INIT;
J
John Garry 已提交
2327 2328
	}

2329
	for (i = 0; i < hisi_hba->queue_count; i++) {
2330
		struct hisi_sas_cq *cq = &hisi_hba->cq[i];
2331
		struct hisi_sas_dq *dq = &hisi_hba->dq[i];
2332 2333 2334 2335 2336

		/* Completion queue structure */
		cq->id = i;
		cq->hisi_hba = hisi_hba;

2337
		/* Delivery queue structure */
2338
		spin_lock_init(&dq->lock);
2339
		INIT_LIST_HEAD(&dq->list);
2340 2341 2342
		dq->id = i;
		dq->hisi_hba = hisi_hba;

2343 2344
		/* Delivery queue */
		s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
2345 2346 2347
		hisi_hba->cmd_hdr[i] = dmam_alloc_coherent(dev, s,
						&hisi_hba->cmd_hdr_dma[i],
						GFP_KERNEL);
2348 2349 2350 2351 2352
		if (!hisi_hba->cmd_hdr[i])
			goto err_out;

		/* Completion queue */
		s = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
2353 2354 2355
		hisi_hba->complete_hdr[i] = dmam_alloc_coherent(dev, s,
						&hisi_hba->complete_hdr_dma[i],
						GFP_KERNEL);
2356 2357 2358 2359 2360
		if (!hisi_hba->complete_hdr[i])
			goto err_out;
	}

	s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
2361
	hisi_hba->itct = dmam_alloc_coherent(dev, s, &hisi_hba->itct_dma,
2362
					     GFP_KERNEL);
2363 2364 2365
	if (!hisi_hba->itct)
		goto err_out;

2366
	hisi_hba->slot_info = devm_kcalloc(dev, max_command_entries,
2367 2368 2369 2370 2371
					   sizeof(struct hisi_sas_slot),
					   GFP_KERNEL);
	if (!hisi_hba->slot_info)
		goto err_out;

2372 2373
	/* roundup to avoid overly large block size */
	max_command_entries_ru = roundup(max_command_entries, 64);
2374 2375 2376 2377 2378
	if (hisi_hba->prot_mask & HISI_SAS_DIX_PROT_MASK)
		sz_slot_buf_ru = sizeof(struct hisi_sas_slot_dif_buf_table);
	else
		sz_slot_buf_ru = sizeof(struct hisi_sas_slot_buf_table);
	sz_slot_buf_ru = roundup(sz_slot_buf_ru, 64);
2379
	s = max(lcm(max_command_entries_ru, sz_slot_buf_ru), PAGE_SIZE);
2380 2381
	blk_cnt = (max_command_entries_ru * sz_slot_buf_ru) / s;
	slots_per_blk = s / sz_slot_buf_ru;
2382

2383 2384
	for (i = 0; i < blk_cnt; i++) {
		int slot_index = i * slots_per_blk;
2385 2386
		dma_addr_t buf_dma;
		void *buf;
2387

2388
		buf = dmam_alloc_coherent(dev, s, &buf_dma,
2389
					  GFP_KERNEL);
2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400
		if (!buf)
			goto err_out;

		for (j = 0; j < slots_per_blk; j++, slot_index++) {
			struct hisi_sas_slot *slot;

			slot = &hisi_hba->slot_info[slot_index];
			slot->buf = buf;
			slot->buf_dma = buf_dma;
			slot->idx = slot_index;

2401 2402
			buf += sz_slot_buf_ru;
			buf_dma += sz_slot_buf_ru;
2403 2404 2405
		}
	}

2406
	s = max_command_entries * sizeof(struct hisi_sas_iost);
2407 2408
	hisi_hba->iost = dmam_alloc_coherent(dev, s, &hisi_hba->iost_dma,
					     GFP_KERNEL);
2409 2410 2411
	if (!hisi_hba->iost)
		goto err_out;

2412
	s = max_command_entries * sizeof(struct hisi_sas_breakpoint);
2413 2414 2415
	hisi_hba->breakpoint = dmam_alloc_coherent(dev, s,
						   &hisi_hba->breakpoint_dma,
						   GFP_KERNEL);
2416 2417 2418
	if (!hisi_hba->breakpoint)
		goto err_out;

2419
	hisi_hba->slot_index_count = max_command_entries;
2420
	s = hisi_hba->slot_index_count / BITS_PER_BYTE;
J
John Garry 已提交
2421 2422 2423 2424
	hisi_hba->slot_index_tags = devm_kzalloc(dev, s, GFP_KERNEL);
	if (!hisi_hba->slot_index_tags)
		goto err_out;

2425
	s = sizeof(struct hisi_sas_initial_fis) * HISI_SAS_MAX_PHYS;
2426 2427 2428
	hisi_hba->initial_fis = dmam_alloc_coherent(dev, s,
						    &hisi_hba->initial_fis_dma,
						    GFP_KERNEL);
2429 2430 2431
	if (!hisi_hba->initial_fis)
		goto err_out;

2432
	s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_sata_breakpoint);
2433 2434 2435
	hisi_hba->sata_breakpoint = dmam_alloc_coherent(dev, s,
					&hisi_hba->sata_breakpoint_dma,
					GFP_KERNEL);
2436 2437 2438
	if (!hisi_hba->sata_breakpoint)
		goto err_out;

J
John Garry 已提交
2439
	hisi_sas_slot_index_init(hisi_hba);
2440
	hisi_hba->last_slot_index = HISI_SAS_UNRESERVED_IPTT;
J
John Garry 已提交
2441

J
John Garry 已提交
2442 2443 2444 2445 2446 2447
	hisi_hba->wq = create_singlethread_workqueue(dev_name(dev));
	if (!hisi_hba->wq) {
		dev_err(dev, "sas_alloc: failed to create workqueue\n");
		goto err_out;
	}

2448 2449 2450 2451
	return 0;
err_out:
	return -ENOMEM;
}
2452
EXPORT_SYMBOL_GPL(hisi_sas_alloc);
2453

2454
void hisi_sas_free(struct hisi_hba *hisi_hba)
J
John Garry 已提交
2455
{
2456 2457 2458 2459 2460 2461 2462 2463
	int i;

	for (i = 0; i < hisi_hba->n_phy; i++) {
		struct hisi_sas_phy *phy = &hisi_hba->phy[i];

		del_timer_sync(&phy->timer);
	}

J
John Garry 已提交
2464 2465
	if (hisi_hba->wq)
		destroy_workqueue(hisi_hba->wq);
J
John Garry 已提交
2466
}
2467
EXPORT_SYMBOL_GPL(hisi_sas_free);
2468

2469
void hisi_sas_rst_work_handler(struct work_struct *work)
2470 2471 2472 2473 2474 2475
{
	struct hisi_hba *hisi_hba =
		container_of(work, struct hisi_hba, rst_work);

	hisi_sas_controller_reset(hisi_hba);
}
2476
EXPORT_SYMBOL_GPL(hisi_sas_rst_work_handler);
2477

2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488
void hisi_sas_sync_rst_work_handler(struct work_struct *work)
{
	struct hisi_sas_rst *rst =
		container_of(work, struct hisi_sas_rst, work);

	if (!hisi_sas_controller_reset(rst->hisi_hba))
		rst->done = true;
	complete(rst->completion);
}
EXPORT_SYMBOL_GPL(hisi_sas_sync_rst_work_handler);

2489
int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba)
J
John Garry 已提交
2490
{
2491 2492 2493
	struct device *dev = hisi_hba->dev;
	struct platform_device *pdev = hisi_hba->platform_dev;
	struct device_node *np = pdev ? pdev->dev.of_node : NULL;
2494
	struct clk *refclk;
J
John Garry 已提交
2495

2496
	if (device_property_read_u8_array(dev, "sas-addr", hisi_hba->sas_addr,
2497 2498 2499 2500
					  SAS_ADDR_SIZE)) {
		dev_err(dev, "could not get property sas-addr\n");
		return -ENOENT;
	}
J
John Garry 已提交
2501

2502
	if (np) {
2503 2504 2505 2506
		/*
		 * These properties are only required for platform device-based
		 * controller with DT firmware.
		 */
2507 2508
		hisi_hba->ctrl = syscon_regmap_lookup_by_phandle(np,
					"hisilicon,sas-syscon");
2509 2510 2511 2512
		if (IS_ERR(hisi_hba->ctrl)) {
			dev_err(dev, "could not get syscon\n");
			return -ENOENT;
		}
J
John Garry 已提交
2513

2514
		if (device_property_read_u32(dev, "ctrl-reset-reg",
2515
					     &hisi_hba->ctrl_reset_reg)) {
X
Xiang Chen 已提交
2516
			dev_err(dev, "could not get property ctrl-reset-reg\n");
2517 2518
			return -ENOENT;
		}
J
John Garry 已提交
2519

2520
		if (device_property_read_u32(dev, "ctrl-reset-sts-reg",
2521
					     &hisi_hba->ctrl_reset_sts_reg)) {
X
Xiang Chen 已提交
2522
			dev_err(dev, "could not get property ctrl-reset-sts-reg\n");
2523 2524
			return -ENOENT;
		}
J
John Garry 已提交
2525

2526
		if (device_property_read_u32(dev, "ctrl-clock-ena-reg",
2527
					     &hisi_hba->ctrl_clock_ena_reg)) {
X
Xiang Chen 已提交
2528
			dev_err(dev, "could not get property ctrl-clock-ena-reg\n");
2529 2530
			return -ENOENT;
		}
2531 2532
	}

2533
	refclk = devm_clk_get(dev, NULL);
2534
	if (IS_ERR(refclk))
2535
		dev_dbg(dev, "no ref clk property\n");
2536 2537 2538
	else
		hisi_hba->refclk_frequency_mhz = clk_get_rate(refclk) / 1000000;

2539 2540 2541 2542
	if (device_property_read_u32(dev, "phy-count", &hisi_hba->n_phy)) {
		dev_err(dev, "could not get property phy-count\n");
		return -ENOENT;
	}
J
John Garry 已提交
2543

2544
	if (device_property_read_u32(dev, "queue-count",
2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560
				     &hisi_hba->queue_count)) {
		dev_err(dev, "could not get property queue-count\n");
		return -ENOENT;
	}

	return 0;
}
EXPORT_SYMBOL_GPL(hisi_sas_get_fw_info);

static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
					      const struct hisi_sas_hw *hw)
{
	struct resource *res;
	struct Scsi_Host *shost;
	struct hisi_hba *hisi_hba;
	struct device *dev = &pdev->dev;
2561
	int error;
2562

2563
	shost = scsi_host_alloc(hw->sht, sizeof(*hisi_hba));
2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576
	if (!shost) {
		dev_err(dev, "scsi host alloc failed\n");
		return NULL;
	}
	hisi_hba = shost_priv(shost);

	INIT_WORK(&hisi_hba->rst_work, hisi_sas_rst_work_handler);
	hisi_hba->hw = hw;
	hisi_hba->dev = dev;
	hisi_hba->platform_dev = pdev;
	hisi_hba->shost = shost;
	SHOST_TO_SAS_HA(shost) = &hisi_hba->sha;

2577
	timer_setup(&hisi_hba->timer, NULL, 0);
2578 2579

	if (hisi_sas_get_fw_info(hisi_hba) < 0)
J
John Garry 已提交
2580 2581
		goto err_out;

2582 2583 2584 2585 2586
	error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
	if (error)
		error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));

	if (error) {
2587 2588 2589 2590
		dev_err(dev, "No usable DMA addressing method\n");
		goto err_out;
	}

2591
	hisi_hba->regs = devm_platform_ioremap_resource(pdev, 0);
J
John Garry 已提交
2592 2593 2594
	if (IS_ERR(hisi_hba->regs))
		goto err_out;

2595 2596 2597 2598 2599 2600 2601
	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (res) {
		hisi_hba->sgpio_regs = devm_ioremap_resource(dev, res);
		if (IS_ERR(hisi_hba->sgpio_regs))
			goto err_out;
	}

2602
	if (hisi_sas_alloc(hisi_hba)) {
J
John Garry 已提交
2603
		hisi_sas_free(hisi_hba);
2604
		goto err_out;
J
John Garry 已提交
2605
	}
2606

J
John Garry 已提交
2607 2608
	return shost;
err_out:
2609
	scsi_host_put(shost);
J
John Garry 已提交
2610 2611 2612 2613 2614
	dev_err(dev, "shost alloc failed\n");
	return NULL;
}

int hisi_sas_probe(struct platform_device *pdev,
2615
		   const struct hisi_sas_hw *hw)
J
John Garry 已提交
2616 2617 2618 2619 2620 2621 2622 2623 2624 2625
{
	struct Scsi_Host *shost;
	struct hisi_hba *hisi_hba;
	struct device *dev = &pdev->dev;
	struct asd_sas_phy **arr_phy;
	struct asd_sas_port **arr_port;
	struct sas_ha_struct *sha;
	int rc, phy_nr, port_nr, i;

	shost = hisi_sas_shost_alloc(pdev, hw);
2626 2627
	if (!shost)
		return -ENOMEM;
J
John Garry 已提交
2628 2629 2630 2631

	sha = SHOST_TO_SAS_HA(shost);
	hisi_hba = shost_priv(shost);
	platform_set_drvdata(pdev, sha);
J
John Garry 已提交
2632

J
John Garry 已提交
2633 2634 2635 2636
	phy_nr = port_nr = hisi_hba->n_phy;

	arr_phy = devm_kcalloc(dev, phy_nr, sizeof(void *), GFP_KERNEL);
	arr_port = devm_kcalloc(dev, port_nr, sizeof(void *), GFP_KERNEL);
2637 2638 2639 2640
	if (!arr_phy || !arr_port) {
		rc = -ENOMEM;
		goto err_out_ha;
	}
J
John Garry 已提交
2641 2642 2643 2644 2645 2646 2647 2648 2649 2650

	sha->sas_phy = arr_phy;
	sha->sas_port = arr_port;
	sha->lldd_ha = hisi_hba;

	shost->transportt = hisi_sas_stt;
	shost->max_id = HISI_SAS_MAX_DEVICES;
	shost->max_lun = ~0;
	shost->max_channel = 1;
	shost->max_cmd_len = 16;
2651
	if (hisi_hba->hw->slot_index_alloc) {
2652 2653
		shost->can_queue = HISI_SAS_MAX_COMMANDS;
		shost->cmd_per_lun = HISI_SAS_MAX_COMMANDS;
2654
	} else {
2655 2656
		shost->can_queue = HISI_SAS_UNRESERVED_IPTT;
		shost->cmd_per_lun = HISI_SAS_UNRESERVED_IPTT;
2657
	}
J
John Garry 已提交
2658 2659

	sha->sas_ha_name = DRV_NAME;
2660
	sha->dev = hisi_hba->dev;
J
John Garry 已提交
2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678
	sha->lldd_module = THIS_MODULE;
	sha->sas_addr = &hisi_hba->sas_addr[0];
	sha->num_phys = hisi_hba->n_phy;
	sha->core.shost = hisi_hba->shost;

	for (i = 0; i < hisi_hba->n_phy; i++) {
		sha->sas_phy[i] = &hisi_hba->phy[i].sas_phy;
		sha->sas_port[i] = &hisi_hba->port[i].sas_port;
	}

	rc = scsi_add_host(shost, &pdev->dev);
	if (rc)
		goto err_out_ha;

	rc = sas_register_ha(sha);
	if (rc)
		goto err_out_register_ha;

2679 2680 2681 2682
	rc = hisi_hba->hw->hw_init(hisi_hba);
	if (rc)
		goto err_out_register_ha;

J
John Garry 已提交
2683 2684 2685 2686 2687 2688 2689
	scsi_scan_host(shost);

	return 0;

err_out_register_ha:
	scsi_remove_host(shost);
err_out_ha:
2690
	hisi_sas_free(hisi_hba);
2691
	scsi_host_put(shost);
J
John Garry 已提交
2692 2693 2694 2695
	return rc;
}
EXPORT_SYMBOL_GPL(hisi_sas_probe);

2696 2697
struct dentry *hisi_sas_debugfs_dir;

2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710
static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba)
{
	int queue_entry_size = hisi_hba->hw->complete_hdr_size;
	int i;

	for (i = 0; i < hisi_hba->queue_count; i++)
		memcpy(hisi_hba->debugfs_complete_hdr[i],
		       hisi_hba->complete_hdr[i],
		       HISI_SAS_QUEUE_SLOTS * queue_entry_size);
}

static void hisi_sas_debugfs_snapshot_dq_reg(struct hisi_hba *hisi_hba)
{
2711
	int queue_entry_size = sizeof(struct hisi_sas_cmd_hdr);
2712 2713
	int i;

J
John Garry 已提交
2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724
	for (i = 0; i < hisi_hba->queue_count; i++) {
		struct hisi_sas_cmd_hdr	*debugfs_cmd_hdr, *cmd_hdr;
		int j;

		debugfs_cmd_hdr = hisi_hba->debugfs_cmd_hdr[i];
		cmd_hdr = hisi_hba->cmd_hdr[i];

		for (j = 0; j < HISI_SAS_QUEUE_SLOTS; j++)
			memcpy(&debugfs_cmd_hdr[j], &cmd_hdr[j],
			       queue_entry_size);
	}
2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746
}

static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba)
{
	const struct hisi_sas_debugfs_reg *port =
		hisi_hba->hw->debugfs_reg_port;
	int i, phy_cnt;
	u32 offset;
	u32 *databuf;

	for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) {
		databuf = (u32 *)hisi_hba->debugfs_port_reg[phy_cnt];
		for (i = 0; i < port->count; i++, databuf++) {
			offset = port->base_off + 4 * i;
			*databuf = port->read_port_reg(hisi_hba, phy_cnt,
						       offset);
		}
	}
}

static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba)
{
2747 2748
	u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_GLOBAL];
	const struct hisi_sas_hw *hw = hisi_hba->hw;
2749
	const struct hisi_sas_debugfs_reg *global =
2750
			hw->debugfs_reg_array[DEBUGFS_GLOBAL];
2751 2752 2753 2754 2755 2756
	int i;

	for (i = 0; i < global->count; i++, databuf++)
		*databuf = global->read_global_reg(hisi_hba, 4 * i);
}

2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782
static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba)
{
	u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_AXI];
	const struct hisi_sas_hw *hw = hisi_hba->hw;
	const struct hisi_sas_debugfs_reg *axi =
			hw->debugfs_reg_array[DEBUGFS_AXI];
	int i;

	for (i = 0; i < axi->count; i++, databuf++)
		*databuf = axi->read_global_reg(hisi_hba,
						4 * i + axi->base_off);
}

static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba)
{
	u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_RAS];
	const struct hisi_sas_hw *hw = hisi_hba->hw;
	const struct hisi_sas_debugfs_reg *ras =
			hw->debugfs_reg_array[DEBUGFS_RAS];
	int i;

	for (i = 0; i < ras->count; i++, databuf++)
		*databuf = ras->read_global_reg(hisi_hba,
						4 * i + ras->base_off);
}

2783 2784
static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba)
{
2785
	void *cachebuf = hisi_hba->debugfs_itct_cache;
2786 2787 2788 2789
	void *databuf = hisi_hba->debugfs_itct;
	struct hisi_sas_itct *itct;
	int i;

2790 2791 2792
	hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_ITCT_CACHE,
					   cachebuf);

2793 2794 2795 2796 2797 2798 2799 2800 2801 2802
	itct = hisi_hba->itct;

	for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) {
		memcpy(databuf, itct, sizeof(struct hisi_sas_itct));
		databuf += sizeof(struct hisi_sas_itct);
	}
}

static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba)
{
2803
	int max_command_entries = HISI_SAS_MAX_COMMANDS;
2804
	void *cachebuf = hisi_hba->debugfs_iost_cache;
2805 2806 2807 2808
	void *databuf = hisi_hba->debugfs_iost;
	struct hisi_sas_iost *iost;
	int i;

2809 2810 2811
	hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_IOST_CACHE,
					   cachebuf);

2812 2813 2814 2815 2816 2817 2818 2819
	iost = hisi_hba->iost;

	for (i = 0; i < max_command_entries; i++, iost++) {
		memcpy(databuf, iost, sizeof(struct hisi_sas_iost));
		databuf += sizeof(struct hisi_sas_iost);
	}
}

2820
static const char *
2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846
hisi_sas_debugfs_to_reg_name(int off, int base_off,
			     const struct hisi_sas_debugfs_reg_lu *lu)
{
	for (; lu->name; lu++) {
		if (off == lu->off - base_off)
			return lu->name;
	}

	return NULL;
}

static void hisi_sas_debugfs_print_reg(u32 *regs_val, const void *ptr,
				       struct seq_file *s)
{
	const struct hisi_sas_debugfs_reg *reg = ptr;
	int i;

	for (i = 0; i < reg->count; i++) {
		int off = i * 4;
		const char *name;

		name = hisi_sas_debugfs_to_reg_name(off, reg->base_off,
						    reg->lu);

		if (name)
			seq_printf(s, "0x%08x 0x%08x %s\n", off,
2847
				   regs_val[i], name);
2848 2849
		else
			seq_printf(s, "0x%08x 0x%08x\n", off,
2850
				   regs_val[i]);
2851 2852 2853 2854 2855 2856 2857
	}
}

static int hisi_sas_debugfs_global_show(struct seq_file *s, void *p)
{
	struct hisi_hba *hisi_hba = s->private;
	const struct hisi_sas_hw *hw = hisi_hba->hw;
2858
	const void *reg_global = hw->debugfs_reg_array[DEBUGFS_GLOBAL];
2859

2860
	hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_GLOBAL],
2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879
				   reg_global, s);

	return 0;
}

static int hisi_sas_debugfs_global_open(struct inode *inode, struct file *filp)
{
	return single_open(filp, hisi_sas_debugfs_global_show,
			   inode->i_private);
}

static const struct file_operations hisi_sas_debugfs_global_fops = {
	.open = hisi_sas_debugfs_global_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931
static int hisi_sas_debugfs_axi_show(struct seq_file *s, void *p)
{
	struct hisi_hba *hisi_hba = s->private;
	const struct hisi_sas_hw *hw = hisi_hba->hw;
	const void *reg_axi = hw->debugfs_reg_array[DEBUGFS_AXI];

	hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_AXI],
				   reg_axi, s);

	return 0;
}

static int hisi_sas_debugfs_axi_open(struct inode *inode, struct file *filp)
{
	return single_open(filp, hisi_sas_debugfs_axi_show,
			   inode->i_private);
}

static const struct file_operations hisi_sas_debugfs_axi_fops = {
	.open = hisi_sas_debugfs_axi_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

static int hisi_sas_debugfs_ras_show(struct seq_file *s, void *p)
{
	struct hisi_hba *hisi_hba = s->private;
	const struct hisi_sas_hw *hw = hisi_hba->hw;
	const void *reg_ras = hw->debugfs_reg_array[DEBUGFS_RAS];

	hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_RAS],
				   reg_ras, s);

	return 0;
}

static int hisi_sas_debugfs_ras_open(struct inode *inode, struct file *filp)
{
	return single_open(filp, hisi_sas_debugfs_ras_show,
			   inode->i_private);
}

static const struct file_operations hisi_sas_debugfs_ras_fops = {
	.open = hisi_sas_debugfs_ras_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957
static int hisi_sas_debugfs_port_show(struct seq_file *s, void *p)
{
	struct hisi_sas_phy *phy = s->private;
	struct hisi_hba *hisi_hba = phy->hisi_hba;
	const struct hisi_sas_hw *hw = hisi_hba->hw;
	const struct hisi_sas_debugfs_reg *reg_port = hw->debugfs_reg_port;
	u32 *databuf = hisi_hba->debugfs_port_reg[phy->sas_phy.id];

	hisi_sas_debugfs_print_reg(databuf, reg_port, s);

	return 0;
}

static int hisi_sas_debugfs_port_open(struct inode *inode, struct file *filp)
{
	return single_open(filp, hisi_sas_debugfs_port_show, inode->i_private);
}

static const struct file_operations hisi_sas_debugfs_port_fops = {
	.open = hisi_sas_debugfs_port_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

2958 2959
static void hisi_sas_show_row_64(struct seq_file *s, int index,
				 int sz, __le64 *ptr)
2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973
{
	int i;

	/* completion header size not fixed per HW version */
	seq_printf(s, "index %04d:\n\t", index);
	for (i = 1; i <= sz / 8; i++, ptr++) {
		seq_printf(s, " 0x%016llx", le64_to_cpu(*ptr));
		if (!(i % 2))
			seq_puts(s, "\n\t");
	}

	seq_puts(s, "\n");
}

2974 2975
static void hisi_sas_show_row_32(struct seq_file *s, int index,
				 int sz, __le32 *ptr)
2976 2977 2978 2979 2980 2981
{
	int i;

	/* completion header size not fixed per HW version */
	seq_printf(s, "index %04d:\n\t", index);
	for (i = 1; i <= sz / 4; i++, ptr++) {
2982
		seq_printf(s, " 0x%08x", le32_to_cpu(*ptr));
2983 2984 2985 2986 2987 2988
		if (!(i % 4))
			seq_puts(s, "\n\t");
	}
	seq_puts(s, "\n");
}

2989
static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr)
2990 2991 2992 2993
{
	struct hisi_sas_cq *cq = cq_ptr;
	struct hisi_hba *hisi_hba = cq->hisi_hba;
	void *complete_queue = hisi_hba->debugfs_complete_hdr[cq->id];
2994
	__le32 *complete_hdr = complete_queue +
2995 2996
			(hisi_hba->hw->complete_hdr_size * slot);

2997 2998 2999
	hisi_sas_show_row_32(s, slot,
			     hisi_hba->hw->complete_hdr_size,
			     complete_hdr);
3000 3001 3002 3003 3004
}

static int hisi_sas_debugfs_cq_show(struct seq_file *s, void *p)
{
	struct hisi_sas_cq *cq = s->private;
3005
	int slot;
3006 3007

	for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) {
3008
		hisi_sas_cq_show_slot(s, slot, cq);
3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025
	}
	return 0;
}

static int hisi_sas_debugfs_cq_open(struct inode *inode, struct file *filp)
{
	return single_open(filp, hisi_sas_debugfs_cq_show, inode->i_private);
}

static const struct file_operations hisi_sas_debugfs_cq_fops = {
	.open = hisi_sas_debugfs_cq_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

3026
static void hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr)
3027 3028 3029 3030
{
	struct hisi_sas_dq *dq = dq_ptr;
	struct hisi_hba *hisi_hba = dq->hisi_hba;
	void *cmd_queue = hisi_hba->debugfs_cmd_hdr[dq->id];
3031 3032
	__le32 *cmd_hdr = cmd_queue +
		sizeof(struct hisi_sas_cmd_hdr) * slot;
3033

3034
	hisi_sas_show_row_32(s, slot, sizeof(struct hisi_sas_cmd_hdr), cmd_hdr);
3035 3036 3037 3038
}

static int hisi_sas_debugfs_dq_show(struct seq_file *s, void *p)
{
3039
	int slot;
3040 3041

	for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) {
3042
		hisi_sas_dq_show_slot(s, slot, s->private);
3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059
	}
	return 0;
}

static int hisi_sas_debugfs_dq_open(struct inode *inode, struct file *filp)
{
	return single_open(filp, hisi_sas_debugfs_dq_show, inode->i_private);
}

static const struct file_operations hisi_sas_debugfs_dq_fops = {
	.open = hisi_sas_debugfs_dq_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

3060 3061 3062 3063
static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p)
{
	struct hisi_hba *hisi_hba = s->private;
	struct hisi_sas_iost *debugfs_iost = hisi_hba->debugfs_iost;
3064
	int i, max_command_entries = HISI_SAS_MAX_COMMANDS;
3065 3066

	for (i = 0; i < max_command_entries; i++, debugfs_iost++) {
3067 3068
		__le64 *iost = &debugfs_iost->qw0;

3069
		hisi_sas_show_row_64(s, i, sizeof(*debugfs_iost), iost);
3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087
	}

	return 0;
}

static int hisi_sas_debugfs_iost_open(struct inode *inode, struct file *filp)
{
	return single_open(filp, hisi_sas_debugfs_iost_show, inode->i_private);
}

static const struct file_operations hisi_sas_debugfs_iost_fops = {
	.open = hisi_sas_debugfs_iost_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127
static int hisi_sas_debugfs_iost_cache_show(struct seq_file *s, void *p)
{
	struct hisi_hba *hisi_hba = s->private;
	struct hisi_sas_iost_itct_cache *iost_cache =
		(struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_iost_cache;
	u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4;
	int i, tab_idx;
	__le64 *iost;

	for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) {
		/*
		 * Data struct of IOST cache:
		 * Data[1]: BIT0~15: Table index
		 *	    Bit16:   Valid mask
		 * Data[2]~[9]: IOST table
		 */
		tab_idx = (iost_cache->data[1] & 0xffff);
		iost = (__le64 *)iost_cache;

		hisi_sas_show_row_64(s, tab_idx, cache_size, iost);
	}

	return 0;
}

static int hisi_sas_debugfs_iost_cache_open(struct inode *inode,
					    struct file *filp)
{
	return single_open(filp, hisi_sas_debugfs_iost_cache_show,
			   inode->i_private);
}

static const struct file_operations hisi_sas_debugfs_iost_cache_fops = {
	.open = hisi_sas_debugfs_iost_cache_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

3128 3129
static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p)
{
3130
	int i;
3131 3132 3133 3134
	struct hisi_hba *hisi_hba = s->private;
	struct hisi_sas_itct *debugfs_itct = hisi_hba->debugfs_itct;

	for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, debugfs_itct++) {
3135 3136
		__le64 *itct = &debugfs_itct->qw0;

3137
		hisi_sas_show_row_64(s, i, sizeof(*debugfs_itct), itct);
3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155
	}

	return 0;
}

static int hisi_sas_debugfs_itct_open(struct inode *inode, struct file *filp)
{
	return single_open(filp, hisi_sas_debugfs_itct_show, inode->i_private);
}

static const struct file_operations hisi_sas_debugfs_itct_fops = {
	.open = hisi_sas_debugfs_itct_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195
static int hisi_sas_debugfs_itct_cache_show(struct seq_file *s, void *p)
{
	struct hisi_hba *hisi_hba = s->private;
	struct hisi_sas_iost_itct_cache *itct_cache =
		(struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_itct_cache;
	u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4;
	int i, tab_idx;
	__le64 *itct;

	for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) {
		/*
		 * Data struct of ITCT cache:
		 * Data[1]: BIT0~15: Table index
		 *	    Bit16:   Valid mask
		 * Data[2]~[9]: ITCT table
		 */
		tab_idx = itct_cache->data[1] & 0xffff;
		itct = (__le64 *)itct_cache;

		hisi_sas_show_row_64(s, tab_idx, cache_size, itct);
	}

	return 0;
}

static int hisi_sas_debugfs_itct_cache_open(struct inode *inode,
					    struct file *filp)
{
	return single_open(filp, hisi_sas_debugfs_itct_cache_show,
			   inode->i_private);
}

static const struct file_operations hisi_sas_debugfs_itct_cache_fops = {
	.open = hisi_sas_debugfs_itct_cache_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

3196 3197 3198
static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba)
{
	struct dentry *dump_dentry;
3199 3200 3201
	struct dentry *dentry;
	char name[256];
	int p;
3202
	int c;
3203
	int d;
3204 3205 3206 3207

	/* Create dump dir inside device dir */
	dump_dentry = debugfs_create_dir("dump", hisi_hba->debugfs_dir);
	hisi_hba->debugfs_dump_dentry = dump_dentry;
3208

3209 3210
	debugfs_create_file("global", 0400, dump_dentry, hisi_hba,
			    &hisi_sas_debugfs_global_fops);
3211 3212 3213 3214 3215

	/* Create port dir and files */
	dentry = debugfs_create_dir("port", dump_dentry);
	for (p = 0; p < hisi_hba->n_phy; p++) {
		snprintf(name, 256, "%d", p);
3216 3217 3218

		debugfs_create_file(name, 0400, dentry, &hisi_hba->phy[p],
				    &hisi_sas_debugfs_port_fops);
3219 3220
	}

3221 3222 3223 3224 3225
	/* Create CQ dir and files */
	dentry = debugfs_create_dir("cq", dump_dentry);
	for (c = 0; c < hisi_hba->queue_count; c++) {
		snprintf(name, 256, "%d", c);

3226 3227
		debugfs_create_file(name, 0400, dentry, &hisi_hba->cq[c],
				    &hisi_sas_debugfs_cq_fops);
3228 3229
	}

3230 3231 3232 3233 3234
	/* Create DQ dir and files */
	dentry = debugfs_create_dir("dq", dump_dentry);
	for (d = 0; d < hisi_hba->queue_count; d++) {
		snprintf(name, 256, "%d", d);

3235 3236
		debugfs_create_file(name, 0400, dentry, &hisi_hba->dq[d],
				    &hisi_sas_debugfs_dq_fops);
3237 3238
	}

3239 3240
	debugfs_create_file("iost", 0400, dump_dentry, hisi_hba,
			    &hisi_sas_debugfs_iost_fops);
3241

3242 3243 3244
	debugfs_create_file("iost_cache", 0400, dump_dentry, hisi_hba,
			    &hisi_sas_debugfs_iost_cache_fops);

3245 3246 3247
	debugfs_create_file("itct", 0400, dump_dentry, hisi_hba,
			    &hisi_sas_debugfs_itct_fops);

3248 3249 3250
	debugfs_create_file("itct_cache", 0400, dump_dentry, hisi_hba,
			    &hisi_sas_debugfs_itct_cache_fops);

3251 3252 3253 3254 3255 3256
	debugfs_create_file("axi", 0400, dump_dentry, hisi_hba,
			    &hisi_sas_debugfs_axi_fops);

	debugfs_create_file("ras", 0400, dump_dentry, hisi_hba,
			    &hisi_sas_debugfs_ras_fops);

3257 3258 3259 3260 3261 3262 3263 3264 3265
	return;
}

static void hisi_sas_debugfs_snapshot_regs(struct hisi_hba *hisi_hba)
{
	hisi_hba->hw->snapshot_prepare(hisi_hba);

	hisi_sas_debugfs_snapshot_global_reg(hisi_hba);
	hisi_sas_debugfs_snapshot_port_reg(hisi_hba);
3266 3267
	hisi_sas_debugfs_snapshot_axi_reg(hisi_hba);
	hisi_sas_debugfs_snapshot_ras_reg(hisi_hba);
3268 3269 3270 3271 3272 3273 3274 3275 3276 3277
	hisi_sas_debugfs_snapshot_cq_reg(hisi_hba);
	hisi_sas_debugfs_snapshot_dq_reg(hisi_hba);
	hisi_sas_debugfs_snapshot_itct_reg(hisi_hba);
	hisi_sas_debugfs_snapshot_iost_reg(hisi_hba);

	hisi_sas_debugfs_create_files(hisi_hba);

	hisi_hba->hw->snapshot_restore(hisi_hba);
}

3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307
static ssize_t hisi_sas_debugfs_trigger_dump_write(struct file *file,
						   const char __user *user_buf,
						   size_t count, loff_t *ppos)
{
	struct hisi_hba *hisi_hba = file->f_inode->i_private;
	char buf[8];

	/* A bit racy, but don't care too much since it's only debugfs */
	if (hisi_hba->debugfs_snapshot)
		return -EFAULT;

	if (count > 8)
		return -EFAULT;

	if (copy_from_user(buf, user_buf, count))
		return -EFAULT;

	if (buf[0] != '1')
		return -EFAULT;

	queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);

	return count;
}

static const struct file_operations hisi_sas_debugfs_trigger_dump_fops = {
	.write = &hisi_sas_debugfs_trigger_dump_write,
	.owner = THIS_MODULE,
};

3308 3309 3310 3311 3312
void hisi_sas_debugfs_work_handler(struct work_struct *work)
{
	struct hisi_hba *hisi_hba =
		container_of(work, struct hisi_hba, debugfs_work);

3313 3314 3315 3316
	if (hisi_hba->debugfs_snapshot)
		return;
	hisi_hba->debugfs_snapshot = true;

3317 3318 3319 3320
	hisi_sas_debugfs_snapshot_regs(hisi_hba);
}
EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler);

3321 3322
void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba)
{
3323
	int max_command_entries = HISI_SAS_MAX_COMMANDS;
3324
	const struct hisi_sas_hw *hw = hisi_hba->hw;
3325
	struct device *dev = hisi_hba->dev;
3326 3327
	int p, i, c, d;
	size_t sz;
3328 3329 3330

	hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev),
						   hisi_sas_debugfs_dir);
3331 3332 3333 3334
	debugfs_create_file("trigger_dump", 0600,
			    hisi_hba->debugfs_dir,
			    hisi_hba,
			    &hisi_sas_debugfs_trigger_dump_fops);
3335

3336 3337 3338
	sz = hw->debugfs_reg_array[DEBUGFS_GLOBAL]->count * 4;
	hisi_hba->debugfs_regs[DEBUGFS_GLOBAL] =
				devm_kmalloc(dev, sz, GFP_KERNEL);
3339

3340
	if (!hisi_hba->debugfs_regs[DEBUGFS_GLOBAL])
3341 3342
		goto fail_global;

3343
	sz = hw->debugfs_reg_port->count * 4;
3344 3345 3346 3347 3348 3349 3350 3351
	for (p = 0; p < hisi_hba->n_phy; p++) {
		hisi_hba->debugfs_port_reg[p] =
			devm_kmalloc(dev, sz, GFP_KERNEL);

		if (!hisi_hba->debugfs_port_reg[p])
			goto fail_port;
	}

3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366
	sz = hw->debugfs_reg_array[DEBUGFS_AXI]->count * 4;
	hisi_hba->debugfs_regs[DEBUGFS_AXI] =
		devm_kmalloc(dev, sz, GFP_KERNEL);

	if (!hisi_hba->debugfs_regs[DEBUGFS_AXI])
		goto fail_axi;

	sz = hw->debugfs_reg_array[DEBUGFS_RAS]->count * 4;
	hisi_hba->debugfs_regs[DEBUGFS_RAS] =
		devm_kmalloc(dev, sz, GFP_KERNEL);

	if (!hisi_hba->debugfs_regs[DEBUGFS_RAS])
		goto fail_ras;

	sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
3367 3368 3369 3370 3371 3372 3373 3374
	for (c = 0; c < hisi_hba->queue_count; c++) {
		hisi_hba->debugfs_complete_hdr[c] =
			devm_kmalloc(dev, sz, GFP_KERNEL);

		if (!hisi_hba->debugfs_complete_hdr[c])
			goto fail_cq;
	}

3375
	sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389
	for (d = 0; d < hisi_hba->queue_count; d++) {
		hisi_hba->debugfs_cmd_hdr[d] =
			devm_kmalloc(dev, sz, GFP_KERNEL);

		if (!hisi_hba->debugfs_cmd_hdr[d])
			goto fail_iost_dq;
	}

	sz = max_command_entries * sizeof(struct hisi_sas_iost);

	hisi_hba->debugfs_iost = devm_kmalloc(dev, sz, GFP_KERNEL);
	if (!hisi_hba->debugfs_iost)
		goto fail_iost_dq;

3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403
	sz = HISI_SAS_IOST_ITCT_CACHE_NUM *
	     sizeof(struct hisi_sas_iost_itct_cache);

	hisi_hba->debugfs_iost_cache = devm_kmalloc(dev, sz, GFP_KERNEL);
	if (!hisi_hba->debugfs_iost_cache)
		goto fail_iost_cache;

	sz = HISI_SAS_IOST_ITCT_CACHE_NUM *
	     sizeof(struct hisi_sas_iost_itct_cache);

	hisi_hba->debugfs_itct_cache = devm_kmalloc(dev, sz, GFP_KERNEL);
	if (!hisi_hba->debugfs_itct_cache)
		goto fail_itct_cache;

3404 3405 3406 3407 3408 3409 3410 3411 3412
	/* New memory allocation must be locate before itct */
	sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);

	hisi_hba->debugfs_itct = devm_kmalloc(dev, sz, GFP_KERNEL);
	if (!hisi_hba->debugfs_itct)
		goto fail_itct;

	return;
fail_itct:
3413 3414 3415 3416
	devm_kfree(dev, hisi_hba->debugfs_iost_cache);
fail_itct_cache:
	devm_kfree(dev, hisi_hba->debugfs_iost_cache);
fail_iost_cache:
3417 3418 3419 3420 3421 3422 3423
	devm_kfree(dev, hisi_hba->debugfs_iost);
fail_iost_dq:
	for (i = 0; i < d; i++)
		devm_kfree(dev, hisi_hba->debugfs_cmd_hdr[i]);
fail_cq:
	for (i = 0; i < c; i++)
		devm_kfree(dev, hisi_hba->debugfs_complete_hdr[i]);
3424 3425 3426 3427
	devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_RAS]);
fail_ras:
	devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_AXI]);
fail_axi:
3428 3429 3430
fail_port:
	for (i = 0; i < p; i++)
		devm_kfree(dev, hisi_hba->debugfs_port_reg[i]);
3431
	devm_kfree(dev, hisi_hba->debugfs_regs[DEBUGFS_GLOBAL]);
3432 3433 3434
fail_global:
	debugfs_remove_recursive(hisi_hba->debugfs_dir);
	dev_dbg(dev, "failed to init debugfs!\n");
3435 3436 3437 3438 3439 3440 3441 3442 3443
}
EXPORT_SYMBOL_GPL(hisi_sas_debugfs_init);

void hisi_sas_debugfs_exit(struct hisi_hba *hisi_hba)
{
	debugfs_remove_recursive(hisi_hba->debugfs_dir);
}
EXPORT_SYMBOL_GPL(hisi_sas_debugfs_exit);

J
John Garry 已提交
3444 3445 3446 3447
int hisi_sas_remove(struct platform_device *pdev)
{
	struct sas_ha_struct *sha = platform_get_drvdata(pdev);
	struct hisi_hba *hisi_hba = sha->lldd_ha;
3448
	struct Scsi_Host *shost = sha->core.shost;
J
John Garry 已提交
3449

3450 3451 3452
	if (timer_pending(&hisi_hba->timer))
		del_timer(&hisi_hba->timer);

J
John Garry 已提交
3453 3454 3455 3456
	sas_unregister_ha(sha);
	sas_remove_host(sha->core.shost);

	hisi_sas_free(hisi_hba);
3457
	scsi_host_put(shost);
J
John Garry 已提交
3458 3459 3460 3461
	return 0;
}
EXPORT_SYMBOL_GPL(hisi_sas_remove);

3462 3463 3464 3465 3466
bool hisi_sas_debugfs_enable;
EXPORT_SYMBOL_GPL(hisi_sas_debugfs_enable);
module_param_named(debugfs_enable, hisi_sas_debugfs_enable, bool, 0444);
MODULE_PARM_DESC(hisi_sas_debugfs_enable, "Enable driver debugfs (default disabled)");

3467 3468 3469 3470 3471 3472
static __init int hisi_sas_init(void)
{
	hisi_sas_stt = sas_domain_attach_transport(&hisi_sas_transport_ops);
	if (!hisi_sas_stt)
		return -ENOMEM;

3473 3474 3475
	if (hisi_sas_debugfs_enable)
		hisi_sas_debugfs_dir = debugfs_create_dir("hisi_sas", NULL);

3476 3477 3478 3479 3480 3481
	return 0;
}

static __exit void hisi_sas_exit(void)
{
	sas_release_transport(hisi_sas_stt);
3482 3483

	debugfs_remove(hisi_sas_debugfs_dir);
3484 3485 3486 3487 3488 3489 3490 3491 3492
}

module_init(hisi_sas_init);
module_exit(hisi_sas_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("John Garry <john.garry@huawei.com>");
MODULE_DESCRIPTION("HISILICON SAS controller driver");
MODULE_ALIAS("platform:" DRV_NAME);