1 /*
2  *    driver for Microsemi PQI-based storage controllers
3  *    Copyright (c) 2016-2017 Microsemi Corporation
4  *    Copyright (c) 2016 PMC-Sierra, Inc.
5  *
6  *    This program is free software; you can redistribute it and/or modify
7  *    it under the terms of the GNU General Public License as published by
8  *    the Free Software Foundation; version 2 of the License.
9  *
10  *    This program is distributed in the hope that it will be useful,
11  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
13  *    NON INFRINGEMENT.  See the GNU General Public License for more details.
14  *
15  *    Questions/Comments/Bugfixes to esc.storagedev@microsemi.com
16  *
17  */
18 
19 #include <linux/kernel.h>
20 #include <linux/bsg-lib.h>
21 #include <scsi/scsi_host.h>
22 #include <scsi/scsi_cmnd.h>
23 #include <scsi/scsi_transport_sas.h>
24 #include <asm/unaligned.h>
25 #include "smartpqi.h"
26 
27 static struct pqi_sas_phy *pqi_alloc_sas_phy(struct pqi_sas_port *pqi_sas_port)
28 {
29 	struct pqi_sas_phy *pqi_sas_phy;
30 	struct sas_phy *phy;
31 
32 	pqi_sas_phy = kzalloc(sizeof(*pqi_sas_phy), GFP_KERNEL);
33 	if (!pqi_sas_phy)
34 		return NULL;
35 
36 	phy = sas_phy_alloc(pqi_sas_port->parent_node->parent_dev,
37 		pqi_sas_port->next_phy_index);
38 	if (!phy) {
39 		kfree(pqi_sas_phy);
40 		return NULL;
41 	}
42 
43 	pqi_sas_port->next_phy_index++;
44 	pqi_sas_phy->phy = phy;
45 	pqi_sas_phy->parent_port = pqi_sas_port;
46 
47 	return pqi_sas_phy;
48 }
49 
50 static void pqi_free_sas_phy(struct pqi_sas_phy *pqi_sas_phy)
51 {
52 	struct sas_phy *phy = pqi_sas_phy->phy;
53 
54 	sas_port_delete_phy(pqi_sas_phy->parent_port->port, phy);
55 	sas_phy_free(phy);
56 	if (pqi_sas_phy->added_to_port)
57 		list_del(&pqi_sas_phy->phy_list_entry);
58 	kfree(pqi_sas_phy);
59 }
60 
61 static int pqi_sas_port_add_phy(struct pqi_sas_phy *pqi_sas_phy)
62 {
63 	int rc;
64 	struct pqi_sas_port *pqi_sas_port;
65 	struct sas_phy *phy;
66 	struct sas_identify *identify;
67 
68 	pqi_sas_port = pqi_sas_phy->parent_port;
69 	phy = pqi_sas_phy->phy;
70 
71 	identify = &phy->identify;
72 	memset(identify, 0, sizeof(*identify));
73 	identify->sas_address = pqi_sas_port->sas_address;
74 	identify->device_type = SAS_END_DEVICE;
75 	identify->initiator_port_protocols = SAS_PROTOCOL_STP;
76 	identify->target_port_protocols = SAS_PROTOCOL_STP;
77 	phy->minimum_linkrate_hw = SAS_LINK_RATE_UNKNOWN;
78 	phy->maximum_linkrate_hw = SAS_LINK_RATE_UNKNOWN;
79 	phy->minimum_linkrate = SAS_LINK_RATE_UNKNOWN;
80 	phy->maximum_linkrate = SAS_LINK_RATE_UNKNOWN;
81 	phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
82 
83 	rc = sas_phy_add(pqi_sas_phy->phy);
84 	if (rc)
85 		return rc;
86 
87 	sas_port_add_phy(pqi_sas_port->port, pqi_sas_phy->phy);
88 	list_add_tail(&pqi_sas_phy->phy_list_entry,
89 		&pqi_sas_port->phy_list_head);
90 	pqi_sas_phy->added_to_port = true;
91 
92 	return 0;
93 }
94 
95 static int pqi_sas_port_add_rphy(struct pqi_sas_port *pqi_sas_port,
96 	struct sas_rphy *rphy)
97 {
98 	struct sas_identify *identify;
99 
100 	identify = &rphy->identify;
101 	identify->sas_address = pqi_sas_port->sas_address;
102 
103 	if (pqi_sas_port->device &&
104 		pqi_sas_port->device->is_expander_smp_device) {
105 		identify->initiator_port_protocols = SAS_PROTOCOL_SMP;
106 		identify->target_port_protocols = SAS_PROTOCOL_SMP;
107 	} else {
108 		identify->initiator_port_protocols = SAS_PROTOCOL_STP;
109 		identify->target_port_protocols = SAS_PROTOCOL_STP;
110 	}
111 
112 	return sas_rphy_add(rphy);
113 }
114 
115 static struct sas_rphy *pqi_sas_rphy_alloc(struct pqi_sas_port *pqi_sas_port)
116 {
117 	if (pqi_sas_port->device &&
118 		pqi_sas_port->device->is_expander_smp_device)
119 		return sas_expander_alloc(pqi_sas_port->port,
120 				SAS_FANOUT_EXPANDER_DEVICE);
121 
122 	return sas_end_device_alloc(pqi_sas_port->port);
123 }
124 
125 static struct pqi_sas_port *pqi_alloc_sas_port(
126 	struct pqi_sas_node *pqi_sas_node, u64 sas_address,
127 	struct pqi_scsi_dev *device)
128 {
129 	int rc;
130 	struct pqi_sas_port *pqi_sas_port;
131 	struct sas_port *port;
132 
133 	pqi_sas_port = kzalloc(sizeof(*pqi_sas_port), GFP_KERNEL);
134 	if (!pqi_sas_port)
135 		return NULL;
136 
137 	INIT_LIST_HEAD(&pqi_sas_port->phy_list_head);
138 	pqi_sas_port->parent_node = pqi_sas_node;
139 
140 	port = sas_port_alloc_num(pqi_sas_node->parent_dev);
141 	if (!port)
142 		goto free_pqi_port;
143 
144 	rc = sas_port_add(port);
145 	if (rc)
146 		goto free_sas_port;
147 
148 	pqi_sas_port->port = port;
149 	pqi_sas_port->sas_address = sas_address;
150 	pqi_sas_port->device = device;
151 	list_add_tail(&pqi_sas_port->port_list_entry,
152 		&pqi_sas_node->port_list_head);
153 
154 	return pqi_sas_port;
155 
156 free_sas_port:
157 	sas_port_free(port);
158 free_pqi_port:
159 	kfree(pqi_sas_port);
160 
161 	return NULL;
162 }
163 
164 static void pqi_free_sas_port(struct pqi_sas_port *pqi_sas_port)
165 {
166 	struct pqi_sas_phy *pqi_sas_phy;
167 	struct pqi_sas_phy *next;
168 
169 	list_for_each_entry_safe(pqi_sas_phy, next,
170 		&pqi_sas_port->phy_list_head, phy_list_entry)
171 		pqi_free_sas_phy(pqi_sas_phy);
172 
173 	sas_port_delete(pqi_sas_port->port);
174 	list_del(&pqi_sas_port->port_list_entry);
175 	kfree(pqi_sas_port);
176 }
177 
178 static struct pqi_sas_node *pqi_alloc_sas_node(struct device *parent_dev)
179 {
180 	struct pqi_sas_node *pqi_sas_node;
181 
182 	pqi_sas_node = kzalloc(sizeof(*pqi_sas_node), GFP_KERNEL);
183 	if (pqi_sas_node) {
184 		pqi_sas_node->parent_dev = parent_dev;
185 		INIT_LIST_HEAD(&pqi_sas_node->port_list_head);
186 	}
187 
188 	return pqi_sas_node;
189 }
190 
191 static void pqi_free_sas_node(struct pqi_sas_node *pqi_sas_node)
192 {
193 	struct pqi_sas_port *pqi_sas_port;
194 	struct pqi_sas_port *next;
195 
196 	if (!pqi_sas_node)
197 		return;
198 
199 	list_for_each_entry_safe(pqi_sas_port, next,
200 		&pqi_sas_node->port_list_head, port_list_entry)
201 		pqi_free_sas_port(pqi_sas_port);
202 
203 	kfree(pqi_sas_node);
204 }
205 
206 struct pqi_scsi_dev *pqi_find_device_by_sas_rphy(
207 	struct pqi_ctrl_info *ctrl_info, struct sas_rphy *rphy)
208 {
209 	struct pqi_scsi_dev *device;
210 
211 	list_for_each_entry(device, &ctrl_info->scsi_device_list,
212 		scsi_device_list_entry) {
213 		if (!device->sas_port)
214 			continue;
215 		if (device->sas_port->rphy == rphy)
216 			return device;
217 	}
218 
219 	return NULL;
220 }
221 
222 int pqi_add_sas_host(struct Scsi_Host *shost, struct pqi_ctrl_info *ctrl_info)
223 {
224 	int rc;
225 	struct device *parent_dev;
226 	struct pqi_sas_node *pqi_sas_node;
227 	struct pqi_sas_port *pqi_sas_port;
228 	struct pqi_sas_phy *pqi_sas_phy;
229 
230 	parent_dev = &shost->shost_dev;
231 
232 	pqi_sas_node = pqi_alloc_sas_node(parent_dev);
233 	if (!pqi_sas_node)
234 		return -ENOMEM;
235 
236 	pqi_sas_port = pqi_alloc_sas_port(pqi_sas_node,
237 		ctrl_info->sas_address, NULL);
238 	if (!pqi_sas_port) {
239 		rc = -ENODEV;
240 		goto free_sas_node;
241 	}
242 
243 	pqi_sas_phy = pqi_alloc_sas_phy(pqi_sas_port);
244 	if (!pqi_sas_phy) {
245 		rc = -ENODEV;
246 		goto free_sas_port;
247 	}
248 
249 	rc = pqi_sas_port_add_phy(pqi_sas_phy);
250 	if (rc)
251 		goto free_sas_phy;
252 
253 	ctrl_info->sas_host = pqi_sas_node;
254 
255 	return 0;
256 
257 free_sas_phy:
258 	pqi_free_sas_phy(pqi_sas_phy);
259 free_sas_port:
260 	pqi_free_sas_port(pqi_sas_port);
261 free_sas_node:
262 	pqi_free_sas_node(pqi_sas_node);
263 
264 	return rc;
265 }
266 
267 void pqi_delete_sas_host(struct pqi_ctrl_info *ctrl_info)
268 {
269 	pqi_free_sas_node(ctrl_info->sas_host);
270 }
271 
272 int pqi_add_sas_device(struct pqi_sas_node *pqi_sas_node,
273 	struct pqi_scsi_dev *device)
274 {
275 	int rc;
276 	struct pqi_sas_port *pqi_sas_port;
277 	struct sas_rphy *rphy;
278 
279 	pqi_sas_port = pqi_alloc_sas_port(pqi_sas_node,
280 		device->sas_address, device);
281 	if (!pqi_sas_port)
282 		return -ENOMEM;
283 
284 	rphy = pqi_sas_rphy_alloc(pqi_sas_port);
285 	if (!rphy) {
286 		rc = -ENODEV;
287 		goto free_sas_port;
288 	}
289 
290 	pqi_sas_port->rphy = rphy;
291 	device->sas_port = pqi_sas_port;
292 
293 	rc = pqi_sas_port_add_rphy(pqi_sas_port, rphy);
294 	if (rc)
295 		goto free_sas_port;
296 
297 	return 0;
298 
299 free_sas_port:
300 	pqi_free_sas_port(pqi_sas_port);
301 	device->sas_port = NULL;
302 
303 	return rc;
304 }
305 
306 void pqi_remove_sas_device(struct pqi_scsi_dev *device)
307 {
308 	if (device->sas_port) {
309 		pqi_free_sas_port(device->sas_port);
310 		device->sas_port = NULL;
311 	}
312 }
313 
314 static int pqi_sas_get_linkerrors(struct sas_phy *phy)
315 {
316 	return 0;
317 }
318 
319 static int pqi_sas_get_enclosure_identifier(struct sas_rphy *rphy,
320 	u64 *identifier)
321 {
322 	return 0;
323 }
324 
325 static int pqi_sas_get_bay_identifier(struct sas_rphy *rphy)
326 {
327 	return -ENXIO;
328 }
329 
330 static int pqi_sas_phy_reset(struct sas_phy *phy, int hard_reset)
331 {
332 	return 0;
333 }
334 
335 static int pqi_sas_phy_enable(struct sas_phy *phy, int enable)
336 {
337 	return 0;
338 }
339 
340 static int pqi_sas_phy_setup(struct sas_phy *phy)
341 {
342 	return 0;
343 }
344 
345 static void pqi_sas_phy_release(struct sas_phy *phy)
346 {
347 }
348 
349 static int pqi_sas_phy_speed(struct sas_phy *phy,
350 	struct sas_phy_linkrates *rates)
351 {
352 	return -EINVAL;
353 }
354 
355 #define CSMI_IOCTL_TIMEOUT	60
356 #define SMP_CRC_FIELD_LENGTH	4
357 
358 static struct bmic_csmi_smp_passthru_buffer *
359 pqi_build_csmi_smp_passthru_buffer(struct sas_rphy *rphy,
360 	struct bsg_job *job)
361 {
362 	struct bmic_csmi_smp_passthru_buffer *smp_buf;
363 	struct bmic_csmi_ioctl_header *ioctl_header;
364 	struct bmic_csmi_smp_passthru *parameters;
365 	u32 req_size;
366 	u32 resp_size;
367 
368 	smp_buf = kzalloc(sizeof(*smp_buf), GFP_KERNEL);
369 	if (!smp_buf)
370 		return NULL;
371 
372 	req_size = job->request_payload.payload_len;
373 	resp_size = job->reply_payload.payload_len;
374 
375 	ioctl_header = &smp_buf->ioctl_header;
376 	put_unaligned_le32(sizeof(smp_buf->ioctl_header),
377 		&ioctl_header->header_length);
378 	put_unaligned_le32(CSMI_IOCTL_TIMEOUT, &ioctl_header->timeout);
379 	put_unaligned_le32(CSMI_CC_SAS_SMP_PASSTHRU,
380 		&ioctl_header->control_code);
381 	put_unaligned_le32(sizeof(smp_buf->parameters), &ioctl_header->length);
382 
383 	parameters = &smp_buf->parameters;
384 	parameters->phy_identifier = rphy->identify.phy_identifier;
385 	parameters->port_identifier = 0;
386 	parameters->connection_rate = 0;
387 	put_unaligned_be64(rphy->identify.sas_address,
388 		&parameters->destination_sas_address);
389 
390 	if (req_size > SMP_CRC_FIELD_LENGTH)
391 		req_size -= SMP_CRC_FIELD_LENGTH;
392 
393 	put_unaligned_le32(req_size, &parameters->request_length);
394 
395 	put_unaligned_le32(resp_size, &parameters->response_length);
396 
397 	sg_copy_to_buffer(job->request_payload.sg_list,
398 		job->reply_payload.sg_cnt, &parameters->request,
399 		req_size);
400 
401 	return smp_buf;
402 }
403 
404 static unsigned int pqi_build_sas_smp_handler_reply(
405 	struct bmic_csmi_smp_passthru_buffer *smp_buf, struct bsg_job *job,
406 	struct pqi_raid_error_info *error_info)
407 {
408 	sg_copy_from_buffer(job->reply_payload.sg_list,
409 		job->reply_payload.sg_cnt, &smp_buf->parameters.response,
410 		le32_to_cpu(smp_buf->parameters.response_length));
411 
412 	job->reply_len = le16_to_cpu(error_info->sense_data_length);
413 	memcpy(job->reply, error_info->data,
414 			le16_to_cpu(error_info->sense_data_length));
415 
416 	return job->reply_payload.payload_len -
417 		get_unaligned_le32(&error_info->data_in_transferred);
418 }
419 
420 void pqi_sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
421 	struct sas_rphy *rphy)
422 {
423 	int rc;
424 	struct pqi_ctrl_info *ctrl_info = shost_to_hba(shost);
425 	struct bmic_csmi_smp_passthru_buffer *smp_buf;
426 	struct pqi_raid_error_info error_info;
427 	unsigned int reslen = 0;
428 
429 	pqi_ctrl_busy(ctrl_info);
430 
431 	if (job->reply_payload.payload_len == 0) {
432 		rc = -ENOMEM;
433 		goto out;
434 	}
435 
436 	if (!rphy) {
437 		rc = -EINVAL;
438 		goto out;
439 	}
440 
441 	if (rphy->identify.device_type != SAS_FANOUT_EXPANDER_DEVICE) {
442 		rc = -EINVAL;
443 		goto out;
444 	}
445 
446 	if (job->request_payload.sg_cnt > 1 || job->reply_payload.sg_cnt > 1) {
447 		rc = -EINVAL;
448 		goto out;
449 	}
450 
451 	if (pqi_ctrl_offline(ctrl_info)) {
452 		rc = -ENXIO;
453 		goto out;
454 	}
455 
456 	if (pqi_ctrl_blocked(ctrl_info)) {
457 		rc = -EBUSY;
458 		goto out;
459 	}
460 
461 	smp_buf = pqi_build_csmi_smp_passthru_buffer(rphy, job);
462 	if (!smp_buf) {
463 		rc = -ENOMEM;
464 		goto out;
465 	}
466 
467 	rc = pqi_csmi_smp_passthru(ctrl_info, smp_buf, sizeof(*smp_buf),
468 		&error_info);
469 	if (rc)
470 		goto out;
471 
472 	reslen = pqi_build_sas_smp_handler_reply(smp_buf, job, &error_info);
473 out:
474 	bsg_job_done(job, rc, reslen);
475 	pqi_ctrl_unbusy(ctrl_info);
476 }
477 struct sas_function_template pqi_sas_transport_functions = {
478 	.get_linkerrors = pqi_sas_get_linkerrors,
479 	.get_enclosure_identifier = pqi_sas_get_enclosure_identifier,
480 	.get_bay_identifier = pqi_sas_get_bay_identifier,
481 	.phy_reset = pqi_sas_phy_reset,
482 	.phy_enable = pqi_sas_phy_enable,
483 	.phy_setup = pqi_sas_phy_setup,
484 	.phy_release = pqi_sas_phy_release,
485 	.set_phy_speed = pqi_sas_phy_speed,
486 	.smp_handler = pqi_sas_smp_handler,
487 };
488