.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2015 Linaro Ltd. |
---|
3 | 4 | * Copyright (c) 2015 Hisilicon Limited. |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify |
---|
6 | | - * it under the terms of the GNU General Public License as published by |
---|
7 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
8 | | - * (at your option) any later version. |
---|
9 | | - * |
---|
10 | 5 | */ |
---|
11 | 6 | |
---|
12 | 7 | #include "hisi_sas.h" |
---|
13 | | -#include "../libsas/sas_internal.h" |
---|
14 | 8 | #define DRV_NAME "hisi_sas" |
---|
15 | 9 | |
---|
16 | 10 | #define DEV_IS_GONE(dev) \ |
---|
.. | .. |
---|
124 | 118 | } |
---|
125 | 119 | EXPORT_SYMBOL_GPL(hisi_sas_sata_done); |
---|
126 | 120 | |
---|
127 | | -int hisi_sas_get_ncq_tag(struct sas_task *task, u32 *tag) |
---|
128 | | -{ |
---|
129 | | - struct ata_queued_cmd *qc = task->uldd_task; |
---|
130 | | - |
---|
131 | | - if (qc) { |
---|
132 | | - if (qc->tf.command == ATA_CMD_FPDMA_WRITE || |
---|
133 | | - qc->tf.command == ATA_CMD_FPDMA_READ) { |
---|
134 | | - *tag = qc->tag; |
---|
135 | | - return 1; |
---|
136 | | - } |
---|
137 | | - } |
---|
138 | | - return 0; |
---|
139 | | -} |
---|
140 | | -EXPORT_SYMBOL_GPL(hisi_sas_get_ncq_tag); |
---|
141 | | - |
---|
142 | 121 | /* |
---|
143 | 122 | * This function assumes linkrate mask fits in 8 bits, which it |
---|
144 | 123 | * does for all HW versions supported. |
---|
145 | 124 | */ |
---|
146 | 125 | u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max) |
---|
147 | 126 | { |
---|
148 | | - u16 rate = 0; |
---|
| 127 | + u8 rate = 0; |
---|
149 | 128 | int i; |
---|
150 | 129 | |
---|
151 | 130 | max -= SAS_LINK_RATE_1_5_GBPS; |
---|
.. | .. |
---|
171 | 150 | int phy_no; |
---|
172 | 151 | |
---|
173 | 152 | for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) |
---|
174 | | - hisi_hba->hw->phy_disable(hisi_hba, phy_no); |
---|
| 153 | + hisi_sas_phy_enable(hisi_hba, phy_no, 0); |
---|
175 | 154 | } |
---|
176 | 155 | EXPORT_SYMBOL_GPL(hisi_sas_stop_phys); |
---|
177 | 156 | |
---|
.. | .. |
---|
184 | 163 | |
---|
185 | 164 | static void hisi_sas_slot_index_free(struct hisi_hba *hisi_hba, int slot_idx) |
---|
186 | 165 | { |
---|
187 | | - hisi_sas_slot_index_clear(hisi_hba, slot_idx); |
---|
| 166 | + if (hisi_hba->hw->slot_index_alloc || |
---|
| 167 | + slot_idx >= HISI_SAS_UNRESERVED_IPTT) { |
---|
| 168 | + spin_lock(&hisi_hba->lock); |
---|
| 169 | + hisi_sas_slot_index_clear(hisi_hba, slot_idx); |
---|
| 170 | + spin_unlock(&hisi_hba->lock); |
---|
| 171 | + } |
---|
188 | 172 | } |
---|
189 | 173 | |
---|
190 | 174 | static void hisi_sas_slot_index_set(struct hisi_hba *hisi_hba, int slot_idx) |
---|
.. | .. |
---|
194 | 178 | set_bit(slot_idx, bitmap); |
---|
195 | 179 | } |
---|
196 | 180 | |
---|
197 | | -static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba, int *slot_idx) |
---|
| 181 | +static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba, |
---|
| 182 | + struct scsi_cmnd *scsi_cmnd) |
---|
198 | 183 | { |
---|
199 | | - unsigned int index; |
---|
| 184 | + int index; |
---|
200 | 185 | void *bitmap = hisi_hba->slot_index_tags; |
---|
201 | 186 | |
---|
| 187 | + if (scsi_cmnd) |
---|
| 188 | + return scsi_cmnd->request->tag; |
---|
| 189 | + |
---|
| 190 | + spin_lock(&hisi_hba->lock); |
---|
202 | 191 | index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count, |
---|
203 | | - hisi_hba->last_slot_index + 1); |
---|
| 192 | + hisi_hba->last_slot_index + 1); |
---|
204 | 193 | if (index >= hisi_hba->slot_index_count) { |
---|
205 | | - index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count, |
---|
206 | | - 0); |
---|
207 | | - if (index >= hisi_hba->slot_index_count) |
---|
| 194 | + index = find_next_zero_bit(bitmap, |
---|
| 195 | + hisi_hba->slot_index_count, |
---|
| 196 | + HISI_SAS_UNRESERVED_IPTT); |
---|
| 197 | + if (index >= hisi_hba->slot_index_count) { |
---|
| 198 | + spin_unlock(&hisi_hba->lock); |
---|
208 | 199 | return -SAS_QUEUE_FULL; |
---|
| 200 | + } |
---|
209 | 201 | } |
---|
210 | 202 | hisi_sas_slot_index_set(hisi_hba, index); |
---|
211 | | - *slot_idx = index; |
---|
212 | 203 | hisi_hba->last_slot_index = index; |
---|
| 204 | + spin_unlock(&hisi_hba->lock); |
---|
213 | 205 | |
---|
214 | | - return 0; |
---|
| 206 | + return index; |
---|
215 | 207 | } |
---|
216 | 208 | |
---|
217 | 209 | static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba) |
---|
.. | .. |
---|
225 | 217 | void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, |
---|
226 | 218 | struct hisi_sas_slot *slot) |
---|
227 | 219 | { |
---|
228 | | - struct hisi_sas_dq *dq = &hisi_hba->dq[slot->dlvry_queue]; |
---|
229 | | - unsigned long flags; |
---|
| 220 | + int device_id = slot->device_id; |
---|
| 221 | + struct hisi_sas_device *sas_dev = &hisi_hba->devices[device_id]; |
---|
230 | 222 | |
---|
231 | 223 | if (task) { |
---|
232 | 224 | struct device *dev = hisi_hba->dev; |
---|
.. | .. |
---|
236 | 228 | |
---|
237 | 229 | task->lldd_task = NULL; |
---|
238 | 230 | |
---|
239 | | - if (!sas_protocol_ata(task->task_proto)) |
---|
| 231 | + if (!sas_protocol_ata(task->task_proto)) { |
---|
240 | 232 | if (slot->n_elem) |
---|
241 | 233 | dma_unmap_sg(dev, task->scatter, |
---|
242 | 234 | task->num_scatter, |
---|
243 | 235 | task->data_dir); |
---|
| 236 | + if (slot->n_elem_dif) { |
---|
| 237 | + struct sas_ssp_task *ssp_task = &task->ssp_task; |
---|
| 238 | + struct scsi_cmnd *scsi_cmnd = ssp_task->cmd; |
---|
| 239 | + |
---|
| 240 | + dma_unmap_sg(dev, scsi_prot_sglist(scsi_cmnd), |
---|
| 241 | + scsi_prot_sg_count(scsi_cmnd), |
---|
| 242 | + task->data_dir); |
---|
| 243 | + } |
---|
| 244 | + } |
---|
244 | 245 | } |
---|
245 | 246 | |
---|
246 | | - |
---|
247 | | - spin_lock_irqsave(&dq->lock, flags); |
---|
| 247 | + spin_lock(&sas_dev->lock); |
---|
248 | 248 | list_del_init(&slot->entry); |
---|
249 | | - spin_unlock_irqrestore(&dq->lock, flags); |
---|
| 249 | + spin_unlock(&sas_dev->lock); |
---|
250 | 250 | |
---|
251 | 251 | memset(slot, 0, offsetof(struct hisi_sas_slot, buf)); |
---|
252 | 252 | |
---|
253 | | - spin_lock_irqsave(&hisi_hba->lock, flags); |
---|
254 | 253 | hisi_sas_slot_index_free(hisi_hba, slot->idx); |
---|
255 | | - spin_unlock_irqrestore(&hisi_hba->lock, flags); |
---|
256 | 254 | } |
---|
257 | 255 | EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free); |
---|
258 | 256 | |
---|
.. | .. |
---|
282 | 280 | device_id, abort_flag, tag_to_abort); |
---|
283 | 281 | } |
---|
284 | 282 | |
---|
| 283 | +static void hisi_sas_dma_unmap(struct hisi_hba *hisi_hba, |
---|
| 284 | + struct sas_task *task, int n_elem, |
---|
| 285 | + int n_elem_req) |
---|
| 286 | +{ |
---|
| 287 | + struct device *dev = hisi_hba->dev; |
---|
| 288 | + |
---|
| 289 | + if (!sas_protocol_ata(task->task_proto)) { |
---|
| 290 | + if (task->num_scatter) { |
---|
| 291 | + if (n_elem) |
---|
| 292 | + dma_unmap_sg(dev, task->scatter, |
---|
| 293 | + task->num_scatter, |
---|
| 294 | + task->data_dir); |
---|
| 295 | + } else if (task->task_proto & SAS_PROTOCOL_SMP) { |
---|
| 296 | + if (n_elem_req) |
---|
| 297 | + dma_unmap_sg(dev, &task->smp_task.smp_req, |
---|
| 298 | + 1, DMA_TO_DEVICE); |
---|
| 299 | + } |
---|
| 300 | + } |
---|
| 301 | +} |
---|
| 302 | + |
---|
| 303 | +static int hisi_sas_dma_map(struct hisi_hba *hisi_hba, |
---|
| 304 | + struct sas_task *task, int *n_elem, |
---|
| 305 | + int *n_elem_req) |
---|
| 306 | +{ |
---|
| 307 | + struct device *dev = hisi_hba->dev; |
---|
| 308 | + int rc; |
---|
| 309 | + |
---|
| 310 | + if (sas_protocol_ata(task->task_proto)) { |
---|
| 311 | + *n_elem = task->num_scatter; |
---|
| 312 | + } else { |
---|
| 313 | + unsigned int req_len; |
---|
| 314 | + |
---|
| 315 | + if (task->num_scatter) { |
---|
| 316 | + *n_elem = dma_map_sg(dev, task->scatter, |
---|
| 317 | + task->num_scatter, task->data_dir); |
---|
| 318 | + if (!*n_elem) { |
---|
| 319 | + rc = -ENOMEM; |
---|
| 320 | + goto prep_out; |
---|
| 321 | + } |
---|
| 322 | + } else if (task->task_proto & SAS_PROTOCOL_SMP) { |
---|
| 323 | + *n_elem_req = dma_map_sg(dev, &task->smp_task.smp_req, |
---|
| 324 | + 1, DMA_TO_DEVICE); |
---|
| 325 | + if (!*n_elem_req) { |
---|
| 326 | + rc = -ENOMEM; |
---|
| 327 | + goto prep_out; |
---|
| 328 | + } |
---|
| 329 | + req_len = sg_dma_len(&task->smp_task.smp_req); |
---|
| 330 | + if (req_len & 0x3) { |
---|
| 331 | + rc = -EINVAL; |
---|
| 332 | + goto err_out_dma_unmap; |
---|
| 333 | + } |
---|
| 334 | + } |
---|
| 335 | + } |
---|
| 336 | + |
---|
| 337 | + if (*n_elem > HISI_SAS_SGE_PAGE_CNT) { |
---|
| 338 | + dev_err(dev, "task prep: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT\n", |
---|
| 339 | + *n_elem); |
---|
| 340 | + rc = -EINVAL; |
---|
| 341 | + goto err_out_dma_unmap; |
---|
| 342 | + } |
---|
| 343 | + return 0; |
---|
| 344 | + |
---|
| 345 | +err_out_dma_unmap: |
---|
| 346 | + /* It would be better to call dma_unmap_sg() here, but it's messy */ |
---|
| 347 | + hisi_sas_dma_unmap(hisi_hba, task, *n_elem, |
---|
| 348 | + *n_elem_req); |
---|
| 349 | +prep_out: |
---|
| 350 | + return rc; |
---|
| 351 | +} |
---|
| 352 | + |
---|
| 353 | +static void hisi_sas_dif_dma_unmap(struct hisi_hba *hisi_hba, |
---|
| 354 | + struct sas_task *task, int n_elem_dif) |
---|
| 355 | +{ |
---|
| 356 | + struct device *dev = hisi_hba->dev; |
---|
| 357 | + |
---|
| 358 | + if (n_elem_dif) { |
---|
| 359 | + struct sas_ssp_task *ssp_task = &task->ssp_task; |
---|
| 360 | + struct scsi_cmnd *scsi_cmnd = ssp_task->cmd; |
---|
| 361 | + |
---|
| 362 | + dma_unmap_sg(dev, scsi_prot_sglist(scsi_cmnd), |
---|
| 363 | + scsi_prot_sg_count(scsi_cmnd), |
---|
| 364 | + task->data_dir); |
---|
| 365 | + } |
---|
| 366 | +} |
---|
| 367 | + |
---|
| 368 | +static int hisi_sas_dif_dma_map(struct hisi_hba *hisi_hba, |
---|
| 369 | + int *n_elem_dif, struct sas_task *task) |
---|
| 370 | +{ |
---|
| 371 | + struct device *dev = hisi_hba->dev; |
---|
| 372 | + struct sas_ssp_task *ssp_task; |
---|
| 373 | + struct scsi_cmnd *scsi_cmnd; |
---|
| 374 | + int rc; |
---|
| 375 | + |
---|
| 376 | + if (task->num_scatter) { |
---|
| 377 | + ssp_task = &task->ssp_task; |
---|
| 378 | + scsi_cmnd = ssp_task->cmd; |
---|
| 379 | + |
---|
| 380 | + if (scsi_prot_sg_count(scsi_cmnd)) { |
---|
| 381 | + *n_elem_dif = dma_map_sg(dev, |
---|
| 382 | + scsi_prot_sglist(scsi_cmnd), |
---|
| 383 | + scsi_prot_sg_count(scsi_cmnd), |
---|
| 384 | + task->data_dir); |
---|
| 385 | + |
---|
| 386 | + if (!*n_elem_dif) |
---|
| 387 | + return -ENOMEM; |
---|
| 388 | + |
---|
| 389 | + if (*n_elem_dif > HISI_SAS_SGE_DIF_PAGE_CNT) { |
---|
| 390 | + dev_err(dev, "task prep: n_elem_dif(%d) too large\n", |
---|
| 391 | + *n_elem_dif); |
---|
| 392 | + rc = -EINVAL; |
---|
| 393 | + goto err_out_dif_dma_unmap; |
---|
| 394 | + } |
---|
| 395 | + } |
---|
| 396 | + } |
---|
| 397 | + |
---|
| 398 | + return 0; |
---|
| 399 | + |
---|
| 400 | +err_out_dif_dma_unmap: |
---|
| 401 | + dma_unmap_sg(dev, scsi_prot_sglist(scsi_cmnd), |
---|
| 402 | + scsi_prot_sg_count(scsi_cmnd), task->data_dir); |
---|
| 403 | + return rc; |
---|
| 404 | +} |
---|
| 405 | + |
---|
285 | 406 | static int hisi_sas_task_prep(struct sas_task *task, |
---|
286 | 407 | struct hisi_sas_dq **dq_pointer, |
---|
287 | 408 | bool is_tmf, struct hisi_sas_tmf_task *tmf, |
---|
.. | .. |
---|
296 | 417 | struct asd_sas_port *sas_port = device->port; |
---|
297 | 418 | struct device *dev = hisi_hba->dev; |
---|
298 | 419 | int dlvry_queue_slot, dlvry_queue, rc, slot_idx; |
---|
299 | | - int n_elem = 0, n_elem_req = 0, n_elem_resp = 0; |
---|
| 420 | + int n_elem = 0, n_elem_dif = 0, n_elem_req = 0; |
---|
| 421 | + struct scsi_cmnd *scmd = NULL; |
---|
300 | 422 | struct hisi_sas_dq *dq; |
---|
301 | 423 | unsigned long flags; |
---|
302 | 424 | int wr_q_index; |
---|
303 | | - |
---|
304 | | - if (!sas_port) { |
---|
305 | | - struct task_status_struct *ts = &task->task_status; |
---|
306 | | - |
---|
307 | | - ts->resp = SAS_TASK_UNDELIVERED; |
---|
308 | | - ts->stat = SAS_PHY_DOWN; |
---|
309 | | - /* |
---|
310 | | - * libsas will use dev->port, should |
---|
311 | | - * not call task_done for sata |
---|
312 | | - */ |
---|
313 | | - if (device->dev_type != SAS_SATA_DEV) |
---|
314 | | - task->task_done(task); |
---|
315 | | - return -ECOMM; |
---|
316 | | - } |
---|
317 | 425 | |
---|
318 | 426 | if (DEV_IS_GONE(sas_dev)) { |
---|
319 | 427 | if (sas_dev) |
---|
.. | .. |
---|
326 | 434 | return -ECOMM; |
---|
327 | 435 | } |
---|
328 | 436 | |
---|
329 | | - *dq_pointer = dq = sas_dev->dq; |
---|
| 437 | + if (task->uldd_task) { |
---|
| 438 | + struct ata_queued_cmd *qc; |
---|
| 439 | + |
---|
| 440 | + if (dev_is_sata(device)) { |
---|
| 441 | + qc = task->uldd_task; |
---|
| 442 | + scmd = qc->scsicmd; |
---|
| 443 | + } else { |
---|
| 444 | + scmd = task->uldd_task; |
---|
| 445 | + } |
---|
| 446 | + } |
---|
| 447 | + |
---|
| 448 | + if (scmd && hisi_hba->shost->nr_hw_queues) { |
---|
| 449 | + unsigned int dq_index; |
---|
| 450 | + u32 blk_tag; |
---|
| 451 | + |
---|
| 452 | + blk_tag = blk_mq_unique_tag(scmd->request); |
---|
| 453 | + dq_index = blk_mq_unique_tag_to_hwq(blk_tag); |
---|
| 454 | + *dq_pointer = dq = &hisi_hba->dq[dq_index]; |
---|
| 455 | + } else if (hisi_hba->shost->nr_hw_queues) { |
---|
| 456 | + struct Scsi_Host *shost = hisi_hba->shost; |
---|
| 457 | + struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; |
---|
| 458 | + int queue = qmap->mq_map[raw_smp_processor_id()]; |
---|
| 459 | + |
---|
| 460 | + *dq_pointer = dq = &hisi_hba->dq[queue]; |
---|
| 461 | + } else { |
---|
| 462 | + *dq_pointer = dq = sas_dev->dq; |
---|
| 463 | + } |
---|
330 | 464 | |
---|
331 | 465 | port = to_hisi_sas_port(sas_port); |
---|
332 | 466 | if (port && !port->port_attached) { |
---|
.. | .. |
---|
338 | 472 | return -ECOMM; |
---|
339 | 473 | } |
---|
340 | 474 | |
---|
| 475 | + rc = hisi_sas_dma_map(hisi_hba, task, &n_elem, |
---|
| 476 | + &n_elem_req); |
---|
| 477 | + if (rc < 0) |
---|
| 478 | + goto prep_out; |
---|
| 479 | + |
---|
341 | 480 | if (!sas_protocol_ata(task->task_proto)) { |
---|
342 | | - unsigned int req_len, resp_len; |
---|
343 | | - |
---|
344 | | - if (task->num_scatter) { |
---|
345 | | - n_elem = dma_map_sg(dev, task->scatter, |
---|
346 | | - task->num_scatter, task->data_dir); |
---|
347 | | - if (!n_elem) { |
---|
348 | | - rc = -ENOMEM; |
---|
349 | | - goto prep_out; |
---|
350 | | - } |
---|
351 | | - } else if (task->task_proto & SAS_PROTOCOL_SMP) { |
---|
352 | | - n_elem_req = dma_map_sg(dev, &task->smp_task.smp_req, |
---|
353 | | - 1, DMA_TO_DEVICE); |
---|
354 | | - if (!n_elem_req) { |
---|
355 | | - rc = -ENOMEM; |
---|
356 | | - goto prep_out; |
---|
357 | | - } |
---|
358 | | - req_len = sg_dma_len(&task->smp_task.smp_req); |
---|
359 | | - if (req_len & 0x3) { |
---|
360 | | - rc = -EINVAL; |
---|
361 | | - goto err_out_dma_unmap; |
---|
362 | | - } |
---|
363 | | - n_elem_resp = dma_map_sg(dev, &task->smp_task.smp_resp, |
---|
364 | | - 1, DMA_FROM_DEVICE); |
---|
365 | | - if (!n_elem_resp) { |
---|
366 | | - rc = -ENOMEM; |
---|
367 | | - goto err_out_dma_unmap; |
---|
368 | | - } |
---|
369 | | - resp_len = sg_dma_len(&task->smp_task.smp_resp); |
---|
370 | | - if (resp_len & 0x3) { |
---|
371 | | - rc = -EINVAL; |
---|
372 | | - goto err_out_dma_unmap; |
---|
373 | | - } |
---|
374 | | - } |
---|
375 | | - } else |
---|
376 | | - n_elem = task->num_scatter; |
---|
377 | | - |
---|
378 | | - if (n_elem > HISI_SAS_SGE_PAGE_CNT) { |
---|
379 | | - dev_err(dev, "task prep: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT", |
---|
380 | | - n_elem); |
---|
381 | | - rc = -EINVAL; |
---|
382 | | - goto err_out_dma_unmap; |
---|
| 481 | + rc = hisi_sas_dif_dma_map(hisi_hba, &n_elem_dif, task); |
---|
| 482 | + if (rc < 0) |
---|
| 483 | + goto err_out_dma_unmap; |
---|
383 | 484 | } |
---|
384 | 485 | |
---|
385 | | - spin_lock_irqsave(&hisi_hba->lock, flags); |
---|
386 | 486 | if (hisi_hba->hw->slot_index_alloc) |
---|
387 | | - rc = hisi_hba->hw->slot_index_alloc(hisi_hba, &slot_idx, |
---|
388 | | - device); |
---|
| 487 | + rc = hisi_hba->hw->slot_index_alloc(hisi_hba, device); |
---|
389 | 488 | else |
---|
390 | | - rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx); |
---|
391 | | - spin_unlock_irqrestore(&hisi_hba->lock, flags); |
---|
392 | | - if (rc) |
---|
393 | | - goto err_out_dma_unmap; |
---|
| 489 | + rc = hisi_sas_slot_index_alloc(hisi_hba, scmd); |
---|
394 | 490 | |
---|
| 491 | + if (rc < 0) |
---|
| 492 | + goto err_out_dif_dma_unmap; |
---|
| 493 | + |
---|
| 494 | + slot_idx = rc; |
---|
395 | 495 | slot = &hisi_hba->slot_info[slot_idx]; |
---|
396 | 496 | |
---|
397 | | - spin_lock_irqsave(&dq->lock, flags); |
---|
398 | | - wr_q_index = hisi_hba->hw->get_free_slot(hisi_hba, dq); |
---|
399 | | - if (wr_q_index < 0) { |
---|
400 | | - spin_unlock_irqrestore(&dq->lock, flags); |
---|
401 | | - rc = -EAGAIN; |
---|
402 | | - goto err_out_tag; |
---|
403 | | - } |
---|
404 | | - |
---|
| 497 | + spin_lock(&dq->lock); |
---|
| 498 | + wr_q_index = dq->wr_point; |
---|
| 499 | + dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS; |
---|
405 | 500 | list_add_tail(&slot->delivery, &dq->list); |
---|
| 501 | + spin_unlock(&dq->lock); |
---|
| 502 | + spin_lock(&sas_dev->lock); |
---|
406 | 503 | list_add_tail(&slot->entry, &sas_dev->list); |
---|
407 | | - spin_unlock_irqrestore(&dq->lock, flags); |
---|
| 504 | + spin_unlock(&sas_dev->lock); |
---|
408 | 505 | |
---|
409 | 506 | dlvry_queue = dq->id; |
---|
410 | 507 | dlvry_queue_slot = wr_q_index; |
---|
411 | 508 | |
---|
| 509 | + slot->device_id = sas_dev->device_id; |
---|
412 | 510 | slot->n_elem = n_elem; |
---|
| 511 | + slot->n_elem_dif = n_elem_dif; |
---|
413 | 512 | slot->dlvry_queue = dlvry_queue; |
---|
414 | 513 | slot->dlvry_queue_slot = dlvry_queue_slot; |
---|
415 | 514 | cmd_hdr_base = hisi_hba->cmd_hdr[dlvry_queue]; |
---|
.. | .. |
---|
422 | 521 | |
---|
423 | 522 | memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr)); |
---|
424 | 523 | memset(hisi_sas_cmd_hdr_addr_mem(slot), 0, HISI_SAS_COMMAND_TABLE_SZ); |
---|
425 | | - memset(hisi_sas_status_buf_addr_mem(slot), 0, HISI_SAS_STATUS_BUF_SZ); |
---|
| 524 | + memset(hisi_sas_status_buf_addr_mem(slot), 0, |
---|
| 525 | + sizeof(struct hisi_sas_err_record)); |
---|
426 | 526 | |
---|
427 | 527 | switch (task->task_proto) { |
---|
428 | 528 | case SAS_PROTOCOL_SMP: |
---|
.. | .. |
---|
451 | 551 | |
---|
452 | 552 | return 0; |
---|
453 | 553 | |
---|
454 | | -err_out_tag: |
---|
455 | | - spin_lock_irqsave(&hisi_hba->lock, flags); |
---|
456 | | - hisi_sas_slot_index_free(hisi_hba, slot_idx); |
---|
457 | | - spin_unlock_irqrestore(&hisi_hba->lock, flags); |
---|
| 554 | +err_out_dif_dma_unmap: |
---|
| 555 | + if (!sas_protocol_ata(task->task_proto)) |
---|
| 556 | + hisi_sas_dif_dma_unmap(hisi_hba, task, n_elem_dif); |
---|
458 | 557 | err_out_dma_unmap: |
---|
459 | | - if (!sas_protocol_ata(task->task_proto)) { |
---|
460 | | - if (task->num_scatter) { |
---|
461 | | - dma_unmap_sg(dev, task->scatter, task->num_scatter, |
---|
462 | | - task->data_dir); |
---|
463 | | - } else if (task->task_proto & SAS_PROTOCOL_SMP) { |
---|
464 | | - if (n_elem_req) |
---|
465 | | - dma_unmap_sg(dev, &task->smp_task.smp_req, |
---|
466 | | - 1, DMA_TO_DEVICE); |
---|
467 | | - if (n_elem_resp) |
---|
468 | | - dma_unmap_sg(dev, &task->smp_task.smp_resp, |
---|
469 | | - 1, DMA_FROM_DEVICE); |
---|
470 | | - } |
---|
471 | | - } |
---|
| 558 | + hisi_sas_dma_unmap(hisi_hba, task, n_elem, |
---|
| 559 | + n_elem_req); |
---|
472 | 560 | prep_out: |
---|
473 | 561 | dev_err(dev, "task prep: failed[%d]!\n", rc); |
---|
474 | 562 | return rc; |
---|
.. | .. |
---|
479 | 567 | { |
---|
480 | 568 | u32 rc; |
---|
481 | 569 | u32 pass = 0; |
---|
482 | | - unsigned long flags; |
---|
483 | | - struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev); |
---|
484 | | - struct device *dev = hisi_hba->dev; |
---|
| 570 | + struct hisi_hba *hisi_hba; |
---|
| 571 | + struct device *dev; |
---|
| 572 | + struct domain_device *device = task->dev; |
---|
| 573 | + struct asd_sas_port *sas_port = device->port; |
---|
485 | 574 | struct hisi_sas_dq *dq = NULL; |
---|
| 575 | + |
---|
| 576 | + if (!sas_port) { |
---|
| 577 | + struct task_status_struct *ts = &task->task_status; |
---|
| 578 | + |
---|
| 579 | + ts->resp = SAS_TASK_UNDELIVERED; |
---|
| 580 | + ts->stat = SAS_PHY_DOWN; |
---|
| 581 | + /* |
---|
| 582 | + * libsas will use dev->port, should |
---|
| 583 | + * not call task_done for sata |
---|
| 584 | + */ |
---|
| 585 | + if (device->dev_type != SAS_SATA_DEV) |
---|
| 586 | + task->task_done(task); |
---|
| 587 | + return -ECOMM; |
---|
| 588 | + } |
---|
| 589 | + |
---|
| 590 | + hisi_hba = dev_to_hisi_hba(device); |
---|
| 591 | + dev = hisi_hba->dev; |
---|
486 | 592 | |
---|
487 | 593 | if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) { |
---|
488 | 594 | /* |
---|
.. | .. |
---|
504 | 610 | dev_err(dev, "task exec: failed[%d]!\n", rc); |
---|
505 | 611 | |
---|
506 | 612 | if (likely(pass)) { |
---|
507 | | - spin_lock_irqsave(&dq->lock, flags); |
---|
| 613 | + spin_lock(&dq->lock); |
---|
508 | 614 | hisi_hba->hw->start_delivery(dq); |
---|
509 | | - spin_unlock_irqrestore(&dq->lock, flags); |
---|
| 615 | + spin_unlock(&dq->lock); |
---|
510 | 616 | } |
---|
511 | 617 | |
---|
512 | 618 | return rc; |
---|
.. | .. |
---|
516 | 622 | { |
---|
517 | 623 | struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; |
---|
518 | 624 | struct asd_sas_phy *sas_phy = &phy->sas_phy; |
---|
519 | | - struct sas_ha_struct *sas_ha; |
---|
520 | 625 | |
---|
521 | 626 | if (!phy->phy_attached) |
---|
522 | 627 | return; |
---|
523 | 628 | |
---|
524 | | - sas_ha = &hisi_hba->sha; |
---|
525 | | - sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE); |
---|
| 629 | + if (test_bit(HISI_SAS_PM_BIT, &hisi_hba->flags) && |
---|
| 630 | + !sas_phy->suspended) { |
---|
| 631 | + dev_warn(hisi_hba->dev, "phy%d during suspend filtered out\n", phy_no); |
---|
| 632 | + return; |
---|
| 633 | + } |
---|
| 634 | + |
---|
| 635 | + sas_notify_phy_event(sas_phy, PHYE_OOB_DONE); |
---|
526 | 636 | |
---|
527 | 637 | if (sas_phy->phy) { |
---|
528 | 638 | struct sas_phy *sphy = sas_phy->phy; |
---|
.. | .. |
---|
546 | 656 | id->initiator_bits = SAS_PROTOCOL_ALL; |
---|
547 | 657 | id->target_bits = phy->identify.target_port_protocols; |
---|
548 | 658 | } else if (phy->phy_type & PORT_TYPE_SATA) { |
---|
549 | | - /*Nothing*/ |
---|
| 659 | + /* Nothing */ |
---|
550 | 660 | } |
---|
551 | 661 | |
---|
552 | 662 | sas_phy->frame_rcvd_size = phy->frame_rcvd_size; |
---|
553 | | - sas_ha->notify_port_event(sas_phy, PORTE_BYTES_DMAED); |
---|
| 663 | + sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED); |
---|
554 | 664 | } |
---|
555 | 665 | |
---|
556 | 666 | static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device) |
---|
557 | 667 | { |
---|
558 | 668 | struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); |
---|
559 | 669 | struct hisi_sas_device *sas_dev = NULL; |
---|
560 | | - unsigned long flags; |
---|
561 | 670 | int last = hisi_hba->last_dev_id; |
---|
562 | 671 | int first = (hisi_hba->last_dev_id + 1) % HISI_SAS_MAX_DEVICES; |
---|
563 | 672 | int i; |
---|
564 | 673 | |
---|
565 | | - spin_lock_irqsave(&hisi_hba->lock, flags); |
---|
| 674 | + spin_lock(&hisi_hba->lock); |
---|
566 | 675 | for (i = first; i != last; i %= HISI_SAS_MAX_DEVICES) { |
---|
567 | 676 | if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) { |
---|
568 | 677 | int queue = i % hisi_hba->queue_count; |
---|
.. | .. |
---|
570 | 679 | |
---|
571 | 680 | hisi_hba->devices[i].device_id = i; |
---|
572 | 681 | sas_dev = &hisi_hba->devices[i]; |
---|
573 | | - sas_dev->dev_status = HISI_SAS_DEV_NORMAL; |
---|
| 682 | + sas_dev->dev_status = HISI_SAS_DEV_INIT; |
---|
574 | 683 | sas_dev->dev_type = device->dev_type; |
---|
575 | 684 | sas_dev->hisi_hba = hisi_hba; |
---|
576 | 685 | sas_dev->sas_device = device; |
---|
577 | 686 | sas_dev->dq = dq; |
---|
| 687 | + spin_lock_init(&sas_dev->lock); |
---|
578 | 688 | INIT_LIST_HEAD(&hisi_hba->devices[i].list); |
---|
579 | 689 | break; |
---|
580 | 690 | } |
---|
581 | 691 | i++; |
---|
582 | 692 | } |
---|
583 | 693 | hisi_hba->last_dev_id = i; |
---|
584 | | - spin_unlock_irqrestore(&hisi_hba->lock, flags); |
---|
| 694 | + spin_unlock(&hisi_hba->lock); |
---|
585 | 695 | |
---|
586 | 696 | return sas_dev; |
---|
587 | 697 | } |
---|
588 | 698 | |
---|
589 | | -#define HISI_SAS_SRST_ATA_DISK_CNT 3 |
---|
| 699 | +#define HISI_SAS_DISK_RECOVER_CNT 3 |
---|
590 | 700 | static int hisi_sas_init_device(struct domain_device *device) |
---|
591 | 701 | { |
---|
592 | 702 | int rc = TMF_RESP_FUNC_COMPLETE; |
---|
593 | 703 | struct scsi_lun lun; |
---|
594 | 704 | struct hisi_sas_tmf_task tmf_task; |
---|
595 | | - int retry = HISI_SAS_SRST_ATA_DISK_CNT; |
---|
| 705 | + int retry = HISI_SAS_DISK_RECOVER_CNT; |
---|
596 | 706 | struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); |
---|
| 707 | + struct device *dev = hisi_hba->dev; |
---|
| 708 | + struct sas_phy *local_phy; |
---|
597 | 709 | |
---|
598 | 710 | switch (device->dev_type) { |
---|
599 | 711 | case SAS_END_DEVICE: |
---|
600 | 712 | int_to_scsilun(0, &lun); |
---|
601 | 713 | |
---|
602 | 714 | tmf_task.tmf = TMF_CLEAR_TASK_SET; |
---|
603 | | - rc = hisi_sas_debug_issue_ssp_tmf(device, lun.scsi_lun, |
---|
604 | | - &tmf_task); |
---|
605 | | - if (rc == TMF_RESP_FUNC_COMPLETE) |
---|
606 | | - hisi_sas_release_task(hisi_hba, device); |
---|
| 715 | + while (retry-- > 0) { |
---|
| 716 | + rc = hisi_sas_debug_issue_ssp_tmf(device, lun.scsi_lun, |
---|
| 717 | + &tmf_task); |
---|
| 718 | + if (rc == TMF_RESP_FUNC_COMPLETE) { |
---|
| 719 | + hisi_sas_release_task(hisi_hba, device); |
---|
| 720 | + break; |
---|
| 721 | + } |
---|
| 722 | + } |
---|
607 | 723 | break; |
---|
608 | 724 | case SAS_SATA_DEV: |
---|
609 | 725 | case SAS_SATA_PM: |
---|
610 | 726 | case SAS_SATA_PM_PORT: |
---|
611 | 727 | case SAS_SATA_PENDING: |
---|
| 728 | + /* |
---|
| 729 | + * send HARD RESET to clear previous affiliation of |
---|
| 730 | + * STP target port |
---|
| 731 | + */ |
---|
| 732 | + local_phy = sas_get_local_phy(device); |
---|
| 733 | + if (!scsi_is_sas_phy_local(local_phy) && |
---|
| 734 | + !test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) { |
---|
| 735 | + unsigned long deadline = ata_deadline(jiffies, 20000); |
---|
| 736 | + struct sata_device *sata_dev = &device->sata_dev; |
---|
| 737 | + struct ata_host *ata_host = sata_dev->ata_host; |
---|
| 738 | + struct ata_port_operations *ops = ata_host->ops; |
---|
| 739 | + struct ata_port *ap = sata_dev->ap; |
---|
| 740 | + struct ata_link *link; |
---|
| 741 | + unsigned int classes; |
---|
| 742 | + |
---|
| 743 | + ata_for_each_link(link, ap, EDGE) |
---|
| 744 | + rc = ops->hardreset(link, &classes, |
---|
| 745 | + deadline); |
---|
| 746 | + } |
---|
| 747 | + sas_put_local_phy(local_phy); |
---|
| 748 | + if (rc) { |
---|
| 749 | + dev_warn(dev, "SATA disk hardreset fail: %d\n", rc); |
---|
| 750 | + return rc; |
---|
| 751 | + } |
---|
| 752 | + |
---|
612 | 753 | while (retry-- > 0) { |
---|
613 | 754 | rc = hisi_sas_softreset_ata_disk(device); |
---|
614 | 755 | if (!rc) |
---|
.. | .. |
---|
643 | 784 | device->lldd_dev = sas_dev; |
---|
644 | 785 | hisi_hba->hw->setup_itct(hisi_hba, sas_dev); |
---|
645 | 786 | |
---|
646 | | - if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) { |
---|
| 787 | + if (parent_dev && dev_is_expander(parent_dev->dev_type)) { |
---|
647 | 788 | int phy_no; |
---|
648 | 789 | u8 phy_num = parent_dev->ex_dev.num_phys; |
---|
649 | 790 | struct ex_phy *phy; |
---|
.. | .. |
---|
671 | 812 | rc = hisi_sas_init_device(device); |
---|
672 | 813 | if (rc) |
---|
673 | 814 | goto err_out; |
---|
| 815 | + sas_dev->dev_status = HISI_SAS_DEV_NORMAL; |
---|
674 | 816 | return 0; |
---|
675 | 817 | |
---|
676 | 818 | err_out: |
---|
.. | .. |
---|
753 | 895 | } |
---|
754 | 896 | EXPORT_SYMBOL_GPL(hisi_sas_notify_phy_event); |
---|
755 | 897 | |
---|
| 898 | +static void hisi_sas_wait_phyup_timedout(struct timer_list *t) |
---|
| 899 | +{ |
---|
| 900 | + struct hisi_sas_phy *phy = from_timer(phy, t, timer); |
---|
| 901 | + struct hisi_hba *hisi_hba = phy->hisi_hba; |
---|
| 902 | + struct device *dev = hisi_hba->dev; |
---|
| 903 | + int phy_no = phy->sas_phy.id; |
---|
| 904 | + |
---|
| 905 | + dev_warn(dev, "phy%d wait phyup timeout, issuing link reset\n", phy_no); |
---|
| 906 | + hisi_sas_notify_phy_event(phy, HISI_PHYE_LINK_RESET); |
---|
| 907 | +} |
---|
| 908 | + |
---|
| 909 | +void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no) |
---|
| 910 | +{ |
---|
| 911 | + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; |
---|
| 912 | + struct device *dev = hisi_hba->dev; |
---|
| 913 | + |
---|
| 914 | + dev_dbg(dev, "phy%d OOB ready\n", phy_no); |
---|
| 915 | + if (phy->phy_attached) |
---|
| 916 | + return; |
---|
| 917 | + |
---|
| 918 | + if (!timer_pending(&phy->timer)) { |
---|
| 919 | + phy->timer.expires = jiffies + HISI_SAS_WAIT_PHYUP_TIMEOUT * HZ; |
---|
| 920 | + add_timer(&phy->timer); |
---|
| 921 | + } |
---|
| 922 | +} |
---|
| 923 | +EXPORT_SYMBOL_GPL(hisi_sas_phy_oob_ready); |
---|
| 924 | + |
---|
756 | 925 | static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no) |
---|
757 | 926 | { |
---|
758 | 927 | struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; |
---|
.. | .. |
---|
781 | 950 | INIT_WORK(&phy->works[i], hisi_sas_phye_fns[i]); |
---|
782 | 951 | |
---|
783 | 952 | spin_lock_init(&phy->lock); |
---|
| 953 | + |
---|
| 954 | + timer_setup(&phy->timer, hisi_sas_wait_phyup_timedout, 0); |
---|
784 | 955 | } |
---|
| 956 | + |
---|
| 957 | +/* Wrapper to ensure we track hisi_sas_phy.enable properly */ |
---|
| 958 | +void hisi_sas_phy_enable(struct hisi_hba *hisi_hba, int phy_no, int enable) |
---|
| 959 | +{ |
---|
| 960 | + struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; |
---|
| 961 | + struct asd_sas_phy *aphy = &phy->sas_phy; |
---|
| 962 | + struct sas_phy *sphy = aphy->phy; |
---|
| 963 | + unsigned long flags; |
---|
| 964 | + |
---|
| 965 | + spin_lock_irqsave(&phy->lock, flags); |
---|
| 966 | + |
---|
| 967 | + if (enable) { |
---|
| 968 | + /* We may have been enabled already; if so, don't touch */ |
---|
| 969 | + if (!phy->enable) |
---|
| 970 | + sphy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; |
---|
| 971 | + hisi_hba->hw->phy_start(hisi_hba, phy_no); |
---|
| 972 | + } else { |
---|
| 973 | + sphy->negotiated_linkrate = SAS_PHY_DISABLED; |
---|
| 974 | + hisi_hba->hw->phy_disable(hisi_hba, phy_no); |
---|
| 975 | + } |
---|
| 976 | + phy->enable = enable; |
---|
| 977 | + spin_unlock_irqrestore(&phy->lock, flags); |
---|
| 978 | +} |
---|
| 979 | +EXPORT_SYMBOL_GPL(hisi_sas_phy_enable); |
---|
785 | 980 | |
---|
786 | 981 | static void hisi_sas_port_notify_formed(struct asd_sas_phy *sas_phy) |
---|
787 | 982 | { |
---|
.. | .. |
---|
867 | 1062 | struct hisi_sas_device *sas_dev = device->lldd_dev; |
---|
868 | 1063 | struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); |
---|
869 | 1064 | struct device *dev = hisi_hba->dev; |
---|
| 1065 | + int ret = 0; |
---|
870 | 1066 | |
---|
871 | 1067 | dev_info(dev, "dev[%d:%x] is gone\n", |
---|
872 | 1068 | sas_dev->device_id, sas_dev->dev_type); |
---|
873 | 1069 | |
---|
| 1070 | + down(&hisi_hba->sem); |
---|
874 | 1071 | if (!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags)) { |
---|
875 | 1072 | hisi_sas_internal_task_abort(hisi_hba, device, |
---|
876 | | - HISI_SAS_INT_ABT_DEV, 0); |
---|
| 1073 | + HISI_SAS_INT_ABT_DEV, 0); |
---|
877 | 1074 | |
---|
878 | 1075 | hisi_sas_dereg_device(hisi_hba, device); |
---|
879 | 1076 | |
---|
880 | | - down(&hisi_hba->sem); |
---|
881 | | - hisi_hba->hw->clear_itct(hisi_hba, sas_dev); |
---|
882 | | - up(&hisi_hba->sem); |
---|
| 1077 | + ret = hisi_hba->hw->clear_itct(hisi_hba, sas_dev); |
---|
883 | 1078 | device->lldd_dev = NULL; |
---|
884 | 1079 | } |
---|
885 | 1080 | |
---|
886 | 1081 | if (hisi_hba->hw->free_device) |
---|
887 | 1082 | hisi_hba->hw->free_device(sas_dev); |
---|
888 | | - sas_dev->dev_type = SAS_PHY_UNUSED; |
---|
| 1083 | + |
---|
| 1084 | + /* Don't mark it as SAS_PHY_UNUSED if failed to clear ITCT */ |
---|
| 1085 | + if (!ret) |
---|
| 1086 | + sas_dev->dev_type = SAS_PHY_UNUSED; |
---|
| 1087 | + sas_dev->sas_device = NULL; |
---|
| 1088 | + up(&hisi_hba->sem); |
---|
889 | 1089 | } |
---|
890 | 1090 | |
---|
891 | 1091 | static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags) |
---|
.. | .. |
---|
920 | 1120 | sas_phy->phy->maximum_linkrate = max; |
---|
921 | 1121 | sas_phy->phy->minimum_linkrate = min; |
---|
922 | 1122 | |
---|
923 | | - hisi_hba->hw->phy_disable(hisi_hba, phy_no); |
---|
| 1123 | + hisi_sas_phy_enable(hisi_hba, phy_no, 0); |
---|
924 | 1124 | msleep(100); |
---|
925 | 1125 | hisi_hba->hw->phy_set_linkrate(hisi_hba, phy_no, &_r); |
---|
926 | | - hisi_hba->hw->phy_start(hisi_hba, phy_no); |
---|
| 1126 | + hisi_sas_phy_enable(hisi_hba, phy_no, 1); |
---|
927 | 1127 | |
---|
928 | 1128 | return 0; |
---|
929 | 1129 | } |
---|
.. | .. |
---|
941 | 1141 | break; |
---|
942 | 1142 | |
---|
943 | 1143 | case PHY_FUNC_LINK_RESET: |
---|
944 | | - hisi_hba->hw->phy_disable(hisi_hba, phy_no); |
---|
| 1144 | + hisi_sas_phy_enable(hisi_hba, phy_no, 0); |
---|
945 | 1145 | msleep(100); |
---|
946 | | - hisi_hba->hw->phy_start(hisi_hba, phy_no); |
---|
| 1146 | + hisi_sas_phy_enable(hisi_hba, phy_no, 1); |
---|
947 | 1147 | break; |
---|
948 | 1148 | |
---|
949 | 1149 | case PHY_FUNC_DISABLE: |
---|
950 | | - hisi_hba->hw->phy_disable(hisi_hba, phy_no); |
---|
| 1150 | + hisi_sas_phy_enable(hisi_hba, phy_no, 0); |
---|
951 | 1151 | break; |
---|
952 | 1152 | |
---|
953 | 1153 | case PHY_FUNC_SET_LINK_RATE: |
---|
.. | .. |
---|
957 | 1157 | hisi_hba->hw->get_events(hisi_hba, phy_no); |
---|
958 | 1158 | break; |
---|
959 | 1159 | } |
---|
960 | | - /* fallthru */ |
---|
| 1160 | + fallthrough; |
---|
961 | 1161 | case PHY_FUNC_RELEASE_SPINUP_HOLD: |
---|
962 | 1162 | default: |
---|
963 | 1163 | return -EOPNOTSUPP; |
---|
.. | .. |
---|
1019 | 1219 | task->task_done = hisi_sas_task_done; |
---|
1020 | 1220 | |
---|
1021 | 1221 | task->slow_task->timer.function = hisi_sas_tmf_timedout; |
---|
1022 | | - task->slow_task->timer.expires = jiffies + TASK_TIMEOUT*HZ; |
---|
| 1222 | + task->slow_task->timer.expires = jiffies + TASK_TIMEOUT * HZ; |
---|
1023 | 1223 | add_timer(&task->slow_task->timer); |
---|
1024 | 1224 | |
---|
1025 | 1225 | res = hisi_sas_task_exec(task, GFP_KERNEL, 1, tmf); |
---|
.. | .. |
---|
1043 | 1243 | struct hisi_sas_cq *cq = |
---|
1044 | 1244 | &hisi_hba->cq[slot->dlvry_queue]; |
---|
1045 | 1245 | /* |
---|
1046 | | - * flush tasklet to avoid free'ing task |
---|
| 1246 | + * sync irq to avoid free'ing task |
---|
1047 | 1247 | * before using task in IO completion |
---|
1048 | 1248 | */ |
---|
1049 | | - tasklet_kill(&cq->tasklet); |
---|
| 1249 | + synchronize_irq(cq->irq_no); |
---|
1050 | 1250 | slot->task = NULL; |
---|
1051 | 1251 | } |
---|
1052 | 1252 | |
---|
.. | .. |
---|
1072 | 1272 | /* no error, but return the number of bytes of |
---|
1073 | 1273 | * underrun |
---|
1074 | 1274 | */ |
---|
1075 | | - dev_warn(dev, "abort tmf: task to dev %016llx " |
---|
1076 | | - "resp: 0x%x sts 0x%x underrun\n", |
---|
| 1275 | + dev_warn(dev, "abort tmf: task to dev %016llx resp: 0x%x sts 0x%x underrun\n", |
---|
1077 | 1276 | SAS_ADDR(device->sas_addr), |
---|
1078 | 1277 | task->task_status.resp, |
---|
1079 | 1278 | task->task_status.stat); |
---|
.. | .. |
---|
1088 | 1287 | break; |
---|
1089 | 1288 | } |
---|
1090 | 1289 | |
---|
1091 | | - dev_warn(dev, "abort tmf: task to dev " |
---|
1092 | | - "%016llx resp: 0x%x status 0x%x\n", |
---|
1093 | | - SAS_ADDR(device->sas_addr), task->task_status.resp, |
---|
1094 | | - task->task_status.stat); |
---|
| 1290 | + if (task->task_status.resp == SAS_TASK_COMPLETE && |
---|
| 1291 | + task->task_status.stat == SAS_OPEN_REJECT) { |
---|
| 1292 | + dev_warn(dev, "abort tmf: open reject failed\n"); |
---|
| 1293 | + res = -EIO; |
---|
| 1294 | + } else { |
---|
| 1295 | + dev_warn(dev, "abort tmf: task to dev %016llx resp: 0x%x status 0x%x\n", |
---|
| 1296 | + SAS_ADDR(device->sas_addr), |
---|
| 1297 | + task->task_status.resp, |
---|
| 1298 | + task->task_status.stat); |
---|
| 1299 | + } |
---|
1095 | 1300 | sas_free_task(task); |
---|
1096 | 1301 | task = NULL; |
---|
1097 | 1302 | } |
---|
.. | .. |
---|
1203 | 1408 | device->linkrate = phy->sas_phy.linkrate; |
---|
1204 | 1409 | |
---|
1205 | 1410 | hisi_hba->hw->setup_itct(hisi_hba, sas_dev); |
---|
1206 | | - } else |
---|
| 1411 | + } else if (!port->port_attached) |
---|
1207 | 1412 | port->id = 0xff; |
---|
1208 | 1413 | } |
---|
1209 | 1414 | } |
---|
1210 | 1415 | |
---|
1211 | | -static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 old_state, |
---|
1212 | | - u32 state) |
---|
| 1416 | +static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state) |
---|
1213 | 1417 | { |
---|
1214 | | - struct sas_ha_struct *sas_ha = &hisi_hba->sha; |
---|
1215 | 1418 | struct asd_sas_port *_sas_port = NULL; |
---|
1216 | 1419 | int phy_no; |
---|
1217 | 1420 | |
---|
.. | .. |
---|
1219 | 1422 | struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; |
---|
1220 | 1423 | struct asd_sas_phy *sas_phy = &phy->sas_phy; |
---|
1221 | 1424 | struct asd_sas_port *sas_port = sas_phy->port; |
---|
1222 | | - bool do_port_check = !!(_sas_port != sas_port); |
---|
| 1425 | + bool do_port_check = _sas_port != sas_port; |
---|
1223 | 1426 | |
---|
1224 | 1427 | if (!sas_phy->phy->enabled) |
---|
1225 | 1428 | continue; |
---|
.. | .. |
---|
1231 | 1434 | |
---|
1232 | 1435 | _sas_port = sas_port; |
---|
1233 | 1436 | |
---|
1234 | | - if (DEV_IS_EXPANDER(dev->dev_type)) |
---|
1235 | | - sas_ha->notify_port_event(sas_phy, |
---|
| 1437 | + if (dev_is_expander(dev->dev_type)) |
---|
| 1438 | + sas_notify_port_event(sas_phy, |
---|
1236 | 1439 | PORTE_BROADCAST_RCVD); |
---|
1237 | 1440 | } |
---|
1238 | | - } else if (old_state & (1 << phy_no)) |
---|
1239 | | - /* PHY down but was up before */ |
---|
| 1441 | + } else { |
---|
1240 | 1442 | hisi_sas_phy_down(hisi_hba, phy_no, 0); |
---|
1241 | | - |
---|
| 1443 | + } |
---|
1242 | 1444 | } |
---|
1243 | 1445 | } |
---|
1244 | 1446 | |
---|
.. | .. |
---|
1318 | 1520 | struct domain_device *port_dev = sas_port->port_dev; |
---|
1319 | 1521 | struct domain_device *device; |
---|
1320 | 1522 | |
---|
1321 | | - if (!port_dev || !DEV_IS_EXPANDER(port_dev->dev_type)) |
---|
| 1523 | + if (!port_dev || !dev_is_expander(port_dev->dev_type)) |
---|
1322 | 1524 | continue; |
---|
1323 | 1525 | |
---|
1324 | 1526 | /* Try to find a SATA device */ |
---|
.. | .. |
---|
1354 | 1556 | void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba) |
---|
1355 | 1557 | { |
---|
1356 | 1558 | struct Scsi_Host *shost = hisi_hba->shost; |
---|
1357 | | - u32 state; |
---|
1358 | 1559 | |
---|
1359 | 1560 | /* Init and wait for PHYs to come up and all libsas event finished. */ |
---|
1360 | 1561 | hisi_hba->hw->phys_init(hisi_hba); |
---|
1361 | 1562 | msleep(1000); |
---|
1362 | 1563 | hisi_sas_refresh_port_id(hisi_hba); |
---|
1363 | 1564 | clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); |
---|
1364 | | - up(&hisi_hba->sem); |
---|
1365 | 1565 | |
---|
1366 | 1566 | if (hisi_hba->reject_stp_links_msk) |
---|
1367 | 1567 | hisi_sas_terminate_stp_reject(hisi_hba); |
---|
1368 | 1568 | hisi_sas_reset_init_all_devices(hisi_hba); |
---|
| 1569 | + up(&hisi_hba->sem); |
---|
1369 | 1570 | scsi_unblock_requests(shost); |
---|
1370 | 1571 | clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); |
---|
1371 | 1572 | |
---|
1372 | | - state = hisi_hba->hw->get_phys_state(hisi_hba); |
---|
1373 | | - hisi_sas_rescan_topology(hisi_hba, hisi_hba->phy_state, state); |
---|
| 1573 | + hisi_sas_rescan_topology(hisi_hba, hisi_hba->phy_state); |
---|
1374 | 1574 | } |
---|
1375 | 1575 | EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_done); |
---|
1376 | 1576 | |
---|
.. | .. |
---|
1379 | 1579 | struct device *dev = hisi_hba->dev; |
---|
1380 | 1580 | struct Scsi_Host *shost = hisi_hba->shost; |
---|
1381 | 1581 | int rc; |
---|
| 1582 | + |
---|
| 1583 | + if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) |
---|
| 1584 | + queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); |
---|
1382 | 1585 | |
---|
1383 | 1586 | if (!hisi_hba->hw->soft_reset) |
---|
1384 | 1587 | return -1; |
---|
.. | .. |
---|
1429 | 1632 | |
---|
1430 | 1633 | if (slot) { |
---|
1431 | 1634 | /* |
---|
1432 | | - * flush tasklet to avoid free'ing task |
---|
| 1635 | + * sync irq to avoid free'ing task |
---|
1433 | 1636 | * before using task in IO completion |
---|
1434 | 1637 | */ |
---|
1435 | 1638 | cq = &hisi_hba->cq[slot->dlvry_queue]; |
---|
1436 | | - tasklet_kill(&cq->tasklet); |
---|
| 1639 | + synchronize_irq(cq->irq_no); |
---|
1437 | 1640 | } |
---|
1438 | 1641 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
---|
1439 | 1642 | rc = TMF_RESP_FUNC_COMPLETE; |
---|
.. | .. |
---|
1442 | 1645 | task->task_state_flags |= SAS_TASK_STATE_ABORTED; |
---|
1443 | 1646 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
---|
1444 | 1647 | |
---|
1445 | | - sas_dev->dev_status = HISI_SAS_DEV_EH; |
---|
1446 | 1648 | if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { |
---|
1447 | 1649 | struct scsi_cmnd *cmnd = task->uldd_task; |
---|
1448 | 1650 | struct hisi_sas_slot *slot = task->lldd_task; |
---|
1449 | | - u32 tag = slot->idx; |
---|
| 1651 | + u16 tag = slot->idx; |
---|
1450 | 1652 | int rc2; |
---|
1451 | 1653 | |
---|
1452 | 1654 | int_to_scsilun(cmnd->device->lun, &lun); |
---|
1453 | 1655 | tmf_task.tmf = TMF_ABORT_TASK; |
---|
1454 | | - tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag); |
---|
| 1656 | + tmf_task.tag_of_task_to_be_managed = tag; |
---|
1455 | 1657 | |
---|
1456 | 1658 | rc = hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun, |
---|
1457 | 1659 | &tmf_task); |
---|
.. | .. |
---|
1478 | 1680 | task->task_proto & SAS_PROTOCOL_STP) { |
---|
1479 | 1681 | if (task->dev->dev_type == SAS_SATA_DEV) { |
---|
1480 | 1682 | rc = hisi_sas_internal_task_abort(hisi_hba, device, |
---|
1481 | | - HISI_SAS_INT_ABT_DEV, 0); |
---|
| 1683 | + HISI_SAS_INT_ABT_DEV, |
---|
| 1684 | + 0); |
---|
1482 | 1685 | if (rc < 0) { |
---|
1483 | 1686 | dev_err(dev, "abort task: internal abort failed\n"); |
---|
1484 | 1687 | goto out; |
---|
.. | .. |
---|
1493 | 1696 | struct hisi_sas_cq *cq = &hisi_hba->cq[slot->dlvry_queue]; |
---|
1494 | 1697 | |
---|
1495 | 1698 | rc = hisi_sas_internal_task_abort(hisi_hba, device, |
---|
1496 | | - HISI_SAS_INT_ABT_CMD, tag); |
---|
| 1699 | + HISI_SAS_INT_ABT_CMD, tag); |
---|
1497 | 1700 | if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) && |
---|
1498 | 1701 | task->lldd_task) { |
---|
1499 | 1702 | /* |
---|
1500 | | - * flush tasklet to avoid free'ing task |
---|
| 1703 | + * sync irq to avoid free'ing task |
---|
1501 | 1704 | * before using task in IO completion |
---|
1502 | 1705 | */ |
---|
1503 | | - tasklet_kill(&cq->tasklet); |
---|
| 1706 | + synchronize_irq(cq->irq_no); |
---|
1504 | 1707 | slot->task = NULL; |
---|
1505 | 1708 | } |
---|
1506 | 1709 | } |
---|
.. | .. |
---|
1516 | 1719 | struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); |
---|
1517 | 1720 | struct device *dev = hisi_hba->dev; |
---|
1518 | 1721 | struct hisi_sas_tmf_task tmf_task; |
---|
1519 | | - int rc = TMF_RESP_FUNC_FAILED; |
---|
| 1722 | + int rc; |
---|
1520 | 1723 | |
---|
1521 | 1724 | rc = hisi_sas_internal_task_abort(hisi_hba, device, |
---|
1522 | | - HISI_SAS_INT_ABT_DEV, 0); |
---|
| 1725 | + HISI_SAS_INT_ABT_DEV, 0); |
---|
1523 | 1726 | if (rc < 0) { |
---|
1524 | 1727 | dev_err(dev, "abort task set: internal abort rc=%d\n", rc); |
---|
1525 | 1728 | return TMF_RESP_FUNC_FAILED; |
---|
.. | .. |
---|
1537 | 1740 | |
---|
1538 | 1741 | static int hisi_sas_clear_aca(struct domain_device *device, u8 *lun) |
---|
1539 | 1742 | { |
---|
1540 | | - int rc = TMF_RESP_FUNC_FAILED; |
---|
1541 | 1743 | struct hisi_sas_tmf_task tmf_task; |
---|
| 1744 | + int rc; |
---|
1542 | 1745 | |
---|
1543 | 1746 | tmf_task.tmf = TMF_CLEAR_ACA; |
---|
1544 | 1747 | rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task); |
---|
.. | .. |
---|
1549 | 1752 | static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) |
---|
1550 | 1753 | { |
---|
1551 | 1754 | struct sas_phy *local_phy = sas_get_local_phy(device); |
---|
1552 | | - int rc, reset_type = (device->dev_type == SAS_SATA_DEV || |
---|
1553 | | - (device->tproto & SAS_PROTOCOL_STP)) ? 0 : 1; |
---|
| 1755 | + struct hisi_sas_device *sas_dev = device->lldd_dev; |
---|
1554 | 1756 | struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); |
---|
1555 | 1757 | struct sas_ha_struct *sas_ha = &hisi_hba->sha; |
---|
1556 | | - struct asd_sas_phy *sas_phy = sas_ha->sas_phy[local_phy->number]; |
---|
1557 | | - struct hisi_sas_phy *phy = container_of(sas_phy, |
---|
1558 | | - struct hisi_sas_phy, sas_phy); |
---|
1559 | 1758 | DECLARE_COMPLETION_ONSTACK(phyreset); |
---|
| 1759 | + int rc, reset_type; |
---|
| 1760 | + |
---|
| 1761 | + if (!local_phy->enabled) { |
---|
| 1762 | + sas_put_local_phy(local_phy); |
---|
| 1763 | + return -ENODEV; |
---|
| 1764 | + } |
---|
1560 | 1765 | |
---|
1561 | 1766 | if (scsi_is_sas_phy_local(local_phy)) { |
---|
| 1767 | + struct asd_sas_phy *sas_phy = |
---|
| 1768 | + sas_ha->sas_phy[local_phy->number]; |
---|
| 1769 | + struct hisi_sas_phy *phy = |
---|
| 1770 | + container_of(sas_phy, struct hisi_sas_phy, sas_phy); |
---|
1562 | 1771 | phy->in_reset = 1; |
---|
1563 | 1772 | phy->reset_completion = &phyreset; |
---|
1564 | 1773 | } |
---|
| 1774 | + |
---|
| 1775 | + reset_type = (sas_dev->dev_status == HISI_SAS_DEV_INIT || |
---|
| 1776 | + !dev_is_sata(device)) ? true : false; |
---|
1565 | 1777 | |
---|
1566 | 1778 | rc = sas_phy_reset(local_phy, reset_type); |
---|
1567 | 1779 | sas_put_local_phy(local_phy); |
---|
1568 | 1780 | |
---|
1569 | 1781 | if (scsi_is_sas_phy_local(local_phy)) { |
---|
| 1782 | + struct asd_sas_phy *sas_phy = |
---|
| 1783 | + sas_ha->sas_phy[local_phy->number]; |
---|
| 1784 | + struct hisi_sas_phy *phy = |
---|
| 1785 | + container_of(sas_phy, struct hisi_sas_phy, sas_phy); |
---|
1570 | 1786 | int ret = wait_for_completion_timeout(&phyreset, 2 * HZ); |
---|
1571 | 1787 | unsigned long flags; |
---|
1572 | 1788 | |
---|
.. | .. |
---|
1578 | 1794 | /* report PHY down if timed out */ |
---|
1579 | 1795 | if (!ret) |
---|
1580 | 1796 | hisi_sas_phy_down(hisi_hba, sas_phy->id, 0); |
---|
1581 | | - } else |
---|
1582 | | - msleep(2000); |
---|
| 1797 | + } else if (sas_dev->dev_status != HISI_SAS_DEV_INIT) { |
---|
| 1798 | + /* |
---|
| 1799 | + * If in init state, we rely on caller to wait for link to be |
---|
| 1800 | + * ready; otherwise, except phy reset is fail, delay. |
---|
| 1801 | + */ |
---|
| 1802 | + if (!rc) |
---|
| 1803 | + msleep(2000); |
---|
| 1804 | + } |
---|
1583 | 1805 | |
---|
1584 | 1806 | return rc; |
---|
1585 | 1807 | } |
---|
1586 | 1808 | |
---|
1587 | 1809 | static int hisi_sas_I_T_nexus_reset(struct domain_device *device) |
---|
1588 | 1810 | { |
---|
1589 | | - struct hisi_sas_device *sas_dev = device->lldd_dev; |
---|
1590 | 1811 | struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); |
---|
1591 | 1812 | struct device *dev = hisi_hba->dev; |
---|
1592 | | - int rc = TMF_RESP_FUNC_FAILED; |
---|
1593 | | - |
---|
1594 | | - if (sas_dev->dev_status != HISI_SAS_DEV_EH) |
---|
1595 | | - return TMF_RESP_FUNC_FAILED; |
---|
1596 | | - sas_dev->dev_status = HISI_SAS_DEV_NORMAL; |
---|
| 1813 | + int rc; |
---|
1597 | 1814 | |
---|
1598 | 1815 | rc = hisi_sas_internal_task_abort(hisi_hba, device, |
---|
1599 | | - HISI_SAS_INT_ABT_DEV, 0); |
---|
| 1816 | + HISI_SAS_INT_ABT_DEV, 0); |
---|
1600 | 1817 | if (rc < 0) { |
---|
1601 | 1818 | dev_err(dev, "I_T nexus reset: internal abort (%d)\n", rc); |
---|
1602 | 1819 | return TMF_RESP_FUNC_FAILED; |
---|
1603 | 1820 | } |
---|
1604 | 1821 | hisi_sas_dereg_device(hisi_hba, device); |
---|
| 1822 | + |
---|
| 1823 | + if (dev_is_sata(device)) { |
---|
| 1824 | + rc = hisi_sas_softreset_ata_disk(device); |
---|
| 1825 | + if (rc == TMF_RESP_FUNC_FAILED) |
---|
| 1826 | + return TMF_RESP_FUNC_FAILED; |
---|
| 1827 | + } |
---|
1605 | 1828 | |
---|
1606 | 1829 | rc = hisi_sas_debug_I_T_nexus_reset(device); |
---|
1607 | 1830 | |
---|
.. | .. |
---|
1618 | 1841 | struct device *dev = hisi_hba->dev; |
---|
1619 | 1842 | int rc = TMF_RESP_FUNC_FAILED; |
---|
1620 | 1843 | |
---|
1621 | | - sas_dev->dev_status = HISI_SAS_DEV_EH; |
---|
| 1844 | + /* Clear internal IO and then lu reset */ |
---|
| 1845 | + rc = hisi_sas_internal_task_abort(hisi_hba, device, |
---|
| 1846 | + HISI_SAS_INT_ABT_DEV, 0); |
---|
| 1847 | + if (rc < 0) { |
---|
| 1848 | + dev_err(dev, "lu_reset: internal abort failed\n"); |
---|
| 1849 | + goto out; |
---|
| 1850 | + } |
---|
| 1851 | + hisi_sas_dereg_device(hisi_hba, device); |
---|
| 1852 | + |
---|
1622 | 1853 | if (dev_is_sata(device)) { |
---|
1623 | 1854 | struct sas_phy *phy; |
---|
1624 | 1855 | |
---|
1625 | | - /* Clear internal IO and then hardreset */ |
---|
1626 | | - rc = hisi_sas_internal_task_abort(hisi_hba, device, |
---|
1627 | | - HISI_SAS_INT_ABT_DEV, 0); |
---|
1628 | | - if (rc < 0) { |
---|
1629 | | - dev_err(dev, "lu_reset: internal abort failed\n"); |
---|
1630 | | - goto out; |
---|
1631 | | - } |
---|
1632 | | - hisi_sas_dereg_device(hisi_hba, device); |
---|
1633 | | - |
---|
1634 | 1856 | phy = sas_get_local_phy(device); |
---|
1635 | 1857 | |
---|
1636 | | - rc = sas_phy_reset(phy, 1); |
---|
| 1858 | + rc = sas_phy_reset(phy, true); |
---|
1637 | 1859 | |
---|
1638 | 1860 | if (rc == 0) |
---|
1639 | 1861 | hisi_sas_release_task(hisi_hba, device); |
---|
1640 | 1862 | sas_put_local_phy(phy); |
---|
1641 | 1863 | } else { |
---|
1642 | 1864 | struct hisi_sas_tmf_task tmf_task = { .tmf = TMF_LU_RESET }; |
---|
1643 | | - |
---|
1644 | | - rc = hisi_sas_internal_task_abort(hisi_hba, device, |
---|
1645 | | - HISI_SAS_INT_ABT_DEV, 0); |
---|
1646 | | - if (rc < 0) { |
---|
1647 | | - dev_err(dev, "lu_reset: internal abort failed\n"); |
---|
1648 | | - goto out; |
---|
1649 | | - } |
---|
1650 | | - hisi_sas_dereg_device(hisi_hba, device); |
---|
1651 | 1865 | |
---|
1652 | 1866 | rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task); |
---|
1653 | 1867 | if (rc == TMF_RESP_FUNC_COMPLETE) |
---|
.. | .. |
---|
1677 | 1891 | struct domain_device *device = sas_dev->sas_device; |
---|
1678 | 1892 | |
---|
1679 | 1893 | if ((sas_dev->dev_type == SAS_PHY_UNUSED) || !device || |
---|
1680 | | - DEV_IS_EXPANDER(device->dev_type)) |
---|
| 1894 | + dev_is_expander(device->dev_type)) |
---|
1681 | 1895 | continue; |
---|
1682 | 1896 | |
---|
1683 | 1897 | rc = hisi_sas_debug_I_T_nexus_reset(device); |
---|
.. | .. |
---|
1705 | 1919 | |
---|
1706 | 1920 | int_to_scsilun(cmnd->device->lun, &lun); |
---|
1707 | 1921 | tmf_task.tmf = TMF_QUERY_TASK; |
---|
1708 | | - tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag); |
---|
| 1922 | + tmf_task.tag_of_task_to_be_managed = tag; |
---|
1709 | 1923 | |
---|
1710 | 1924 | rc = hisi_sas_debug_issue_ssp_tmf(device, |
---|
1711 | 1925 | lun.scsi_lun, |
---|
.. | .. |
---|
1728 | 1942 | static int |
---|
1729 | 1943 | hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id, |
---|
1730 | 1944 | struct sas_task *task, int abort_flag, |
---|
1731 | | - int task_tag) |
---|
| 1945 | + int task_tag, struct hisi_sas_dq *dq) |
---|
1732 | 1946 | { |
---|
1733 | 1947 | struct domain_device *device = task->dev; |
---|
1734 | 1948 | struct hisi_sas_device *sas_dev = device->lldd_dev; |
---|
.. | .. |
---|
1737 | 1951 | struct hisi_sas_slot *slot; |
---|
1738 | 1952 | struct asd_sas_port *sas_port = device->port; |
---|
1739 | 1953 | struct hisi_sas_cmd_hdr *cmd_hdr_base; |
---|
1740 | | - struct hisi_sas_dq *dq = sas_dev->dq; |
---|
1741 | 1954 | int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx; |
---|
1742 | | - unsigned long flags, flags_dq = 0; |
---|
| 1955 | + unsigned long flags; |
---|
1743 | 1956 | int wr_q_index; |
---|
1744 | 1957 | |
---|
1745 | 1958 | if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) |
---|
.. | .. |
---|
1751 | 1964 | port = to_hisi_sas_port(sas_port); |
---|
1752 | 1965 | |
---|
1753 | 1966 | /* simply get a slot and send abort command */ |
---|
1754 | | - spin_lock_irqsave(&hisi_hba->lock, flags); |
---|
1755 | | - rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx); |
---|
1756 | | - if (rc) { |
---|
1757 | | - spin_unlock_irqrestore(&hisi_hba->lock, flags); |
---|
| 1967 | + rc = hisi_sas_slot_index_alloc(hisi_hba, NULL); |
---|
| 1968 | + if (rc < 0) |
---|
1758 | 1969 | goto err_out; |
---|
1759 | | - } |
---|
1760 | | - spin_unlock_irqrestore(&hisi_hba->lock, flags); |
---|
1761 | 1970 | |
---|
| 1971 | + slot_idx = rc; |
---|
1762 | 1972 | slot = &hisi_hba->slot_info[slot_idx]; |
---|
1763 | 1973 | |
---|
1764 | | - spin_lock_irqsave(&dq->lock, flags_dq); |
---|
1765 | | - wr_q_index = hisi_hba->hw->get_free_slot(hisi_hba, dq); |
---|
1766 | | - if (wr_q_index < 0) { |
---|
1767 | | - spin_unlock_irqrestore(&dq->lock, flags_dq); |
---|
1768 | | - rc = -EAGAIN; |
---|
1769 | | - goto err_out_tag; |
---|
1770 | | - } |
---|
| 1974 | + spin_lock(&dq->lock); |
---|
| 1975 | + wr_q_index = dq->wr_point; |
---|
| 1976 | + dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS; |
---|
1771 | 1977 | list_add_tail(&slot->delivery, &dq->list); |
---|
1772 | | - spin_unlock_irqrestore(&dq->lock, flags_dq); |
---|
| 1978 | + spin_unlock(&dq->lock); |
---|
| 1979 | + spin_lock(&sas_dev->lock); |
---|
| 1980 | + list_add_tail(&slot->entry, &sas_dev->list); |
---|
| 1981 | + spin_unlock(&sas_dev->lock); |
---|
1773 | 1982 | |
---|
1774 | 1983 | dlvry_queue = dq->id; |
---|
1775 | 1984 | dlvry_queue_slot = wr_q_index; |
---|
1776 | 1985 | |
---|
| 1986 | + slot->device_id = sas_dev->device_id; |
---|
1777 | 1987 | slot->n_elem = n_elem; |
---|
1778 | 1988 | slot->dlvry_queue = dlvry_queue; |
---|
1779 | 1989 | slot->dlvry_queue_slot = dlvry_queue_slot; |
---|
.. | .. |
---|
1786 | 1996 | |
---|
1787 | 1997 | memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr)); |
---|
1788 | 1998 | memset(hisi_sas_cmd_hdr_addr_mem(slot), 0, HISI_SAS_COMMAND_TABLE_SZ); |
---|
1789 | | - memset(hisi_sas_status_buf_addr_mem(slot), 0, HISI_SAS_STATUS_BUF_SZ); |
---|
| 1999 | + memset(hisi_sas_status_buf_addr_mem(slot), 0, |
---|
| 2000 | + sizeof(struct hisi_sas_err_record)); |
---|
1790 | 2001 | |
---|
1791 | 2002 | hisi_sas_task_prep_abort(hisi_hba, slot, device_id, |
---|
1792 | 2003 | abort_flag, task_tag); |
---|
.. | .. |
---|
1794 | 2005 | spin_lock_irqsave(&task->task_state_lock, flags); |
---|
1795 | 2006 | task->task_state_flags |= SAS_TASK_AT_INITIATOR; |
---|
1796 | 2007 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
---|
1797 | | - |
---|
1798 | 2008 | WRITE_ONCE(slot->ready, 1); |
---|
1799 | 2009 | /* send abort command to the chip */ |
---|
1800 | | - spin_lock_irqsave(&dq->lock, flags); |
---|
1801 | | - list_add_tail(&slot->entry, &sas_dev->list); |
---|
| 2010 | + spin_lock(&dq->lock); |
---|
1802 | 2011 | hisi_hba->hw->start_delivery(dq); |
---|
1803 | | - spin_unlock_irqrestore(&dq->lock, flags); |
---|
| 2012 | + spin_unlock(&dq->lock); |
---|
1804 | 2013 | |
---|
1805 | 2014 | return 0; |
---|
1806 | 2015 | |
---|
1807 | | -err_out_tag: |
---|
1808 | | - spin_lock_irqsave(&hisi_hba->lock, flags); |
---|
1809 | | - hisi_sas_slot_index_free(hisi_hba, slot_idx); |
---|
1810 | | - spin_unlock_irqrestore(&hisi_hba->lock, flags); |
---|
1811 | 2016 | err_out: |
---|
1812 | 2017 | dev_err(dev, "internal abort task prep: failed[%d]!\n", rc); |
---|
1813 | 2018 | |
---|
.. | .. |
---|
1815 | 2020 | } |
---|
1816 | 2021 | |
---|
1817 | 2022 | /** |
---|
1818 | | - * hisi_sas_internal_task_abort -- execute an internal |
---|
| 2023 | + * _hisi_sas_internal_task_abort -- execute an internal |
---|
1819 | 2024 | * abort command for single IO command or a device |
---|
1820 | 2025 | * @hisi_hba: host controller struct |
---|
1821 | 2026 | * @device: domain device |
---|
1822 | 2027 | * @abort_flag: mode of operation, device or single IO |
---|
1823 | 2028 | * @tag: tag of IO to be aborted (only relevant to single |
---|
1824 | 2029 | * IO mode) |
---|
| 2030 | + * @dq: delivery queue for this internal abort command |
---|
1825 | 2031 | */ |
---|
1826 | 2032 | static int |
---|
1827 | | -hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, |
---|
1828 | | - struct domain_device *device, |
---|
1829 | | - int abort_flag, int tag) |
---|
| 2033 | +_hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, |
---|
| 2034 | + struct domain_device *device, int abort_flag, |
---|
| 2035 | + int tag, struct hisi_sas_dq *dq) |
---|
1830 | 2036 | { |
---|
1831 | 2037 | struct sas_task *task; |
---|
1832 | 2038 | struct hisi_sas_device *sas_dev = device->lldd_dev; |
---|
.. | .. |
---|
1850 | 2056 | task->task_proto = device->tproto; |
---|
1851 | 2057 | task->task_done = hisi_sas_task_done; |
---|
1852 | 2058 | task->slow_task->timer.function = hisi_sas_tmf_timedout; |
---|
1853 | | - task->slow_task->timer.expires = jiffies + INTERNAL_ABORT_TIMEOUT*HZ; |
---|
| 2059 | + task->slow_task->timer.expires = jiffies + INTERNAL_ABORT_TIMEOUT * HZ; |
---|
1854 | 2060 | add_timer(&task->slow_task->timer); |
---|
1855 | 2061 | |
---|
1856 | 2062 | res = hisi_sas_internal_abort_task_exec(hisi_hba, sas_dev->device_id, |
---|
1857 | | - task, abort_flag, tag); |
---|
| 2063 | + task, abort_flag, tag, dq); |
---|
1858 | 2064 | if (res) { |
---|
1859 | 2065 | del_timer(&task->slow_task->timer); |
---|
1860 | 2066 | dev_err(dev, "internal task abort: executing internal task failed: %d\n", |
---|
.. | .. |
---|
1866 | 2072 | |
---|
1867 | 2073 | /* Internal abort timed out */ |
---|
1868 | 2074 | if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { |
---|
| 2075 | + if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) |
---|
| 2076 | + queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); |
---|
| 2077 | + |
---|
1869 | 2078 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { |
---|
1870 | 2079 | struct hisi_sas_slot *slot = task->lldd_task; |
---|
1871 | 2080 | |
---|
.. | .. |
---|
1873 | 2082 | struct hisi_sas_cq *cq = |
---|
1874 | 2083 | &hisi_hba->cq[slot->dlvry_queue]; |
---|
1875 | 2084 | /* |
---|
1876 | | - * flush tasklet to avoid free'ing task |
---|
| 2085 | + * sync irq to avoid free'ing task |
---|
1877 | 2086 | * before using task in IO completion |
---|
1878 | 2087 | */ |
---|
1879 | | - tasklet_kill(&cq->tasklet); |
---|
| 2088 | + synchronize_irq(cq->irq_no); |
---|
1880 | 2089 | slot->task = NULL; |
---|
1881 | 2090 | } |
---|
1882 | 2091 | dev_err(dev, "internal task abort: timeout and not done.\n"); |
---|
| 2092 | + |
---|
1883 | 2093 | res = -EIO; |
---|
1884 | 2094 | goto exit; |
---|
1885 | 2095 | } else |
---|
.. | .. |
---|
1899 | 2109 | } |
---|
1900 | 2110 | |
---|
1901 | 2111 | exit: |
---|
1902 | | - dev_dbg(dev, "internal task abort: task to dev %016llx task=%p " |
---|
1903 | | - "resp: 0x%x sts 0x%x\n", |
---|
1904 | | - SAS_ADDR(device->sas_addr), |
---|
1905 | | - task, |
---|
| 2112 | + dev_dbg(dev, "internal task abort: task to dev %016llx task=%pK resp: 0x%x sts 0x%x\n", |
---|
| 2113 | + SAS_ADDR(device->sas_addr), task, |
---|
1906 | 2114 | task->task_status.resp, /* 0 is complete, -1 is undelivered */ |
---|
1907 | 2115 | task->task_status.stat); |
---|
1908 | 2116 | sas_free_task(task); |
---|
.. | .. |
---|
1910 | 2118 | return res; |
---|
1911 | 2119 | } |
---|
1912 | 2120 | |
---|
| 2121 | +static int |
---|
| 2122 | +hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba, |
---|
| 2123 | + struct domain_device *device, |
---|
| 2124 | + int abort_flag, int tag) |
---|
| 2125 | +{ |
---|
| 2126 | + struct hisi_sas_slot *slot; |
---|
| 2127 | + struct device *dev = hisi_hba->dev; |
---|
| 2128 | + struct hisi_sas_dq *dq; |
---|
| 2129 | + int i, rc; |
---|
| 2130 | + |
---|
| 2131 | + switch (abort_flag) { |
---|
| 2132 | + case HISI_SAS_INT_ABT_CMD: |
---|
| 2133 | + slot = &hisi_hba->slot_info[tag]; |
---|
| 2134 | + dq = &hisi_hba->dq[slot->dlvry_queue]; |
---|
| 2135 | + return _hisi_sas_internal_task_abort(hisi_hba, device, |
---|
| 2136 | + abort_flag, tag, dq); |
---|
| 2137 | + case HISI_SAS_INT_ABT_DEV: |
---|
| 2138 | + for (i = 0; i < hisi_hba->cq_nvecs; i++) { |
---|
| 2139 | + struct hisi_sas_cq *cq = &hisi_hba->cq[i]; |
---|
| 2140 | + const struct cpumask *mask = cq->irq_mask; |
---|
| 2141 | + |
---|
| 2142 | + if (mask && !cpumask_intersects(cpu_online_mask, mask)) |
---|
| 2143 | + continue; |
---|
| 2144 | + dq = &hisi_hba->dq[i]; |
---|
| 2145 | + rc = _hisi_sas_internal_task_abort(hisi_hba, device, |
---|
| 2146 | + abort_flag, tag, |
---|
| 2147 | + dq); |
---|
| 2148 | + if (rc) |
---|
| 2149 | + return rc; |
---|
| 2150 | + } |
---|
| 2151 | + break; |
---|
| 2152 | + default: |
---|
| 2153 | + dev_err(dev, "Unrecognised internal abort flag (%d)\n", |
---|
| 2154 | + abort_flag); |
---|
| 2155 | + return -EINVAL; |
---|
| 2156 | + } |
---|
| 2157 | + |
---|
| 2158 | + return 0; |
---|
| 2159 | +} |
---|
| 2160 | + |
---|
1913 | 2161 | static void hisi_sas_port_formed(struct asd_sas_phy *sas_phy) |
---|
1914 | 2162 | { |
---|
1915 | 2163 | hisi_sas_port_notify_formed(sas_phy); |
---|
1916 | | -} |
---|
1917 | | - |
---|
1918 | | -static void hisi_sas_port_deformed(struct asd_sas_phy *sas_phy) |
---|
1919 | | -{ |
---|
1920 | 2164 | } |
---|
1921 | 2165 | |
---|
1922 | 2166 | static int hisi_sas_write_gpio(struct sas_ha_struct *sha, u8 reg_type, |
---|
.. | .. |
---|
1935 | 2179 | { |
---|
1936 | 2180 | struct asd_sas_phy *sas_phy = &phy->sas_phy; |
---|
1937 | 2181 | struct sas_phy *sphy = sas_phy->phy; |
---|
1938 | | - struct sas_phy_data *d = sphy->hostdata; |
---|
| 2182 | + unsigned long flags; |
---|
1939 | 2183 | |
---|
1940 | 2184 | phy->phy_attached = 0; |
---|
1941 | 2185 | phy->phy_type = 0; |
---|
1942 | 2186 | phy->port = NULL; |
---|
1943 | 2187 | |
---|
1944 | | - if (d->enable) |
---|
| 2188 | + spin_lock_irqsave(&phy->lock, flags); |
---|
| 2189 | + if (phy->enable) |
---|
1945 | 2190 | sphy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; |
---|
1946 | 2191 | else |
---|
1947 | 2192 | sphy->negotiated_linkrate = SAS_PHY_DISABLED; |
---|
| 2193 | + spin_unlock_irqrestore(&phy->lock, flags); |
---|
1948 | 2194 | } |
---|
1949 | 2195 | |
---|
1950 | 2196 | void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy) |
---|
1951 | 2197 | { |
---|
1952 | 2198 | struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; |
---|
1953 | 2199 | struct asd_sas_phy *sas_phy = &phy->sas_phy; |
---|
1954 | | - struct sas_ha_struct *sas_ha = &hisi_hba->sha; |
---|
1955 | 2200 | struct device *dev = hisi_hba->dev; |
---|
1956 | 2201 | |
---|
1957 | 2202 | if (rdy) { |
---|
.. | .. |
---|
1967 | 2212 | return; |
---|
1968 | 2213 | } |
---|
1969 | 2214 | /* Phy down and not ready */ |
---|
1970 | | - sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL); |
---|
| 2215 | + sas_notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL); |
---|
1971 | 2216 | sas_phy_disconnected(sas_phy); |
---|
1972 | 2217 | |
---|
1973 | 2218 | if (port) { |
---|
.. | .. |
---|
1985 | 2230 | } |
---|
1986 | 2231 | EXPORT_SYMBOL_GPL(hisi_sas_phy_down); |
---|
1987 | 2232 | |
---|
1988 | | -void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba) |
---|
| 2233 | +void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba) |
---|
1989 | 2234 | { |
---|
1990 | 2235 | int i; |
---|
1991 | 2236 | |
---|
1992 | | - for (i = 0; i < hisi_hba->queue_count; i++) { |
---|
| 2237 | + for (i = 0; i < hisi_hba->cq_nvecs; i++) { |
---|
1993 | 2238 | struct hisi_sas_cq *cq = &hisi_hba->cq[i]; |
---|
1994 | 2239 | |
---|
1995 | | - tasklet_kill(&cq->tasklet); |
---|
| 2240 | + synchronize_irq(cq->irq_no); |
---|
1996 | 2241 | } |
---|
1997 | 2242 | } |
---|
1998 | | -EXPORT_SYMBOL_GPL(hisi_sas_kill_tasklets); |
---|
| 2243 | +EXPORT_SYMBOL_GPL(hisi_sas_sync_irqs); |
---|
| 2244 | + |
---|
| 2245 | +int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type) |
---|
| 2246 | +{ |
---|
| 2247 | + struct hisi_hba *hisi_hba = shost_priv(shost); |
---|
| 2248 | + |
---|
| 2249 | + if (reset_type != SCSI_ADAPTER_RESET) |
---|
| 2250 | + return -EOPNOTSUPP; |
---|
| 2251 | + |
---|
| 2252 | + queue_work(hisi_hba->wq, &hisi_hba->rst_work); |
---|
| 2253 | + |
---|
| 2254 | + return 0; |
---|
| 2255 | +} |
---|
| 2256 | +EXPORT_SYMBOL_GPL(hisi_sas_host_reset); |
---|
1999 | 2257 | |
---|
2000 | 2258 | struct scsi_transport_template *hisi_sas_stt; |
---|
2001 | 2259 | EXPORT_SYMBOL_GPL(hisi_sas_stt); |
---|
2002 | | - |
---|
2003 | | -struct device_attribute *host_attrs[] = { |
---|
2004 | | - &dev_attr_phy_event_threshold, |
---|
2005 | | - NULL, |
---|
2006 | | -}; |
---|
2007 | | -EXPORT_SYMBOL_GPL(host_attrs); |
---|
2008 | 2260 | |
---|
2009 | 2261 | static struct sas_domain_function_template hisi_sas_transport_ops = { |
---|
2010 | 2262 | .lldd_dev_found = hisi_sas_dev_found, |
---|
.. | .. |
---|
2017 | 2269 | .lldd_I_T_nexus_reset = hisi_sas_I_T_nexus_reset, |
---|
2018 | 2270 | .lldd_lu_reset = hisi_sas_lu_reset, |
---|
2019 | 2271 | .lldd_query_task = hisi_sas_query_task, |
---|
2020 | | - .lldd_clear_nexus_ha = hisi_sas_clear_nexus_ha, |
---|
| 2272 | + .lldd_clear_nexus_ha = hisi_sas_clear_nexus_ha, |
---|
2021 | 2273 | .lldd_port_formed = hisi_sas_port_formed, |
---|
2022 | | - .lldd_port_deformed = hisi_sas_port_deformed, |
---|
2023 | | - .lldd_write_gpio = hisi_sas_write_gpio, |
---|
| 2274 | + .lldd_write_gpio = hisi_sas_write_gpio, |
---|
2024 | 2275 | }; |
---|
2025 | 2276 | |
---|
2026 | 2277 | void hisi_sas_init_mem(struct hisi_hba *hisi_hba) |
---|
2027 | 2278 | { |
---|
2028 | | - int i, s, max_command_entries = hisi_hba->hw->max_command_entries; |
---|
| 2279 | + int i, s, j, max_command_entries = HISI_SAS_MAX_COMMANDS; |
---|
| 2280 | + struct hisi_sas_breakpoint *sata_breakpoint = hisi_hba->sata_breakpoint; |
---|
2029 | 2281 | |
---|
2030 | 2282 | for (i = 0; i < hisi_hba->queue_count; i++) { |
---|
2031 | 2283 | struct hisi_sas_cq *cq = &hisi_hba->cq[i]; |
---|
2032 | 2284 | struct hisi_sas_dq *dq = &hisi_hba->dq[i]; |
---|
| 2285 | + struct hisi_sas_cmd_hdr *cmd_hdr = hisi_hba->cmd_hdr[i]; |
---|
2033 | 2286 | |
---|
2034 | | - s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; |
---|
2035 | | - memset(hisi_hba->cmd_hdr[i], 0, s); |
---|
| 2287 | + s = sizeof(struct hisi_sas_cmd_hdr); |
---|
| 2288 | + for (j = 0; j < HISI_SAS_QUEUE_SLOTS; j++) |
---|
| 2289 | + memset(&cmd_hdr[j], 0, s); |
---|
| 2290 | + |
---|
2036 | 2291 | dq->wr_point = 0; |
---|
2037 | 2292 | |
---|
2038 | 2293 | s = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; |
---|
.. | .. |
---|
2049 | 2304 | s = max_command_entries * sizeof(struct hisi_sas_breakpoint); |
---|
2050 | 2305 | memset(hisi_hba->breakpoint, 0, s); |
---|
2051 | 2306 | |
---|
2052 | | - s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_sata_breakpoint); |
---|
2053 | | - memset(hisi_hba->sata_breakpoint, 0, s); |
---|
| 2307 | + s = sizeof(struct hisi_sas_sata_breakpoint); |
---|
| 2308 | + for (j = 0; j < HISI_SAS_MAX_ITCT_ENTRIES; j++) |
---|
| 2309 | + memset(&sata_breakpoint[j], 0, s); |
---|
2054 | 2310 | } |
---|
2055 | 2311 | EXPORT_SYMBOL_GPL(hisi_sas_init_mem); |
---|
2056 | 2312 | |
---|
2057 | | -int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost) |
---|
| 2313 | +int hisi_sas_alloc(struct hisi_hba *hisi_hba) |
---|
2058 | 2314 | { |
---|
2059 | 2315 | struct device *dev = hisi_hba->dev; |
---|
2060 | | - int i, j, s, max_command_entries = hisi_hba->hw->max_command_entries; |
---|
| 2316 | + int i, j, s, max_command_entries = HISI_SAS_MAX_COMMANDS; |
---|
2061 | 2317 | int max_command_entries_ru, sz_slot_buf_ru; |
---|
2062 | 2318 | int blk_cnt, slots_per_blk; |
---|
2063 | 2319 | |
---|
.. | .. |
---|
2072 | 2328 | for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) { |
---|
2073 | 2329 | hisi_hba->devices[i].dev_type = SAS_PHY_UNUSED; |
---|
2074 | 2330 | hisi_hba->devices[i].device_id = i; |
---|
2075 | | - hisi_hba->devices[i].dev_status = HISI_SAS_DEV_NORMAL; |
---|
| 2331 | + hisi_hba->devices[i].dev_status = HISI_SAS_DEV_INIT; |
---|
2076 | 2332 | } |
---|
2077 | 2333 | |
---|
2078 | 2334 | for (i = 0; i < hisi_hba->queue_count; i++) { |
---|
.. | .. |
---|
2111 | 2367 | GFP_KERNEL); |
---|
2112 | 2368 | if (!hisi_hba->itct) |
---|
2113 | 2369 | goto err_out; |
---|
2114 | | - memset(hisi_hba->itct, 0, s); |
---|
2115 | 2370 | |
---|
2116 | 2371 | hisi_hba->slot_info = devm_kcalloc(dev, max_command_entries, |
---|
2117 | 2372 | sizeof(struct hisi_sas_slot), |
---|
.. | .. |
---|
2121 | 2376 | |
---|
2122 | 2377 | /* roundup to avoid overly large block size */ |
---|
2123 | 2378 | max_command_entries_ru = roundup(max_command_entries, 64); |
---|
2124 | | - sz_slot_buf_ru = roundup(sizeof(struct hisi_sas_slot_buf_table), 64); |
---|
2125 | | - s = lcm(max_command_entries_ru, sz_slot_buf_ru); |
---|
| 2379 | + if (hisi_hba->prot_mask & HISI_SAS_DIX_PROT_MASK) |
---|
| 2380 | + sz_slot_buf_ru = sizeof(struct hisi_sas_slot_dif_buf_table); |
---|
| 2381 | + else |
---|
| 2382 | + sz_slot_buf_ru = sizeof(struct hisi_sas_slot_buf_table); |
---|
| 2383 | + sz_slot_buf_ru = roundup(sz_slot_buf_ru, 64); |
---|
| 2384 | + s = max(lcm(max_command_entries_ru, sz_slot_buf_ru), PAGE_SIZE); |
---|
2126 | 2385 | blk_cnt = (max_command_entries_ru * sz_slot_buf_ru) / s; |
---|
2127 | 2386 | slots_per_blk = s / sz_slot_buf_ru; |
---|
2128 | | - for (i = 0; i < blk_cnt; i++) { |
---|
2129 | | - struct hisi_sas_slot_buf_table *buf; |
---|
2130 | | - dma_addr_t buf_dma; |
---|
2131 | | - int slot_index = i * slots_per_blk; |
---|
2132 | 2387 | |
---|
2133 | | - buf = dmam_alloc_coherent(dev, s, &buf_dma, GFP_KERNEL); |
---|
| 2388 | + for (i = 0; i < blk_cnt; i++) { |
---|
| 2389 | + int slot_index = i * slots_per_blk; |
---|
| 2390 | + dma_addr_t buf_dma; |
---|
| 2391 | + void *buf; |
---|
| 2392 | + |
---|
| 2393 | + buf = dmam_alloc_coherent(dev, s, &buf_dma, |
---|
| 2394 | + GFP_KERNEL); |
---|
2134 | 2395 | if (!buf) |
---|
2135 | 2396 | goto err_out; |
---|
2136 | | - memset(buf, 0, s); |
---|
2137 | 2397 | |
---|
2138 | 2398 | for (j = 0; j < slots_per_blk; j++, slot_index++) { |
---|
2139 | 2399 | struct hisi_sas_slot *slot; |
---|
.. | .. |
---|
2143 | 2403 | slot->buf_dma = buf_dma; |
---|
2144 | 2404 | slot->idx = slot_index; |
---|
2145 | 2405 | |
---|
2146 | | - buf++; |
---|
2147 | | - buf_dma += sizeof(*buf); |
---|
| 2406 | + buf += sz_slot_buf_ru; |
---|
| 2407 | + buf_dma += sz_slot_buf_ru; |
---|
2148 | 2408 | } |
---|
2149 | 2409 | } |
---|
2150 | 2410 | |
---|
.. | .. |
---|
2180 | 2440 | GFP_KERNEL); |
---|
2181 | 2441 | if (!hisi_hba->sata_breakpoint) |
---|
2182 | 2442 | goto err_out; |
---|
2183 | | - hisi_sas_init_mem(hisi_hba); |
---|
2184 | 2443 | |
---|
2185 | 2444 | hisi_sas_slot_index_init(hisi_hba); |
---|
| 2445 | + hisi_hba->last_slot_index = HISI_SAS_UNRESERVED_IPTT; |
---|
2186 | 2446 | |
---|
2187 | 2447 | hisi_hba->wq = create_singlethread_workqueue(dev_name(dev)); |
---|
2188 | 2448 | if (!hisi_hba->wq) { |
---|
.. | .. |
---|
2198 | 2458 | |
---|
2199 | 2459 | void hisi_sas_free(struct hisi_hba *hisi_hba) |
---|
2200 | 2460 | { |
---|
| 2461 | + int i; |
---|
| 2462 | + |
---|
| 2463 | + for (i = 0; i < hisi_hba->n_phy; i++) { |
---|
| 2464 | + struct hisi_sas_phy *phy = &hisi_hba->phy[i]; |
---|
| 2465 | + |
---|
| 2466 | + del_timer_sync(&phy->timer); |
---|
| 2467 | + } |
---|
| 2468 | + |
---|
2201 | 2469 | if (hisi_hba->wq) |
---|
2202 | 2470 | destroy_workqueue(hisi_hba->wq); |
---|
2203 | 2471 | } |
---|
.. | .. |
---|
2250 | 2518 | |
---|
2251 | 2519 | if (device_property_read_u32(dev, "ctrl-reset-reg", |
---|
2252 | 2520 | &hisi_hba->ctrl_reset_reg)) { |
---|
2253 | | - dev_err(dev, |
---|
2254 | | - "could not get property ctrl-reset-reg\n"); |
---|
| 2521 | + dev_err(dev, "could not get property ctrl-reset-reg\n"); |
---|
2255 | 2522 | return -ENOENT; |
---|
2256 | 2523 | } |
---|
2257 | 2524 | |
---|
2258 | 2525 | if (device_property_read_u32(dev, "ctrl-reset-sts-reg", |
---|
2259 | 2526 | &hisi_hba->ctrl_reset_sts_reg)) { |
---|
2260 | | - dev_err(dev, |
---|
2261 | | - "could not get property ctrl-reset-sts-reg\n"); |
---|
| 2527 | + dev_err(dev, "could not get property ctrl-reset-sts-reg\n"); |
---|
2262 | 2528 | return -ENOENT; |
---|
2263 | 2529 | } |
---|
2264 | 2530 | |
---|
2265 | 2531 | if (device_property_read_u32(dev, "ctrl-clock-ena-reg", |
---|
2266 | 2532 | &hisi_hba->ctrl_clock_ena_reg)) { |
---|
2267 | | - dev_err(dev, |
---|
2268 | | - "could not get property ctrl-clock-ena-reg\n"); |
---|
| 2533 | + dev_err(dev, "could not get property ctrl-clock-ena-reg\n"); |
---|
2269 | 2534 | return -ENOENT; |
---|
2270 | 2535 | } |
---|
2271 | 2536 | } |
---|
.. | .. |
---|
2298 | 2563 | struct Scsi_Host *shost; |
---|
2299 | 2564 | struct hisi_hba *hisi_hba; |
---|
2300 | 2565 | struct device *dev = &pdev->dev; |
---|
| 2566 | + int error; |
---|
2301 | 2567 | |
---|
2302 | 2568 | shost = scsi_host_alloc(hw->sht, sizeof(*hisi_hba)); |
---|
2303 | 2569 | if (!shost) { |
---|
.. | .. |
---|
2318 | 2584 | if (hisi_sas_get_fw_info(hisi_hba) < 0) |
---|
2319 | 2585 | goto err_out; |
---|
2320 | 2586 | |
---|
2321 | | - if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) && |
---|
2322 | | - dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) { |
---|
| 2587 | + error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); |
---|
| 2588 | + if (error) |
---|
| 2589 | + error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); |
---|
| 2590 | + |
---|
| 2591 | + if (error) { |
---|
2323 | 2592 | dev_err(dev, "No usable DMA addressing method\n"); |
---|
2324 | 2593 | goto err_out; |
---|
2325 | 2594 | } |
---|
2326 | 2595 | |
---|
2327 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
2328 | | - hisi_hba->regs = devm_ioremap_resource(dev, res); |
---|
| 2596 | + hisi_hba->regs = devm_platform_ioremap_resource(pdev, 0); |
---|
2329 | 2597 | if (IS_ERR(hisi_hba->regs)) |
---|
2330 | 2598 | goto err_out; |
---|
2331 | 2599 | |
---|
.. | .. |
---|
2336 | 2604 | goto err_out; |
---|
2337 | 2605 | } |
---|
2338 | 2606 | |
---|
2339 | | - if (hisi_sas_alloc(hisi_hba, shost)) { |
---|
| 2607 | + if (hisi_sas_alloc(hisi_hba)) { |
---|
2340 | 2608 | hisi_sas_free(hisi_hba); |
---|
2341 | 2609 | goto err_out; |
---|
2342 | 2610 | } |
---|
.. | .. |
---|
2385 | 2653 | shost->max_lun = ~0; |
---|
2386 | 2654 | shost->max_channel = 1; |
---|
2387 | 2655 | shost->max_cmd_len = 16; |
---|
2388 | | - shost->sg_tablesize = min_t(u16, SG_ALL, HISI_SAS_SGE_PAGE_CNT); |
---|
2389 | | - shost->can_queue = hisi_hba->hw->max_command_entries; |
---|
2390 | | - shost->cmd_per_lun = hisi_hba->hw->max_command_entries; |
---|
| 2656 | + if (hisi_hba->hw->slot_index_alloc) { |
---|
| 2657 | + shost->can_queue = HISI_SAS_MAX_COMMANDS; |
---|
| 2658 | + shost->cmd_per_lun = HISI_SAS_MAX_COMMANDS; |
---|
| 2659 | + } else { |
---|
| 2660 | + shost->can_queue = HISI_SAS_UNRESERVED_IPTT; |
---|
| 2661 | + shost->cmd_per_lun = HISI_SAS_UNRESERVED_IPTT; |
---|
| 2662 | + } |
---|
2391 | 2663 | |
---|
2392 | 2664 | sha->sas_ha_name = DRV_NAME; |
---|
2393 | 2665 | sha->dev = hisi_hba->dev; |
---|
.. | .. |
---|
2420 | 2692 | err_out_register_ha: |
---|
2421 | 2693 | scsi_remove_host(shost); |
---|
2422 | 2694 | err_out_ha: |
---|
| 2695 | + hisi_sas_debugfs_exit(hisi_hba); |
---|
2423 | 2696 | hisi_sas_free(hisi_hba); |
---|
2424 | 2697 | scsi_host_put(shost); |
---|
2425 | 2698 | return rc; |
---|
2426 | 2699 | } |
---|
2427 | 2700 | EXPORT_SYMBOL_GPL(hisi_sas_probe); |
---|
| 2701 | + |
---|
| 2702 | +struct dentry *hisi_sas_debugfs_dir; |
---|
| 2703 | + |
---|
| 2704 | +static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba) |
---|
| 2705 | +{ |
---|
| 2706 | + int queue_entry_size = hisi_hba->hw->complete_hdr_size; |
---|
| 2707 | + int dump_index = hisi_hba->debugfs_dump_index; |
---|
| 2708 | + int i; |
---|
| 2709 | + |
---|
| 2710 | + for (i = 0; i < hisi_hba->queue_count; i++) |
---|
| 2711 | + memcpy(hisi_hba->debugfs_cq[dump_index][i].complete_hdr, |
---|
| 2712 | + hisi_hba->complete_hdr[i], |
---|
| 2713 | + HISI_SAS_QUEUE_SLOTS * queue_entry_size); |
---|
| 2714 | +} |
---|
| 2715 | + |
---|
| 2716 | +static void hisi_sas_debugfs_snapshot_dq_reg(struct hisi_hba *hisi_hba) |
---|
| 2717 | +{ |
---|
| 2718 | + int queue_entry_size = sizeof(struct hisi_sas_cmd_hdr); |
---|
| 2719 | + int dump_index = hisi_hba->debugfs_dump_index; |
---|
| 2720 | + int i; |
---|
| 2721 | + |
---|
| 2722 | + for (i = 0; i < hisi_hba->queue_count; i++) { |
---|
| 2723 | + struct hisi_sas_cmd_hdr *debugfs_cmd_hdr, *cmd_hdr; |
---|
| 2724 | + int j; |
---|
| 2725 | + |
---|
| 2726 | + debugfs_cmd_hdr = hisi_hba->debugfs_dq[dump_index][i].hdr; |
---|
| 2727 | + cmd_hdr = hisi_hba->cmd_hdr[i]; |
---|
| 2728 | + |
---|
| 2729 | + for (j = 0; j < HISI_SAS_QUEUE_SLOTS; j++) |
---|
| 2730 | + memcpy(&debugfs_cmd_hdr[j], &cmd_hdr[j], |
---|
| 2731 | + queue_entry_size); |
---|
| 2732 | + } |
---|
| 2733 | +} |
---|
| 2734 | + |
---|
| 2735 | +static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba) |
---|
| 2736 | +{ |
---|
| 2737 | + int dump_index = hisi_hba->debugfs_dump_index; |
---|
| 2738 | + const struct hisi_sas_debugfs_reg *port = |
---|
| 2739 | + hisi_hba->hw->debugfs_reg_port; |
---|
| 2740 | + int i, phy_cnt; |
---|
| 2741 | + u32 offset; |
---|
| 2742 | + u32 *databuf; |
---|
| 2743 | + |
---|
| 2744 | + for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) { |
---|
| 2745 | + databuf = hisi_hba->debugfs_port_reg[dump_index][phy_cnt].data; |
---|
| 2746 | + for (i = 0; i < port->count; i++, databuf++) { |
---|
| 2747 | + offset = port->base_off + 4 * i; |
---|
| 2748 | + *databuf = port->read_port_reg(hisi_hba, phy_cnt, |
---|
| 2749 | + offset); |
---|
| 2750 | + } |
---|
| 2751 | + } |
---|
| 2752 | +} |
---|
| 2753 | + |
---|
| 2754 | +static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) |
---|
| 2755 | +{ |
---|
| 2756 | + int dump_index = hisi_hba->debugfs_dump_index; |
---|
| 2757 | + u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data; |
---|
| 2758 | + const struct hisi_sas_hw *hw = hisi_hba->hw; |
---|
| 2759 | + const struct hisi_sas_debugfs_reg *global = |
---|
| 2760 | + hw->debugfs_reg_array[DEBUGFS_GLOBAL]; |
---|
| 2761 | + int i; |
---|
| 2762 | + |
---|
| 2763 | + for (i = 0; i < global->count; i++, databuf++) |
---|
| 2764 | + *databuf = global->read_global_reg(hisi_hba, 4 * i); |
---|
| 2765 | +} |
---|
| 2766 | + |
---|
| 2767 | +static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba) |
---|
| 2768 | +{ |
---|
| 2769 | + int dump_index = hisi_hba->debugfs_dump_index; |
---|
| 2770 | + u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI].data; |
---|
| 2771 | + const struct hisi_sas_hw *hw = hisi_hba->hw; |
---|
| 2772 | + const struct hisi_sas_debugfs_reg *axi = |
---|
| 2773 | + hw->debugfs_reg_array[DEBUGFS_AXI]; |
---|
| 2774 | + int i; |
---|
| 2775 | + |
---|
| 2776 | + for (i = 0; i < axi->count; i++, databuf++) |
---|
| 2777 | + *databuf = axi->read_global_reg(hisi_hba, |
---|
| 2778 | + 4 * i + axi->base_off); |
---|
| 2779 | +} |
---|
| 2780 | + |
---|
| 2781 | +static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba) |
---|
| 2782 | +{ |
---|
| 2783 | + int dump_index = hisi_hba->debugfs_dump_index; |
---|
| 2784 | + u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS].data; |
---|
| 2785 | + const struct hisi_sas_hw *hw = hisi_hba->hw; |
---|
| 2786 | + const struct hisi_sas_debugfs_reg *ras = |
---|
| 2787 | + hw->debugfs_reg_array[DEBUGFS_RAS]; |
---|
| 2788 | + int i; |
---|
| 2789 | + |
---|
| 2790 | + for (i = 0; i < ras->count; i++, databuf++) |
---|
| 2791 | + *databuf = ras->read_global_reg(hisi_hba, |
---|
| 2792 | + 4 * i + ras->base_off); |
---|
| 2793 | +} |
---|
| 2794 | + |
---|
| 2795 | +static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) |
---|
| 2796 | +{ |
---|
| 2797 | + int dump_index = hisi_hba->debugfs_dump_index; |
---|
| 2798 | + void *cachebuf = hisi_hba->debugfs_itct_cache[dump_index].cache; |
---|
| 2799 | + void *databuf = hisi_hba->debugfs_itct[dump_index].itct; |
---|
| 2800 | + struct hisi_sas_itct *itct; |
---|
| 2801 | + int i; |
---|
| 2802 | + |
---|
| 2803 | + hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_ITCT_CACHE, |
---|
| 2804 | + cachebuf); |
---|
| 2805 | + |
---|
| 2806 | + itct = hisi_hba->itct; |
---|
| 2807 | + |
---|
| 2808 | + for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { |
---|
| 2809 | + memcpy(databuf, itct, sizeof(struct hisi_sas_itct)); |
---|
| 2810 | + databuf += sizeof(struct hisi_sas_itct); |
---|
| 2811 | + } |
---|
| 2812 | +} |
---|
| 2813 | + |
---|
| 2814 | +static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba) |
---|
| 2815 | +{ |
---|
| 2816 | + int dump_index = hisi_hba->debugfs_dump_index; |
---|
| 2817 | + int max_command_entries = HISI_SAS_MAX_COMMANDS; |
---|
| 2818 | + void *cachebuf = hisi_hba->debugfs_iost_cache[dump_index].cache; |
---|
| 2819 | + void *databuf = hisi_hba->debugfs_iost[dump_index].iost; |
---|
| 2820 | + struct hisi_sas_iost *iost; |
---|
| 2821 | + int i; |
---|
| 2822 | + |
---|
| 2823 | + hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_IOST_CACHE, |
---|
| 2824 | + cachebuf); |
---|
| 2825 | + |
---|
| 2826 | + iost = hisi_hba->iost; |
---|
| 2827 | + |
---|
| 2828 | + for (i = 0; i < max_command_entries; i++, iost++) { |
---|
| 2829 | + memcpy(databuf, iost, sizeof(struct hisi_sas_iost)); |
---|
| 2830 | + databuf += sizeof(struct hisi_sas_iost); |
---|
| 2831 | + } |
---|
| 2832 | +} |
---|
| 2833 | + |
---|
| 2834 | +static const char * |
---|
| 2835 | +hisi_sas_debugfs_to_reg_name(int off, int base_off, |
---|
| 2836 | + const struct hisi_sas_debugfs_reg_lu *lu) |
---|
| 2837 | +{ |
---|
| 2838 | + for (; lu->name; lu++) { |
---|
| 2839 | + if (off == lu->off - base_off) |
---|
| 2840 | + return lu->name; |
---|
| 2841 | + } |
---|
| 2842 | + |
---|
| 2843 | + return NULL; |
---|
| 2844 | +} |
---|
| 2845 | + |
---|
| 2846 | +static void hisi_sas_debugfs_print_reg(u32 *regs_val, const void *ptr, |
---|
| 2847 | + struct seq_file *s) |
---|
| 2848 | +{ |
---|
| 2849 | + const struct hisi_sas_debugfs_reg *reg = ptr; |
---|
| 2850 | + int i; |
---|
| 2851 | + |
---|
| 2852 | + for (i = 0; i < reg->count; i++) { |
---|
| 2853 | + int off = i * 4; |
---|
| 2854 | + const char *name; |
---|
| 2855 | + |
---|
| 2856 | + name = hisi_sas_debugfs_to_reg_name(off, reg->base_off, |
---|
| 2857 | + reg->lu); |
---|
| 2858 | + |
---|
| 2859 | + if (name) |
---|
| 2860 | + seq_printf(s, "0x%08x 0x%08x %s\n", off, |
---|
| 2861 | + regs_val[i], name); |
---|
| 2862 | + else |
---|
| 2863 | + seq_printf(s, "0x%08x 0x%08x\n", off, |
---|
| 2864 | + regs_val[i]); |
---|
| 2865 | + } |
---|
| 2866 | +} |
---|
| 2867 | + |
---|
| 2868 | +static int hisi_sas_debugfs_global_show(struct seq_file *s, void *p) |
---|
| 2869 | +{ |
---|
| 2870 | + struct hisi_sas_debugfs_regs *global = s->private; |
---|
| 2871 | + struct hisi_hba *hisi_hba = global->hisi_hba; |
---|
| 2872 | + const struct hisi_sas_hw *hw = hisi_hba->hw; |
---|
| 2873 | + const void *reg_global = hw->debugfs_reg_array[DEBUGFS_GLOBAL]; |
---|
| 2874 | + |
---|
| 2875 | + hisi_sas_debugfs_print_reg(global->data, |
---|
| 2876 | + reg_global, s); |
---|
| 2877 | + |
---|
| 2878 | + return 0; |
---|
| 2879 | +} |
---|
| 2880 | + |
---|
| 2881 | +static int hisi_sas_debugfs_global_open(struct inode *inode, struct file *filp) |
---|
| 2882 | +{ |
---|
| 2883 | + return single_open(filp, hisi_sas_debugfs_global_show, |
---|
| 2884 | + inode->i_private); |
---|
| 2885 | +} |
---|
| 2886 | + |
---|
| 2887 | +static const struct file_operations hisi_sas_debugfs_global_fops = { |
---|
| 2888 | + .open = hisi_sas_debugfs_global_open, |
---|
| 2889 | + .read = seq_read, |
---|
| 2890 | + .llseek = seq_lseek, |
---|
| 2891 | + .release = single_release, |
---|
| 2892 | + .owner = THIS_MODULE, |
---|
| 2893 | +}; |
---|
| 2894 | + |
---|
| 2895 | +static int hisi_sas_debugfs_axi_show(struct seq_file *s, void *p) |
---|
| 2896 | +{ |
---|
| 2897 | + struct hisi_sas_debugfs_regs *axi = s->private; |
---|
| 2898 | + struct hisi_hba *hisi_hba = axi->hisi_hba; |
---|
| 2899 | + const struct hisi_sas_hw *hw = hisi_hba->hw; |
---|
| 2900 | + const void *reg_axi = hw->debugfs_reg_array[DEBUGFS_AXI]; |
---|
| 2901 | + |
---|
| 2902 | + hisi_sas_debugfs_print_reg(axi->data, |
---|
| 2903 | + reg_axi, s); |
---|
| 2904 | + |
---|
| 2905 | + return 0; |
---|
| 2906 | +} |
---|
| 2907 | + |
---|
| 2908 | +static int hisi_sas_debugfs_axi_open(struct inode *inode, struct file *filp) |
---|
| 2909 | +{ |
---|
| 2910 | + return single_open(filp, hisi_sas_debugfs_axi_show, |
---|
| 2911 | + inode->i_private); |
---|
| 2912 | +} |
---|
| 2913 | + |
---|
| 2914 | +static const struct file_operations hisi_sas_debugfs_axi_fops = { |
---|
| 2915 | + .open = hisi_sas_debugfs_axi_open, |
---|
| 2916 | + .read = seq_read, |
---|
| 2917 | + .llseek = seq_lseek, |
---|
| 2918 | + .release = single_release, |
---|
| 2919 | + .owner = THIS_MODULE, |
---|
| 2920 | +}; |
---|
| 2921 | + |
---|
| 2922 | +static int hisi_sas_debugfs_ras_show(struct seq_file *s, void *p) |
---|
| 2923 | +{ |
---|
| 2924 | + struct hisi_sas_debugfs_regs *ras = s->private; |
---|
| 2925 | + struct hisi_hba *hisi_hba = ras->hisi_hba; |
---|
| 2926 | + const struct hisi_sas_hw *hw = hisi_hba->hw; |
---|
| 2927 | + const void *reg_ras = hw->debugfs_reg_array[DEBUGFS_RAS]; |
---|
| 2928 | + |
---|
| 2929 | + hisi_sas_debugfs_print_reg(ras->data, |
---|
| 2930 | + reg_ras, s); |
---|
| 2931 | + |
---|
| 2932 | + return 0; |
---|
| 2933 | +} |
---|
| 2934 | + |
---|
| 2935 | +static int hisi_sas_debugfs_ras_open(struct inode *inode, struct file *filp) |
---|
| 2936 | +{ |
---|
| 2937 | + return single_open(filp, hisi_sas_debugfs_ras_show, |
---|
| 2938 | + inode->i_private); |
---|
| 2939 | +} |
---|
| 2940 | + |
---|
| 2941 | +static const struct file_operations hisi_sas_debugfs_ras_fops = { |
---|
| 2942 | + .open = hisi_sas_debugfs_ras_open, |
---|
| 2943 | + .read = seq_read, |
---|
| 2944 | + .llseek = seq_lseek, |
---|
| 2945 | + .release = single_release, |
---|
| 2946 | + .owner = THIS_MODULE, |
---|
| 2947 | +}; |
---|
| 2948 | + |
---|
| 2949 | +static int hisi_sas_debugfs_port_show(struct seq_file *s, void *p) |
---|
| 2950 | +{ |
---|
| 2951 | + struct hisi_sas_debugfs_port *port = s->private; |
---|
| 2952 | + struct hisi_sas_phy *phy = port->phy; |
---|
| 2953 | + struct hisi_hba *hisi_hba = phy->hisi_hba; |
---|
| 2954 | + const struct hisi_sas_hw *hw = hisi_hba->hw; |
---|
| 2955 | + const struct hisi_sas_debugfs_reg *reg_port = hw->debugfs_reg_port; |
---|
| 2956 | + |
---|
| 2957 | + hisi_sas_debugfs_print_reg(port->data, reg_port, s); |
---|
| 2958 | + |
---|
| 2959 | + return 0; |
---|
| 2960 | +} |
---|
| 2961 | + |
---|
| 2962 | +static int hisi_sas_debugfs_port_open(struct inode *inode, struct file *filp) |
---|
| 2963 | +{ |
---|
| 2964 | + return single_open(filp, hisi_sas_debugfs_port_show, inode->i_private); |
---|
| 2965 | +} |
---|
| 2966 | + |
---|
| 2967 | +static const struct file_operations hisi_sas_debugfs_port_fops = { |
---|
| 2968 | + .open = hisi_sas_debugfs_port_open, |
---|
| 2969 | + .read = seq_read, |
---|
| 2970 | + .llseek = seq_lseek, |
---|
| 2971 | + .release = single_release, |
---|
| 2972 | + .owner = THIS_MODULE, |
---|
| 2973 | +}; |
---|
| 2974 | + |
---|
| 2975 | +static void hisi_sas_show_row_64(struct seq_file *s, int index, |
---|
| 2976 | + int sz, __le64 *ptr) |
---|
| 2977 | +{ |
---|
| 2978 | + int i; |
---|
| 2979 | + |
---|
| 2980 | + /* completion header size not fixed per HW version */ |
---|
| 2981 | + seq_printf(s, "index %04d:\n\t", index); |
---|
| 2982 | + for (i = 1; i <= sz / 8; i++, ptr++) { |
---|
| 2983 | + seq_printf(s, " 0x%016llx", le64_to_cpu(*ptr)); |
---|
| 2984 | + if (!(i % 2)) |
---|
| 2985 | + seq_puts(s, "\n\t"); |
---|
| 2986 | + } |
---|
| 2987 | + |
---|
| 2988 | + seq_puts(s, "\n"); |
---|
| 2989 | +} |
---|
| 2990 | + |
---|
| 2991 | +static void hisi_sas_show_row_32(struct seq_file *s, int index, |
---|
| 2992 | + int sz, __le32 *ptr) |
---|
| 2993 | +{ |
---|
| 2994 | + int i; |
---|
| 2995 | + |
---|
| 2996 | + /* completion header size not fixed per HW version */ |
---|
| 2997 | + seq_printf(s, "index %04d:\n\t", index); |
---|
| 2998 | + for (i = 1; i <= sz / 4; i++, ptr++) { |
---|
| 2999 | + seq_printf(s, " 0x%08x", le32_to_cpu(*ptr)); |
---|
| 3000 | + if (!(i % 4)) |
---|
| 3001 | + seq_puts(s, "\n\t"); |
---|
| 3002 | + } |
---|
| 3003 | + seq_puts(s, "\n"); |
---|
| 3004 | +} |
---|
| 3005 | + |
---|
| 3006 | +static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, |
---|
| 3007 | + struct hisi_sas_debugfs_cq *debugfs_cq) |
---|
| 3008 | +{ |
---|
| 3009 | + struct hisi_sas_cq *cq = debugfs_cq->cq; |
---|
| 3010 | + struct hisi_hba *hisi_hba = cq->hisi_hba; |
---|
| 3011 | + __le32 *complete_hdr = debugfs_cq->complete_hdr + |
---|
| 3012 | + (hisi_hba->hw->complete_hdr_size * slot); |
---|
| 3013 | + |
---|
| 3014 | + hisi_sas_show_row_32(s, slot, |
---|
| 3015 | + hisi_hba->hw->complete_hdr_size, |
---|
| 3016 | + complete_hdr); |
---|
| 3017 | +} |
---|
| 3018 | + |
---|
| 3019 | +static int hisi_sas_debugfs_cq_show(struct seq_file *s, void *p) |
---|
| 3020 | +{ |
---|
| 3021 | + struct hisi_sas_debugfs_cq *debugfs_cq = s->private; |
---|
| 3022 | + int slot; |
---|
| 3023 | + |
---|
| 3024 | + for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) { |
---|
| 3025 | + hisi_sas_cq_show_slot(s, slot, debugfs_cq); |
---|
| 3026 | + } |
---|
| 3027 | + return 0; |
---|
| 3028 | +} |
---|
| 3029 | + |
---|
| 3030 | +static int hisi_sas_debugfs_cq_open(struct inode *inode, struct file *filp) |
---|
| 3031 | +{ |
---|
| 3032 | + return single_open(filp, hisi_sas_debugfs_cq_show, inode->i_private); |
---|
| 3033 | +} |
---|
| 3034 | + |
---|
| 3035 | +static const struct file_operations hisi_sas_debugfs_cq_fops = { |
---|
| 3036 | + .open = hisi_sas_debugfs_cq_open, |
---|
| 3037 | + .read = seq_read, |
---|
| 3038 | + .llseek = seq_lseek, |
---|
| 3039 | + .release = single_release, |
---|
| 3040 | + .owner = THIS_MODULE, |
---|
| 3041 | +}; |
---|
| 3042 | + |
---|
| 3043 | +static void hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr) |
---|
| 3044 | +{ |
---|
| 3045 | + struct hisi_sas_debugfs_dq *debugfs_dq = dq_ptr; |
---|
| 3046 | + void *cmd_queue = debugfs_dq->hdr; |
---|
| 3047 | + __le32 *cmd_hdr = cmd_queue + |
---|
| 3048 | + sizeof(struct hisi_sas_cmd_hdr) * slot; |
---|
| 3049 | + |
---|
| 3050 | + hisi_sas_show_row_32(s, slot, sizeof(struct hisi_sas_cmd_hdr), cmd_hdr); |
---|
| 3051 | +} |
---|
| 3052 | + |
---|
| 3053 | +static int hisi_sas_debugfs_dq_show(struct seq_file *s, void *p) |
---|
| 3054 | +{ |
---|
| 3055 | + int slot; |
---|
| 3056 | + |
---|
| 3057 | + for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) { |
---|
| 3058 | + hisi_sas_dq_show_slot(s, slot, s->private); |
---|
| 3059 | + } |
---|
| 3060 | + return 0; |
---|
| 3061 | +} |
---|
| 3062 | + |
---|
| 3063 | +static int hisi_sas_debugfs_dq_open(struct inode *inode, struct file *filp) |
---|
| 3064 | +{ |
---|
| 3065 | + return single_open(filp, hisi_sas_debugfs_dq_show, inode->i_private); |
---|
| 3066 | +} |
---|
| 3067 | + |
---|
| 3068 | +static const struct file_operations hisi_sas_debugfs_dq_fops = { |
---|
| 3069 | + .open = hisi_sas_debugfs_dq_open, |
---|
| 3070 | + .read = seq_read, |
---|
| 3071 | + .llseek = seq_lseek, |
---|
| 3072 | + .release = single_release, |
---|
| 3073 | + .owner = THIS_MODULE, |
---|
| 3074 | +}; |
---|
| 3075 | + |
---|
| 3076 | +static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p) |
---|
| 3077 | +{ |
---|
| 3078 | + struct hisi_sas_debugfs_iost *debugfs_iost = s->private; |
---|
| 3079 | + struct hisi_sas_iost *iost = debugfs_iost->iost; |
---|
| 3080 | + int i, max_command_entries = HISI_SAS_MAX_COMMANDS; |
---|
| 3081 | + |
---|
| 3082 | + for (i = 0; i < max_command_entries; i++, iost++) { |
---|
| 3083 | + __le64 *data = &iost->qw0; |
---|
| 3084 | + |
---|
| 3085 | + hisi_sas_show_row_64(s, i, sizeof(*iost), data); |
---|
| 3086 | + } |
---|
| 3087 | + |
---|
| 3088 | + return 0; |
---|
| 3089 | +} |
---|
| 3090 | + |
---|
| 3091 | +static int hisi_sas_debugfs_iost_open(struct inode *inode, struct file *filp) |
---|
| 3092 | +{ |
---|
| 3093 | + return single_open(filp, hisi_sas_debugfs_iost_show, inode->i_private); |
---|
| 3094 | +} |
---|
| 3095 | + |
---|
| 3096 | +static const struct file_operations hisi_sas_debugfs_iost_fops = { |
---|
| 3097 | + .open = hisi_sas_debugfs_iost_open, |
---|
| 3098 | + .read = seq_read, |
---|
| 3099 | + .llseek = seq_lseek, |
---|
| 3100 | + .release = single_release, |
---|
| 3101 | + .owner = THIS_MODULE, |
---|
| 3102 | +}; |
---|
| 3103 | + |
---|
| 3104 | +static int hisi_sas_debugfs_iost_cache_show(struct seq_file *s, void *p) |
---|
| 3105 | +{ |
---|
| 3106 | + struct hisi_sas_debugfs_iost_cache *debugfs_iost_cache = s->private; |
---|
| 3107 | + struct hisi_sas_iost_itct_cache *iost_cache = debugfs_iost_cache->cache; |
---|
| 3108 | + u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; |
---|
| 3109 | + int i, tab_idx; |
---|
| 3110 | + __le64 *iost; |
---|
| 3111 | + |
---|
| 3112 | + for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) { |
---|
| 3113 | + /* |
---|
| 3114 | + * Data struct of IOST cache: |
---|
| 3115 | + * Data[1]: BIT0~15: Table index |
---|
| 3116 | + * Bit16: Valid mask |
---|
| 3117 | + * Data[2]~[9]: IOST table |
---|
| 3118 | + */ |
---|
| 3119 | + tab_idx = (iost_cache->data[1] & 0xffff); |
---|
| 3120 | + iost = (__le64 *)iost_cache; |
---|
| 3121 | + |
---|
| 3122 | + hisi_sas_show_row_64(s, tab_idx, cache_size, iost); |
---|
| 3123 | + } |
---|
| 3124 | + |
---|
| 3125 | + return 0; |
---|
| 3126 | +} |
---|
| 3127 | + |
---|
| 3128 | +static int hisi_sas_debugfs_iost_cache_open(struct inode *inode, |
---|
| 3129 | + struct file *filp) |
---|
| 3130 | +{ |
---|
| 3131 | + return single_open(filp, hisi_sas_debugfs_iost_cache_show, |
---|
| 3132 | + inode->i_private); |
---|
| 3133 | +} |
---|
| 3134 | + |
---|
| 3135 | +static const struct file_operations hisi_sas_debugfs_iost_cache_fops = { |
---|
| 3136 | + .open = hisi_sas_debugfs_iost_cache_open, |
---|
| 3137 | + .read = seq_read, |
---|
| 3138 | + .llseek = seq_lseek, |
---|
| 3139 | + .release = single_release, |
---|
| 3140 | + .owner = THIS_MODULE, |
---|
| 3141 | +}; |
---|
| 3142 | + |
---|
| 3143 | +static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p) |
---|
| 3144 | +{ |
---|
| 3145 | + int i; |
---|
| 3146 | + struct hisi_sas_debugfs_itct *debugfs_itct = s->private; |
---|
| 3147 | + struct hisi_sas_itct *itct = debugfs_itct->itct; |
---|
| 3148 | + |
---|
| 3149 | + for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { |
---|
| 3150 | + __le64 *data = &itct->qw0; |
---|
| 3151 | + |
---|
| 3152 | + hisi_sas_show_row_64(s, i, sizeof(*itct), data); |
---|
| 3153 | + } |
---|
| 3154 | + |
---|
| 3155 | + return 0; |
---|
| 3156 | +} |
---|
| 3157 | + |
---|
| 3158 | +static int hisi_sas_debugfs_itct_open(struct inode *inode, struct file *filp) |
---|
| 3159 | +{ |
---|
| 3160 | + return single_open(filp, hisi_sas_debugfs_itct_show, inode->i_private); |
---|
| 3161 | +} |
---|
| 3162 | + |
---|
| 3163 | +static const struct file_operations hisi_sas_debugfs_itct_fops = { |
---|
| 3164 | + .open = hisi_sas_debugfs_itct_open, |
---|
| 3165 | + .read = seq_read, |
---|
| 3166 | + .llseek = seq_lseek, |
---|
| 3167 | + .release = single_release, |
---|
| 3168 | + .owner = THIS_MODULE, |
---|
| 3169 | +}; |
---|
| 3170 | + |
---|
| 3171 | +static int hisi_sas_debugfs_itct_cache_show(struct seq_file *s, void *p) |
---|
| 3172 | +{ |
---|
| 3173 | + struct hisi_sas_debugfs_itct_cache *debugfs_itct_cache = s->private; |
---|
| 3174 | + struct hisi_sas_iost_itct_cache *itct_cache = debugfs_itct_cache->cache; |
---|
| 3175 | + u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; |
---|
| 3176 | + int i, tab_idx; |
---|
| 3177 | + __le64 *itct; |
---|
| 3178 | + |
---|
| 3179 | + for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) { |
---|
| 3180 | + /* |
---|
| 3181 | + * Data struct of ITCT cache: |
---|
| 3182 | + * Data[1]: BIT0~15: Table index |
---|
| 3183 | + * Bit16: Valid mask |
---|
| 3184 | + * Data[2]~[9]: ITCT table |
---|
| 3185 | + */ |
---|
| 3186 | + tab_idx = itct_cache->data[1] & 0xffff; |
---|
| 3187 | + itct = (__le64 *)itct_cache; |
---|
| 3188 | + |
---|
| 3189 | + hisi_sas_show_row_64(s, tab_idx, cache_size, itct); |
---|
| 3190 | + } |
---|
| 3191 | + |
---|
| 3192 | + return 0; |
---|
| 3193 | +} |
---|
| 3194 | + |
---|
| 3195 | +static int hisi_sas_debugfs_itct_cache_open(struct inode *inode, |
---|
| 3196 | + struct file *filp) |
---|
| 3197 | +{ |
---|
| 3198 | + return single_open(filp, hisi_sas_debugfs_itct_cache_show, |
---|
| 3199 | + inode->i_private); |
---|
| 3200 | +} |
---|
| 3201 | + |
---|
| 3202 | +static const struct file_operations hisi_sas_debugfs_itct_cache_fops = { |
---|
| 3203 | + .open = hisi_sas_debugfs_itct_cache_open, |
---|
| 3204 | + .read = seq_read, |
---|
| 3205 | + .llseek = seq_lseek, |
---|
| 3206 | + .release = single_release, |
---|
| 3207 | + .owner = THIS_MODULE, |
---|
| 3208 | +}; |
---|
| 3209 | + |
---|
| 3210 | +static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) |
---|
| 3211 | +{ |
---|
| 3212 | + u64 *debugfs_timestamp; |
---|
| 3213 | + int dump_index = hisi_hba->debugfs_dump_index; |
---|
| 3214 | + struct dentry *dump_dentry; |
---|
| 3215 | + struct dentry *dentry; |
---|
| 3216 | + char name[256]; |
---|
| 3217 | + int p; |
---|
| 3218 | + int c; |
---|
| 3219 | + int d; |
---|
| 3220 | + |
---|
| 3221 | + snprintf(name, 256, "%d", dump_index); |
---|
| 3222 | + |
---|
| 3223 | + dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry); |
---|
| 3224 | + |
---|
| 3225 | + debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index]; |
---|
| 3226 | + |
---|
| 3227 | + debugfs_create_u64("timestamp", 0400, dump_dentry, |
---|
| 3228 | + debugfs_timestamp); |
---|
| 3229 | + |
---|
| 3230 | + debugfs_create_file("global", 0400, dump_dentry, |
---|
| 3231 | + &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL], |
---|
| 3232 | + &hisi_sas_debugfs_global_fops); |
---|
| 3233 | + |
---|
| 3234 | + /* Create port dir and files */ |
---|
| 3235 | + dentry = debugfs_create_dir("port", dump_dentry); |
---|
| 3236 | + for (p = 0; p < hisi_hba->n_phy; p++) { |
---|
| 3237 | + snprintf(name, 256, "%d", p); |
---|
| 3238 | + |
---|
| 3239 | + debugfs_create_file(name, 0400, dentry, |
---|
| 3240 | + &hisi_hba->debugfs_port_reg[dump_index][p], |
---|
| 3241 | + &hisi_sas_debugfs_port_fops); |
---|
| 3242 | + } |
---|
| 3243 | + |
---|
| 3244 | + /* Create CQ dir and files */ |
---|
| 3245 | + dentry = debugfs_create_dir("cq", dump_dentry); |
---|
| 3246 | + for (c = 0; c < hisi_hba->queue_count; c++) { |
---|
| 3247 | + snprintf(name, 256, "%d", c); |
---|
| 3248 | + |
---|
| 3249 | + debugfs_create_file(name, 0400, dentry, |
---|
| 3250 | + &hisi_hba->debugfs_cq[dump_index][c], |
---|
| 3251 | + &hisi_sas_debugfs_cq_fops); |
---|
| 3252 | + } |
---|
| 3253 | + |
---|
| 3254 | + /* Create DQ dir and files */ |
---|
| 3255 | + dentry = debugfs_create_dir("dq", dump_dentry); |
---|
| 3256 | + for (d = 0; d < hisi_hba->queue_count; d++) { |
---|
| 3257 | + snprintf(name, 256, "%d", d); |
---|
| 3258 | + |
---|
| 3259 | + debugfs_create_file(name, 0400, dentry, |
---|
| 3260 | + &hisi_hba->debugfs_dq[dump_index][d], |
---|
| 3261 | + &hisi_sas_debugfs_dq_fops); |
---|
| 3262 | + } |
---|
| 3263 | + |
---|
| 3264 | + debugfs_create_file("iost", 0400, dump_dentry, |
---|
| 3265 | + &hisi_hba->debugfs_iost[dump_index], |
---|
| 3266 | + &hisi_sas_debugfs_iost_fops); |
---|
| 3267 | + |
---|
| 3268 | + debugfs_create_file("iost_cache", 0400, dump_dentry, |
---|
| 3269 | + &hisi_hba->debugfs_iost_cache[dump_index], |
---|
| 3270 | + &hisi_sas_debugfs_iost_cache_fops); |
---|
| 3271 | + |
---|
| 3272 | + debugfs_create_file("itct", 0400, dump_dentry, |
---|
| 3273 | + &hisi_hba->debugfs_itct[dump_index], |
---|
| 3274 | + &hisi_sas_debugfs_itct_fops); |
---|
| 3275 | + |
---|
| 3276 | + debugfs_create_file("itct_cache", 0400, dump_dentry, |
---|
| 3277 | + &hisi_hba->debugfs_itct_cache[dump_index], |
---|
| 3278 | + &hisi_sas_debugfs_itct_cache_fops); |
---|
| 3279 | + |
---|
| 3280 | + debugfs_create_file("axi", 0400, dump_dentry, |
---|
| 3281 | + &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI], |
---|
| 3282 | + &hisi_sas_debugfs_axi_fops); |
---|
| 3283 | + |
---|
| 3284 | + debugfs_create_file("ras", 0400, dump_dentry, |
---|
| 3285 | + &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS], |
---|
| 3286 | + &hisi_sas_debugfs_ras_fops); |
---|
| 3287 | + |
---|
| 3288 | + return; |
---|
| 3289 | +} |
---|
| 3290 | + |
---|
| 3291 | +static void hisi_sas_debugfs_snapshot_regs(struct hisi_hba *hisi_hba) |
---|
| 3292 | +{ |
---|
| 3293 | + hisi_hba->hw->snapshot_prepare(hisi_hba); |
---|
| 3294 | + |
---|
| 3295 | + hisi_sas_debugfs_snapshot_global_reg(hisi_hba); |
---|
| 3296 | + hisi_sas_debugfs_snapshot_port_reg(hisi_hba); |
---|
| 3297 | + hisi_sas_debugfs_snapshot_axi_reg(hisi_hba); |
---|
| 3298 | + hisi_sas_debugfs_snapshot_ras_reg(hisi_hba); |
---|
| 3299 | + hisi_sas_debugfs_snapshot_cq_reg(hisi_hba); |
---|
| 3300 | + hisi_sas_debugfs_snapshot_dq_reg(hisi_hba); |
---|
| 3301 | + hisi_sas_debugfs_snapshot_itct_reg(hisi_hba); |
---|
| 3302 | + hisi_sas_debugfs_snapshot_iost_reg(hisi_hba); |
---|
| 3303 | + |
---|
| 3304 | + hisi_sas_debugfs_create_files(hisi_hba); |
---|
| 3305 | + |
---|
| 3306 | + hisi_hba->hw->snapshot_restore(hisi_hba); |
---|
| 3307 | +} |
---|
| 3308 | + |
---|
| 3309 | +static ssize_t hisi_sas_debugfs_trigger_dump_write(struct file *file, |
---|
| 3310 | + const char __user *user_buf, |
---|
| 3311 | + size_t count, loff_t *ppos) |
---|
| 3312 | +{ |
---|
| 3313 | + struct hisi_hba *hisi_hba = file->f_inode->i_private; |
---|
| 3314 | + char buf[8]; |
---|
| 3315 | + |
---|
| 3316 | + if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count) |
---|
| 3317 | + return -EFAULT; |
---|
| 3318 | + |
---|
| 3319 | + if (count > 8) |
---|
| 3320 | + return -EFAULT; |
---|
| 3321 | + |
---|
| 3322 | + if (copy_from_user(buf, user_buf, count)) |
---|
| 3323 | + return -EFAULT; |
---|
| 3324 | + |
---|
| 3325 | + if (buf[0] != '1') |
---|
| 3326 | + return -EFAULT; |
---|
| 3327 | + |
---|
| 3328 | + queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); |
---|
| 3329 | + |
---|
| 3330 | + return count; |
---|
| 3331 | +} |
---|
| 3332 | + |
---|
| 3333 | +static const struct file_operations hisi_sas_debugfs_trigger_dump_fops = { |
---|
| 3334 | + .write = &hisi_sas_debugfs_trigger_dump_write, |
---|
| 3335 | + .owner = THIS_MODULE, |
---|
| 3336 | +}; |
---|
| 3337 | + |
---|
| 3338 | +enum { |
---|
| 3339 | + HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL = 0, |
---|
| 3340 | + HISI_SAS_BIST_LOOPBACK_MODE_SERDES, |
---|
| 3341 | + HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, |
---|
| 3342 | +}; |
---|
| 3343 | + |
---|
| 3344 | +static const struct { |
---|
| 3345 | + int value; |
---|
| 3346 | + char *name; |
---|
| 3347 | +} hisi_sas_debugfs_loop_linkrate[] = { |
---|
| 3348 | + { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, |
---|
| 3349 | + { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, |
---|
| 3350 | + { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, |
---|
| 3351 | + { SAS_LINK_RATE_12_0_GBPS, "12.0 Gbit" }, |
---|
| 3352 | +}; |
---|
| 3353 | + |
---|
| 3354 | +static int hisi_sas_debugfs_bist_linkrate_show(struct seq_file *s, void *p) |
---|
| 3355 | +{ |
---|
| 3356 | + struct hisi_hba *hisi_hba = s->private; |
---|
| 3357 | + int i; |
---|
| 3358 | + |
---|
| 3359 | + for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_linkrate); i++) { |
---|
| 3360 | + int match = (hisi_hba->debugfs_bist_linkrate == |
---|
| 3361 | + hisi_sas_debugfs_loop_linkrate[i].value); |
---|
| 3362 | + |
---|
| 3363 | + seq_printf(s, "%s%s%s ", match ? "[" : "", |
---|
| 3364 | + hisi_sas_debugfs_loop_linkrate[i].name, |
---|
| 3365 | + match ? "]" : ""); |
---|
| 3366 | + } |
---|
| 3367 | + seq_puts(s, "\n"); |
---|
| 3368 | + |
---|
| 3369 | + return 0; |
---|
| 3370 | +} |
---|
| 3371 | + |
---|
| 3372 | +static ssize_t hisi_sas_debugfs_bist_linkrate_write(struct file *filp, |
---|
| 3373 | + const char __user *buf, |
---|
| 3374 | + size_t count, loff_t *ppos) |
---|
| 3375 | +{ |
---|
| 3376 | + struct seq_file *m = filp->private_data; |
---|
| 3377 | + struct hisi_hba *hisi_hba = m->private; |
---|
| 3378 | + char kbuf[16] = {}, *pkbuf; |
---|
| 3379 | + bool found = false; |
---|
| 3380 | + int i; |
---|
| 3381 | + |
---|
| 3382 | + if (hisi_hba->debugfs_bist_enable) |
---|
| 3383 | + return -EPERM; |
---|
| 3384 | + |
---|
| 3385 | + if (count >= sizeof(kbuf)) |
---|
| 3386 | + return -EOVERFLOW; |
---|
| 3387 | + |
---|
| 3388 | + if (copy_from_user(kbuf, buf, count)) |
---|
| 3389 | + return -EINVAL; |
---|
| 3390 | + |
---|
| 3391 | + pkbuf = strstrip(kbuf); |
---|
| 3392 | + |
---|
| 3393 | + for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_linkrate); i++) { |
---|
| 3394 | + if (!strncmp(hisi_sas_debugfs_loop_linkrate[i].name, |
---|
| 3395 | + pkbuf, 16)) { |
---|
| 3396 | + hisi_hba->debugfs_bist_linkrate = |
---|
| 3397 | + hisi_sas_debugfs_loop_linkrate[i].value; |
---|
| 3398 | + found = true; |
---|
| 3399 | + break; |
---|
| 3400 | + } |
---|
| 3401 | + } |
---|
| 3402 | + |
---|
| 3403 | + if (!found) |
---|
| 3404 | + return -EINVAL; |
---|
| 3405 | + |
---|
| 3406 | + return count; |
---|
| 3407 | +} |
---|
| 3408 | + |
---|
| 3409 | +static int hisi_sas_debugfs_bist_linkrate_open(struct inode *inode, |
---|
| 3410 | + struct file *filp) |
---|
| 3411 | +{ |
---|
| 3412 | + return single_open(filp, hisi_sas_debugfs_bist_linkrate_show, |
---|
| 3413 | + inode->i_private); |
---|
| 3414 | +} |
---|
| 3415 | + |
---|
| 3416 | +static const struct file_operations hisi_sas_debugfs_bist_linkrate_ops = { |
---|
| 3417 | + .open = hisi_sas_debugfs_bist_linkrate_open, |
---|
| 3418 | + .read = seq_read, |
---|
| 3419 | + .write = hisi_sas_debugfs_bist_linkrate_write, |
---|
| 3420 | + .llseek = seq_lseek, |
---|
| 3421 | + .release = single_release, |
---|
| 3422 | + .owner = THIS_MODULE, |
---|
| 3423 | +}; |
---|
| 3424 | + |
---|
| 3425 | +static const struct { |
---|
| 3426 | + int value; |
---|
| 3427 | + char *name; |
---|
| 3428 | +} hisi_sas_debugfs_loop_code_mode[] = { |
---|
| 3429 | + { HISI_SAS_BIST_CODE_MODE_PRBS7, "PRBS7" }, |
---|
| 3430 | + { HISI_SAS_BIST_CODE_MODE_PRBS23, "PRBS23" }, |
---|
| 3431 | + { HISI_SAS_BIST_CODE_MODE_PRBS31, "PRBS31" }, |
---|
| 3432 | + { HISI_SAS_BIST_CODE_MODE_JTPAT, "JTPAT" }, |
---|
| 3433 | + { HISI_SAS_BIST_CODE_MODE_CJTPAT, "CJTPAT" }, |
---|
| 3434 | + { HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, "SCRAMBED_0" }, |
---|
| 3435 | + { HISI_SAS_BIST_CODE_MODE_TRAIN, "TRAIN" }, |
---|
| 3436 | + { HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, "TRAIN_DONE" }, |
---|
| 3437 | + { HISI_SAS_BIST_CODE_MODE_HFTP, "HFTP" }, |
---|
| 3438 | + { HISI_SAS_BIST_CODE_MODE_MFTP, "MFTP" }, |
---|
| 3439 | + { HISI_SAS_BIST_CODE_MODE_LFTP, "LFTP" }, |
---|
| 3440 | + { HISI_SAS_BIST_CODE_MODE_FIXED_DATA, "FIXED_DATA" }, |
---|
| 3441 | +}; |
---|
| 3442 | + |
---|
| 3443 | +static int hisi_sas_debugfs_bist_code_mode_show(struct seq_file *s, void *p) |
---|
| 3444 | +{ |
---|
| 3445 | + struct hisi_hba *hisi_hba = s->private; |
---|
| 3446 | + int i; |
---|
| 3447 | + |
---|
| 3448 | + for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_code_mode); i++) { |
---|
| 3449 | + int match = (hisi_hba->debugfs_bist_code_mode == |
---|
| 3450 | + hisi_sas_debugfs_loop_code_mode[i].value); |
---|
| 3451 | + |
---|
| 3452 | + seq_printf(s, "%s%s%s ", match ? "[" : "", |
---|
| 3453 | + hisi_sas_debugfs_loop_code_mode[i].name, |
---|
| 3454 | + match ? "]" : ""); |
---|
| 3455 | + } |
---|
| 3456 | + seq_puts(s, "\n"); |
---|
| 3457 | + |
---|
| 3458 | + return 0; |
---|
| 3459 | +} |
---|
| 3460 | + |
---|
| 3461 | +static ssize_t hisi_sas_debugfs_bist_code_mode_write(struct file *filp, |
---|
| 3462 | + const char __user *buf, |
---|
| 3463 | + size_t count, |
---|
| 3464 | + loff_t *ppos) |
---|
| 3465 | +{ |
---|
| 3466 | + struct seq_file *m = filp->private_data; |
---|
| 3467 | + struct hisi_hba *hisi_hba = m->private; |
---|
| 3468 | + char kbuf[16] = {}, *pkbuf; |
---|
| 3469 | + bool found = false; |
---|
| 3470 | + int i; |
---|
| 3471 | + |
---|
| 3472 | + if (hisi_hba->debugfs_bist_enable) |
---|
| 3473 | + return -EPERM; |
---|
| 3474 | + |
---|
| 3475 | + if (count >= sizeof(kbuf)) |
---|
| 3476 | + return -EINVAL; |
---|
| 3477 | + |
---|
| 3478 | + if (copy_from_user(kbuf, buf, count)) |
---|
| 3479 | + return -EOVERFLOW; |
---|
| 3480 | + |
---|
| 3481 | + pkbuf = strstrip(kbuf); |
---|
| 3482 | + |
---|
| 3483 | + for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_code_mode); i++) { |
---|
| 3484 | + if (!strncmp(hisi_sas_debugfs_loop_code_mode[i].name, |
---|
| 3485 | + pkbuf, 16)) { |
---|
| 3486 | + hisi_hba->debugfs_bist_code_mode = |
---|
| 3487 | + hisi_sas_debugfs_loop_code_mode[i].value; |
---|
| 3488 | + found = true; |
---|
| 3489 | + break; |
---|
| 3490 | + } |
---|
| 3491 | + } |
---|
| 3492 | + |
---|
| 3493 | + if (!found) |
---|
| 3494 | + return -EINVAL; |
---|
| 3495 | + |
---|
| 3496 | + return count; |
---|
| 3497 | +} |
---|
| 3498 | + |
---|
| 3499 | +static int hisi_sas_debugfs_bist_code_mode_open(struct inode *inode, |
---|
| 3500 | + struct file *filp) |
---|
| 3501 | +{ |
---|
| 3502 | + return single_open(filp, hisi_sas_debugfs_bist_code_mode_show, |
---|
| 3503 | + inode->i_private); |
---|
| 3504 | +} |
---|
| 3505 | + |
---|
| 3506 | +static const struct file_operations hisi_sas_debugfs_bist_code_mode_ops = { |
---|
| 3507 | + .open = hisi_sas_debugfs_bist_code_mode_open, |
---|
| 3508 | + .read = seq_read, |
---|
| 3509 | + .write = hisi_sas_debugfs_bist_code_mode_write, |
---|
| 3510 | + .llseek = seq_lseek, |
---|
| 3511 | + .release = single_release, |
---|
| 3512 | + .owner = THIS_MODULE, |
---|
| 3513 | +}; |
---|
| 3514 | + |
---|
| 3515 | +static ssize_t hisi_sas_debugfs_bist_phy_write(struct file *filp, |
---|
| 3516 | + const char __user *buf, |
---|
| 3517 | + size_t count, loff_t *ppos) |
---|
| 3518 | +{ |
---|
| 3519 | + struct seq_file *m = filp->private_data; |
---|
| 3520 | + struct hisi_hba *hisi_hba = m->private; |
---|
| 3521 | + unsigned int phy_no; |
---|
| 3522 | + int val; |
---|
| 3523 | + |
---|
| 3524 | + if (hisi_hba->debugfs_bist_enable) |
---|
| 3525 | + return -EPERM; |
---|
| 3526 | + |
---|
| 3527 | + val = kstrtouint_from_user(buf, count, 0, &phy_no); |
---|
| 3528 | + if (val) |
---|
| 3529 | + return val; |
---|
| 3530 | + |
---|
| 3531 | + if (phy_no >= hisi_hba->n_phy) |
---|
| 3532 | + return -EINVAL; |
---|
| 3533 | + |
---|
| 3534 | + hisi_hba->debugfs_bist_phy_no = phy_no; |
---|
| 3535 | + |
---|
| 3536 | + return count; |
---|
| 3537 | +} |
---|
| 3538 | + |
---|
| 3539 | +static int hisi_sas_debugfs_bist_phy_show(struct seq_file *s, void *p) |
---|
| 3540 | +{ |
---|
| 3541 | + struct hisi_hba *hisi_hba = s->private; |
---|
| 3542 | + |
---|
| 3543 | + seq_printf(s, "%d\n", hisi_hba->debugfs_bist_phy_no); |
---|
| 3544 | + |
---|
| 3545 | + return 0; |
---|
| 3546 | +} |
---|
| 3547 | + |
---|
| 3548 | +static int hisi_sas_debugfs_bist_phy_open(struct inode *inode, |
---|
| 3549 | + struct file *filp) |
---|
| 3550 | +{ |
---|
| 3551 | + return single_open(filp, hisi_sas_debugfs_bist_phy_show, |
---|
| 3552 | + inode->i_private); |
---|
| 3553 | +} |
---|
| 3554 | + |
---|
| 3555 | +static const struct file_operations hisi_sas_debugfs_bist_phy_ops = { |
---|
| 3556 | + .open = hisi_sas_debugfs_bist_phy_open, |
---|
| 3557 | + .read = seq_read, |
---|
| 3558 | + .write = hisi_sas_debugfs_bist_phy_write, |
---|
| 3559 | + .llseek = seq_lseek, |
---|
| 3560 | + .release = single_release, |
---|
| 3561 | + .owner = THIS_MODULE, |
---|
| 3562 | +}; |
---|
| 3563 | + |
---|
| 3564 | +static const struct { |
---|
| 3565 | + int value; |
---|
| 3566 | + char *name; |
---|
| 3567 | +} hisi_sas_debugfs_loop_modes[] = { |
---|
| 3568 | + { HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digital" }, |
---|
| 3569 | + { HISI_SAS_BIST_LOOPBACK_MODE_SERDES, "serdes" }, |
---|
| 3570 | + { HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, "remote" }, |
---|
| 3571 | +}; |
---|
| 3572 | + |
---|
| 3573 | +static int hisi_sas_debugfs_bist_mode_show(struct seq_file *s, void *p) |
---|
| 3574 | +{ |
---|
| 3575 | + struct hisi_hba *hisi_hba = s->private; |
---|
| 3576 | + int i; |
---|
| 3577 | + |
---|
| 3578 | + for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_modes); i++) { |
---|
| 3579 | + int match = (hisi_hba->debugfs_bist_mode == |
---|
| 3580 | + hisi_sas_debugfs_loop_modes[i].value); |
---|
| 3581 | + |
---|
| 3582 | + seq_printf(s, "%s%s%s ", match ? "[" : "", |
---|
| 3583 | + hisi_sas_debugfs_loop_modes[i].name, |
---|
| 3584 | + match ? "]" : ""); |
---|
| 3585 | + } |
---|
| 3586 | + seq_puts(s, "\n"); |
---|
| 3587 | + |
---|
| 3588 | + return 0; |
---|
| 3589 | +} |
---|
| 3590 | + |
---|
| 3591 | +static ssize_t hisi_sas_debugfs_bist_mode_write(struct file *filp, |
---|
| 3592 | + const char __user *buf, |
---|
| 3593 | + size_t count, loff_t *ppos) |
---|
| 3594 | +{ |
---|
| 3595 | + struct seq_file *m = filp->private_data; |
---|
| 3596 | + struct hisi_hba *hisi_hba = m->private; |
---|
| 3597 | + char kbuf[16] = {}, *pkbuf; |
---|
| 3598 | + bool found = false; |
---|
| 3599 | + int i; |
---|
| 3600 | + |
---|
| 3601 | + if (hisi_hba->debugfs_bist_enable) |
---|
| 3602 | + return -EPERM; |
---|
| 3603 | + |
---|
| 3604 | + if (count >= sizeof(kbuf)) |
---|
| 3605 | + return -EINVAL; |
---|
| 3606 | + |
---|
| 3607 | + if (copy_from_user(kbuf, buf, count)) |
---|
| 3608 | + return -EOVERFLOW; |
---|
| 3609 | + |
---|
| 3610 | + pkbuf = strstrip(kbuf); |
---|
| 3611 | + |
---|
| 3612 | + for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_modes); i++) { |
---|
| 3613 | + if (!strncmp(hisi_sas_debugfs_loop_modes[i].name, pkbuf, 16)) { |
---|
| 3614 | + hisi_hba->debugfs_bist_mode = |
---|
| 3615 | + hisi_sas_debugfs_loop_modes[i].value; |
---|
| 3616 | + found = true; |
---|
| 3617 | + break; |
---|
| 3618 | + } |
---|
| 3619 | + } |
---|
| 3620 | + |
---|
| 3621 | + if (!found) |
---|
| 3622 | + return -EINVAL; |
---|
| 3623 | + |
---|
| 3624 | + return count; |
---|
| 3625 | +} |
---|
| 3626 | + |
---|
| 3627 | +static int hisi_sas_debugfs_bist_mode_open(struct inode *inode, |
---|
| 3628 | + struct file *filp) |
---|
| 3629 | +{ |
---|
| 3630 | + return single_open(filp, hisi_sas_debugfs_bist_mode_show, |
---|
| 3631 | + inode->i_private); |
---|
| 3632 | +} |
---|
| 3633 | + |
---|
| 3634 | +static const struct file_operations hisi_sas_debugfs_bist_mode_ops = { |
---|
| 3635 | + .open = hisi_sas_debugfs_bist_mode_open, |
---|
| 3636 | + .read = seq_read, |
---|
| 3637 | + .write = hisi_sas_debugfs_bist_mode_write, |
---|
| 3638 | + .llseek = seq_lseek, |
---|
| 3639 | + .release = single_release, |
---|
| 3640 | + .owner = THIS_MODULE, |
---|
| 3641 | +}; |
---|
| 3642 | + |
---|
| 3643 | +static ssize_t hisi_sas_debugfs_bist_enable_write(struct file *filp, |
---|
| 3644 | + const char __user *buf, |
---|
| 3645 | + size_t count, loff_t *ppos) |
---|
| 3646 | +{ |
---|
| 3647 | + struct seq_file *m = filp->private_data; |
---|
| 3648 | + struct hisi_hba *hisi_hba = m->private; |
---|
| 3649 | + unsigned int enable; |
---|
| 3650 | + int val; |
---|
| 3651 | + |
---|
| 3652 | + val = kstrtouint_from_user(buf, count, 0, &enable); |
---|
| 3653 | + if (val) |
---|
| 3654 | + return val; |
---|
| 3655 | + |
---|
| 3656 | + if (enable > 1) |
---|
| 3657 | + return -EINVAL; |
---|
| 3658 | + |
---|
| 3659 | + if (enable == hisi_hba->debugfs_bist_enable) |
---|
| 3660 | + return count; |
---|
| 3661 | + |
---|
| 3662 | + if (!hisi_hba->hw->set_bist) |
---|
| 3663 | + return -EPERM; |
---|
| 3664 | + |
---|
| 3665 | + val = hisi_hba->hw->set_bist(hisi_hba, enable); |
---|
| 3666 | + if (val < 0) |
---|
| 3667 | + return val; |
---|
| 3668 | + |
---|
| 3669 | + hisi_hba->debugfs_bist_enable = enable; |
---|
| 3670 | + |
---|
| 3671 | + return count; |
---|
| 3672 | +} |
---|
| 3673 | + |
---|
| 3674 | +static int hisi_sas_debugfs_bist_enable_show(struct seq_file *s, void *p) |
---|
| 3675 | +{ |
---|
| 3676 | + struct hisi_hba *hisi_hba = s->private; |
---|
| 3677 | + |
---|
| 3678 | + seq_printf(s, "%d\n", hisi_hba->debugfs_bist_enable); |
---|
| 3679 | + |
---|
| 3680 | + return 0; |
---|
| 3681 | +} |
---|
| 3682 | + |
---|
| 3683 | +static int hisi_sas_debugfs_bist_enable_open(struct inode *inode, |
---|
| 3684 | + struct file *filp) |
---|
| 3685 | +{ |
---|
| 3686 | + return single_open(filp, hisi_sas_debugfs_bist_enable_show, |
---|
| 3687 | + inode->i_private); |
---|
| 3688 | +} |
---|
| 3689 | + |
---|
| 3690 | +static const struct file_operations hisi_sas_debugfs_bist_enable_ops = { |
---|
| 3691 | + .open = hisi_sas_debugfs_bist_enable_open, |
---|
| 3692 | + .read = seq_read, |
---|
| 3693 | + .write = hisi_sas_debugfs_bist_enable_write, |
---|
| 3694 | + .llseek = seq_lseek, |
---|
| 3695 | + .release = single_release, |
---|
| 3696 | + .owner = THIS_MODULE, |
---|
| 3697 | +}; |
---|
| 3698 | + |
---|
| 3699 | +static const struct { |
---|
| 3700 | + char *name; |
---|
| 3701 | +} hisi_sas_debugfs_ffe_name[FFE_CFG_MAX] = { |
---|
| 3702 | + { "SAS_1_5_GBPS" }, |
---|
| 3703 | + { "SAS_3_0_GBPS" }, |
---|
| 3704 | + { "SAS_6_0_GBPS" }, |
---|
| 3705 | + { "SAS_12_0_GBPS" }, |
---|
| 3706 | + { "FFE_RESV" }, |
---|
| 3707 | + { "SATA_1_5_GBPS" }, |
---|
| 3708 | + { "SATA_3_0_GBPS" }, |
---|
| 3709 | + { "SATA_6_0_GBPS" }, |
---|
| 3710 | +}; |
---|
| 3711 | + |
---|
| 3712 | +static ssize_t hisi_sas_debugfs_write(struct file *filp, |
---|
| 3713 | + const char __user *buf, |
---|
| 3714 | + size_t count, loff_t *ppos) |
---|
| 3715 | +{ |
---|
| 3716 | + struct seq_file *m = filp->private_data; |
---|
| 3717 | + u32 *val = m->private; |
---|
| 3718 | + int res; |
---|
| 3719 | + |
---|
| 3720 | + res = kstrtouint_from_user(buf, count, 0, val); |
---|
| 3721 | + if (res) |
---|
| 3722 | + return res; |
---|
| 3723 | + |
---|
| 3724 | + return count; |
---|
| 3725 | +} |
---|
| 3726 | + |
---|
| 3727 | +static int hisi_sas_debugfs_show(struct seq_file *s, void *p) |
---|
| 3728 | +{ |
---|
| 3729 | + u32 *val = s->private; |
---|
| 3730 | + |
---|
| 3731 | + seq_printf(s, "0x%x\n", *val); |
---|
| 3732 | + |
---|
| 3733 | + return 0; |
---|
| 3734 | +} |
---|
| 3735 | + |
---|
| 3736 | +static int hisi_sas_debugfs_open(struct inode *inode, struct file *filp) |
---|
| 3737 | +{ |
---|
| 3738 | + return single_open(filp, hisi_sas_debugfs_show, |
---|
| 3739 | + inode->i_private); |
---|
| 3740 | +} |
---|
| 3741 | + |
---|
| 3742 | +static const struct file_operations hisi_sas_debugfs_ops = { |
---|
| 3743 | + .open = hisi_sas_debugfs_open, |
---|
| 3744 | + .read = seq_read, |
---|
| 3745 | + .write = hisi_sas_debugfs_write, |
---|
| 3746 | + .llseek = seq_lseek, |
---|
| 3747 | + .release = single_release, |
---|
| 3748 | + .owner = THIS_MODULE, |
---|
| 3749 | +}; |
---|
| 3750 | + |
---|
| 3751 | +static ssize_t hisi_sas_debugfs_phy_down_cnt_write(struct file *filp, |
---|
| 3752 | + const char __user *buf, |
---|
| 3753 | + size_t count, loff_t *ppos) |
---|
| 3754 | +{ |
---|
| 3755 | + struct seq_file *s = filp->private_data; |
---|
| 3756 | + struct hisi_sas_phy *phy = s->private; |
---|
| 3757 | + unsigned int set_val; |
---|
| 3758 | + int res; |
---|
| 3759 | + |
---|
| 3760 | + res = kstrtouint_from_user(buf, count, 0, &set_val); |
---|
| 3761 | + if (res) |
---|
| 3762 | + return res; |
---|
| 3763 | + |
---|
| 3764 | + if (set_val > 0) |
---|
| 3765 | + return -EINVAL; |
---|
| 3766 | + |
---|
| 3767 | + atomic_set(&phy->down_cnt, 0); |
---|
| 3768 | + |
---|
| 3769 | + return count; |
---|
| 3770 | +} |
---|
| 3771 | + |
---|
| 3772 | +static int hisi_sas_debugfs_phy_down_cnt_show(struct seq_file *s, void *p) |
---|
| 3773 | +{ |
---|
| 3774 | + struct hisi_sas_phy *phy = s->private; |
---|
| 3775 | + |
---|
| 3776 | + seq_printf(s, "%d\n", atomic_read(&phy->down_cnt)); |
---|
| 3777 | + |
---|
| 3778 | + return 0; |
---|
| 3779 | +} |
---|
| 3780 | + |
---|
| 3781 | +static int hisi_sas_debugfs_phy_down_cnt_open(struct inode *inode, |
---|
| 3782 | + struct file *filp) |
---|
| 3783 | +{ |
---|
| 3784 | + return single_open(filp, hisi_sas_debugfs_phy_down_cnt_show, |
---|
| 3785 | + inode->i_private); |
---|
| 3786 | +} |
---|
| 3787 | + |
---|
| 3788 | +static const struct file_operations hisi_sas_debugfs_phy_down_cnt_ops = { |
---|
| 3789 | + .open = hisi_sas_debugfs_phy_down_cnt_open, |
---|
| 3790 | + .read = seq_read, |
---|
| 3791 | + .write = hisi_sas_debugfs_phy_down_cnt_write, |
---|
| 3792 | + .llseek = seq_lseek, |
---|
| 3793 | + .release = single_release, |
---|
| 3794 | + .owner = THIS_MODULE, |
---|
| 3795 | +}; |
---|
| 3796 | + |
---|
| 3797 | +void hisi_sas_debugfs_work_handler(struct work_struct *work) |
---|
| 3798 | +{ |
---|
| 3799 | + struct hisi_hba *hisi_hba = |
---|
| 3800 | + container_of(work, struct hisi_hba, debugfs_work); |
---|
| 3801 | + int debugfs_dump_index = hisi_hba->debugfs_dump_index; |
---|
| 3802 | + struct device *dev = hisi_hba->dev; |
---|
| 3803 | + u64 timestamp = local_clock(); |
---|
| 3804 | + |
---|
| 3805 | + if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { |
---|
| 3806 | + dev_warn(dev, "dump count exceeded!\n"); |
---|
| 3807 | + return; |
---|
| 3808 | + } |
---|
| 3809 | + |
---|
| 3810 | + do_div(timestamp, NSEC_PER_MSEC); |
---|
| 3811 | + hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; |
---|
| 3812 | + |
---|
| 3813 | + hisi_sas_debugfs_snapshot_regs(hisi_hba); |
---|
| 3814 | + hisi_hba->debugfs_dump_index++; |
---|
| 3815 | +} |
---|
| 3816 | +EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); |
---|
| 3817 | + |
---|
| 3818 | +static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba, int dump_index) |
---|
| 3819 | +{ |
---|
| 3820 | + struct device *dev = hisi_hba->dev; |
---|
| 3821 | + int i; |
---|
| 3822 | + |
---|
| 3823 | + devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache); |
---|
| 3824 | + devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache); |
---|
| 3825 | + devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost); |
---|
| 3826 | + devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct); |
---|
| 3827 | + |
---|
| 3828 | + for (i = 0; i < hisi_hba->queue_count; i++) |
---|
| 3829 | + devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr); |
---|
| 3830 | + |
---|
| 3831 | + for (i = 0; i < hisi_hba->queue_count; i++) |
---|
| 3832 | + devm_kfree(dev, |
---|
| 3833 | + hisi_hba->debugfs_cq[dump_index][i].complete_hdr); |
---|
| 3834 | + |
---|
| 3835 | + for (i = 0; i < DEBUGFS_REGS_NUM; i++) |
---|
| 3836 | + devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data); |
---|
| 3837 | + |
---|
| 3838 | + for (i = 0; i < hisi_hba->n_phy; i++) |
---|
| 3839 | + devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data); |
---|
| 3840 | +} |
---|
| 3841 | + |
---|
| 3842 | +static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba, int dump_index) |
---|
| 3843 | +{ |
---|
| 3844 | + const struct hisi_sas_hw *hw = hisi_hba->hw; |
---|
| 3845 | + struct device *dev = hisi_hba->dev; |
---|
| 3846 | + int p, c, d, r, i; |
---|
| 3847 | + size_t sz; |
---|
| 3848 | + |
---|
| 3849 | + for (r = 0; r < DEBUGFS_REGS_NUM; r++) { |
---|
| 3850 | + struct hisi_sas_debugfs_regs *regs = |
---|
| 3851 | + &hisi_hba->debugfs_regs[dump_index][r]; |
---|
| 3852 | + |
---|
| 3853 | + sz = hw->debugfs_reg_array[r]->count * 4; |
---|
| 3854 | + regs->data = devm_kmalloc(dev, sz, GFP_KERNEL); |
---|
| 3855 | + if (!regs->data) |
---|
| 3856 | + goto fail; |
---|
| 3857 | + regs->hisi_hba = hisi_hba; |
---|
| 3858 | + } |
---|
| 3859 | + |
---|
| 3860 | + sz = hw->debugfs_reg_port->count * 4; |
---|
| 3861 | + for (p = 0; p < hisi_hba->n_phy; p++) { |
---|
| 3862 | + struct hisi_sas_debugfs_port *port = |
---|
| 3863 | + &hisi_hba->debugfs_port_reg[dump_index][p]; |
---|
| 3864 | + |
---|
| 3865 | + port->data = devm_kmalloc(dev, sz, GFP_KERNEL); |
---|
| 3866 | + if (!port->data) |
---|
| 3867 | + goto fail; |
---|
| 3868 | + port->phy = &hisi_hba->phy[p]; |
---|
| 3869 | + } |
---|
| 3870 | + |
---|
| 3871 | + sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; |
---|
| 3872 | + for (c = 0; c < hisi_hba->queue_count; c++) { |
---|
| 3873 | + struct hisi_sas_debugfs_cq *cq = |
---|
| 3874 | + &hisi_hba->debugfs_cq[dump_index][c]; |
---|
| 3875 | + |
---|
| 3876 | + cq->complete_hdr = devm_kmalloc(dev, sz, GFP_KERNEL); |
---|
| 3877 | + if (!cq->complete_hdr) |
---|
| 3878 | + goto fail; |
---|
| 3879 | + cq->cq = &hisi_hba->cq[c]; |
---|
| 3880 | + } |
---|
| 3881 | + |
---|
| 3882 | + sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; |
---|
| 3883 | + for (d = 0; d < hisi_hba->queue_count; d++) { |
---|
| 3884 | + struct hisi_sas_debugfs_dq *dq = |
---|
| 3885 | + &hisi_hba->debugfs_dq[dump_index][d]; |
---|
| 3886 | + |
---|
| 3887 | + dq->hdr = devm_kmalloc(dev, sz, GFP_KERNEL); |
---|
| 3888 | + if (!dq->hdr) |
---|
| 3889 | + goto fail; |
---|
| 3890 | + dq->dq = &hisi_hba->dq[d]; |
---|
| 3891 | + } |
---|
| 3892 | + |
---|
| 3893 | + sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost); |
---|
| 3894 | + |
---|
| 3895 | + hisi_hba->debugfs_iost[dump_index].iost = |
---|
| 3896 | + devm_kmalloc(dev, sz, GFP_KERNEL); |
---|
| 3897 | + if (!hisi_hba->debugfs_iost[dump_index].iost) |
---|
| 3898 | + goto fail; |
---|
| 3899 | + |
---|
| 3900 | + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * |
---|
| 3901 | + sizeof(struct hisi_sas_iost_itct_cache); |
---|
| 3902 | + |
---|
| 3903 | + hisi_hba->debugfs_iost_cache[dump_index].cache = |
---|
| 3904 | + devm_kmalloc(dev, sz, GFP_KERNEL); |
---|
| 3905 | + if (!hisi_hba->debugfs_iost_cache[dump_index].cache) |
---|
| 3906 | + goto fail; |
---|
| 3907 | + |
---|
| 3908 | + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * |
---|
| 3909 | + sizeof(struct hisi_sas_iost_itct_cache); |
---|
| 3910 | + |
---|
| 3911 | + hisi_hba->debugfs_itct_cache[dump_index].cache = |
---|
| 3912 | + devm_kmalloc(dev, sz, GFP_KERNEL); |
---|
| 3913 | + if (!hisi_hba->debugfs_itct_cache[dump_index].cache) |
---|
| 3914 | + goto fail; |
---|
| 3915 | + |
---|
| 3916 | + /* New memory allocation must be locate before itct */ |
---|
| 3917 | + sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); |
---|
| 3918 | + |
---|
| 3919 | + hisi_hba->debugfs_itct[dump_index].itct = |
---|
| 3920 | + devm_kmalloc(dev, sz, GFP_KERNEL); |
---|
| 3921 | + if (!hisi_hba->debugfs_itct[dump_index].itct) |
---|
| 3922 | + goto fail; |
---|
| 3923 | + |
---|
| 3924 | + return 0; |
---|
| 3925 | +fail: |
---|
| 3926 | + for (i = 0; i < hisi_sas_debugfs_dump_count; i++) |
---|
| 3927 | + hisi_sas_debugfs_release(hisi_hba, i); |
---|
| 3928 | + return -ENOMEM; |
---|
| 3929 | +} |
---|
| 3930 | + |
---|
| 3931 | +static void hisi_sas_debugfs_phy_down_cnt_init(struct hisi_hba *hisi_hba) |
---|
| 3932 | +{ |
---|
| 3933 | + struct dentry *dir = debugfs_create_dir("phy_down_cnt", |
---|
| 3934 | + hisi_hba->debugfs_dir); |
---|
| 3935 | + char name[16]; |
---|
| 3936 | + int phy_no; |
---|
| 3937 | + |
---|
| 3938 | + for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { |
---|
| 3939 | + snprintf(name, 16, "%d", phy_no); |
---|
| 3940 | + debugfs_create_file(name, 0600, dir, |
---|
| 3941 | + &hisi_hba->phy[phy_no], |
---|
| 3942 | + &hisi_sas_debugfs_phy_down_cnt_ops); |
---|
| 3943 | + } |
---|
| 3944 | +} |
---|
| 3945 | + |
---|
| 3946 | +static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba) |
---|
| 3947 | +{ |
---|
| 3948 | + struct dentry *ports_dentry; |
---|
| 3949 | + int phy_no; |
---|
| 3950 | + |
---|
| 3951 | + hisi_hba->debugfs_bist_dentry = |
---|
| 3952 | + debugfs_create_dir("bist", hisi_hba->debugfs_dir); |
---|
| 3953 | + debugfs_create_file("link_rate", 0600, |
---|
| 3954 | + hisi_hba->debugfs_bist_dentry, hisi_hba, |
---|
| 3955 | + &hisi_sas_debugfs_bist_linkrate_ops); |
---|
| 3956 | + |
---|
| 3957 | + debugfs_create_file("code_mode", 0600, |
---|
| 3958 | + hisi_hba->debugfs_bist_dentry, hisi_hba, |
---|
| 3959 | + &hisi_sas_debugfs_bist_code_mode_ops); |
---|
| 3960 | + |
---|
| 3961 | + debugfs_create_file("fixed_code", 0600, |
---|
| 3962 | + hisi_hba->debugfs_bist_dentry, |
---|
| 3963 | + &hisi_hba->debugfs_bist_fixed_code[0], |
---|
| 3964 | + &hisi_sas_debugfs_ops); |
---|
| 3965 | + |
---|
| 3966 | + debugfs_create_file("fixed_code_1", 0600, |
---|
| 3967 | + hisi_hba->debugfs_bist_dentry, |
---|
| 3968 | + &hisi_hba->debugfs_bist_fixed_code[1], |
---|
| 3969 | + &hisi_sas_debugfs_ops); |
---|
| 3970 | + |
---|
| 3971 | + debugfs_create_file("phy_id", 0600, hisi_hba->debugfs_bist_dentry, |
---|
| 3972 | + hisi_hba, &hisi_sas_debugfs_bist_phy_ops); |
---|
| 3973 | + |
---|
| 3974 | + debugfs_create_u32("cnt", 0600, hisi_hba->debugfs_bist_dentry, |
---|
| 3975 | + &hisi_hba->debugfs_bist_cnt); |
---|
| 3976 | + |
---|
| 3977 | + debugfs_create_file("loopback_mode", 0600, |
---|
| 3978 | + hisi_hba->debugfs_bist_dentry, |
---|
| 3979 | + hisi_hba, &hisi_sas_debugfs_bist_mode_ops); |
---|
| 3980 | + |
---|
| 3981 | + debugfs_create_file("enable", 0600, hisi_hba->debugfs_bist_dentry, |
---|
| 3982 | + hisi_hba, &hisi_sas_debugfs_bist_enable_ops); |
---|
| 3983 | + |
---|
| 3984 | + ports_dentry = debugfs_create_dir("port", hisi_hba->debugfs_bist_dentry); |
---|
| 3985 | + |
---|
| 3986 | + for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { |
---|
| 3987 | + struct dentry *port_dentry; |
---|
| 3988 | + struct dentry *ffe_dentry; |
---|
| 3989 | + char name[256]; |
---|
| 3990 | + int i; |
---|
| 3991 | + |
---|
| 3992 | + snprintf(name, 256, "%d", phy_no); |
---|
| 3993 | + port_dentry = debugfs_create_dir(name, ports_dentry); |
---|
| 3994 | + ffe_dentry = debugfs_create_dir("ffe", port_dentry); |
---|
| 3995 | + for (i = 0; i < FFE_CFG_MAX; i++) { |
---|
| 3996 | + if (i == FFE_RESV) |
---|
| 3997 | + continue; |
---|
| 3998 | + debugfs_create_file(hisi_sas_debugfs_ffe_name[i].name, |
---|
| 3999 | + 0600, ffe_dentry, |
---|
| 4000 | + &hisi_hba->debugfs_bist_ffe[phy_no][i], |
---|
| 4001 | + &hisi_sas_debugfs_ops); |
---|
| 4002 | + } |
---|
| 4003 | + } |
---|
| 4004 | + |
---|
| 4005 | + hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS; |
---|
| 4006 | +} |
---|
| 4007 | + |
---|
| 4008 | +void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) |
---|
| 4009 | +{ |
---|
| 4010 | + struct device *dev = hisi_hba->dev; |
---|
| 4011 | + int i; |
---|
| 4012 | + |
---|
| 4013 | + hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), |
---|
| 4014 | + hisi_sas_debugfs_dir); |
---|
| 4015 | + debugfs_create_file("trigger_dump", 0200, |
---|
| 4016 | + hisi_hba->debugfs_dir, |
---|
| 4017 | + hisi_hba, |
---|
| 4018 | + &hisi_sas_debugfs_trigger_dump_fops); |
---|
| 4019 | + |
---|
| 4020 | + /* create bist structures */ |
---|
| 4021 | + hisi_sas_debugfs_bist_init(hisi_hba); |
---|
| 4022 | + |
---|
| 4023 | + hisi_hba->debugfs_dump_dentry = |
---|
| 4024 | + debugfs_create_dir("dump", hisi_hba->debugfs_dir); |
---|
| 4025 | + |
---|
| 4026 | + hisi_sas_debugfs_phy_down_cnt_init(hisi_hba); |
---|
| 4027 | + |
---|
| 4028 | + for (i = 0; i < hisi_sas_debugfs_dump_count; i++) { |
---|
| 4029 | + if (hisi_sas_debugfs_alloc(hisi_hba, i)) { |
---|
| 4030 | + debugfs_remove_recursive(hisi_hba->debugfs_dir); |
---|
| 4031 | + dev_dbg(dev, "failed to init debugfs!\n"); |
---|
| 4032 | + break; |
---|
| 4033 | + } |
---|
| 4034 | + } |
---|
| 4035 | +} |
---|
| 4036 | +EXPORT_SYMBOL_GPL(hisi_sas_debugfs_init); |
---|
| 4037 | + |
---|
| 4038 | +void hisi_sas_debugfs_exit(struct hisi_hba *hisi_hba) |
---|
| 4039 | +{ |
---|
| 4040 | + debugfs_remove_recursive(hisi_hba->debugfs_dir); |
---|
| 4041 | +} |
---|
| 4042 | +EXPORT_SYMBOL_GPL(hisi_sas_debugfs_exit); |
---|
2428 | 4043 | |
---|
2429 | 4044 | int hisi_sas_remove(struct platform_device *pdev) |
---|
2430 | 4045 | { |
---|
.. | .. |
---|
2444 | 4059 | } |
---|
2445 | 4060 | EXPORT_SYMBOL_GPL(hisi_sas_remove); |
---|
2446 | 4061 | |
---|
| 4062 | +bool hisi_sas_debugfs_enable; |
---|
| 4063 | +EXPORT_SYMBOL_GPL(hisi_sas_debugfs_enable); |
---|
| 4064 | +module_param_named(debugfs_enable, hisi_sas_debugfs_enable, bool, 0444); |
---|
| 4065 | +MODULE_PARM_DESC(hisi_sas_debugfs_enable, "Enable driver debugfs (default disabled)"); |
---|
| 4066 | + |
---|
| 4067 | +u32 hisi_sas_debugfs_dump_count = 1; |
---|
| 4068 | +EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dump_count); |
---|
| 4069 | +module_param_named(debugfs_dump_count, hisi_sas_debugfs_dump_count, uint, 0444); |
---|
| 4070 | +MODULE_PARM_DESC(hisi_sas_debugfs_dump_count, "Number of debugfs dumps to allow"); |
---|
| 4071 | + |
---|
2447 | 4072 | static __init int hisi_sas_init(void) |
---|
2448 | 4073 | { |
---|
2449 | 4074 | hisi_sas_stt = sas_domain_attach_transport(&hisi_sas_transport_ops); |
---|
2450 | 4075 | if (!hisi_sas_stt) |
---|
2451 | 4076 | return -ENOMEM; |
---|
| 4077 | + |
---|
| 4078 | + if (hisi_sas_debugfs_enable) { |
---|
| 4079 | + hisi_sas_debugfs_dir = debugfs_create_dir("hisi_sas", NULL); |
---|
| 4080 | + if (hisi_sas_debugfs_dump_count > HISI_SAS_MAX_DEBUGFS_DUMP) { |
---|
| 4081 | + pr_info("hisi_sas: Limiting debugfs dump count\n"); |
---|
| 4082 | + hisi_sas_debugfs_dump_count = HISI_SAS_MAX_DEBUGFS_DUMP; |
---|
| 4083 | + } |
---|
| 4084 | + } |
---|
2452 | 4085 | |
---|
2453 | 4086 | return 0; |
---|
2454 | 4087 | } |
---|
.. | .. |
---|
2456 | 4089 | static __exit void hisi_sas_exit(void) |
---|
2457 | 4090 | { |
---|
2458 | 4091 | sas_release_transport(hisi_sas_stt); |
---|
| 4092 | + |
---|
| 4093 | + debugfs_remove(hisi_sas_debugfs_dir); |
---|
2459 | 4094 | } |
---|
2460 | 4095 | |
---|
2461 | 4096 | module_init(hisi_sas_init); |
---|