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