1/*
2 * SAS Transport Layer for MPT (Message Passing Technology) based controllers
3 *
4 * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c
5 * Copyright (C) 2007-2010  LSI Corporation
6 *  (mailto:DL-MPTFusionLinux@lsi.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * NO WARRANTY
19 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
20 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
21 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
22 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
23 * solely responsible for determining the appropriateness of using and
24 * distributing the Program and assumes all risks associated with its
25 * exercise of rights under this Agreement, including but not limited to
26 * the risks and costs of program errors, damage to or loss of data,
27 * programs or equipment, and unavailability or interruption of operations.
28
29 * DISCLAIMER OF LIABILITY
30 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
31 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
36 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
37
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
41 * USA.
42 */
43
44#include <linux/module.h>
45#include <linux/kernel.h>
46#include <linux/init.h>
47#include <linux/errno.h>
48#include <linux/sched.h>
49#include <linux/workqueue.h>
50#include <linux/delay.h>
51#include <linux/pci.h>
52#include <linux/slab.h>
53
54#include <scsi/scsi.h>
55#include <scsi/scsi_cmnd.h>
56#include <scsi/scsi_device.h>
57#include <scsi/scsi_host.h>
58#include <scsi/scsi_transport_sas.h>
59#include <scsi/scsi_dbg.h>
60
61#include "mpt2sas_base.h"
62/**
63 * _transport_sas_node_find_by_sas_address - sas node search
64 * @ioc: per adapter object
65 * @sas_address: sas address of expander or sas host
66 * Context: Calling function should acquire ioc->sas_node_lock.
67 *
68 * Search for either hba phys or expander device based on handle, then returns
69 * the sas_node object.
70 */
71static struct _sas_node *
72_transport_sas_node_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
73    u64 sas_address)
74{
75	if (ioc->sas_hba.sas_address == sas_address)
76		return &ioc->sas_hba;
77	else
78		return mpt2sas_scsih_expander_find_by_sas_address(ioc,
79		    sas_address);
80}
81
82/**
83 * _transport_convert_phy_link_rate -
84 * @link_rate: link rate returned from mpt firmware
85 *
86 * Convert link_rate from mpi fusion into sas_transport form.
87 */
88static enum sas_linkrate
89_transport_convert_phy_link_rate(u8 link_rate)
90{
91	enum sas_linkrate rc;
92
93	switch (link_rate) {
94	case MPI2_SAS_NEG_LINK_RATE_1_5:
95		rc = SAS_LINK_RATE_1_5_GBPS;
96		break;
97	case MPI2_SAS_NEG_LINK_RATE_3_0:
98		rc = SAS_LINK_RATE_3_0_GBPS;
99		break;
100	case MPI2_SAS_NEG_LINK_RATE_6_0:
101		rc = SAS_LINK_RATE_6_0_GBPS;
102		break;
103	case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED:
104		rc = SAS_PHY_DISABLED;
105		break;
106	case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
107		rc = SAS_LINK_RATE_FAILED;
108		break;
109	case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR:
110		rc = SAS_SATA_PORT_SELECTOR;
111		break;
112	case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
113		rc = SAS_PHY_RESET_IN_PROGRESS;
114		break;
115	default:
116	case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
117	case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
118		rc = SAS_LINK_RATE_UNKNOWN;
119		break;
120	}
121	return rc;
122}
123
124/**
125 * _transport_set_identify - set identify for phys and end devices
126 * @ioc: per adapter object
127 * @handle: device handle
128 * @identify: sas identify info
129 *
130 * Populates sas identify info.
131 *
132 * Returns 0 for success, non-zero for failure.
133 */
134static int
135_transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
136    struct sas_identify *identify)
137{
138	Mpi2SasDevicePage0_t sas_device_pg0;
139	Mpi2ConfigReply_t mpi_reply;
140	u32 device_info;
141	u32 ioc_status;
142
143	if (ioc->shost_recovery || ioc->pci_error_recovery) {
144		printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
145		    __func__, ioc->name);
146		return -EFAULT;
147	}
148
149	if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
150	    MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
151		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
152
153		    ioc->name, __FILE__, __LINE__, __func__);
154		return -ENXIO;
155	}
156
157	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
158	    MPI2_IOCSTATUS_MASK;
159	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
160		printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
161		    "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
162		     __FILE__, __LINE__, __func__);
163		return -EIO;
164	}
165
166	memset(identify, 0, sizeof(*identify));
167	device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
168
169	/* sas_address */
170	identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
171
172	/* device_type */
173	switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
174	case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
175		identify->device_type = SAS_PHY_UNUSED;
176		break;
177	case MPI2_SAS_DEVICE_INFO_END_DEVICE:
178		identify->device_type = SAS_END_DEVICE;
179		break;
180	case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER:
181		identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
182		break;
183	case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER:
184		identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
185		break;
186	}
187
188	/* initiator_port_protocols */
189	if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR)
190		identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
191	if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR)
192		identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
193	if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR)
194		identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
195	if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST)
196		identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
197
198	/* target_port_protocols */
199	if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
200		identify->target_port_protocols |= SAS_PROTOCOL_SSP;
201	if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
202		identify->target_port_protocols |= SAS_PROTOCOL_STP;
203	if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET)
204		identify->target_port_protocols |= SAS_PROTOCOL_SMP;
205	if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
206		identify->target_port_protocols |= SAS_PROTOCOL_SATA;
207
208	return 0;
209}
210
211/**
212 * mpt2sas_transport_done -  internal transport layer callback handler.
213 * @ioc: per adapter object
214 * @smid: system request message index
215 * @msix_index: MSIX table index supplied by the OS
216 * @reply: reply message frame(lower 32bit addr)
217 *
218 * Callback handler when sending internal generated transport cmds.
219 * The callback index passed is `ioc->transport_cb_idx`
220 *
221 * Return 1 meaning mf should be freed from _base_interrupt
222 *        0 means the mf is freed from this function.
223 */
224u8
225mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
226    u32 reply)
227{
228	MPI2DefaultReply_t *mpi_reply;
229
230	mpi_reply =  mpt2sas_base_get_reply_virt_addr(ioc, reply);
231	if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED)
232		return 1;
233	if (ioc->transport_cmds.smid != smid)
234		return 1;
235	ioc->transport_cmds.status |= MPT2_CMD_COMPLETE;
236	if (mpi_reply) {
237		memcpy(ioc->transport_cmds.reply, mpi_reply,
238		    mpi_reply->MsgLength*4);
239		ioc->transport_cmds.status |= MPT2_CMD_REPLY_VALID;
240	}
241	ioc->transport_cmds.status &= ~MPT2_CMD_PENDING;
242	complete(&ioc->transport_cmds.done);
243	return 1;
244}
245
246/* report manufacture request structure */
247struct rep_manu_request{
248	u8 smp_frame_type;
249	u8 function;
250	u8 reserved;
251	u8 request_length;
252};
253
254/* report manufacture reply structure */
255struct rep_manu_reply{
256	u8 smp_frame_type; /* 0x41 */
257	u8 function; /* 0x01 */
258	u8 function_result;
259	u8 response_length;
260	u16 expander_change_count;
261	u8 reserved0[2];
262	u8 sas_format;
263	u8 reserved2[3];
264	u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
265	u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
266	u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
267	u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
268	u16 component_id;
269	u8 component_revision_id;
270	u8 reserved3;
271	u8 vendor_specific[8];
272};
273
274/**
275 * _transport_expander_report_manufacture - obtain SMP report_manufacture
276 * @ioc: per adapter object
277 * @sas_address: expander sas address
278 * @edev: the sas_expander_device object
279 *
280 * Fills in the sas_expander_device object when SMP port is created.
281 *
282 * Returns 0 for success, non-zero for failure.
283 */
284static int
285_transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
286    u64 sas_address, struct sas_expander_device *edev)
287{
288	Mpi2SmpPassthroughRequest_t *mpi_request;
289	Mpi2SmpPassthroughReply_t *mpi_reply;
290	struct rep_manu_reply *manufacture_reply;
291	struct rep_manu_request *manufacture_request;
292	int rc;
293	u16 smid;
294	u32 ioc_state;
295	unsigned long timeleft;
296	void *psge;
297	u32 sgl_flags;
298	u8 issue_reset = 0;
299	void *data_out = NULL;
300	dma_addr_t data_out_dma;
301	u32 sz;
302	u16 wait_state_count;
303
304	if (ioc->shost_recovery || ioc->pci_error_recovery) {
305		printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
306		    __func__, ioc->name);
307		return -EFAULT;
308	}
309
310	mutex_lock(&ioc->transport_cmds.mutex);
311
312	if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
313		printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
314		    ioc->name, __func__);
315		rc = -EAGAIN;
316		goto out;
317	}
318	ioc->transport_cmds.status = MPT2_CMD_PENDING;
319
320	wait_state_count = 0;
321	ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
322	while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
323		if (wait_state_count++ == 10) {
324			printk(MPT2SAS_ERR_FMT
325			    "%s: failed due to ioc not operational\n",
326			    ioc->name, __func__);
327			rc = -EFAULT;
328			goto out;
329		}
330		ssleep(1);
331		ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
332		printk(MPT2SAS_INFO_FMT "%s: waiting for "
333		    "operational state(count=%d)\n", ioc->name,
334		    __func__, wait_state_count);
335	}
336	if (wait_state_count)
337		printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
338		    ioc->name, __func__);
339
340	smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
341	if (!smid) {
342		printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
343		    ioc->name, __func__);
344		rc = -EAGAIN;
345		goto out;
346	}
347
348	rc = 0;
349	mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
350	ioc->transport_cmds.smid = smid;
351
352	sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
353	data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
354
355	if (!data_out) {
356		printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
357		    __LINE__, __func__);
358		rc = -ENOMEM;
359		mpt2sas_base_free_smid(ioc, smid);
360		goto out;
361	}
362
363	manufacture_request = data_out;
364	manufacture_request->smp_frame_type = 0x40;
365	manufacture_request->function = 1;
366	manufacture_request->reserved = 0;
367	manufacture_request->request_length = 0;
368
369	memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
370	mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
371	mpi_request->PhysicalPort = 0xFF;
372	mpi_request->VF_ID = 0; /* TODO */
373	mpi_request->VP_ID = 0;
374	mpi_request->SASAddress = cpu_to_le64(sas_address);
375	mpi_request->RequestDataLength =
376	    cpu_to_le16(sizeof(struct rep_manu_request));
377	psge = &mpi_request->SGL;
378
379	/* WRITE sgel first */
380	sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
381	    MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
382	sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
383	ioc->base_add_sg_single(psge, sgl_flags |
384	    sizeof(struct rep_manu_request), data_out_dma);
385
386	/* incr sgel */
387	psge += ioc->sge_size;
388
389	/* READ sgel last */
390	sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
391	    MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
392	    MPI2_SGE_FLAGS_END_OF_LIST);
393	sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
394	ioc->base_add_sg_single(psge, sgl_flags |
395	    sizeof(struct rep_manu_reply), data_out_dma +
396	    sizeof(struct rep_manu_request));
397
398	dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
399	    "send to sas_addr(0x%016llx)\n", ioc->name,
400	    (unsigned long long)sas_address));
401	init_completion(&ioc->transport_cmds.done);
402	mpt2sas_base_put_smid_default(ioc, smid);
403	timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
404	    10*HZ);
405
406	if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
407		printk(MPT2SAS_ERR_FMT "%s: timeout\n",
408		    ioc->name, __func__);
409		_debug_dump_mf(mpi_request,
410		    sizeof(Mpi2SmpPassthroughRequest_t)/4);
411		if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
412			issue_reset = 1;
413		goto issue_host_reset;
414	}
415
416	dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
417	    "complete\n", ioc->name));
418
419	if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
420		u8 *tmp;
421
422		mpi_reply = ioc->transport_cmds.reply;
423
424		dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
425		    "report_manufacture - reply data transfer size(%d)\n",
426		    ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
427
428		if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
429		    sizeof(struct rep_manu_reply))
430			goto out;
431
432		manufacture_reply = data_out + sizeof(struct rep_manu_request);
433		strncpy(edev->vendor_id, manufacture_reply->vendor_id,
434		     SAS_EXPANDER_VENDOR_ID_LEN);
435		strncpy(edev->product_id, manufacture_reply->product_id,
436		     SAS_EXPANDER_PRODUCT_ID_LEN);
437		strncpy(edev->product_rev, manufacture_reply->product_rev,
438		     SAS_EXPANDER_PRODUCT_REV_LEN);
439		edev->level = manufacture_reply->sas_format & 1;
440		if (edev->level) {
441			strncpy(edev->component_vendor_id,
442			    manufacture_reply->component_vendor_id,
443			     SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
444			tmp = (u8 *)&manufacture_reply->component_id;
445			edev->component_id = tmp[0] << 8 | tmp[1];
446			edev->component_revision_id =
447			    manufacture_reply->component_revision_id;
448		}
449	} else
450		dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
451		    "report_manufacture - no reply\n", ioc->name));
452
453 issue_host_reset:
454	if (issue_reset)
455		mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
456		    FORCE_BIG_HAMMER);
457 out:
458	ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
459	if (data_out)
460		pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
461
462	mutex_unlock(&ioc->transport_cmds.mutex);
463	return rc;
464}
465
466/**
467 * _transport_delete_port - helper function to removing a port
468 * @ioc: per adapter object
469 * @mpt2sas_port: mpt2sas per port object
470 *
471 * Returns nothing.
472 */
473static void
474_transport_delete_port(struct MPT2SAS_ADAPTER *ioc,
475	struct _sas_port *mpt2sas_port)
476{
477	u64 sas_address = mpt2sas_port->remote_identify.sas_address;
478	enum sas_device_type device_type =
479	    mpt2sas_port->remote_identify.device_type;
480
481	dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
482	    "remove: sas_addr(0x%016llx)\n",
483	    (unsigned long long) sas_address);
484
485	ioc->logging_level |= MPT_DEBUG_TRANSPORT;
486	if (device_type == SAS_END_DEVICE)
487		mpt2sas_device_remove(ioc, sas_address);
488	else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
489	    device_type == SAS_FANOUT_EXPANDER_DEVICE)
490		mpt2sas_expander_remove(ioc, sas_address);
491	ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
492}
493
494/**
495 * _transport_delete_phy - helper function to removing single phy from port
496 * @ioc: per adapter object
497 * @mpt2sas_port: mpt2sas per port object
498 * @mpt2sas_phy: mpt2sas per phy object
499 *
500 * Returns nothing.
501 */
502static void
503_transport_delete_phy(struct MPT2SAS_ADAPTER *ioc,
504	struct _sas_port *mpt2sas_port, struct _sas_phy *mpt2sas_phy)
505{
506	u64 sas_address = mpt2sas_port->remote_identify.sas_address;
507
508	dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
509	    "remove: sas_addr(0x%016llx), phy(%d)\n",
510	    (unsigned long long) sas_address, mpt2sas_phy->phy_id);
511
512	list_del(&mpt2sas_phy->port_siblings);
513	mpt2sas_port->num_phys--;
514	sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
515	mpt2sas_phy->phy_belongs_to_port = 0;
516}
517
518/**
519 * _transport_add_phy - helper function to adding single phy to port
520 * @ioc: per adapter object
521 * @mpt2sas_port: mpt2sas per port object
522 * @mpt2sas_phy: mpt2sas per phy object
523 *
524 * Returns nothing.
525 */
526static void
527_transport_add_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_port *mpt2sas_port,
528	struct _sas_phy *mpt2sas_phy)
529{
530	u64 sas_address = mpt2sas_port->remote_identify.sas_address;
531
532	dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
533	    "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
534	    sas_address, mpt2sas_phy->phy_id);
535
536	list_add_tail(&mpt2sas_phy->port_siblings, &mpt2sas_port->phy_list);
537	mpt2sas_port->num_phys++;
538	sas_port_add_phy(mpt2sas_port->port, mpt2sas_phy->phy);
539	mpt2sas_phy->phy_belongs_to_port = 1;
540}
541
542/**
543 * _transport_add_phy_to_an_existing_port - adding new phy to existing port
544 * @ioc: per adapter object
545 * @sas_node: sas node object (either expander or sas host)
546 * @mpt2sas_phy: mpt2sas per phy object
547 * @sas_address: sas address of device/expander were phy needs to be added to
548 *
549 * Returns nothing.
550 */
551static void
552_transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
553struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy, u64 sas_address)
554{
555	struct _sas_port *mpt2sas_port;
556	struct _sas_phy *phy_srch;
557
558	if (mpt2sas_phy->phy_belongs_to_port == 1)
559		return;
560
561	list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list,
562	    port_list) {
563		if (mpt2sas_port->remote_identify.sas_address !=
564		    sas_address)
565			continue;
566		list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
567		    port_siblings) {
568			if (phy_srch == mpt2sas_phy)
569				return;
570		}
571		_transport_add_phy(ioc, mpt2sas_port, mpt2sas_phy);
572			return;
573	}
574
575}
576
577/**
578 * _transport_del_phy_from_an_existing_port - delete phy from existing port
579 * @ioc: per adapter object
580 * @sas_node: sas node object (either expander or sas host)
581 * @mpt2sas_phy: mpt2sas per phy object
582 *
583 * Returns nothing.
584 */
585static void
586_transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
587	struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy)
588{
589	struct _sas_port *mpt2sas_port, *next;
590	struct _sas_phy *phy_srch;
591
592	if (mpt2sas_phy->phy_belongs_to_port == 0)
593		return;
594
595	list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
596	    port_list) {
597		list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
598		    port_siblings) {
599			if (phy_srch != mpt2sas_phy)
600				continue;
601			if (mpt2sas_port->num_phys == 1)
602				_transport_delete_port(ioc, mpt2sas_port);
603			else
604				_transport_delete_phy(ioc, mpt2sas_port,
605				    mpt2sas_phy);
606			return;
607		}
608	}
609}
610
611/**
612 * _transport_sanity_check - sanity check when adding a new port
613 * @ioc: per adapter object
614 * @sas_node: sas node object (either expander or sas host)
615 * @sas_address: sas address of device being added
616 *
617 * See the explanation above from _transport_delete_duplicate_port
618 */
619static void
620_transport_sanity_check(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node,
621     u64 sas_address)
622{
623	int i;
624
625	for (i = 0; i < sas_node->num_phys; i++) {
626		if (sas_node->phy[i].remote_identify.sas_address != sas_address)
627			continue;
628		if (sas_node->phy[i].phy_belongs_to_port == 1)
629			_transport_del_phy_from_an_existing_port(ioc, sas_node,
630			    &sas_node->phy[i]);
631	}
632}
633
634/**
635 * mpt2sas_transport_port_add - insert port to the list
636 * @ioc: per adapter object
637 * @handle: handle of attached device
638 * @sas_address: sas address of parent expander or sas host
639 * Context: This function will acquire ioc->sas_node_lock.
640 *
641 * Adding new port object to the sas_node->sas_port_list.
642 *
643 * Returns mpt2sas_port.
644 */
645struct _sas_port *
646mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
647    u64 sas_address)
648{
649	struct _sas_phy *mpt2sas_phy, *next;
650	struct _sas_port *mpt2sas_port;
651	unsigned long flags;
652	struct _sas_node *sas_node;
653	struct sas_rphy *rphy;
654	int i;
655	struct sas_port *port;
656
657	mpt2sas_port = kzalloc(sizeof(struct _sas_port),
658	    GFP_KERNEL);
659	if (!mpt2sas_port) {
660		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
661		    ioc->name, __FILE__, __LINE__, __func__);
662		return NULL;
663	}
664
665	INIT_LIST_HEAD(&mpt2sas_port->port_list);
666	INIT_LIST_HEAD(&mpt2sas_port->phy_list);
667	spin_lock_irqsave(&ioc->sas_node_lock, flags);
668	sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
669	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
670
671	if (!sas_node) {
672		printk(MPT2SAS_ERR_FMT "%s: Could not find "
673		    "parent sas_address(0x%016llx)!\n", ioc->name,
674		    __func__, (unsigned long long)sas_address);
675		goto out_fail;
676	}
677
678	if ((_transport_set_identify(ioc, handle,
679	    &mpt2sas_port->remote_identify))) {
680		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
681		    ioc->name, __FILE__, __LINE__, __func__);
682		goto out_fail;
683	}
684
685	if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
686		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
687		    ioc->name, __FILE__, __LINE__, __func__);
688		goto out_fail;
689	}
690
691	_transport_sanity_check(ioc, sas_node,
692	    mpt2sas_port->remote_identify.sas_address);
693
694	for (i = 0; i < sas_node->num_phys; i++) {
695		if (sas_node->phy[i].remote_identify.sas_address !=
696		    mpt2sas_port->remote_identify.sas_address)
697			continue;
698		list_add_tail(&sas_node->phy[i].port_siblings,
699		    &mpt2sas_port->phy_list);
700		mpt2sas_port->num_phys++;
701	}
702
703	if (!mpt2sas_port->num_phys) {
704		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
705		    ioc->name, __FILE__, __LINE__, __func__);
706		goto out_fail;
707	}
708
709	port = sas_port_alloc_num(sas_node->parent_dev);
710	if ((sas_port_add(port))) {
711		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
712		    ioc->name, __FILE__, __LINE__, __func__);
713		goto out_fail;
714	}
715
716	list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
717	    port_siblings) {
718		if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
719			dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
720			    ", sas_addr(0x%016llx), phy(%d)\n", handle,
721			    (unsigned long long)
722			    mpt2sas_port->remote_identify.sas_address,
723			    mpt2sas_phy->phy_id);
724		sas_port_add_phy(port, mpt2sas_phy->phy);
725		mpt2sas_phy->phy_belongs_to_port = 1;
726	}
727
728	mpt2sas_port->port = port;
729	if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
730		rphy = sas_end_device_alloc(port);
731	else
732		rphy = sas_expander_alloc(port,
733		    mpt2sas_port->remote_identify.device_type);
734
735	rphy->identify = mpt2sas_port->remote_identify;
736	if ((sas_rphy_add(rphy))) {
737		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
738		    ioc->name, __FILE__, __LINE__, __func__);
739	}
740	if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
741		dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
742		    "sas_addr(0x%016llx)\n", handle,
743		    (unsigned long long)
744		    mpt2sas_port->remote_identify.sas_address);
745	mpt2sas_port->rphy = rphy;
746	spin_lock_irqsave(&ioc->sas_node_lock, flags);
747	list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
748	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
749
750	/* fill in report manufacture */
751	if (mpt2sas_port->remote_identify.device_type ==
752	    MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
753	    mpt2sas_port->remote_identify.device_type ==
754	    MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
755		_transport_expander_report_manufacture(ioc,
756		    mpt2sas_port->remote_identify.sas_address,
757		    rphy_to_expander_device(rphy));
758
759	return mpt2sas_port;
760
761 out_fail:
762	list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
763	    port_siblings)
764		list_del(&mpt2sas_phy->port_siblings);
765	kfree(mpt2sas_port);
766	return NULL;
767}
768
769/**
770 * mpt2sas_transport_port_remove - remove port from the list
771 * @ioc: per adapter object
772 * @sas_address: sas address of attached device
773 * @sas_address_parent: sas address of parent expander or sas host
774 * Context: This function will acquire ioc->sas_node_lock.
775 *
776 * Removing object and freeing associated memory from the
777 * ioc->sas_port_list.
778 *
779 * Return nothing.
780 */
781void
782mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
783    u64 sas_address_parent)
784{
785	int i;
786	unsigned long flags;
787	struct _sas_port *mpt2sas_port, *next;
788	struct _sas_node *sas_node;
789	u8 found = 0;
790	struct _sas_phy *mpt2sas_phy, *next_phy;
791
792	spin_lock_irqsave(&ioc->sas_node_lock, flags);
793	sas_node = _transport_sas_node_find_by_sas_address(ioc,
794	    sas_address_parent);
795	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
796	if (!sas_node)
797		return;
798	list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
799	    port_list) {
800		if (mpt2sas_port->remote_identify.sas_address != sas_address)
801			continue;
802		found = 1;
803		list_del(&mpt2sas_port->port_list);
804		goto out;
805	}
806 out:
807	if (!found)
808		return;
809
810	for (i = 0; i < sas_node->num_phys; i++) {
811		if (sas_node->phy[i].remote_identify.sas_address == sas_address)
812			memset(&sas_node->phy[i].remote_identify, 0 ,
813			    sizeof(struct sas_identify));
814	}
815
816	list_for_each_entry_safe(mpt2sas_phy, next_phy,
817	    &mpt2sas_port->phy_list, port_siblings) {
818		if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
819			dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
820			    "remove: sas_addr(0x%016llx), phy(%d)\n",
821			    (unsigned long long)
822			    mpt2sas_port->remote_identify.sas_address,
823			    mpt2sas_phy->phy_id);
824		mpt2sas_phy->phy_belongs_to_port = 0;
825		sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
826		list_del(&mpt2sas_phy->port_siblings);
827	}
828	sas_port_delete(mpt2sas_port->port);
829	kfree(mpt2sas_port);
830}
831
832/**
833 * mpt2sas_transport_add_host_phy - report sas_host phy to transport
834 * @ioc: per adapter object
835 * @mpt2sas_phy: mpt2sas per phy object
836 * @phy_pg0: sas phy page 0
837 * @parent_dev: parent device class object
838 *
839 * Returns 0 for success, non-zero for failure.
840 */
841int
842mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
843    *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
844{
845	struct sas_phy *phy;
846	int phy_index = mpt2sas_phy->phy_id;
847
848
849	INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
850	phy = sas_phy_alloc(parent_dev, phy_index);
851	if (!phy) {
852		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
853		    ioc->name, __FILE__, __LINE__, __func__);
854		return -1;
855	}
856	if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
857	    &mpt2sas_phy->identify))) {
858		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
859		    ioc->name, __FILE__, __LINE__, __func__);
860		return -1;
861	}
862	phy->identify = mpt2sas_phy->identify;
863	mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
864	if (mpt2sas_phy->attached_handle)
865		_transport_set_identify(ioc, mpt2sas_phy->attached_handle,
866		    &mpt2sas_phy->remote_identify);
867	phy->identify.phy_identifier = mpt2sas_phy->phy_id;
868	phy->negotiated_linkrate = _transport_convert_phy_link_rate(
869	    phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
870	phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
871	    phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
872	phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
873	    phy_pg0.HwLinkRate >> 4);
874	phy->minimum_linkrate = _transport_convert_phy_link_rate(
875	    phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
876	phy->maximum_linkrate = _transport_convert_phy_link_rate(
877	    phy_pg0.ProgrammedLinkRate >> 4);
878
879	if ((sas_phy_add(phy))) {
880		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
881		    ioc->name, __FILE__, __LINE__, __func__);
882		sas_phy_free(phy);
883		return -1;
884	}
885	if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
886		dev_printk(KERN_INFO, &phy->dev,
887		    "add: handle(0x%04x), sas_addr(0x%016llx)\n"
888		    "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
889		    mpt2sas_phy->handle, (unsigned long long)
890		    mpt2sas_phy->identify.sas_address,
891		    mpt2sas_phy->attached_handle,
892		    (unsigned long long)
893		    mpt2sas_phy->remote_identify.sas_address);
894	mpt2sas_phy->phy = phy;
895	return 0;
896}
897
898
899/**
900 * mpt2sas_transport_add_expander_phy - report expander phy to transport
901 * @ioc: per adapter object
902 * @mpt2sas_phy: mpt2sas per phy object
903 * @expander_pg1: expander page 1
904 * @parent_dev: parent device class object
905 *
906 * Returns 0 for success, non-zero for failure.
907 */
908int
909mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
910    *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
911{
912	struct sas_phy *phy;
913	int phy_index = mpt2sas_phy->phy_id;
914
915	INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
916	phy = sas_phy_alloc(parent_dev, phy_index);
917	if (!phy) {
918		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
919		    ioc->name, __FILE__, __LINE__, __func__);
920		return -1;
921	}
922	if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
923	    &mpt2sas_phy->identify))) {
924		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
925		    ioc->name, __FILE__, __LINE__, __func__);
926		return -1;
927	}
928	phy->identify = mpt2sas_phy->identify;
929	mpt2sas_phy->attached_handle =
930	    le16_to_cpu(expander_pg1.AttachedDevHandle);
931	if (mpt2sas_phy->attached_handle)
932		_transport_set_identify(ioc, mpt2sas_phy->attached_handle,
933		    &mpt2sas_phy->remote_identify);
934	phy->identify.phy_identifier = mpt2sas_phy->phy_id;
935	phy->negotiated_linkrate = _transport_convert_phy_link_rate(
936	    expander_pg1.NegotiatedLinkRate &
937	    MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
938	phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
939	    expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
940	phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
941	    expander_pg1.HwLinkRate >> 4);
942	phy->minimum_linkrate = _transport_convert_phy_link_rate(
943	    expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
944	phy->maximum_linkrate = _transport_convert_phy_link_rate(
945	    expander_pg1.ProgrammedLinkRate >> 4);
946
947	if ((sas_phy_add(phy))) {
948		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
949		    ioc->name, __FILE__, __LINE__, __func__);
950		sas_phy_free(phy);
951		return -1;
952	}
953	if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
954		dev_printk(KERN_INFO, &phy->dev,
955		    "add: handle(0x%04x), sas_addr(0x%016llx)\n"
956		    "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
957		    mpt2sas_phy->handle, (unsigned long long)
958		    mpt2sas_phy->identify.sas_address,
959		    mpt2sas_phy->attached_handle,
960		    (unsigned long long)
961		    mpt2sas_phy->remote_identify.sas_address);
962	mpt2sas_phy->phy = phy;
963	return 0;
964}
965
966/**
967 * mpt2sas_transport_update_links - refreshing phy link changes
968 * @ioc: per adapter object
969 * @sas_address: sas address of parent expander or sas host
970 * @handle: attached device handle
971 * @phy_numberv: phy number
972 * @link_rate: new link rate
973 *
974 * Returns nothing.
975 */
976void
977mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
978     u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
979{
980	unsigned long flags;
981	struct _sas_node *sas_node;
982	struct _sas_phy *mpt2sas_phy;
983
984	if (ioc->shost_recovery || ioc->pci_error_recovery)
985		return;
986
987	spin_lock_irqsave(&ioc->sas_node_lock, flags);
988	sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
989	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
990	if (!sas_node)
991		return;
992
993	mpt2sas_phy = &sas_node->phy[phy_number];
994	mpt2sas_phy->attached_handle = handle;
995	if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
996		_transport_set_identify(ioc, handle,
997		    &mpt2sas_phy->remote_identify);
998		_transport_add_phy_to_an_existing_port(ioc, sas_node,
999		    mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address);
1000	} else
1001		memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
1002		    sas_identify));
1003
1004	if (mpt2sas_phy->phy)
1005		mpt2sas_phy->phy->negotiated_linkrate =
1006		    _transport_convert_phy_link_rate(link_rate);
1007
1008	if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
1009		dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
1010		    "refresh: parent sas_addr(0x%016llx),\n"
1011		    "\tlink_rate(0x%02x), phy(%d)\n"
1012		    "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
1013		    (unsigned long long)sas_address,
1014		    link_rate, phy_number, handle, (unsigned long long)
1015		    mpt2sas_phy->remote_identify.sas_address);
1016}
1017
1018static inline void *
1019phy_to_ioc(struct sas_phy *phy)
1020{
1021	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1022	return shost_priv(shost);
1023}
1024
1025static inline void *
1026rphy_to_ioc(struct sas_rphy *rphy)
1027{
1028	struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
1029	return shost_priv(shost);
1030}
1031
1032
1033/* report phy error log structure */
1034struct phy_error_log_request{
1035	u8 smp_frame_type; /* 0x40 */
1036	u8 function; /* 0x11 */
1037	u8 allocated_response_length;
1038	u8 request_length; /* 02 */
1039	u8 reserved_1[5];
1040	u8 phy_identifier;
1041	u8 reserved_2[2];
1042};
1043
1044/* report phy error log reply structure */
1045struct phy_error_log_reply{
1046	u8 smp_frame_type; /* 0x41 */
1047	u8 function; /* 0x11 */
1048	u8 function_result;
1049	u8 response_length;
1050	__be16 expander_change_count;
1051	u8 reserved_1[3];
1052	u8 phy_identifier;
1053	u8 reserved_2[2];
1054	__be32 invalid_dword;
1055	__be32 running_disparity_error;
1056	__be32 loss_of_dword_sync;
1057	__be32 phy_reset_problem;
1058};
1059
1060/**
1061 * _transport_get_expander_phy_error_log - return expander counters
1062 * @ioc: per adapter object
1063 * @phy: The sas phy object
1064 *
1065 * Returns 0 for success, non-zero for failure.
1066 *
1067 */
1068static int
1069_transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
1070    struct sas_phy *phy)
1071{
1072	Mpi2SmpPassthroughRequest_t *mpi_request;
1073	Mpi2SmpPassthroughReply_t *mpi_reply;
1074	struct phy_error_log_request *phy_error_log_request;
1075	struct phy_error_log_reply *phy_error_log_reply;
1076	int rc;
1077	u16 smid;
1078	u32 ioc_state;
1079	unsigned long timeleft;
1080	void *psge;
1081	u32 sgl_flags;
1082	u8 issue_reset = 0;
1083	void *data_out = NULL;
1084	dma_addr_t data_out_dma;
1085	u32 sz;
1086	u16 wait_state_count;
1087
1088	if (ioc->shost_recovery || ioc->pci_error_recovery) {
1089		printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1090		    __func__, ioc->name);
1091		return -EFAULT;
1092	}
1093
1094	mutex_lock(&ioc->transport_cmds.mutex);
1095
1096	if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1097		printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
1098		    ioc->name, __func__);
1099		rc = -EAGAIN;
1100		goto out;
1101	}
1102	ioc->transport_cmds.status = MPT2_CMD_PENDING;
1103
1104	wait_state_count = 0;
1105	ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1106	while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1107		if (wait_state_count++ == 10) {
1108			printk(MPT2SAS_ERR_FMT
1109			    "%s: failed due to ioc not operational\n",
1110			    ioc->name, __func__);
1111			rc = -EFAULT;
1112			goto out;
1113		}
1114		ssleep(1);
1115		ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1116		printk(MPT2SAS_INFO_FMT "%s: waiting for "
1117		    "operational state(count=%d)\n", ioc->name,
1118		    __func__, wait_state_count);
1119	}
1120	if (wait_state_count)
1121		printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1122		    ioc->name, __func__);
1123
1124	smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1125	if (!smid) {
1126		printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1127		    ioc->name, __func__);
1128		rc = -EAGAIN;
1129		goto out;
1130	}
1131
1132	mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1133	ioc->transport_cmds.smid = smid;
1134
1135	sz = sizeof(struct phy_error_log_request) +
1136	    sizeof(struct phy_error_log_reply);
1137	data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1138	if (!data_out) {
1139		printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
1140		    __LINE__, __func__);
1141		rc = -ENOMEM;
1142		mpt2sas_base_free_smid(ioc, smid);
1143		goto out;
1144	}
1145
1146	rc = -EINVAL;
1147	memset(data_out, 0, sz);
1148	phy_error_log_request = data_out;
1149	phy_error_log_request->smp_frame_type = 0x40;
1150	phy_error_log_request->function = 0x11;
1151	phy_error_log_request->request_length = 2;
1152	phy_error_log_request->allocated_response_length = 0;
1153	phy_error_log_request->phy_identifier = phy->number;
1154
1155	memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1156	mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1157	mpi_request->PhysicalPort = 0xFF;
1158	mpi_request->VF_ID = 0; /* TODO */
1159	mpi_request->VP_ID = 0;
1160	mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1161	mpi_request->RequestDataLength =
1162	    cpu_to_le16(sizeof(struct phy_error_log_request));
1163	psge = &mpi_request->SGL;
1164
1165	/* WRITE sgel first */
1166	sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1167	    MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1168	sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1169	ioc->base_add_sg_single(psge, sgl_flags |
1170	    sizeof(struct phy_error_log_request), data_out_dma);
1171
1172	/* incr sgel */
1173	psge += ioc->sge_size;
1174
1175	/* READ sgel last */
1176	sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1177	    MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1178	    MPI2_SGE_FLAGS_END_OF_LIST);
1179	sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1180	ioc->base_add_sg_single(psge, sgl_flags |
1181	    sizeof(struct phy_error_log_reply), data_out_dma +
1182	    sizeof(struct phy_error_log_request));
1183
1184	dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
1185	    "send to sas_addr(0x%016llx), phy(%d)\n", ioc->name,
1186	    (unsigned long long)phy->identify.sas_address, phy->number));
1187	init_completion(&ioc->transport_cmds.done);
1188	mpt2sas_base_put_smid_default(ioc, smid);
1189	timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1190	    10*HZ);
1191
1192	if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1193		printk(MPT2SAS_ERR_FMT "%s: timeout\n",
1194		    ioc->name, __func__);
1195		_debug_dump_mf(mpi_request,
1196		    sizeof(Mpi2SmpPassthroughRequest_t)/4);
1197		if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1198			issue_reset = 1;
1199		goto issue_host_reset;
1200	}
1201
1202	dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
1203	    "complete\n", ioc->name));
1204
1205	if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1206
1207		mpi_reply = ioc->transport_cmds.reply;
1208
1209		dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1210		    "phy_error_log - reply data transfer size(%d)\n",
1211		    ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1212
1213		if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1214		    sizeof(struct phy_error_log_reply))
1215			goto out;
1216
1217		phy_error_log_reply = data_out +
1218		    sizeof(struct phy_error_log_request);
1219
1220		dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1221		    "phy_error_log - function_result(%d)\n",
1222		    ioc->name, phy_error_log_reply->function_result));
1223
1224		phy->invalid_dword_count =
1225		    be32_to_cpu(phy_error_log_reply->invalid_dword);
1226		phy->running_disparity_error_count =
1227		    be32_to_cpu(phy_error_log_reply->running_disparity_error);
1228		phy->loss_of_dword_sync_count =
1229		    be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
1230		phy->phy_reset_problem_count =
1231		    be32_to_cpu(phy_error_log_reply->phy_reset_problem);
1232		rc = 0;
1233	} else
1234		dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1235		    "phy_error_log - no reply\n", ioc->name));
1236
1237 issue_host_reset:
1238	if (issue_reset)
1239		mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1240		    FORCE_BIG_HAMMER);
1241 out:
1242	ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1243	if (data_out)
1244		pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1245
1246	mutex_unlock(&ioc->transport_cmds.mutex);
1247	return rc;
1248}
1249
1250/**
1251 * _transport_get_linkerrors - return phy counters for both hba and expanders
1252 * @phy: The sas phy object
1253 *
1254 * Returns 0 for success, non-zero for failure.
1255 *
1256 */
1257static int
1258_transport_get_linkerrors(struct sas_phy *phy)
1259{
1260	struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1261	unsigned long flags;
1262	Mpi2ConfigReply_t mpi_reply;
1263	Mpi2SasPhyPage1_t phy_pg1;
1264
1265	spin_lock_irqsave(&ioc->sas_node_lock, flags);
1266	if (_transport_sas_node_find_by_sas_address(ioc,
1267	    phy->identify.sas_address) == NULL) {
1268		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1269		return -EINVAL;
1270	}
1271	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1272
1273	if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1274		return _transport_get_expander_phy_error_log(ioc, phy);
1275
1276	/* get hba phy error logs */
1277	if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
1278		    phy->number))) {
1279		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1280		    ioc->name, __FILE__, __LINE__, __func__);
1281		return -ENXIO;
1282	}
1283
1284	if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1285		printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1286		    "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1287		    phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1288		    le32_to_cpu(mpi_reply.IOCLogInfo));
1289
1290	phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
1291	phy->running_disparity_error_count =
1292	    le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
1293	phy->loss_of_dword_sync_count =
1294	    le32_to_cpu(phy_pg1.LossDwordSynchCount);
1295	phy->phy_reset_problem_count =
1296	    le32_to_cpu(phy_pg1.PhyResetProblemCount);
1297	return 0;
1298}
1299
1300/**
1301 * _transport_get_enclosure_identifier -
1302 * @phy: The sas phy object
1303 *
1304 * Obtain the enclosure logical id for an expander.
1305 * Returns 0 for success, non-zero for failure.
1306 */
1307static int
1308_transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1309{
1310	struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1311	struct _sas_device *sas_device;
1312	unsigned long flags;
1313
1314	spin_lock_irqsave(&ioc->sas_device_lock, flags);
1315	sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1316	    rphy->identify.sas_address);
1317	spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1318
1319	if (!sas_device)
1320		return -ENXIO;
1321
1322	*identifier = sas_device->enclosure_logical_id;
1323	return 0;
1324}
1325
1326/**
1327 * _transport_get_bay_identifier -
1328 * @phy: The sas phy object
1329 *
1330 * Returns the slot id for a device that resides inside an enclosure.
1331 */
1332static int
1333_transport_get_bay_identifier(struct sas_rphy *rphy)
1334{
1335	struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1336	struct _sas_device *sas_device;
1337	unsigned long flags;
1338
1339	spin_lock_irqsave(&ioc->sas_device_lock, flags);
1340	sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1341	    rphy->identify.sas_address);
1342	spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1343
1344	if (!sas_device)
1345		return -ENXIO;
1346
1347	return sas_device->slot;
1348}
1349
1350/* phy control request structure */
1351struct phy_control_request{
1352	u8 smp_frame_type; /* 0x40 */
1353	u8 function; /* 0x91 */
1354	u8 allocated_response_length;
1355	u8 request_length; /* 0x09 */
1356	u16 expander_change_count;
1357	u8 reserved_1[3];
1358	u8 phy_identifier;
1359	u8 phy_operation;
1360	u8 reserved_2[13];
1361	u64 attached_device_name;
1362	u8 programmed_min_physical_link_rate;
1363	u8 programmed_max_physical_link_rate;
1364	u8 reserved_3[6];
1365};
1366
1367/* phy control reply structure */
1368struct phy_control_reply{
1369	u8 smp_frame_type; /* 0x41 */
1370	u8 function; /* 0x11 */
1371	u8 function_result;
1372	u8 response_length;
1373};
1374
1375#define SMP_PHY_CONTROL_LINK_RESET	(0x01)
1376#define SMP_PHY_CONTROL_HARD_RESET	(0x02)
1377#define SMP_PHY_CONTROL_DISABLE		(0x03)
1378
1379/**
1380 * _transport_expander_phy_control - expander phy control
1381 * @ioc: per adapter object
1382 * @phy: The sas phy object
1383 *
1384 * Returns 0 for success, non-zero for failure.
1385 *
1386 */
1387static int
1388_transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
1389    struct sas_phy *phy, u8 phy_operation)
1390{
1391	Mpi2SmpPassthroughRequest_t *mpi_request;
1392	Mpi2SmpPassthroughReply_t *mpi_reply;
1393	struct phy_control_request *phy_control_request;
1394	struct phy_control_reply *phy_control_reply;
1395	int rc;
1396	u16 smid;
1397	u32 ioc_state;
1398	unsigned long timeleft;
1399	void *psge;
1400	u32 sgl_flags;
1401	u8 issue_reset = 0;
1402	void *data_out = NULL;
1403	dma_addr_t data_out_dma;
1404	u32 sz;
1405	u16 wait_state_count;
1406
1407	if (ioc->shost_recovery) {
1408		printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1409		    __func__, ioc->name);
1410		return -EFAULT;
1411	}
1412
1413	mutex_lock(&ioc->transport_cmds.mutex);
1414
1415	if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1416		printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
1417		    ioc->name, __func__);
1418		rc = -EAGAIN;
1419		goto out;
1420	}
1421	ioc->transport_cmds.status = MPT2_CMD_PENDING;
1422
1423	wait_state_count = 0;
1424	ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1425	while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1426		if (wait_state_count++ == 10) {
1427			printk(MPT2SAS_ERR_FMT
1428			    "%s: failed due to ioc not operational\n",
1429			    ioc->name, __func__);
1430			rc = -EFAULT;
1431			goto out;
1432		}
1433		ssleep(1);
1434		ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1435		printk(MPT2SAS_INFO_FMT "%s: waiting for "
1436		    "operational state(count=%d)\n", ioc->name,
1437		    __func__, wait_state_count);
1438	}
1439	if (wait_state_count)
1440		printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1441		    ioc->name, __func__);
1442
1443	smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1444	if (!smid) {
1445		printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1446		    ioc->name, __func__);
1447		rc = -EAGAIN;
1448		goto out;
1449	}
1450
1451	mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1452	ioc->transport_cmds.smid = smid;
1453
1454	sz = sizeof(struct phy_control_request) +
1455	    sizeof(struct phy_control_reply);
1456	data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1457	if (!data_out) {
1458		printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
1459		    __LINE__, __func__);
1460		rc = -ENOMEM;
1461		mpt2sas_base_free_smid(ioc, smid);
1462		goto out;
1463	}
1464
1465	rc = -EINVAL;
1466	memset(data_out, 0, sz);
1467	phy_control_request = data_out;
1468	phy_control_request->smp_frame_type = 0x40;
1469	phy_control_request->function = 0x91;
1470	phy_control_request->request_length = 9;
1471	phy_control_request->allocated_response_length = 0;
1472	phy_control_request->phy_identifier = phy->number;
1473	phy_control_request->phy_operation = phy_operation;
1474	phy_control_request->programmed_min_physical_link_rate =
1475	    phy->minimum_linkrate << 4;
1476	phy_control_request->programmed_max_physical_link_rate =
1477	    phy->maximum_linkrate << 4;
1478
1479	memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1480	mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1481	mpi_request->PhysicalPort = 0xFF;
1482	mpi_request->VF_ID = 0; /* TODO */
1483	mpi_request->VP_ID = 0;
1484	mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1485	mpi_request->RequestDataLength =
1486	    cpu_to_le16(sizeof(struct phy_error_log_request));
1487	psge = &mpi_request->SGL;
1488
1489	/* WRITE sgel first */
1490	sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1491	    MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1492	sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1493	ioc->base_add_sg_single(psge, sgl_flags |
1494	    sizeof(struct phy_control_request), data_out_dma);
1495
1496	/* incr sgel */
1497	psge += ioc->sge_size;
1498
1499	/* READ sgel last */
1500	sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1501	    MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1502	    MPI2_SGE_FLAGS_END_OF_LIST);
1503	sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1504	ioc->base_add_sg_single(psge, sgl_flags |
1505	    sizeof(struct phy_control_reply), data_out_dma +
1506	    sizeof(struct phy_control_request));
1507
1508	dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
1509	    "send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", ioc->name,
1510	    (unsigned long long)phy->identify.sas_address, phy->number,
1511	    phy_operation));
1512
1513	init_completion(&ioc->transport_cmds.done);
1514	mpt2sas_base_put_smid_default(ioc, smid);
1515	timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1516	    10*HZ);
1517
1518	if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1519		printk(MPT2SAS_ERR_FMT "%s: timeout\n",
1520		    ioc->name, __func__);
1521		_debug_dump_mf(mpi_request,
1522		    sizeof(Mpi2SmpPassthroughRequest_t)/4);
1523		if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1524			issue_reset = 1;
1525		goto issue_host_reset;
1526	}
1527
1528	dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
1529	    "complete\n", ioc->name));
1530
1531	if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1532
1533		mpi_reply = ioc->transport_cmds.reply;
1534
1535		dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1536		    "phy_control - reply data transfer size(%d)\n",
1537		    ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1538
1539		if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1540		    sizeof(struct phy_control_reply))
1541			goto out;
1542
1543		phy_control_reply = data_out +
1544		    sizeof(struct phy_control_request);
1545
1546		dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1547		    "phy_control - function_result(%d)\n",
1548		    ioc->name, phy_control_reply->function_result));
1549
1550		rc = 0;
1551	} else
1552		dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1553		    "phy_control - no reply\n", ioc->name));
1554
1555 issue_host_reset:
1556	if (issue_reset)
1557		mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1558		    FORCE_BIG_HAMMER);
1559 out:
1560	ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1561	if (data_out)
1562		pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1563
1564	mutex_unlock(&ioc->transport_cmds.mutex);
1565	return rc;
1566}
1567
1568/**
1569 * _transport_phy_reset -
1570 * @phy: The sas phy object
1571 * @hard_reset:
1572 *
1573 * Returns 0 for success, non-zero for failure.
1574 */
1575static int
1576_transport_phy_reset(struct sas_phy *phy, int hard_reset)
1577{
1578	struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1579	Mpi2SasIoUnitControlReply_t mpi_reply;
1580	Mpi2SasIoUnitControlRequest_t mpi_request;
1581	unsigned long flags;
1582
1583	spin_lock_irqsave(&ioc->sas_node_lock, flags);
1584	if (_transport_sas_node_find_by_sas_address(ioc,
1585	    phy->identify.sas_address) == NULL) {
1586		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1587		return -EINVAL;
1588	}
1589	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1590
1591	/* handle expander phys */
1592	if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1593		return _transport_expander_phy_control(ioc, phy,
1594		    (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
1595		    SMP_PHY_CONTROL_LINK_RESET);
1596
1597	/* handle hba phys */
1598	memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
1599	mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
1600	mpi_request.Operation = hard_reset ?
1601	    MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
1602	mpi_request.PhyNum = phy->number;
1603
1604	if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
1605		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1606		    ioc->name, __FILE__, __LINE__, __func__);
1607		return -ENXIO;
1608	}
1609
1610	if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1611		printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1612		    "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1613		    phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1614		    le32_to_cpu(mpi_reply.IOCLogInfo));
1615
1616	return 0;
1617}
1618
1619/**
1620 * _transport_phy_enable - enable/disable phys
1621 * @phy: The sas phy object
1622 * @enable: enable phy when true
1623 *
1624 * Only support sas_host direct attached phys.
1625 * Returns 0 for success, non-zero for failure.
1626 */
1627static int
1628_transport_phy_enable(struct sas_phy *phy, int enable)
1629{
1630	struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1631	Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1632	Mpi2ConfigReply_t mpi_reply;
1633	u16 ioc_status;
1634	u16 sz;
1635	int rc = 0;
1636	unsigned long flags;
1637
1638	spin_lock_irqsave(&ioc->sas_node_lock, flags);
1639	if (_transport_sas_node_find_by_sas_address(ioc,
1640	    phy->identify.sas_address) == NULL) {
1641		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1642		return -EINVAL;
1643	}
1644	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1645
1646	/* handle expander phys */
1647	if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1648		return _transport_expander_phy_control(ioc, phy,
1649		    (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
1650		    SMP_PHY_CONTROL_DISABLE);
1651
1652	/* handle hba phys */
1653
1654	/* sas_iounit page 1 */
1655	sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1656	    sizeof(Mpi2SasIOUnit1PhyData_t));
1657	sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1658	if (!sas_iounit_pg1) {
1659		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1660		    ioc->name, __FILE__, __LINE__, __func__);
1661		rc = -ENOMEM;
1662		goto out;
1663	}
1664	if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1665	    sas_iounit_pg1, sz))) {
1666		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1667		    ioc->name, __FILE__, __LINE__, __func__);
1668		rc = -ENXIO;
1669		goto out;
1670	}
1671	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1672	    MPI2_IOCSTATUS_MASK;
1673	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1674		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1675		    ioc->name, __FILE__, __LINE__, __func__);
1676		rc = -EIO;
1677		goto out;
1678	}
1679
1680	if (enable)
1681		sas_iounit_pg1->PhyData[phy->number].PhyFlags
1682		    &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1683	else
1684		sas_iounit_pg1->PhyData[phy->number].PhyFlags
1685		    |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1686
1687	mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1688
1689	/* link reset */
1690	if (enable)
1691		_transport_phy_reset(phy, 0);
1692
1693 out:
1694	kfree(sas_iounit_pg1);
1695	return rc;
1696}
1697
1698/**
1699 * _transport_phy_speed - set phy min/max link rates
1700 * @phy: The sas phy object
1701 * @rates: rates defined in sas_phy_linkrates
1702 *
1703 * Only support sas_host direct attached phys.
1704 * Returns 0 for success, non-zero for failure.
1705 */
1706static int
1707_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1708{
1709	struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1710	Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1711	Mpi2SasPhyPage0_t phy_pg0;
1712	Mpi2ConfigReply_t mpi_reply;
1713	u16 ioc_status;
1714	u16 sz;
1715	int i;
1716	int rc = 0;
1717	unsigned long flags;
1718
1719	spin_lock_irqsave(&ioc->sas_node_lock, flags);
1720	if (_transport_sas_node_find_by_sas_address(ioc,
1721	    phy->identify.sas_address) == NULL) {
1722		spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1723		return -EINVAL;
1724	}
1725	spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1726
1727	if (!rates->minimum_linkrate)
1728		rates->minimum_linkrate = phy->minimum_linkrate;
1729	else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
1730		rates->minimum_linkrate = phy->minimum_linkrate_hw;
1731
1732	if (!rates->maximum_linkrate)
1733		rates->maximum_linkrate = phy->maximum_linkrate;
1734	else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
1735		rates->maximum_linkrate = phy->maximum_linkrate_hw;
1736
1737	/* handle expander phys */
1738	if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
1739		phy->minimum_linkrate = rates->minimum_linkrate;
1740		phy->maximum_linkrate = rates->maximum_linkrate;
1741		return _transport_expander_phy_control(ioc, phy,
1742		    SMP_PHY_CONTROL_LINK_RESET);
1743	}
1744
1745	/* handle hba phys */
1746
1747	/* sas_iounit page 1 */
1748	sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1749	    sizeof(Mpi2SasIOUnit1PhyData_t));
1750	sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1751	if (!sas_iounit_pg1) {
1752		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1753		    ioc->name, __FILE__, __LINE__, __func__);
1754		rc = -ENOMEM;
1755		goto out;
1756	}
1757	if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1758	    sas_iounit_pg1, sz))) {
1759		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1760		    ioc->name, __FILE__, __LINE__, __func__);
1761		rc = -ENXIO;
1762		goto out;
1763	}
1764	ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1765	    MPI2_IOCSTATUS_MASK;
1766	if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1767		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1768		    ioc->name, __FILE__, __LINE__, __func__);
1769		rc = -EIO;
1770		goto out;
1771	}
1772
1773	for (i = 0; i < ioc->sas_hba.num_phys; i++) {
1774		if (phy->number != i) {
1775			sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1776			    (ioc->sas_hba.phy[i].phy->minimum_linkrate +
1777			    (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
1778		} else {
1779			sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1780			    (rates->minimum_linkrate +
1781			    (rates->maximum_linkrate << 4));
1782		}
1783	}
1784
1785	if (mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
1786	    sz)) {
1787		printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1788		    ioc->name, __FILE__, __LINE__, __func__);
1789		rc = -ENXIO;
1790		goto out;
1791	}
1792
1793	/* link reset */
1794	_transport_phy_reset(phy, 0);
1795
1796	/* read phy page 0, then update the rates in the sas transport phy */
1797	if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
1798	    phy->number)) {
1799		phy->minimum_linkrate = _transport_convert_phy_link_rate(
1800		    phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1801		phy->maximum_linkrate = _transport_convert_phy_link_rate(
1802		    phy_pg0.ProgrammedLinkRate >> 4);
1803		phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1804		    phy_pg0.NegotiatedLinkRate &
1805		    MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1806	}
1807
1808 out:
1809	kfree(sas_iounit_pg1);
1810	return rc;
1811}
1812
1813
1814/**
1815 * _transport_smp_handler - transport portal for smp passthru
1816 * @shost: shost object
1817 * @rphy: sas transport rphy object
1818 * @req:
1819 *
1820 * This used primarily for smp_utils.
1821 * Example:
1822 *           smp_rep_general /sys/class/bsg/expander-5:0
1823 */
1824static int
1825_transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1826    struct request *req)
1827{
1828	struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1829	Mpi2SmpPassthroughRequest_t *mpi_request;
1830	Mpi2SmpPassthroughReply_t *mpi_reply;
1831	int rc;
1832	u16 smid;
1833	u32 ioc_state;
1834	unsigned long timeleft;
1835	void *psge;
1836	u32 sgl_flags;
1837	u8 issue_reset = 0;
1838	dma_addr_t dma_addr_in = 0;
1839	dma_addr_t dma_addr_out = 0;
1840	u16 wait_state_count;
1841	struct request *rsp = req->next_rq;
1842
1843	if (!rsp) {
1844		printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
1845		    "missing\n", ioc->name, __func__);
1846		return -EINVAL;
1847	}
1848
1849	/* do we need to support multiple segments? */
1850	if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
1851		printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, "
1852		    "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt,
1853		    blk_rq_bytes(req), rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
1854		return -EINVAL;
1855	}
1856
1857	if (ioc->shost_recovery) {
1858		printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1859		    __func__, ioc->name);
1860		return -EFAULT;
1861	}
1862
1863	rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1864	if (rc)
1865		return rc;
1866
1867	if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1868		printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
1869		    __func__);
1870		rc = -EAGAIN;
1871		goto out;
1872	}
1873	ioc->transport_cmds.status = MPT2_CMD_PENDING;
1874
1875	wait_state_count = 0;
1876	ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1877	while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1878		if (wait_state_count++ == 10) {
1879			printk(MPT2SAS_ERR_FMT
1880			    "%s: failed due to ioc not operational\n",
1881			    ioc->name, __func__);
1882			rc = -EFAULT;
1883			goto out;
1884		}
1885		ssleep(1);
1886		ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1887		printk(MPT2SAS_INFO_FMT "%s: waiting for "
1888		    "operational state(count=%d)\n", ioc->name,
1889		    __func__, wait_state_count);
1890	}
1891	if (wait_state_count)
1892		printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1893		    ioc->name, __func__);
1894
1895	smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1896	if (!smid) {
1897		printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1898		    ioc->name, __func__);
1899		rc = -EAGAIN;
1900		goto out;
1901	}
1902
1903	rc = 0;
1904	mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1905	ioc->transport_cmds.smid = smid;
1906
1907	memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1908	mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1909	mpi_request->PhysicalPort = 0xFF;
1910	mpi_request->VF_ID = 0; /* TODO */
1911	mpi_request->VP_ID = 0;
1912	mpi_request->SASAddress = (rphy) ?
1913	    cpu_to_le64(rphy->identify.sas_address) :
1914	    cpu_to_le64(ioc->sas_hba.sas_address);
1915	mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
1916	psge = &mpi_request->SGL;
1917
1918	/* WRITE sgel first */
1919	sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1920	    MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1921	sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1922	dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
1923		blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
1924	if (!dma_addr_out) {
1925		mpt2sas_base_free_smid(ioc, smid);
1926		goto unmap;
1927	}
1928
1929	ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(req) - 4),
1930	    dma_addr_out);
1931
1932	/* incr sgel */
1933	psge += ioc->sge_size;
1934
1935	/* READ sgel last */
1936	sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1937	    MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1938	    MPI2_SGE_FLAGS_END_OF_LIST);
1939	sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1940	dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
1941				     blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
1942	if (!dma_addr_in) {
1943		mpt2sas_base_free_smid(ioc, smid);
1944		goto unmap;
1945	}
1946
1947	ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4),
1948	    dma_addr_in);
1949
1950	dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
1951	    "sending smp request\n", ioc->name, __func__));
1952
1953	init_completion(&ioc->transport_cmds.done);
1954	mpt2sas_base_put_smid_default(ioc, smid);
1955	timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1956	    10*HZ);
1957
1958	if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1959		printk(MPT2SAS_ERR_FMT "%s : timeout\n",
1960		    __func__, ioc->name);
1961		_debug_dump_mf(mpi_request,
1962		    sizeof(Mpi2SmpPassthroughRequest_t)/4);
1963		if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1964			issue_reset = 1;
1965		goto issue_host_reset;
1966	}
1967
1968	dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
1969	    "complete\n", ioc->name, __func__));
1970
1971	if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1972
1973		mpi_reply = ioc->transport_cmds.reply;
1974
1975		dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1976		    "%s - reply data transfer size(%d)\n",
1977		    ioc->name, __func__,
1978		    le16_to_cpu(mpi_reply->ResponseDataLength)));
1979
1980		memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
1981		req->sense_len = sizeof(*mpi_reply);
1982		req->resid_len = 0;
1983		rsp->resid_len -=
1984		    le16_to_cpu(mpi_reply->ResponseDataLength);
1985	} else {
1986		dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1987		    "%s - no reply\n", ioc->name, __func__));
1988		rc = -ENXIO;
1989	}
1990
1991 issue_host_reset:
1992	if (issue_reset) {
1993		mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1994		    FORCE_BIG_HAMMER);
1995		rc = -ETIMEDOUT;
1996	}
1997
1998 unmap:
1999	if (dma_addr_out)
2000		pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
2001		    PCI_DMA_BIDIRECTIONAL);
2002	if (dma_addr_in)
2003		pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
2004		    PCI_DMA_BIDIRECTIONAL);
2005
2006 out:
2007	ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
2008	mutex_unlock(&ioc->transport_cmds.mutex);
2009	return rc;
2010}
2011
2012struct sas_function_template mpt2sas_transport_functions = {
2013	.get_linkerrors		= _transport_get_linkerrors,
2014	.get_enclosure_identifier = _transport_get_enclosure_identifier,
2015	.get_bay_identifier	= _transport_get_bay_identifier,
2016	.phy_reset		= _transport_phy_reset,
2017	.phy_enable		= _transport_phy_enable,
2018	.set_phy_speed		= _transport_phy_speed,
2019	.smp_handler		= _transport_smp_handler,
2020};
2021
2022struct scsi_transport_template *mpt2sas_transport_template;
2023