]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/scsi/hisi_sas/hisi_sas_main.c
hisi_sas: Add scan finished and start
[mirror_ubuntu-artful-kernel.git] / drivers / scsi / hisi_sas / hisi_sas_main.c
CommitLineData
e8899fad
JG
1/*
2 * Copyright (c) 2015 Linaro Ltd.
3 * 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 */
11
12#include "hisi_sas.h"
13#define DRV_NAME "hisi_sas"
14
abda97c2
JG
15#define DEV_IS_EXPANDER(type) \
16 ((type == SAS_EDGE_EXPANDER_DEVICE) || \
17 (type == SAS_FANOUT_EXPANDER_DEVICE))
42e7a693
JG
18
19#define DEV_IS_GONE(dev) \
20 ((!dev) || (dev->dev_type == SAS_PHY_UNUSED))
21
22static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
23{
24 return device->port->ha->lldd_ha;
25}
26
257efd1f
JG
27static void hisi_sas_slot_index_clear(struct hisi_hba *hisi_hba, int slot_idx)
28{
29 void *bitmap = hisi_hba->slot_index_tags;
30
31 clear_bit(slot_idx, bitmap);
32}
33
42e7a693
JG
34static void hisi_sas_slot_index_free(struct hisi_hba *hisi_hba, int slot_idx)
35{
36 hisi_sas_slot_index_clear(hisi_hba, slot_idx);
37}
38
39static void hisi_sas_slot_index_set(struct hisi_hba *hisi_hba, int slot_idx)
40{
41 void *bitmap = hisi_hba->slot_index_tags;
42
43 set_bit(slot_idx, bitmap);
44}
45
46static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba, int *slot_idx)
47{
48 unsigned int index;
49 void *bitmap = hisi_hba->slot_index_tags;
50
51 index = find_first_zero_bit(bitmap, hisi_hba->slot_index_count);
52 if (index >= hisi_hba->slot_index_count)
53 return -SAS_QUEUE_FULL;
54 hisi_sas_slot_index_set(hisi_hba, index);
55 *slot_idx = index;
56 return 0;
57}
58
257efd1f
JG
59static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba)
60{
61 int i;
62
63 for (i = 0; i < hisi_hba->slot_index_count; ++i)
64 hisi_sas_slot_index_clear(hisi_hba, i);
65}
27a3f229
JG
66
67void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
68 struct hisi_sas_slot *slot)
69{
70 struct device *dev = &hisi_hba->pdev->dev;
71
72 if (!slot->task)
73 return;
74
75 if (!sas_protocol_ata(task->task_proto))
76 if (slot->n_elem)
77 dma_unmap_sg(dev, task->scatter, slot->n_elem,
78 task->data_dir);
79
80 if (slot->command_table)
81 dma_pool_free(hisi_hba->command_table_pool,
82 slot->command_table, slot->command_table_dma);
83
84 if (slot->status_buffer)
85 dma_pool_free(hisi_hba->status_buffer_pool,
86 slot->status_buffer, slot->status_buffer_dma);
87
88 if (slot->sge_page)
89 dma_pool_free(hisi_hba->sge_page_pool, slot->sge_page,
90 slot->sge_page_dma);
91
92 list_del_init(&slot->entry);
93 task->lldd_task = NULL;
94 slot->task = NULL;
95 slot->port = NULL;
96 hisi_sas_slot_index_free(hisi_hba, slot->idx);
97 memset(slot, 0, sizeof(*slot));
98}
99EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free);
100
66ee999b
JG
101static int hisi_sas_task_prep_smp(struct hisi_hba *hisi_hba,
102 struct hisi_sas_slot *slot)
103{
104 return hisi_hba->hw->prep_smp(hisi_hba, slot);
105}
106
42e7a693
JG
107static int hisi_sas_task_prep_ssp(struct hisi_hba *hisi_hba,
108 struct hisi_sas_slot *slot, int is_tmf,
109 struct hisi_sas_tmf_task *tmf)
110{
111 return hisi_hba->hw->prep_ssp(hisi_hba, slot, is_tmf, tmf);
112}
113
114static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
115 int is_tmf, struct hisi_sas_tmf_task *tmf,
116 int *pass)
117{
118 struct domain_device *device = task->dev;
119 struct hisi_sas_device *sas_dev = device->lldd_dev;
120 struct hisi_sas_port *port;
121 struct hisi_sas_slot *slot;
122 struct hisi_sas_cmd_hdr *cmd_hdr_base;
123 struct device *dev = &hisi_hba->pdev->dev;
124 int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
125
126 if (!device->port) {
127 struct task_status_struct *ts = &task->task_status;
128
129 ts->resp = SAS_TASK_UNDELIVERED;
130 ts->stat = SAS_PHY_DOWN;
131 /*
132 * libsas will use dev->port, should
133 * not call task_done for sata
134 */
135 if (device->dev_type != SAS_SATA_DEV)
136 task->task_done(task);
137 return 0;
138 }
139
140 if (DEV_IS_GONE(sas_dev)) {
141 if (sas_dev)
142 dev_info(dev, "task prep: device %llu not ready\n",
143 sas_dev->device_id);
144 else
145 dev_info(dev, "task prep: device %016llx not ready\n",
146 SAS_ADDR(device->sas_addr));
147
148 rc = SAS_PHY_DOWN;
149 return rc;
150 }
151 port = device->port->lldd_port;
152 if (port && !port->port_attached && !tmf) {
153 if (sas_protocol_ata(task->task_proto)) {
154 struct task_status_struct *ts = &task->task_status;
155
156 dev_info(dev,
157 "task prep: SATA/STP port%d not attach device\n",
158 device->port->id);
159 ts->resp = SAS_TASK_COMPLETE;
160 ts->stat = SAS_PHY_DOWN;
161 task->task_done(task);
162 } else {
163 struct task_status_struct *ts = &task->task_status;
164
165 dev_info(dev,
166 "task prep: SAS port%d does not attach device\n",
167 device->port->id);
168 ts->resp = SAS_TASK_UNDELIVERED;
169 ts->stat = SAS_PHY_DOWN;
170 task->task_done(task);
171 }
172 return 0;
173 }
174
175 if (!sas_protocol_ata(task->task_proto)) {
176 if (task->num_scatter) {
177 n_elem = dma_map_sg(dev, task->scatter,
178 task->num_scatter, task->data_dir);
179 if (!n_elem) {
180 rc = -ENOMEM;
181 goto prep_out;
182 }
183 }
184 } else
185 n_elem = task->num_scatter;
186
187 rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx);
188 if (rc)
189 goto err_out;
190 rc = hisi_hba->hw->get_free_slot(hisi_hba, &dlvry_queue,
191 &dlvry_queue_slot);
192 if (rc)
193 goto err_out_tag;
194
195 slot = &hisi_hba->slot_info[slot_idx];
196 memset(slot, 0, sizeof(struct hisi_sas_slot));
197
198 slot->idx = slot_idx;
199 slot->n_elem = n_elem;
200 slot->dlvry_queue = dlvry_queue;
201 slot->dlvry_queue_slot = dlvry_queue_slot;
202 cmd_hdr_base = hisi_hba->cmd_hdr[dlvry_queue];
203 slot->cmd_hdr = &cmd_hdr_base[dlvry_queue_slot];
204 slot->task = task;
205 slot->port = port;
206 task->lldd_task = slot;
207
208 slot->status_buffer = dma_pool_alloc(hisi_hba->status_buffer_pool,
209 GFP_ATOMIC,
210 &slot->status_buffer_dma);
211 if (!slot->status_buffer)
212 goto err_out_slot_buf;
213 memset(slot->status_buffer, 0, HISI_SAS_STATUS_BUF_SZ);
214
215 slot->command_table = dma_pool_alloc(hisi_hba->command_table_pool,
216 GFP_ATOMIC,
217 &slot->command_table_dma);
218 if (!slot->command_table)
219 goto err_out_status_buf;
220 memset(slot->command_table, 0, HISI_SAS_COMMAND_TABLE_SZ);
221 memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr));
222
223 switch (task->task_proto) {
66ee999b
JG
224 case SAS_PROTOCOL_SMP:
225 rc = hisi_sas_task_prep_smp(hisi_hba, slot);
226 break;
42e7a693
JG
227 case SAS_PROTOCOL_SSP:
228 rc = hisi_sas_task_prep_ssp(hisi_hba, slot, is_tmf, tmf);
229 break;
230 case SAS_PROTOCOL_SATA:
231 case SAS_PROTOCOL_STP:
232 case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
233 default:
234 dev_err(dev, "task prep: unknown/unsupported proto (0x%x)\n",
235 task->task_proto);
236 rc = -EINVAL;
237 break;
238 }
239
240 if (rc) {
241 dev_err(dev, "task prep: rc = 0x%x\n", rc);
242 if (slot->sge_page)
243 goto err_out_sge;
244 goto err_out_command_table;
245 }
246
247 list_add_tail(&slot->entry, &port->list);
248 spin_lock(&task->task_state_lock);
249 task->task_state_flags |= SAS_TASK_AT_INITIATOR;
250 spin_unlock(&task->task_state_lock);
251
252 hisi_hba->slot_prep = slot;
253
254 sas_dev->running_req++;
255 ++(*pass);
256
257 return rc;
258
259err_out_sge:
260 dma_pool_free(hisi_hba->sge_page_pool, slot->sge_page,
261 slot->sge_page_dma);
262err_out_command_table:
263 dma_pool_free(hisi_hba->command_table_pool, slot->command_table,
264 slot->command_table_dma);
265err_out_status_buf:
266 dma_pool_free(hisi_hba->status_buffer_pool, slot->status_buffer,
267 slot->status_buffer_dma);
268err_out_slot_buf:
269 /* Nothing to be done */
270err_out_tag:
271 hisi_sas_slot_index_free(hisi_hba, slot_idx);
272err_out:
273 dev_err(dev, "task prep: failed[%d]!\n", rc);
274 if (!sas_protocol_ata(task->task_proto))
275 if (n_elem)
276 dma_unmap_sg(dev, task->scatter, n_elem,
277 task->data_dir);
278prep_out:
279 return rc;
280}
281
282static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags,
283 int is_tmf, struct hisi_sas_tmf_task *tmf)
284{
285 u32 rc;
286 u32 pass = 0;
287 unsigned long flags;
288 struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev);
289 struct device *dev = &hisi_hba->pdev->dev;
290
291 /* protect task_prep and start_delivery sequence */
292 spin_lock_irqsave(&hisi_hba->lock, flags);
293 rc = hisi_sas_task_prep(task, hisi_hba, is_tmf, tmf, &pass);
294 if (rc)
295 dev_err(dev, "task exec: failed[%d]!\n", rc);
296
297 if (likely(pass))
298 hisi_hba->hw->start_delivery(hisi_hba);
299 spin_unlock_irqrestore(&hisi_hba->lock, flags);
300
301 return rc;
302}
257efd1f 303
66139921
JG
304static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no)
305{
306 struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
307 struct asd_sas_phy *sas_phy = &phy->sas_phy;
308 struct sas_ha_struct *sas_ha;
309
310 if (!phy->phy_attached)
311 return;
312
313 sas_ha = &hisi_hba->sha;
314 sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE);
315
316 if (sas_phy->phy) {
317 struct sas_phy *sphy = sas_phy->phy;
318
319 sphy->negotiated_linkrate = sas_phy->linkrate;
320 sphy->minimum_linkrate = phy->minimum_linkrate;
321 sphy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
322 sphy->maximum_linkrate = phy->maximum_linkrate;
323 }
324
325 if (phy->phy_type & PORT_TYPE_SAS) {
326 struct sas_identify_frame *id;
327
328 id = (struct sas_identify_frame *)phy->frame_rcvd;
329 id->dev_type = phy->identify.device_type;
330 id->initiator_bits = SAS_PROTOCOL_ALL;
331 id->target_bits = phy->identify.target_port_protocols;
332 } else if (phy->phy_type & PORT_TYPE_SATA) {
333 /*Nothing*/
334 }
335
336 sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
337 sas_ha->notify_port_event(sas_phy, PORTE_BYTES_DMAED);
338}
339
abda97c2
JG
340static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
341{
342 struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
343 struct hisi_sas_device *sas_dev = NULL;
344 int i;
345
346 spin_lock(&hisi_hba->lock);
347 for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
348 if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) {
349 hisi_hba->devices[i].device_id = i;
350 sas_dev = &hisi_hba->devices[i];
351 sas_dev->dev_status = HISI_SAS_DEV_NORMAL;
352 sas_dev->dev_type = device->dev_type;
353 sas_dev->hisi_hba = hisi_hba;
354 sas_dev->sas_device = device;
355 break;
356 }
357 }
358 spin_unlock(&hisi_hba->lock);
359
360 return sas_dev;
361}
362
363static int hisi_sas_dev_found(struct domain_device *device)
364{
365 struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
366 struct domain_device *parent_dev = device->parent;
367 struct hisi_sas_device *sas_dev;
368 struct device *dev = &hisi_hba->pdev->dev;
369
370 sas_dev = hisi_sas_alloc_dev(device);
371 if (!sas_dev) {
372 dev_err(dev, "fail alloc dev: max support %d devices\n",
373 HISI_SAS_MAX_DEVICES);
374 return -EINVAL;
375 }
376
377 device->lldd_dev = sas_dev;
378 hisi_hba->hw->setup_itct(hisi_hba, sas_dev);
379
380 if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) {
381 int phy_no;
382 u8 phy_num = parent_dev->ex_dev.num_phys;
383 struct ex_phy *phy;
384
385 for (phy_no = 0; phy_no < phy_num; phy_no++) {
386 phy = &parent_dev->ex_dev.ex_phy[phy_no];
387 if (SAS_ADDR(phy->attached_sas_addr) ==
388 SAS_ADDR(device->sas_addr)) {
389 sas_dev->attached_phy = phy_no;
390 break;
391 }
392 }
393
394 if (phy_no == phy_num) {
395 dev_info(dev, "dev found: no attached "
396 "dev:%016llx at ex:%016llx\n",
397 SAS_ADDR(device->sas_addr),
398 SAS_ADDR(parent_dev->sas_addr));
399 return -EINVAL;
400 }
401 }
402
403 return 0;
404}
405
701f75ec
JG
406static void hisi_sas_scan_start(struct Scsi_Host *shost)
407{
408 struct hisi_hba *hisi_hba = shost_priv(shost);
409 int i;
410
411 for (i = 0; i < hisi_hba->n_phy; ++i)
412 hisi_sas_bytes_dmaed(hisi_hba, i);
413
414 hisi_hba->scan_finished = 1;
415}
416
417static int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
418{
419 struct hisi_hba *hisi_hba = shost_priv(shost);
420 struct sas_ha_struct *sha = &hisi_hba->sha;
421
422 if (hisi_hba->scan_finished == 0)
423 return 0;
424
425 sas_drain_work(sha);
426 return 1;
427}
428
66139921
JG
429static void hisi_sas_phyup_work(struct work_struct *work)
430{
431 struct hisi_sas_phy *phy =
432 container_of(work, struct hisi_sas_phy, phyup_ws);
433 struct hisi_hba *hisi_hba = phy->hisi_hba;
434 struct asd_sas_phy *sas_phy = &phy->sas_phy;
435 int phy_no = sas_phy->id;
436
437 hisi_hba->hw->sl_notify(hisi_hba, phy_no); /* This requires a sleep */
438 hisi_sas_bytes_dmaed(hisi_hba, phy_no);
439}
976867e6
JG
440
441static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no)
442{
443 struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
444 struct asd_sas_phy *sas_phy = &phy->sas_phy;
445
446 phy->hisi_hba = hisi_hba;
447 phy->port = NULL;
448 init_timer(&phy->timer);
449 sas_phy->enabled = (phy_no < hisi_hba->n_phy) ? 1 : 0;
450 sas_phy->class = SAS;
451 sas_phy->iproto = SAS_PROTOCOL_ALL;
452 sas_phy->tproto = 0;
453 sas_phy->type = PHY_TYPE_PHYSICAL;
454 sas_phy->role = PHY_ROLE_INITIATOR;
455 sas_phy->oob_mode = OOB_NOT_CONNECTED;
456 sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
457 sas_phy->id = phy_no;
458 sas_phy->sas_addr = &hisi_hba->sas_addr[0];
459 sas_phy->frame_rcvd = &phy->frame_rcvd[0];
460 sas_phy->ha = (struct sas_ha_struct *)hisi_hba->shost->hostdata;
461 sas_phy->lldd_phy = phy;
66139921
JG
462
463 INIT_WORK(&phy->phyup_ws, hisi_sas_phyup_work);
976867e6
JG
464}
465
184a4635
JG
466static void hisi_sas_port_notify_formed(struct asd_sas_phy *sas_phy)
467{
468 struct sas_ha_struct *sas_ha = sas_phy->ha;
469 struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
470 struct hisi_sas_phy *phy = sas_phy->lldd_phy;
471 struct asd_sas_port *sas_port = sas_phy->port;
472 struct hisi_sas_port *port = &hisi_hba->port[sas_phy->id];
473 unsigned long flags;
474
475 if (!sas_port)
476 return;
477
478 spin_lock_irqsave(&hisi_hba->lock, flags);
479 port->port_attached = 1;
480 port->id = phy->port_id;
481 phy->port = port;
482 sas_port->lldd_port = port;
483 spin_unlock_irqrestore(&hisi_hba->lock, flags);
484}
485
486static void hisi_sas_do_release_task(struct hisi_hba *hisi_hba, int phy_no,
487 struct domain_device *device)
488{
489 struct hisi_sas_phy *phy;
490 struct hisi_sas_port *port;
491 struct hisi_sas_slot *slot, *slot2;
492 struct device *dev = &hisi_hba->pdev->dev;
493
494 phy = &hisi_hba->phy[phy_no];
495 port = phy->port;
496 if (!port)
497 return;
498
499 list_for_each_entry_safe(slot, slot2, &port->list, entry) {
500 struct sas_task *task;
501
502 task = slot->task;
503 if (device && task->dev != device)
504 continue;
505
506 dev_info(dev, "Release slot [%d:%d], task [%p]:\n",
507 slot->dlvry_queue, slot->dlvry_queue_slot, task);
508 hisi_hba->hw->slot_complete(hisi_hba, slot, 1);
509 }
510}
511
512static void hisi_sas_port_notify_deformed(struct asd_sas_phy *sas_phy)
513{
514 struct domain_device *device;
515 struct hisi_sas_phy *phy = sas_phy->lldd_phy;
516 struct asd_sas_port *sas_port = sas_phy->port;
517
518 list_for_each_entry(device, &sas_port->dev_list, dev_list_node)
519 hisi_sas_do_release_task(phy->hisi_hba, sas_phy->id, device);
520}
521
522static void hisi_sas_release_task(struct hisi_hba *hisi_hba,
523 struct domain_device *device)
524{
525 struct asd_sas_port *port = device->port;
526 struct asd_sas_phy *sas_phy;
527
528 list_for_each_entry(sas_phy, &port->phy_list, port_phy_el)
529 hisi_sas_do_release_task(hisi_hba, sas_phy->id, device);
530}
531
abda97c2
JG
532static void hisi_sas_dev_gone(struct domain_device *device)
533{
534 struct hisi_sas_device *sas_dev = device->lldd_dev;
535 struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
536 struct device *dev = &hisi_hba->pdev->dev;
537 u64 dev_id = sas_dev->device_id;
538
539 dev_info(dev, "found dev[%lld:%x] is gone\n",
540 sas_dev->device_id, sas_dev->dev_type);
541
542 hisi_hba->hw->free_device(hisi_hba, sas_dev);
543 device->lldd_dev = NULL;
544 memset(sas_dev, 0, sizeof(*sas_dev));
545 sas_dev->device_id = dev_id;
546 sas_dev->dev_type = SAS_PHY_UNUSED;
547 sas_dev->dev_status = HISI_SAS_DEV_NORMAL;
548}
42e7a693
JG
549
550static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags)
551{
552 return hisi_sas_task_exec(task, gfp_flags, 0, NULL);
553}
554
184a4635
JG
555
556static void hisi_sas_port_formed(struct asd_sas_phy *sas_phy)
557{
558 hisi_sas_port_notify_formed(sas_phy);
559}
560
561static void hisi_sas_port_deformed(struct asd_sas_phy *sas_phy)
562{
563 hisi_sas_port_notify_deformed(sas_phy);
564}
565
566static void hisi_sas_phy_disconnected(struct hisi_sas_phy *phy)
567{
568 phy->phy_attached = 0;
569 phy->phy_type = 0;
570 phy->port = NULL;
571}
572
573void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy)
574{
575 struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
576 struct asd_sas_phy *sas_phy = &phy->sas_phy;
577 struct sas_ha_struct *sas_ha = &hisi_hba->sha;
578
579 if (rdy) {
580 /* Phy down but ready */
581 hisi_sas_bytes_dmaed(hisi_hba, phy_no);
582 hisi_sas_port_notify_formed(sas_phy);
583 } else {
584 struct hisi_sas_port *port = phy->port;
585
586 /* Phy down and not ready */
587 sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL);
588 sas_phy_disconnected(sas_phy);
589
590 if (port) {
591 if (phy->phy_type & PORT_TYPE_SAS) {
592 int port_id = port->id;
593
594 if (!hisi_hba->hw->get_wideport_bitmap(hisi_hba,
595 port_id))
596 port->port_attached = 0;
597 } else if (phy->phy_type & PORT_TYPE_SATA)
598 port->port_attached = 0;
599 }
600 hisi_sas_phy_disconnected(phy);
601 }
602}
603EXPORT_SYMBOL_GPL(hisi_sas_phy_down);
604
e8899fad
JG
605static struct scsi_transport_template *hisi_sas_stt;
606
7eb7869f
JG
607static struct scsi_host_template hisi_sas_sht = {
608 .module = THIS_MODULE,
609 .name = DRV_NAME,
610 .queuecommand = sas_queuecommand,
611 .target_alloc = sas_target_alloc,
612 .slave_configure = sas_slave_configure,
701f75ec
JG
613 .scan_finished = hisi_sas_scan_finished,
614 .scan_start = hisi_sas_scan_start,
7eb7869f
JG
615 .change_queue_depth = sas_change_queue_depth,
616 .bios_param = sas_bios_param,
617 .can_queue = 1,
618 .this_id = -1,
619 .sg_tablesize = SG_ALL,
620 .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
621 .use_clustering = ENABLE_CLUSTERING,
622 .eh_device_reset_handler = sas_eh_device_reset_handler,
623 .eh_bus_reset_handler = sas_eh_bus_reset_handler,
624 .target_destroy = sas_target_destroy,
625 .ioctl = sas_ioctl,
626};
627
e8899fad 628static struct sas_domain_function_template hisi_sas_transport_ops = {
abda97c2
JG
629 .lldd_dev_found = hisi_sas_dev_found,
630 .lldd_dev_gone = hisi_sas_dev_gone,
42e7a693 631 .lldd_execute_task = hisi_sas_queue_command,
184a4635
JG
632 .lldd_port_formed = hisi_sas_port_formed,
633 .lldd_port_deformed = hisi_sas_port_deformed,
e8899fad
JG
634};
635
6be6de18
JG
636static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
637{
638 int i, s;
639 struct platform_device *pdev = hisi_hba->pdev;
640 struct device *dev = &pdev->dev;
641
fa42d80d 642 spin_lock_init(&hisi_hba->lock);
976867e6
JG
643 for (i = 0; i < hisi_hba->n_phy; i++) {
644 hisi_sas_phy_init(hisi_hba, i);
645 hisi_hba->port[i].port_attached = 0;
646 hisi_hba->port[i].id = -1;
647 INIT_LIST_HEAD(&hisi_hba->port[i].list);
648 }
649
af740dbe
JG
650 for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
651 hisi_hba->devices[i].dev_type = SAS_PHY_UNUSED;
652 hisi_hba->devices[i].device_id = i;
653 hisi_hba->devices[i].dev_status = HISI_SAS_DEV_NORMAL;
654 }
655
6be6de18 656 for (i = 0; i < hisi_hba->queue_count; i++) {
9101a079
JG
657 struct hisi_sas_cq *cq = &hisi_hba->cq[i];
658
659 /* Completion queue structure */
660 cq->id = i;
661 cq->hisi_hba = hisi_hba;
662
6be6de18
JG
663 /* Delivery queue */
664 s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
665 hisi_hba->cmd_hdr[i] = dma_alloc_coherent(dev, s,
666 &hisi_hba->cmd_hdr_dma[i], GFP_KERNEL);
667 if (!hisi_hba->cmd_hdr[i])
668 goto err_out;
669 memset(hisi_hba->cmd_hdr[i], 0, s);
670
671 /* Completion queue */
672 s = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
673 hisi_hba->complete_hdr[i] = dma_alloc_coherent(dev, s,
674 &hisi_hba->complete_hdr_dma[i], GFP_KERNEL);
675 if (!hisi_hba->complete_hdr[i])
676 goto err_out;
677 memset(hisi_hba->complete_hdr[i], 0, s);
678 }
679
680 s = HISI_SAS_STATUS_BUF_SZ;
681 hisi_hba->status_buffer_pool = dma_pool_create("status_buffer",
682 dev, s, 16, 0);
683 if (!hisi_hba->status_buffer_pool)
684 goto err_out;
685
686 s = HISI_SAS_COMMAND_TABLE_SZ;
687 hisi_hba->command_table_pool = dma_pool_create("command_table",
688 dev, s, 16, 0);
689 if (!hisi_hba->command_table_pool)
690 goto err_out;
691
692 s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
693 hisi_hba->itct = dma_alloc_coherent(dev, s, &hisi_hba->itct_dma,
694 GFP_KERNEL);
695 if (!hisi_hba->itct)
696 goto err_out;
697
698 memset(hisi_hba->itct, 0, s);
699
700 hisi_hba->slot_info = devm_kcalloc(dev, HISI_SAS_COMMAND_ENTRIES,
701 sizeof(struct hisi_sas_slot),
702 GFP_KERNEL);
703 if (!hisi_hba->slot_info)
704 goto err_out;
705
706 s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_iost);
707 hisi_hba->iost = dma_alloc_coherent(dev, s, &hisi_hba->iost_dma,
708 GFP_KERNEL);
709 if (!hisi_hba->iost)
710 goto err_out;
711
712 memset(hisi_hba->iost, 0, s);
713
714 s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint);
715 hisi_hba->breakpoint = dma_alloc_coherent(dev, s,
716 &hisi_hba->breakpoint_dma, GFP_KERNEL);
717 if (!hisi_hba->breakpoint)
718 goto err_out;
719
720 memset(hisi_hba->breakpoint, 0, s);
721
257efd1f
JG
722 hisi_hba->slot_index_count = HISI_SAS_COMMAND_ENTRIES;
723 s = hisi_hba->slot_index_count / sizeof(unsigned long);
724 hisi_hba->slot_index_tags = devm_kzalloc(dev, s, GFP_KERNEL);
725 if (!hisi_hba->slot_index_tags)
726 goto err_out;
727
6be6de18
JG
728 hisi_hba->sge_page_pool = dma_pool_create("status_sge", dev,
729 sizeof(struct hisi_sas_sge_page), 16, 0);
730 if (!hisi_hba->sge_page_pool)
731 goto err_out;
732
733 s = sizeof(struct hisi_sas_initial_fis) * HISI_SAS_MAX_PHYS;
734 hisi_hba->initial_fis = dma_alloc_coherent(dev, s,
735 &hisi_hba->initial_fis_dma, GFP_KERNEL);
736 if (!hisi_hba->initial_fis)
737 goto err_out;
738 memset(hisi_hba->initial_fis, 0, s);
739
740 s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint) * 2;
741 hisi_hba->sata_breakpoint = dma_alloc_coherent(dev, s,
742 &hisi_hba->sata_breakpoint_dma, GFP_KERNEL);
743 if (!hisi_hba->sata_breakpoint)
744 goto err_out;
745 memset(hisi_hba->sata_breakpoint, 0, s);
746
257efd1f
JG
747 hisi_sas_slot_index_init(hisi_hba);
748
7e9080e1
JG
749 hisi_hba->wq = create_singlethread_workqueue(dev_name(dev));
750 if (!hisi_hba->wq) {
751 dev_err(dev, "sas_alloc: failed to create workqueue\n");
752 goto err_out;
753 }
754
6be6de18
JG
755 return 0;
756err_out:
757 return -ENOMEM;
758}
759
89d53322
JG
760static void hisi_sas_free(struct hisi_hba *hisi_hba)
761{
762 struct device *dev = &hisi_hba->pdev->dev;
763 int i, s;
764
765 for (i = 0; i < hisi_hba->queue_count; i++) {
766 s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
767 if (hisi_hba->cmd_hdr[i])
768 dma_free_coherent(dev, s,
769 hisi_hba->cmd_hdr[i],
770 hisi_hba->cmd_hdr_dma[i]);
771
772 s = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
773 if (hisi_hba->complete_hdr[i])
774 dma_free_coherent(dev, s,
775 hisi_hba->complete_hdr[i],
776 hisi_hba->complete_hdr_dma[i]);
777 }
778
779 dma_pool_destroy(hisi_hba->status_buffer_pool);
780 dma_pool_destroy(hisi_hba->command_table_pool);
781 dma_pool_destroy(hisi_hba->sge_page_pool);
782
783 s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
784 if (hisi_hba->itct)
785 dma_free_coherent(dev, s,
786 hisi_hba->itct, hisi_hba->itct_dma);
787
788 s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_iost);
789 if (hisi_hba->iost)
790 dma_free_coherent(dev, s,
791 hisi_hba->iost, hisi_hba->iost_dma);
792
793 s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint);
794 if (hisi_hba->breakpoint)
795 dma_free_coherent(dev, s,
796 hisi_hba->breakpoint,
797 hisi_hba->breakpoint_dma);
798
799
800 s = sizeof(struct hisi_sas_initial_fis) * HISI_SAS_MAX_PHYS;
801 if (hisi_hba->initial_fis)
802 dma_free_coherent(dev, s,
803 hisi_hba->initial_fis,
804 hisi_hba->initial_fis_dma);
805
806 s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint) * 2;
807 if (hisi_hba->sata_breakpoint)
808 dma_free_coherent(dev, s,
809 hisi_hba->sata_breakpoint,
810 hisi_hba->sata_breakpoint_dma);
811
7e9080e1
JG
812 if (hisi_hba->wq)
813 destroy_workqueue(hisi_hba->wq);
89d53322 814}
6be6de18 815
7eb7869f
JG
816static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
817 const struct hisi_sas_hw *hw)
818{
e26b2f40 819 struct resource *res;
7eb7869f
JG
820 struct Scsi_Host *shost;
821 struct hisi_hba *hisi_hba;
822 struct device *dev = &pdev->dev;
e26b2f40
JG
823 struct device_node *np = pdev->dev.of_node;
824 struct property *sas_addr_prop;
825 int num;
7eb7869f
JG
826
827 shost = scsi_host_alloc(&hisi_sas_sht, sizeof(*hisi_hba));
828 if (!shost)
829 goto err_out;
830 hisi_hba = shost_priv(shost);
831
832 hisi_hba->hw = hw;
833 hisi_hba->pdev = pdev;
834 hisi_hba->shost = shost;
835 SHOST_TO_SAS_HA(shost) = &hisi_hba->sha;
836
fa42d80d
JG
837 init_timer(&hisi_hba->timer);
838
e26b2f40
JG
839 sas_addr_prop = of_find_property(np, "sas-addr", NULL);
840 if (!sas_addr_prop || (sas_addr_prop->length != SAS_ADDR_SIZE))
841 goto err_out;
842 memcpy(hisi_hba->sas_addr, sas_addr_prop->value, SAS_ADDR_SIZE);
843
844 if (of_property_read_u32(np, "ctrl-reset-reg",
845 &hisi_hba->ctrl_reset_reg))
846 goto err_out;
847
848 if (of_property_read_u32(np, "ctrl-reset-sts-reg",
849 &hisi_hba->ctrl_reset_sts_reg))
850 goto err_out;
851
852 if (of_property_read_u32(np, "ctrl-clock-ena-reg",
853 &hisi_hba->ctrl_clock_ena_reg))
854 goto err_out;
855
856 if (of_property_read_u32(np, "phy-count", &hisi_hba->n_phy))
857 goto err_out;
858
859 if (of_property_read_u32(np, "queue-count", &hisi_hba->queue_count))
860 goto err_out;
861
862 num = of_irq_count(np);
863 hisi_hba->int_names = devm_kcalloc(dev, num,
864 HISI_SAS_NAME_LEN,
865 GFP_KERNEL);
866 if (!hisi_hba->int_names)
867 goto err_out;
868
869 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
870 hisi_hba->regs = devm_ioremap_resource(dev, res);
871 if (IS_ERR(hisi_hba->regs))
872 goto err_out;
873
874 hisi_hba->ctrl = syscon_regmap_lookup_by_phandle(
875 np, "hisilicon,sas-syscon");
876 if (IS_ERR(hisi_hba->ctrl))
877 goto err_out;
878
89d53322
JG
879 if (hisi_sas_alloc(hisi_hba, shost)) {
880 hisi_sas_free(hisi_hba);
6be6de18 881 goto err_out;
89d53322 882 }
6be6de18 883
7eb7869f
JG
884 return shost;
885err_out:
886 dev_err(dev, "shost alloc failed\n");
887 return NULL;
888}
889
5d74242e
JG
890static void hisi_sas_init_add(struct hisi_hba *hisi_hba)
891{
892 int i;
893
894 for (i = 0; i < hisi_hba->n_phy; i++)
895 memcpy(&hisi_hba->phy[i].dev_sas_addr,
896 hisi_hba->sas_addr,
897 SAS_ADDR_SIZE);
898}
899
7eb7869f
JG
900int hisi_sas_probe(struct platform_device *pdev,
901 const struct hisi_sas_hw *hw)
902{
903 struct Scsi_Host *shost;
904 struct hisi_hba *hisi_hba;
905 struct device *dev = &pdev->dev;
906 struct asd_sas_phy **arr_phy;
907 struct asd_sas_port **arr_port;
908 struct sas_ha_struct *sha;
909 int rc, phy_nr, port_nr, i;
910
911 shost = hisi_sas_shost_alloc(pdev, hw);
912 if (!shost) {
913 rc = -ENOMEM;
914 goto err_out_ha;
915 }
916
917 sha = SHOST_TO_SAS_HA(shost);
918 hisi_hba = shost_priv(shost);
919 platform_set_drvdata(pdev, sha);
50cb916f
JG
920
921 if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) &&
922 dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
923 dev_err(dev, "No usable DMA addressing method\n");
924 rc = -EIO;
925 goto err_out_ha;
926 }
927
7eb7869f
JG
928 phy_nr = port_nr = hisi_hba->n_phy;
929
930 arr_phy = devm_kcalloc(dev, phy_nr, sizeof(void *), GFP_KERNEL);
931 arr_port = devm_kcalloc(dev, port_nr, sizeof(void *), GFP_KERNEL);
932 if (!arr_phy || !arr_port)
933 return -ENOMEM;
934
935 sha->sas_phy = arr_phy;
936 sha->sas_port = arr_port;
937 sha->core.shost = shost;
938 sha->lldd_ha = hisi_hba;
939
940 shost->transportt = hisi_sas_stt;
941 shost->max_id = HISI_SAS_MAX_DEVICES;
942 shost->max_lun = ~0;
943 shost->max_channel = 1;
944 shost->max_cmd_len = 16;
945 shost->sg_tablesize = min_t(u16, SG_ALL, HISI_SAS_SGE_PAGE_CNT);
946 shost->can_queue = HISI_SAS_COMMAND_ENTRIES;
947 shost->cmd_per_lun = HISI_SAS_COMMAND_ENTRIES;
948
949 sha->sas_ha_name = DRV_NAME;
950 sha->dev = &hisi_hba->pdev->dev;
951 sha->lldd_module = THIS_MODULE;
952 sha->sas_addr = &hisi_hba->sas_addr[0];
953 sha->num_phys = hisi_hba->n_phy;
954 sha->core.shost = hisi_hba->shost;
955
956 for (i = 0; i < hisi_hba->n_phy; i++) {
957 sha->sas_phy[i] = &hisi_hba->phy[i].sas_phy;
958 sha->sas_port[i] = &hisi_hba->port[i].sas_port;
959 }
960
5d74242e
JG
961 hisi_sas_init_add(hisi_hba);
962
8ff1d571
JG
963 rc = hisi_hba->hw->hw_init(hisi_hba);
964 if (rc)
965 goto err_out_ha;
966
7eb7869f
JG
967 rc = scsi_add_host(shost, &pdev->dev);
968 if (rc)
969 goto err_out_ha;
970
971 rc = sas_register_ha(sha);
972 if (rc)
973 goto err_out_register_ha;
974
975 scsi_scan_host(shost);
976
977 return 0;
978
979err_out_register_ha:
980 scsi_remove_host(shost);
981err_out_ha:
982 kfree(shost);
983 return rc;
984}
985EXPORT_SYMBOL_GPL(hisi_sas_probe);
986
89d53322
JG
987int hisi_sas_remove(struct platform_device *pdev)
988{
989 struct sas_ha_struct *sha = platform_get_drvdata(pdev);
990 struct hisi_hba *hisi_hba = sha->lldd_ha;
991
992 scsi_remove_host(sha->core.shost);
993 sas_unregister_ha(sha);
994 sas_remove_host(sha->core.shost);
995
996 hisi_sas_free(hisi_hba);
997 return 0;
998}
999EXPORT_SYMBOL_GPL(hisi_sas_remove);
1000
e8899fad
JG
1001static __init int hisi_sas_init(void)
1002{
1003 pr_info("hisi_sas: driver version %s\n", DRV_VERSION);
1004
1005 hisi_sas_stt = sas_domain_attach_transport(&hisi_sas_transport_ops);
1006 if (!hisi_sas_stt)
1007 return -ENOMEM;
1008
1009 return 0;
1010}
1011
1012static __exit void hisi_sas_exit(void)
1013{
1014 sas_release_transport(hisi_sas_stt);
1015}
1016
1017module_init(hisi_sas_init);
1018module_exit(hisi_sas_exit);
1019
1020MODULE_VERSION(DRV_VERSION);
1021MODULE_LICENSE("GPL");
1022MODULE_AUTHOR("John Garry <john.garry@huawei.com>");
1023MODULE_DESCRIPTION("HISILICON SAS controller driver");
1024MODULE_ALIAS("platform:" DRV_NAME);