blob: 406ffa08fc1aac0b7d01e8451e2af960d7753a0d [file] [log] [blame]
John Garrye8899fa2015-11-18 00:50:30 +08001/*
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
John Garryabda97c2015-11-18 00:50:51 +080015#define DEV_IS_EXPANDER(type) \
16 ((type == SAS_EDGE_EXPANDER_DEVICE) || \
17 (type == SAS_FANOUT_EXPANDER_DEVICE))
John Garry42e7a692015-11-18 00:50:49 +080018
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
John Garry257efd12015-11-18 00:50:36 +080027static 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
John Garry42e7a692015-11-18 00:50:49 +080034static 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
John Garry257efd12015-11-18 00:50:36 +080059static 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}
John Garry27a3f222015-11-18 00:50:50 +080066
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
John Garry66ee9992015-11-18 00:50:54 +0800101static 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
John Garry42e7a692015-11-18 00:50:49 +0800107static 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) {
John Garry66ee9992015-11-18 00:50:54 +0800224 case SAS_PROTOCOL_SMP:
225 rc = hisi_sas_task_prep_smp(hisi_hba, slot);
226 break;
John Garry42e7a692015-11-18 00:50:49 +0800227 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}
John Garry257efd12015-11-18 00:50:36 +0800303
John Garry66139922015-11-18 00:50:48 +0800304static 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
John Garryabda97c2015-11-18 00:50:51 +0800340static 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
John Garry66139922015-11-18 00:50:48 +0800406static void hisi_sas_phyup_work(struct work_struct *work)
407{
408 struct hisi_sas_phy *phy =
409 container_of(work, struct hisi_sas_phy, phyup_ws);
410 struct hisi_hba *hisi_hba = phy->hisi_hba;
411 struct asd_sas_phy *sas_phy = &phy->sas_phy;
412 int phy_no = sas_phy->id;
413
414 hisi_hba->hw->sl_notify(hisi_hba, phy_no); /* This requires a sleep */
415 hisi_sas_bytes_dmaed(hisi_hba, phy_no);
416}
John Garry976867e2015-11-18 00:50:42 +0800417
418static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no)
419{
420 struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
421 struct asd_sas_phy *sas_phy = &phy->sas_phy;
422
423 phy->hisi_hba = hisi_hba;
424 phy->port = NULL;
425 init_timer(&phy->timer);
426 sas_phy->enabled = (phy_no < hisi_hba->n_phy) ? 1 : 0;
427 sas_phy->class = SAS;
428 sas_phy->iproto = SAS_PROTOCOL_ALL;
429 sas_phy->tproto = 0;
430 sas_phy->type = PHY_TYPE_PHYSICAL;
431 sas_phy->role = PHY_ROLE_INITIATOR;
432 sas_phy->oob_mode = OOB_NOT_CONNECTED;
433 sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
434 sas_phy->id = phy_no;
435 sas_phy->sas_addr = &hisi_hba->sas_addr[0];
436 sas_phy->frame_rcvd = &phy->frame_rcvd[0];
437 sas_phy->ha = (struct sas_ha_struct *)hisi_hba->shost->hostdata;
438 sas_phy->lldd_phy = phy;
John Garry66139922015-11-18 00:50:48 +0800439
440 INIT_WORK(&phy->phyup_ws, hisi_sas_phyup_work);
John Garry976867e2015-11-18 00:50:42 +0800441}
442
John Garry184a4632015-11-18 00:50:52 +0800443static void hisi_sas_port_notify_formed(struct asd_sas_phy *sas_phy)
444{
445 struct sas_ha_struct *sas_ha = sas_phy->ha;
446 struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
447 struct hisi_sas_phy *phy = sas_phy->lldd_phy;
448 struct asd_sas_port *sas_port = sas_phy->port;
449 struct hisi_sas_port *port = &hisi_hba->port[sas_phy->id];
450 unsigned long flags;
451
452 if (!sas_port)
453 return;
454
455 spin_lock_irqsave(&hisi_hba->lock, flags);
456 port->port_attached = 1;
457 port->id = phy->port_id;
458 phy->port = port;
459 sas_port->lldd_port = port;
460 spin_unlock_irqrestore(&hisi_hba->lock, flags);
461}
462
463static void hisi_sas_do_release_task(struct hisi_hba *hisi_hba, int phy_no,
464 struct domain_device *device)
465{
466 struct hisi_sas_phy *phy;
467 struct hisi_sas_port *port;
468 struct hisi_sas_slot *slot, *slot2;
469 struct device *dev = &hisi_hba->pdev->dev;
470
471 phy = &hisi_hba->phy[phy_no];
472 port = phy->port;
473 if (!port)
474 return;
475
476 list_for_each_entry_safe(slot, slot2, &port->list, entry) {
477 struct sas_task *task;
478
479 task = slot->task;
480 if (device && task->dev != device)
481 continue;
482
483 dev_info(dev, "Release slot [%d:%d], task [%p]:\n",
484 slot->dlvry_queue, slot->dlvry_queue_slot, task);
485 hisi_hba->hw->slot_complete(hisi_hba, slot, 1);
486 }
487}
488
489static void hisi_sas_port_notify_deformed(struct asd_sas_phy *sas_phy)
490{
491 struct domain_device *device;
492 struct hisi_sas_phy *phy = sas_phy->lldd_phy;
493 struct asd_sas_port *sas_port = sas_phy->port;
494
495 list_for_each_entry(device, &sas_port->dev_list, dev_list_node)
496 hisi_sas_do_release_task(phy->hisi_hba, sas_phy->id, device);
497}
498
499static void hisi_sas_release_task(struct hisi_hba *hisi_hba,
500 struct domain_device *device)
501{
502 struct asd_sas_port *port = device->port;
503 struct asd_sas_phy *sas_phy;
504
505 list_for_each_entry(sas_phy, &port->phy_list, port_phy_el)
506 hisi_sas_do_release_task(hisi_hba, sas_phy->id, device);
507}
508
John Garryabda97c2015-11-18 00:50:51 +0800509static void hisi_sas_dev_gone(struct domain_device *device)
510{
511 struct hisi_sas_device *sas_dev = device->lldd_dev;
512 struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
513 struct device *dev = &hisi_hba->pdev->dev;
514 u64 dev_id = sas_dev->device_id;
515
516 dev_info(dev, "found dev[%lld:%x] is gone\n",
517 sas_dev->device_id, sas_dev->dev_type);
518
519 hisi_hba->hw->free_device(hisi_hba, sas_dev);
520 device->lldd_dev = NULL;
521 memset(sas_dev, 0, sizeof(*sas_dev));
522 sas_dev->device_id = dev_id;
523 sas_dev->dev_type = SAS_PHY_UNUSED;
524 sas_dev->dev_status = HISI_SAS_DEV_NORMAL;
525}
John Garry42e7a692015-11-18 00:50:49 +0800526
527static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags)
528{
529 return hisi_sas_task_exec(task, gfp_flags, 0, NULL);
530}
531
John Garry184a4632015-11-18 00:50:52 +0800532
533static void hisi_sas_port_formed(struct asd_sas_phy *sas_phy)
534{
535 hisi_sas_port_notify_formed(sas_phy);
536}
537
538static void hisi_sas_port_deformed(struct asd_sas_phy *sas_phy)
539{
540 hisi_sas_port_notify_deformed(sas_phy);
541}
542
543static void hisi_sas_phy_disconnected(struct hisi_sas_phy *phy)
544{
545 phy->phy_attached = 0;
546 phy->phy_type = 0;
547 phy->port = NULL;
548}
549
550void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy)
551{
552 struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
553 struct asd_sas_phy *sas_phy = &phy->sas_phy;
554 struct sas_ha_struct *sas_ha = &hisi_hba->sha;
555
556 if (rdy) {
557 /* Phy down but ready */
558 hisi_sas_bytes_dmaed(hisi_hba, phy_no);
559 hisi_sas_port_notify_formed(sas_phy);
560 } else {
561 struct hisi_sas_port *port = phy->port;
562
563 /* Phy down and not ready */
564 sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL);
565 sas_phy_disconnected(sas_phy);
566
567 if (port) {
568 if (phy->phy_type & PORT_TYPE_SAS) {
569 int port_id = port->id;
570
571 if (!hisi_hba->hw->get_wideport_bitmap(hisi_hba,
572 port_id))
573 port->port_attached = 0;
574 } else if (phy->phy_type & PORT_TYPE_SATA)
575 port->port_attached = 0;
576 }
577 hisi_sas_phy_disconnected(phy);
578 }
579}
580EXPORT_SYMBOL_GPL(hisi_sas_phy_down);
581
John Garrye8899fa2015-11-18 00:50:30 +0800582static struct scsi_transport_template *hisi_sas_stt;
583
John Garry7eb78692015-11-18 00:50:31 +0800584static struct scsi_host_template hisi_sas_sht = {
585 .module = THIS_MODULE,
586 .name = DRV_NAME,
587 .queuecommand = sas_queuecommand,
588 .target_alloc = sas_target_alloc,
589 .slave_configure = sas_slave_configure,
590 .change_queue_depth = sas_change_queue_depth,
591 .bios_param = sas_bios_param,
592 .can_queue = 1,
593 .this_id = -1,
594 .sg_tablesize = SG_ALL,
595 .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
596 .use_clustering = ENABLE_CLUSTERING,
597 .eh_device_reset_handler = sas_eh_device_reset_handler,
598 .eh_bus_reset_handler = sas_eh_bus_reset_handler,
599 .target_destroy = sas_target_destroy,
600 .ioctl = sas_ioctl,
601};
602
John Garrye8899fa2015-11-18 00:50:30 +0800603static struct sas_domain_function_template hisi_sas_transport_ops = {
John Garryabda97c2015-11-18 00:50:51 +0800604 .lldd_dev_found = hisi_sas_dev_found,
605 .lldd_dev_gone = hisi_sas_dev_gone,
John Garry42e7a692015-11-18 00:50:49 +0800606 .lldd_execute_task = hisi_sas_queue_command,
John Garry184a4632015-11-18 00:50:52 +0800607 .lldd_port_formed = hisi_sas_port_formed,
608 .lldd_port_deformed = hisi_sas_port_deformed,
John Garrye8899fa2015-11-18 00:50:30 +0800609};
610
John Garry6be6de12015-11-18 00:50:34 +0800611static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
612{
613 int i, s;
614 struct platform_device *pdev = hisi_hba->pdev;
615 struct device *dev = &pdev->dev;
616
John Garryfa42d802015-11-18 00:50:43 +0800617 spin_lock_init(&hisi_hba->lock);
John Garry976867e2015-11-18 00:50:42 +0800618 for (i = 0; i < hisi_hba->n_phy; i++) {
619 hisi_sas_phy_init(hisi_hba, i);
620 hisi_hba->port[i].port_attached = 0;
621 hisi_hba->port[i].id = -1;
622 INIT_LIST_HEAD(&hisi_hba->port[i].list);
623 }
624
John Garryaf740db2015-11-18 00:50:41 +0800625 for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
626 hisi_hba->devices[i].dev_type = SAS_PHY_UNUSED;
627 hisi_hba->devices[i].device_id = i;
628 hisi_hba->devices[i].dev_status = HISI_SAS_DEV_NORMAL;
629 }
630
John Garry6be6de12015-11-18 00:50:34 +0800631 for (i = 0; i < hisi_hba->queue_count; i++) {
John Garry9101a072015-11-18 00:50:37 +0800632 struct hisi_sas_cq *cq = &hisi_hba->cq[i];
633
634 /* Completion queue structure */
635 cq->id = i;
636 cq->hisi_hba = hisi_hba;
637
John Garry6be6de12015-11-18 00:50:34 +0800638 /* Delivery queue */
639 s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
640 hisi_hba->cmd_hdr[i] = dma_alloc_coherent(dev, s,
641 &hisi_hba->cmd_hdr_dma[i], GFP_KERNEL);
642 if (!hisi_hba->cmd_hdr[i])
643 goto err_out;
644 memset(hisi_hba->cmd_hdr[i], 0, s);
645
646 /* Completion queue */
647 s = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
648 hisi_hba->complete_hdr[i] = dma_alloc_coherent(dev, s,
649 &hisi_hba->complete_hdr_dma[i], GFP_KERNEL);
650 if (!hisi_hba->complete_hdr[i])
651 goto err_out;
652 memset(hisi_hba->complete_hdr[i], 0, s);
653 }
654
655 s = HISI_SAS_STATUS_BUF_SZ;
656 hisi_hba->status_buffer_pool = dma_pool_create("status_buffer",
657 dev, s, 16, 0);
658 if (!hisi_hba->status_buffer_pool)
659 goto err_out;
660
661 s = HISI_SAS_COMMAND_TABLE_SZ;
662 hisi_hba->command_table_pool = dma_pool_create("command_table",
663 dev, s, 16, 0);
664 if (!hisi_hba->command_table_pool)
665 goto err_out;
666
667 s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
668 hisi_hba->itct = dma_alloc_coherent(dev, s, &hisi_hba->itct_dma,
669 GFP_KERNEL);
670 if (!hisi_hba->itct)
671 goto err_out;
672
673 memset(hisi_hba->itct, 0, s);
674
675 hisi_hba->slot_info = devm_kcalloc(dev, HISI_SAS_COMMAND_ENTRIES,
676 sizeof(struct hisi_sas_slot),
677 GFP_KERNEL);
678 if (!hisi_hba->slot_info)
679 goto err_out;
680
681 s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_iost);
682 hisi_hba->iost = dma_alloc_coherent(dev, s, &hisi_hba->iost_dma,
683 GFP_KERNEL);
684 if (!hisi_hba->iost)
685 goto err_out;
686
687 memset(hisi_hba->iost, 0, s);
688
689 s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint);
690 hisi_hba->breakpoint = dma_alloc_coherent(dev, s,
691 &hisi_hba->breakpoint_dma, GFP_KERNEL);
692 if (!hisi_hba->breakpoint)
693 goto err_out;
694
695 memset(hisi_hba->breakpoint, 0, s);
696
John Garry257efd12015-11-18 00:50:36 +0800697 hisi_hba->slot_index_count = HISI_SAS_COMMAND_ENTRIES;
698 s = hisi_hba->slot_index_count / sizeof(unsigned long);
699 hisi_hba->slot_index_tags = devm_kzalloc(dev, s, GFP_KERNEL);
700 if (!hisi_hba->slot_index_tags)
701 goto err_out;
702
John Garry6be6de12015-11-18 00:50:34 +0800703 hisi_hba->sge_page_pool = dma_pool_create("status_sge", dev,
704 sizeof(struct hisi_sas_sge_page), 16, 0);
705 if (!hisi_hba->sge_page_pool)
706 goto err_out;
707
708 s = sizeof(struct hisi_sas_initial_fis) * HISI_SAS_MAX_PHYS;
709 hisi_hba->initial_fis = dma_alloc_coherent(dev, s,
710 &hisi_hba->initial_fis_dma, GFP_KERNEL);
711 if (!hisi_hba->initial_fis)
712 goto err_out;
713 memset(hisi_hba->initial_fis, 0, s);
714
715 s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint) * 2;
716 hisi_hba->sata_breakpoint = dma_alloc_coherent(dev, s,
717 &hisi_hba->sata_breakpoint_dma, GFP_KERNEL);
718 if (!hisi_hba->sata_breakpoint)
719 goto err_out;
720 memset(hisi_hba->sata_breakpoint, 0, s);
721
John Garry257efd12015-11-18 00:50:36 +0800722 hisi_sas_slot_index_init(hisi_hba);
723
John Garry7e9080e2015-11-18 00:50:40 +0800724 hisi_hba->wq = create_singlethread_workqueue(dev_name(dev));
725 if (!hisi_hba->wq) {
726 dev_err(dev, "sas_alloc: failed to create workqueue\n");
727 goto err_out;
728 }
729
John Garry6be6de12015-11-18 00:50:34 +0800730 return 0;
731err_out:
732 return -ENOMEM;
733}
734
John Garry89d53322015-11-18 00:50:35 +0800735static void hisi_sas_free(struct hisi_hba *hisi_hba)
736{
737 struct device *dev = &hisi_hba->pdev->dev;
738 int i, s;
739
740 for (i = 0; i < hisi_hba->queue_count; i++) {
741 s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
742 if (hisi_hba->cmd_hdr[i])
743 dma_free_coherent(dev, s,
744 hisi_hba->cmd_hdr[i],
745 hisi_hba->cmd_hdr_dma[i]);
746
747 s = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
748 if (hisi_hba->complete_hdr[i])
749 dma_free_coherent(dev, s,
750 hisi_hba->complete_hdr[i],
751 hisi_hba->complete_hdr_dma[i]);
752 }
753
754 dma_pool_destroy(hisi_hba->status_buffer_pool);
755 dma_pool_destroy(hisi_hba->command_table_pool);
756 dma_pool_destroy(hisi_hba->sge_page_pool);
757
758 s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
759 if (hisi_hba->itct)
760 dma_free_coherent(dev, s,
761 hisi_hba->itct, hisi_hba->itct_dma);
762
763 s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_iost);
764 if (hisi_hba->iost)
765 dma_free_coherent(dev, s,
766 hisi_hba->iost, hisi_hba->iost_dma);
767
768 s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint);
769 if (hisi_hba->breakpoint)
770 dma_free_coherent(dev, s,
771 hisi_hba->breakpoint,
772 hisi_hba->breakpoint_dma);
773
774
775 s = sizeof(struct hisi_sas_initial_fis) * HISI_SAS_MAX_PHYS;
776 if (hisi_hba->initial_fis)
777 dma_free_coherent(dev, s,
778 hisi_hba->initial_fis,
779 hisi_hba->initial_fis_dma);
780
781 s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint) * 2;
782 if (hisi_hba->sata_breakpoint)
783 dma_free_coherent(dev, s,
784 hisi_hba->sata_breakpoint,
785 hisi_hba->sata_breakpoint_dma);
786
John Garry7e9080e2015-11-18 00:50:40 +0800787 if (hisi_hba->wq)
788 destroy_workqueue(hisi_hba->wq);
John Garry89d53322015-11-18 00:50:35 +0800789}
John Garry6be6de12015-11-18 00:50:34 +0800790
John Garry7eb78692015-11-18 00:50:31 +0800791static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
792 const struct hisi_sas_hw *hw)
793{
John Garrye26b2f42015-11-18 00:50:32 +0800794 struct resource *res;
John Garry7eb78692015-11-18 00:50:31 +0800795 struct Scsi_Host *shost;
796 struct hisi_hba *hisi_hba;
797 struct device *dev = &pdev->dev;
John Garrye26b2f42015-11-18 00:50:32 +0800798 struct device_node *np = pdev->dev.of_node;
799 struct property *sas_addr_prop;
800 int num;
John Garry7eb78692015-11-18 00:50:31 +0800801
802 shost = scsi_host_alloc(&hisi_sas_sht, sizeof(*hisi_hba));
803 if (!shost)
804 goto err_out;
805 hisi_hba = shost_priv(shost);
806
807 hisi_hba->hw = hw;
808 hisi_hba->pdev = pdev;
809 hisi_hba->shost = shost;
810 SHOST_TO_SAS_HA(shost) = &hisi_hba->sha;
811
John Garryfa42d802015-11-18 00:50:43 +0800812 init_timer(&hisi_hba->timer);
813
John Garrye26b2f42015-11-18 00:50:32 +0800814 sas_addr_prop = of_find_property(np, "sas-addr", NULL);
815 if (!sas_addr_prop || (sas_addr_prop->length != SAS_ADDR_SIZE))
816 goto err_out;
817 memcpy(hisi_hba->sas_addr, sas_addr_prop->value, SAS_ADDR_SIZE);
818
819 if (of_property_read_u32(np, "ctrl-reset-reg",
820 &hisi_hba->ctrl_reset_reg))
821 goto err_out;
822
823 if (of_property_read_u32(np, "ctrl-reset-sts-reg",
824 &hisi_hba->ctrl_reset_sts_reg))
825 goto err_out;
826
827 if (of_property_read_u32(np, "ctrl-clock-ena-reg",
828 &hisi_hba->ctrl_clock_ena_reg))
829 goto err_out;
830
831 if (of_property_read_u32(np, "phy-count", &hisi_hba->n_phy))
832 goto err_out;
833
834 if (of_property_read_u32(np, "queue-count", &hisi_hba->queue_count))
835 goto err_out;
836
837 num = of_irq_count(np);
838 hisi_hba->int_names = devm_kcalloc(dev, num,
839 HISI_SAS_NAME_LEN,
840 GFP_KERNEL);
841 if (!hisi_hba->int_names)
842 goto err_out;
843
844 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
845 hisi_hba->regs = devm_ioremap_resource(dev, res);
846 if (IS_ERR(hisi_hba->regs))
847 goto err_out;
848
849 hisi_hba->ctrl = syscon_regmap_lookup_by_phandle(
850 np, "hisilicon,sas-syscon");
851 if (IS_ERR(hisi_hba->ctrl))
852 goto err_out;
853
John Garry89d53322015-11-18 00:50:35 +0800854 if (hisi_sas_alloc(hisi_hba, shost)) {
855 hisi_sas_free(hisi_hba);
John Garry6be6de12015-11-18 00:50:34 +0800856 goto err_out;
John Garry89d53322015-11-18 00:50:35 +0800857 }
John Garry6be6de12015-11-18 00:50:34 +0800858
John Garry7eb78692015-11-18 00:50:31 +0800859 return shost;
860err_out:
861 dev_err(dev, "shost alloc failed\n");
862 return NULL;
863}
864
John Garry5d742422015-11-18 00:50:38 +0800865static void hisi_sas_init_add(struct hisi_hba *hisi_hba)
866{
867 int i;
868
869 for (i = 0; i < hisi_hba->n_phy; i++)
870 memcpy(&hisi_hba->phy[i].dev_sas_addr,
871 hisi_hba->sas_addr,
872 SAS_ADDR_SIZE);
873}
874
John Garry7eb78692015-11-18 00:50:31 +0800875int hisi_sas_probe(struct platform_device *pdev,
876 const struct hisi_sas_hw *hw)
877{
878 struct Scsi_Host *shost;
879 struct hisi_hba *hisi_hba;
880 struct device *dev = &pdev->dev;
881 struct asd_sas_phy **arr_phy;
882 struct asd_sas_port **arr_port;
883 struct sas_ha_struct *sha;
884 int rc, phy_nr, port_nr, i;
885
886 shost = hisi_sas_shost_alloc(pdev, hw);
887 if (!shost) {
888 rc = -ENOMEM;
889 goto err_out_ha;
890 }
891
892 sha = SHOST_TO_SAS_HA(shost);
893 hisi_hba = shost_priv(shost);
894 platform_set_drvdata(pdev, sha);
John Garry50cb9162015-11-18 00:50:39 +0800895
896 if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) &&
897 dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
898 dev_err(dev, "No usable DMA addressing method\n");
899 rc = -EIO;
900 goto err_out_ha;
901 }
902
John Garry7eb78692015-11-18 00:50:31 +0800903 phy_nr = port_nr = hisi_hba->n_phy;
904
905 arr_phy = devm_kcalloc(dev, phy_nr, sizeof(void *), GFP_KERNEL);
906 arr_port = devm_kcalloc(dev, port_nr, sizeof(void *), GFP_KERNEL);
907 if (!arr_phy || !arr_port)
908 return -ENOMEM;
909
910 sha->sas_phy = arr_phy;
911 sha->sas_port = arr_port;
912 sha->core.shost = shost;
913 sha->lldd_ha = hisi_hba;
914
915 shost->transportt = hisi_sas_stt;
916 shost->max_id = HISI_SAS_MAX_DEVICES;
917 shost->max_lun = ~0;
918 shost->max_channel = 1;
919 shost->max_cmd_len = 16;
920 shost->sg_tablesize = min_t(u16, SG_ALL, HISI_SAS_SGE_PAGE_CNT);
921 shost->can_queue = HISI_SAS_COMMAND_ENTRIES;
922 shost->cmd_per_lun = HISI_SAS_COMMAND_ENTRIES;
923
924 sha->sas_ha_name = DRV_NAME;
925 sha->dev = &hisi_hba->pdev->dev;
926 sha->lldd_module = THIS_MODULE;
927 sha->sas_addr = &hisi_hba->sas_addr[0];
928 sha->num_phys = hisi_hba->n_phy;
929 sha->core.shost = hisi_hba->shost;
930
931 for (i = 0; i < hisi_hba->n_phy; i++) {
932 sha->sas_phy[i] = &hisi_hba->phy[i].sas_phy;
933 sha->sas_port[i] = &hisi_hba->port[i].sas_port;
934 }
935
John Garry5d742422015-11-18 00:50:38 +0800936 hisi_sas_init_add(hisi_hba);
937
John Garry8ff1d572015-11-18 00:50:46 +0800938 rc = hisi_hba->hw->hw_init(hisi_hba);
939 if (rc)
940 goto err_out_ha;
941
John Garry7eb78692015-11-18 00:50:31 +0800942 rc = scsi_add_host(shost, &pdev->dev);
943 if (rc)
944 goto err_out_ha;
945
946 rc = sas_register_ha(sha);
947 if (rc)
948 goto err_out_register_ha;
949
950 scsi_scan_host(shost);
951
952 return 0;
953
954err_out_register_ha:
955 scsi_remove_host(shost);
956err_out_ha:
957 kfree(shost);
958 return rc;
959}
960EXPORT_SYMBOL_GPL(hisi_sas_probe);
961
John Garry89d53322015-11-18 00:50:35 +0800962int hisi_sas_remove(struct platform_device *pdev)
963{
964 struct sas_ha_struct *sha = platform_get_drvdata(pdev);
965 struct hisi_hba *hisi_hba = sha->lldd_ha;
966
967 scsi_remove_host(sha->core.shost);
968 sas_unregister_ha(sha);
969 sas_remove_host(sha->core.shost);
970
971 hisi_sas_free(hisi_hba);
972 return 0;
973}
974EXPORT_SYMBOL_GPL(hisi_sas_remove);
975
John Garrye8899fa2015-11-18 00:50:30 +0800976static __init int hisi_sas_init(void)
977{
978 pr_info("hisi_sas: driver version %s\n", DRV_VERSION);
979
980 hisi_sas_stt = sas_domain_attach_transport(&hisi_sas_transport_ops);
981 if (!hisi_sas_stt)
982 return -ENOMEM;
983
984 return 0;
985}
986
987static __exit void hisi_sas_exit(void)
988{
989 sas_release_transport(hisi_sas_stt);
990}
991
992module_init(hisi_sas_init);
993module_exit(hisi_sas_exit);
994
995MODULE_VERSION(DRV_VERSION);
996MODULE_LICENSE("GPL");
997MODULE_AUTHOR("John Garry <john.garry@huawei.com>");
998MODULE_DESCRIPTION("HISILICON SAS controller driver");
999MODULE_ALIAS("platform:" DRV_NAME);