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