perf record: Fix segfault with --no-mmap-pages
[linux/fpc-iii.git] / drivers / scsi / mpt3sas / mpt3sas_transport.c
blobe771a88c6a7441c45c6b49e8ffb85d5258b22e99
1 /*
2 * SAS Transport Layer for MPT (Message Passing Technology) based controllers
4 * This code is based on drivers/scsi/mpt3sas/mpt3sas_transport.c
5 * Copyright (C) 2012-2013 LSI Corporation
6 * (mailto:DL-MPTFusionLinux@lsi.com)
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.
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.
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.
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
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.
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>
53 #include <scsi/scsi.h>
54 #include <scsi/scsi_cmnd.h>
55 #include <scsi/scsi_device.h>
56 #include <scsi/scsi_host.h>
57 #include <scsi/scsi_transport_sas.h>
58 #include <scsi/scsi_dbg.h>
60 #include "mpt3sas_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.
68 * Search for either hba phys or expander device based on handle, then returns
69 * the sas_node object.
71 static struct _sas_node *
72 _transport_sas_node_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
73 u64 sas_address)
75 if (ioc->sas_hba.sas_address == sas_address)
76 return &ioc->sas_hba;
77 else
78 return mpt3sas_scsih_expander_find_by_sas_address(ioc,
79 sas_address);
82 /**
83 * _transport_convert_phy_link_rate -
84 * @link_rate: link rate returned from mpt firmware
86 * Convert link_rate from mpi fusion into sas_transport form.
88 static enum sas_linkrate
89 _transport_convert_phy_link_rate(u8 link_rate)
91 enum sas_linkrate rc;
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 MPI25_SAS_NEG_LINK_RATE_12_0:
104 rc = SAS_LINK_RATE_12_0_GBPS;
105 break;
106 case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED:
107 rc = SAS_PHY_DISABLED;
108 break;
109 case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
110 rc = SAS_LINK_RATE_FAILED;
111 break;
112 case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR:
113 rc = SAS_SATA_PORT_SELECTOR;
114 break;
115 case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
116 rc = SAS_PHY_RESET_IN_PROGRESS;
117 break;
119 default:
120 case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
121 case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
122 rc = SAS_LINK_RATE_UNKNOWN;
123 break;
125 return rc;
129 * _transport_set_identify - set identify for phys and end devices
130 * @ioc: per adapter object
131 * @handle: device handle
132 * @identify: sas identify info
134 * Populates sas identify info.
136 * Returns 0 for success, non-zero for failure.
138 static int
139 _transport_set_identify(struct MPT3SAS_ADAPTER *ioc, u16 handle,
140 struct sas_identify *identify)
142 Mpi2SasDevicePage0_t sas_device_pg0;
143 Mpi2ConfigReply_t mpi_reply;
144 u32 device_info;
145 u32 ioc_status;
147 if (ioc->shost_recovery || ioc->pci_error_recovery) {
148 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
149 __func__, ioc->name);
150 return -EFAULT;
153 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
154 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
155 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
156 ioc->name, __FILE__, __LINE__, __func__);
157 return -ENXIO;
160 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
161 MPI2_IOCSTATUS_MASK;
162 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
163 pr_err(MPT3SAS_FMT
164 "handle(0x%04x), ioc_status(0x%04x)\nfailure at %s:%d/%s()!\n",
165 ioc->name, handle, ioc_status,
166 __FILE__, __LINE__, __func__);
167 return -EIO;
170 memset(identify, 0, sizeof(struct sas_identify));
171 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
173 /* sas_address */
174 identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
176 /* phy number of the parent device this device is linked to */
177 identify->phy_identifier = sas_device_pg0.PhyNum;
179 /* device_type */
180 switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
181 case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
182 identify->device_type = SAS_PHY_UNUSED;
183 break;
184 case MPI2_SAS_DEVICE_INFO_END_DEVICE:
185 identify->device_type = SAS_END_DEVICE;
186 break;
187 case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER:
188 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
189 break;
190 case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER:
191 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
192 break;
195 /* initiator_port_protocols */
196 if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR)
197 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
198 if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR)
199 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
200 if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR)
201 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
202 if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST)
203 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
205 /* target_port_protocols */
206 if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
207 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
208 if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
209 identify->target_port_protocols |= SAS_PROTOCOL_STP;
210 if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET)
211 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
212 if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
213 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
215 return 0;
219 * mpt3sas_transport_done - internal transport layer callback handler.
220 * @ioc: per adapter object
221 * @smid: system request message index
222 * @msix_index: MSIX table index supplied by the OS
223 * @reply: reply message frame(lower 32bit addr)
225 * Callback handler when sending internal generated transport cmds.
226 * The callback index passed is `ioc->transport_cb_idx`
228 * Return 1 meaning mf should be freed from _base_interrupt
229 * 0 means the mf is freed from this function.
232 mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
233 u32 reply)
235 MPI2DefaultReply_t *mpi_reply;
237 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
238 if (ioc->transport_cmds.status == MPT3_CMD_NOT_USED)
239 return 1;
240 if (ioc->transport_cmds.smid != smid)
241 return 1;
242 ioc->transport_cmds.status |= MPT3_CMD_COMPLETE;
243 if (mpi_reply) {
244 memcpy(ioc->transport_cmds.reply, mpi_reply,
245 mpi_reply->MsgLength*4);
246 ioc->transport_cmds.status |= MPT3_CMD_REPLY_VALID;
248 ioc->transport_cmds.status &= ~MPT3_CMD_PENDING;
249 complete(&ioc->transport_cmds.done);
250 return 1;
253 /* report manufacture request structure */
254 struct rep_manu_request {
255 u8 smp_frame_type;
256 u8 function;
257 u8 reserved;
258 u8 request_length;
261 /* report manufacture reply structure */
262 struct rep_manu_reply {
263 u8 smp_frame_type; /* 0x41 */
264 u8 function; /* 0x01 */
265 u8 function_result;
266 u8 response_length;
267 u16 expander_change_count;
268 u8 reserved0[2];
269 u8 sas_format;
270 u8 reserved2[3];
271 u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
272 u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
273 u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
274 u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
275 u16 component_id;
276 u8 component_revision_id;
277 u8 reserved3;
278 u8 vendor_specific[8];
282 * transport_expander_report_manufacture - obtain SMP report_manufacture
283 * @ioc: per adapter object
284 * @sas_address: expander sas address
285 * @edev: the sas_expander_device object
287 * Fills in the sas_expander_device object when SMP port is created.
289 * Returns 0 for success, non-zero for failure.
291 static int
292 _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc,
293 u64 sas_address, struct sas_expander_device *edev)
295 Mpi2SmpPassthroughRequest_t *mpi_request;
296 Mpi2SmpPassthroughReply_t *mpi_reply;
297 struct rep_manu_reply *manufacture_reply;
298 struct rep_manu_request *manufacture_request;
299 int rc;
300 u16 smid;
301 u32 ioc_state;
302 unsigned long timeleft;
303 void *psge;
304 u8 issue_reset = 0;
305 void *data_out = NULL;
306 dma_addr_t data_out_dma;
307 dma_addr_t data_in_dma;
308 size_t data_in_sz;
309 size_t data_out_sz;
310 u16 wait_state_count;
312 if (ioc->shost_recovery || ioc->pci_error_recovery) {
313 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
314 __func__, ioc->name);
315 return -EFAULT;
318 mutex_lock(&ioc->transport_cmds.mutex);
320 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
321 pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n",
322 ioc->name, __func__);
323 rc = -EAGAIN;
324 goto out;
326 ioc->transport_cmds.status = MPT3_CMD_PENDING;
328 wait_state_count = 0;
329 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
330 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
331 if (wait_state_count++ == 10) {
332 pr_err(MPT3SAS_FMT
333 "%s: failed due to ioc not operational\n",
334 ioc->name, __func__);
335 rc = -EFAULT;
336 goto out;
338 ssleep(1);
339 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
340 pr_info(MPT3SAS_FMT
341 "%s: waiting for operational state(count=%d)\n",
342 ioc->name, __func__, wait_state_count);
344 if (wait_state_count)
345 pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
346 ioc->name, __func__);
348 smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
349 if (!smid) {
350 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
351 ioc->name, __func__);
352 rc = -EAGAIN;
353 goto out;
356 rc = 0;
357 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
358 ioc->transport_cmds.smid = smid;
360 data_out_sz = sizeof(struct rep_manu_request);
361 data_in_sz = sizeof(struct rep_manu_reply);
362 data_out = pci_alloc_consistent(ioc->pdev, data_out_sz + data_in_sz,
363 &data_out_dma);
365 if (!data_out) {
366 pr_err("failure at %s:%d/%s()!\n", __FILE__,
367 __LINE__, __func__);
368 rc = -ENOMEM;
369 mpt3sas_base_free_smid(ioc, smid);
370 goto out;
373 data_in_dma = data_out_dma + sizeof(struct rep_manu_request);
375 manufacture_request = data_out;
376 manufacture_request->smp_frame_type = 0x40;
377 manufacture_request->function = 1;
378 manufacture_request->reserved = 0;
379 manufacture_request->request_length = 0;
381 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
382 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
383 mpi_request->PhysicalPort = 0xFF;
384 mpi_request->SASAddress = cpu_to_le64(sas_address);
385 mpi_request->RequestDataLength = cpu_to_le16(data_out_sz);
386 psge = &mpi_request->SGL;
388 ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
389 data_in_sz);
391 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
392 "report_manufacture - send to sas_addr(0x%016llx)\n",
393 ioc->name, (unsigned long long)sas_address));
394 init_completion(&ioc->transport_cmds.done);
395 mpt3sas_base_put_smid_default(ioc, smid);
396 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
397 10*HZ);
399 if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
400 pr_err(MPT3SAS_FMT "%s: timeout\n",
401 ioc->name, __func__);
402 _debug_dump_mf(mpi_request,
403 sizeof(Mpi2SmpPassthroughRequest_t)/4);
404 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
405 issue_reset = 1;
406 goto issue_host_reset;
409 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
410 "report_manufacture - complete\n", ioc->name));
412 if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
413 u8 *tmp;
415 mpi_reply = ioc->transport_cmds.reply;
417 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
418 "report_manufacture - reply data transfer size(%d)\n",
419 ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
421 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
422 sizeof(struct rep_manu_reply))
423 goto out;
425 manufacture_reply = data_out + sizeof(struct rep_manu_request);
426 strncpy(edev->vendor_id, manufacture_reply->vendor_id,
427 SAS_EXPANDER_VENDOR_ID_LEN);
428 strncpy(edev->product_id, manufacture_reply->product_id,
429 SAS_EXPANDER_PRODUCT_ID_LEN);
430 strncpy(edev->product_rev, manufacture_reply->product_rev,
431 SAS_EXPANDER_PRODUCT_REV_LEN);
432 edev->level = manufacture_reply->sas_format & 1;
433 if (edev->level) {
434 strncpy(edev->component_vendor_id,
435 manufacture_reply->component_vendor_id,
436 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
437 tmp = (u8 *)&manufacture_reply->component_id;
438 edev->component_id = tmp[0] << 8 | tmp[1];
439 edev->component_revision_id =
440 manufacture_reply->component_revision_id;
442 } else
443 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
444 "report_manufacture - no reply\n", ioc->name));
446 issue_host_reset:
447 if (issue_reset)
448 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
449 FORCE_BIG_HAMMER);
450 out:
451 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
452 if (data_out)
453 pci_free_consistent(ioc->pdev, data_out_sz + data_in_sz,
454 data_out, data_out_dma);
456 mutex_unlock(&ioc->transport_cmds.mutex);
457 return rc;
462 * _transport_delete_port - helper function to removing a port
463 * @ioc: per adapter object
464 * @mpt3sas_port: mpt3sas per port object
466 * Returns nothing.
468 static void
469 _transport_delete_port(struct MPT3SAS_ADAPTER *ioc,
470 struct _sas_port *mpt3sas_port)
472 u64 sas_address = mpt3sas_port->remote_identify.sas_address;
473 enum sas_device_type device_type =
474 mpt3sas_port->remote_identify.device_type;
476 dev_printk(KERN_INFO, &mpt3sas_port->port->dev,
477 "remove: sas_addr(0x%016llx)\n",
478 (unsigned long long) sas_address);
480 ioc->logging_level |= MPT_DEBUG_TRANSPORT;
481 if (device_type == SAS_END_DEVICE)
482 mpt3sas_device_remove_by_sas_address(ioc, sas_address);
483 else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
484 device_type == SAS_FANOUT_EXPANDER_DEVICE)
485 mpt3sas_expander_remove(ioc, sas_address);
486 ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
490 * _transport_delete_phy - helper function to removing single phy from port
491 * @ioc: per adapter object
492 * @mpt3sas_port: mpt3sas per port object
493 * @mpt3sas_phy: mpt3sas per phy object
495 * Returns nothing.
497 static void
498 _transport_delete_phy(struct MPT3SAS_ADAPTER *ioc,
499 struct _sas_port *mpt3sas_port, struct _sas_phy *mpt3sas_phy)
501 u64 sas_address = mpt3sas_port->remote_identify.sas_address;
503 dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
504 "remove: sas_addr(0x%016llx), phy(%d)\n",
505 (unsigned long long) sas_address, mpt3sas_phy->phy_id);
507 list_del(&mpt3sas_phy->port_siblings);
508 mpt3sas_port->num_phys--;
509 sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
510 mpt3sas_phy->phy_belongs_to_port = 0;
514 * _transport_add_phy - helper function to adding single phy to port
515 * @ioc: per adapter object
516 * @mpt3sas_port: mpt3sas per port object
517 * @mpt3sas_phy: mpt3sas per phy object
519 * Returns nothing.
521 static void
522 _transport_add_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_port *mpt3sas_port,
523 struct _sas_phy *mpt3sas_phy)
525 u64 sas_address = mpt3sas_port->remote_identify.sas_address;
527 dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
528 "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
529 sas_address, mpt3sas_phy->phy_id);
531 list_add_tail(&mpt3sas_phy->port_siblings, &mpt3sas_port->phy_list);
532 mpt3sas_port->num_phys++;
533 sas_port_add_phy(mpt3sas_port->port, mpt3sas_phy->phy);
534 mpt3sas_phy->phy_belongs_to_port = 1;
538 * _transport_add_phy_to_an_existing_port - adding new phy to existing port
539 * @ioc: per adapter object
540 * @sas_node: sas node object (either expander or sas host)
541 * @mpt3sas_phy: mpt3sas per phy object
542 * @sas_address: sas address of device/expander were phy needs to be added to
544 * Returns nothing.
546 static void
547 _transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
548 struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy,
549 u64 sas_address)
551 struct _sas_port *mpt3sas_port;
552 struct _sas_phy *phy_srch;
554 if (mpt3sas_phy->phy_belongs_to_port == 1)
555 return;
557 list_for_each_entry(mpt3sas_port, &sas_node->sas_port_list,
558 port_list) {
559 if (mpt3sas_port->remote_identify.sas_address !=
560 sas_address)
561 continue;
562 list_for_each_entry(phy_srch, &mpt3sas_port->phy_list,
563 port_siblings) {
564 if (phy_srch == mpt3sas_phy)
565 return;
567 _transport_add_phy(ioc, mpt3sas_port, mpt3sas_phy);
568 return;
574 * _transport_del_phy_from_an_existing_port - delete phy from existing port
575 * @ioc: per adapter object
576 * @sas_node: sas node object (either expander or sas host)
577 * @mpt3sas_phy: mpt3sas per phy object
579 * Returns nothing.
581 static void
582 _transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
583 struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy)
585 struct _sas_port *mpt3sas_port, *next;
586 struct _sas_phy *phy_srch;
588 if (mpt3sas_phy->phy_belongs_to_port == 0)
589 return;
591 list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list,
592 port_list) {
593 list_for_each_entry(phy_srch, &mpt3sas_port->phy_list,
594 port_siblings) {
595 if (phy_srch != mpt3sas_phy)
596 continue;
598 if (mpt3sas_port->num_phys == 1)
599 _transport_delete_port(ioc, mpt3sas_port);
600 else
601 _transport_delete_phy(ioc, mpt3sas_port,
602 mpt3sas_phy);
603 return;
609 * _transport_sanity_check - sanity check when adding a new port
610 * @ioc: per adapter object
611 * @sas_node: sas node object (either expander or sas host)
612 * @sas_address: sas address of device being added
614 * See the explanation above from _transport_delete_duplicate_port
616 static void
617 _transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node,
618 u64 sas_address)
620 int i;
622 for (i = 0; i < sas_node->num_phys; i++) {
623 if (sas_node->phy[i].remote_identify.sas_address != sas_address)
624 continue;
625 if (sas_node->phy[i].phy_belongs_to_port == 1)
626 _transport_del_phy_from_an_existing_port(ioc, sas_node,
627 &sas_node->phy[i]);
632 * mpt3sas_transport_port_add - insert port to the list
633 * @ioc: per adapter object
634 * @handle: handle of attached device
635 * @sas_address: sas address of parent expander or sas host
636 * Context: This function will acquire ioc->sas_node_lock.
638 * Adding new port object to the sas_node->sas_port_list.
640 * Returns mpt3sas_port.
642 struct _sas_port *
643 mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
644 u64 sas_address)
646 struct _sas_phy *mpt3sas_phy, *next;
647 struct _sas_port *mpt3sas_port;
648 unsigned long flags;
649 struct _sas_node *sas_node;
650 struct sas_rphy *rphy;
651 int i;
652 struct sas_port *port;
654 mpt3sas_port = kzalloc(sizeof(struct _sas_port),
655 GFP_KERNEL);
656 if (!mpt3sas_port) {
657 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
658 ioc->name, __FILE__, __LINE__, __func__);
659 return NULL;
662 INIT_LIST_HEAD(&mpt3sas_port->port_list);
663 INIT_LIST_HEAD(&mpt3sas_port->phy_list);
664 spin_lock_irqsave(&ioc->sas_node_lock, flags);
665 sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
666 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
668 if (!sas_node) {
669 pr_err(MPT3SAS_FMT
670 "%s: Could not find parent sas_address(0x%016llx)!\n",
671 ioc->name, __func__, (unsigned long long)sas_address);
672 goto out_fail;
675 if ((_transport_set_identify(ioc, handle,
676 &mpt3sas_port->remote_identify))) {
677 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
678 ioc->name, __FILE__, __LINE__, __func__);
679 goto out_fail;
682 if (mpt3sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
683 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
684 ioc->name, __FILE__, __LINE__, __func__);
685 goto out_fail;
688 _transport_sanity_check(ioc, sas_node,
689 mpt3sas_port->remote_identify.sas_address);
691 for (i = 0; i < sas_node->num_phys; i++) {
692 if (sas_node->phy[i].remote_identify.sas_address !=
693 mpt3sas_port->remote_identify.sas_address)
694 continue;
695 list_add_tail(&sas_node->phy[i].port_siblings,
696 &mpt3sas_port->phy_list);
697 mpt3sas_port->num_phys++;
700 if (!mpt3sas_port->num_phys) {
701 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
702 ioc->name, __FILE__, __LINE__, __func__);
703 goto out_fail;
706 port = sas_port_alloc_num(sas_node->parent_dev);
707 if ((sas_port_add(port))) {
708 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
709 ioc->name, __FILE__, __LINE__, __func__);
710 goto out_fail;
713 list_for_each_entry(mpt3sas_phy, &mpt3sas_port->phy_list,
714 port_siblings) {
715 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
716 dev_printk(KERN_INFO, &port->dev,
717 "add: handle(0x%04x), sas_addr(0x%016llx), phy(%d)\n",
718 handle, (unsigned long long)
719 mpt3sas_port->remote_identify.sas_address,
720 mpt3sas_phy->phy_id);
721 sas_port_add_phy(port, mpt3sas_phy->phy);
722 mpt3sas_phy->phy_belongs_to_port = 1;
725 mpt3sas_port->port = port;
726 if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE)
727 rphy = sas_end_device_alloc(port);
728 else
729 rphy = sas_expander_alloc(port,
730 mpt3sas_port->remote_identify.device_type);
732 rphy->identify = mpt3sas_port->remote_identify;
733 if ((sas_rphy_add(rphy))) {
734 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
735 ioc->name, __FILE__, __LINE__, __func__);
737 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
738 dev_printk(KERN_INFO, &rphy->dev,
739 "add: handle(0x%04x), sas_addr(0x%016llx)\n",
740 handle, (unsigned long long)
741 mpt3sas_port->remote_identify.sas_address);
742 mpt3sas_port->rphy = rphy;
743 spin_lock_irqsave(&ioc->sas_node_lock, flags);
744 list_add_tail(&mpt3sas_port->port_list, &sas_node->sas_port_list);
745 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
747 /* fill in report manufacture */
748 if (mpt3sas_port->remote_identify.device_type ==
749 MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
750 mpt3sas_port->remote_identify.device_type ==
751 MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
752 _transport_expander_report_manufacture(ioc,
753 mpt3sas_port->remote_identify.sas_address,
754 rphy_to_expander_device(rphy));
755 return mpt3sas_port;
757 out_fail:
758 list_for_each_entry_safe(mpt3sas_phy, next, &mpt3sas_port->phy_list,
759 port_siblings)
760 list_del(&mpt3sas_phy->port_siblings);
761 kfree(mpt3sas_port);
762 return NULL;
766 * mpt3sas_transport_port_remove - remove port from the list
767 * @ioc: per adapter object
768 * @sas_address: sas address of attached device
769 * @sas_address_parent: sas address of parent expander or sas host
770 * Context: This function will acquire ioc->sas_node_lock.
772 * Removing object and freeing associated memory from the
773 * ioc->sas_port_list.
775 * Return nothing.
777 void
778 mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
779 u64 sas_address_parent)
781 int i;
782 unsigned long flags;
783 struct _sas_port *mpt3sas_port, *next;
784 struct _sas_node *sas_node;
785 u8 found = 0;
786 struct _sas_phy *mpt3sas_phy, *next_phy;
788 spin_lock_irqsave(&ioc->sas_node_lock, flags);
789 sas_node = _transport_sas_node_find_by_sas_address(ioc,
790 sas_address_parent);
791 if (!sas_node) {
792 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
793 return;
795 list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list,
796 port_list) {
797 if (mpt3sas_port->remote_identify.sas_address != sas_address)
798 continue;
799 found = 1;
800 list_del(&mpt3sas_port->port_list);
801 goto out;
803 out:
804 if (!found) {
805 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
806 return;
809 for (i = 0; i < sas_node->num_phys; i++) {
810 if (sas_node->phy[i].remote_identify.sas_address == sas_address)
811 memset(&sas_node->phy[i].remote_identify, 0 ,
812 sizeof(struct sas_identify));
815 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
817 list_for_each_entry_safe(mpt3sas_phy, next_phy,
818 &mpt3sas_port->phy_list, port_siblings) {
819 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
820 dev_printk(KERN_INFO, &mpt3sas_port->port->dev,
821 "remove: sas_addr(0x%016llx), phy(%d)\n",
822 (unsigned long long)
823 mpt3sas_port->remote_identify.sas_address,
824 mpt3sas_phy->phy_id);
825 mpt3sas_phy->phy_belongs_to_port = 0;
826 sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
827 list_del(&mpt3sas_phy->port_siblings);
829 sas_port_delete(mpt3sas_port->port);
830 kfree(mpt3sas_port);
834 * mpt3sas_transport_add_host_phy - report sas_host phy to transport
835 * @ioc: per adapter object
836 * @mpt3sas_phy: mpt3sas per phy object
837 * @phy_pg0: sas phy page 0
838 * @parent_dev: parent device class object
840 * Returns 0 for success, non-zero for failure.
843 mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
844 *mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
846 struct sas_phy *phy;
847 int phy_index = mpt3sas_phy->phy_id;
850 INIT_LIST_HEAD(&mpt3sas_phy->port_siblings);
851 phy = sas_phy_alloc(parent_dev, phy_index);
852 if (!phy) {
853 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
854 ioc->name, __FILE__, __LINE__, __func__);
855 return -1;
857 if ((_transport_set_identify(ioc, mpt3sas_phy->handle,
858 &mpt3sas_phy->identify))) {
859 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
860 ioc->name, __FILE__, __LINE__, __func__);
861 sas_phy_free(phy);
862 return -1;
864 phy->identify = mpt3sas_phy->identify;
865 mpt3sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
866 if (mpt3sas_phy->attached_handle)
867 _transport_set_identify(ioc, mpt3sas_phy->attached_handle,
868 &mpt3sas_phy->remote_identify);
869 phy->identify.phy_identifier = mpt3sas_phy->phy_id;
870 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
871 phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
872 phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
873 phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
874 phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
875 phy_pg0.HwLinkRate >> 4);
876 phy->minimum_linkrate = _transport_convert_phy_link_rate(
877 phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
878 phy->maximum_linkrate = _transport_convert_phy_link_rate(
879 phy_pg0.ProgrammedLinkRate >> 4);
881 if ((sas_phy_add(phy))) {
882 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
883 ioc->name, __FILE__, __LINE__, __func__);
884 sas_phy_free(phy);
885 return -1;
887 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
888 dev_printk(KERN_INFO, &phy->dev,
889 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
890 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
891 mpt3sas_phy->handle, (unsigned long long)
892 mpt3sas_phy->identify.sas_address,
893 mpt3sas_phy->attached_handle,
894 (unsigned long long)
895 mpt3sas_phy->remote_identify.sas_address);
896 mpt3sas_phy->phy = phy;
897 return 0;
902 * mpt3sas_transport_add_expander_phy - report expander phy to transport
903 * @ioc: per adapter object
904 * @mpt3sas_phy: mpt3sas per phy object
905 * @expander_pg1: expander page 1
906 * @parent_dev: parent device class object
908 * Returns 0 for success, non-zero for failure.
911 mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
912 *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1,
913 struct device *parent_dev)
915 struct sas_phy *phy;
916 int phy_index = mpt3sas_phy->phy_id;
918 INIT_LIST_HEAD(&mpt3sas_phy->port_siblings);
919 phy = sas_phy_alloc(parent_dev, phy_index);
920 if (!phy) {
921 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
922 ioc->name, __FILE__, __LINE__, __func__);
923 return -1;
925 if ((_transport_set_identify(ioc, mpt3sas_phy->handle,
926 &mpt3sas_phy->identify))) {
927 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
928 ioc->name, __FILE__, __LINE__, __func__);
929 sas_phy_free(phy);
930 return -1;
932 phy->identify = mpt3sas_phy->identify;
933 mpt3sas_phy->attached_handle =
934 le16_to_cpu(expander_pg1.AttachedDevHandle);
935 if (mpt3sas_phy->attached_handle)
936 _transport_set_identify(ioc, mpt3sas_phy->attached_handle,
937 &mpt3sas_phy->remote_identify);
938 phy->identify.phy_identifier = mpt3sas_phy->phy_id;
939 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
940 expander_pg1.NegotiatedLinkRate &
941 MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
942 phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
943 expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
944 phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
945 expander_pg1.HwLinkRate >> 4);
946 phy->minimum_linkrate = _transport_convert_phy_link_rate(
947 expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
948 phy->maximum_linkrate = _transport_convert_phy_link_rate(
949 expander_pg1.ProgrammedLinkRate >> 4);
951 if ((sas_phy_add(phy))) {
952 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
953 ioc->name, __FILE__, __LINE__, __func__);
954 sas_phy_free(phy);
955 return -1;
957 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
958 dev_printk(KERN_INFO, &phy->dev,
959 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
960 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
961 mpt3sas_phy->handle, (unsigned long long)
962 mpt3sas_phy->identify.sas_address,
963 mpt3sas_phy->attached_handle,
964 (unsigned long long)
965 mpt3sas_phy->remote_identify.sas_address);
966 mpt3sas_phy->phy = phy;
967 return 0;
971 * mpt3sas_transport_update_links - refreshing phy link changes
972 * @ioc: per adapter object
973 * @sas_address: sas address of parent expander or sas host
974 * @handle: attached device handle
975 * @phy_numberv: phy number
976 * @link_rate: new link rate
978 * Returns nothing.
980 void
981 mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
982 u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
984 unsigned long flags;
985 struct _sas_node *sas_node;
986 struct _sas_phy *mpt3sas_phy;
988 if (ioc->shost_recovery || ioc->pci_error_recovery)
989 return;
991 spin_lock_irqsave(&ioc->sas_node_lock, flags);
992 sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
993 if (!sas_node) {
994 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
995 return;
998 mpt3sas_phy = &sas_node->phy[phy_number];
999 mpt3sas_phy->attached_handle = handle;
1000 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1001 if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
1002 _transport_set_identify(ioc, handle,
1003 &mpt3sas_phy->remote_identify);
1004 _transport_add_phy_to_an_existing_port(ioc, sas_node,
1005 mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address);
1006 } else {
1007 memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct
1008 sas_identify));
1009 _transport_del_phy_from_an_existing_port(ioc, sas_node,
1010 mpt3sas_phy);
1013 if (mpt3sas_phy->phy)
1014 mpt3sas_phy->phy->negotiated_linkrate =
1015 _transport_convert_phy_link_rate(link_rate);
1017 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
1018 dev_printk(KERN_INFO, &mpt3sas_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 mpt3sas_phy->remote_identify.sas_address);
1027 static inline void *
1028 phy_to_ioc(struct sas_phy *phy)
1030 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1031 return shost_priv(shost);
1034 static inline void *
1035 rphy_to_ioc(struct sas_rphy *rphy)
1037 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
1038 return shost_priv(shost);
1041 /* report phy error log structure */
1042 struct phy_error_log_request {
1043 u8 smp_frame_type; /* 0x40 */
1044 u8 function; /* 0x11 */
1045 u8 allocated_response_length;
1046 u8 request_length; /* 02 */
1047 u8 reserved_1[5];
1048 u8 phy_identifier;
1049 u8 reserved_2[2];
1052 /* report phy error log reply structure */
1053 struct phy_error_log_reply {
1054 u8 smp_frame_type; /* 0x41 */
1055 u8 function; /* 0x11 */
1056 u8 function_result;
1057 u8 response_length;
1058 __be16 expander_change_count;
1059 u8 reserved_1[3];
1060 u8 phy_identifier;
1061 u8 reserved_2[2];
1062 __be32 invalid_dword;
1063 __be32 running_disparity_error;
1064 __be32 loss_of_dword_sync;
1065 __be32 phy_reset_problem;
1069 * _transport_get_expander_phy_error_log - return expander counters
1070 * @ioc: per adapter object
1071 * @phy: The sas phy object
1073 * Returns 0 for success, non-zero for failure.
1076 static int
1077 _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc,
1078 struct sas_phy *phy)
1080 Mpi2SmpPassthroughRequest_t *mpi_request;
1081 Mpi2SmpPassthroughReply_t *mpi_reply;
1082 struct phy_error_log_request *phy_error_log_request;
1083 struct phy_error_log_reply *phy_error_log_reply;
1084 int rc;
1085 u16 smid;
1086 u32 ioc_state;
1087 unsigned long timeleft;
1088 void *psge;
1089 u8 issue_reset = 0;
1090 void *data_out = NULL;
1091 dma_addr_t data_out_dma;
1092 u32 sz;
1093 u16 wait_state_count;
1095 if (ioc->shost_recovery || ioc->pci_error_recovery) {
1096 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
1097 __func__, ioc->name);
1098 return -EFAULT;
1101 mutex_lock(&ioc->transport_cmds.mutex);
1103 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1104 pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n",
1105 ioc->name, __func__);
1106 rc = -EAGAIN;
1107 goto out;
1109 ioc->transport_cmds.status = MPT3_CMD_PENDING;
1111 wait_state_count = 0;
1112 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1113 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1114 if (wait_state_count++ == 10) {
1115 pr_err(MPT3SAS_FMT
1116 "%s: failed due to ioc not operational\n",
1117 ioc->name, __func__);
1118 rc = -EFAULT;
1119 goto out;
1121 ssleep(1);
1122 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1123 pr_info(MPT3SAS_FMT
1124 "%s: waiting for operational state(count=%d)\n",
1125 ioc->name, __func__, wait_state_count);
1127 if (wait_state_count)
1128 pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
1129 ioc->name, __func__);
1131 smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
1132 if (!smid) {
1133 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
1134 ioc->name, __func__);
1135 rc = -EAGAIN;
1136 goto out;
1139 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1140 ioc->transport_cmds.smid = smid;
1142 sz = sizeof(struct phy_error_log_request) +
1143 sizeof(struct phy_error_log_reply);
1144 data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1145 if (!data_out) {
1146 pr_err("failure at %s:%d/%s()!\n", __FILE__,
1147 __LINE__, __func__);
1148 rc = -ENOMEM;
1149 mpt3sas_base_free_smid(ioc, smid);
1150 goto out;
1153 rc = -EINVAL;
1154 memset(data_out, 0, sz);
1155 phy_error_log_request = data_out;
1156 phy_error_log_request->smp_frame_type = 0x40;
1157 phy_error_log_request->function = 0x11;
1158 phy_error_log_request->request_length = 2;
1159 phy_error_log_request->allocated_response_length = 0;
1160 phy_error_log_request->phy_identifier = phy->number;
1162 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1163 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1164 mpi_request->PhysicalPort = 0xFF;
1165 mpi_request->VF_ID = 0; /* TODO */
1166 mpi_request->VP_ID = 0;
1167 mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1168 mpi_request->RequestDataLength =
1169 cpu_to_le16(sizeof(struct phy_error_log_request));
1170 psge = &mpi_request->SGL;
1172 ioc->build_sg(ioc, psge, data_out_dma,
1173 sizeof(struct phy_error_log_request),
1174 data_out_dma + sizeof(struct phy_error_log_request),
1175 sizeof(struct phy_error_log_reply));
1177 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1178 "phy_error_log - send to sas_addr(0x%016llx), phy(%d)\n",
1179 ioc->name, (unsigned long long)phy->identify.sas_address,
1180 phy->number));
1181 init_completion(&ioc->transport_cmds.done);
1182 mpt3sas_base_put_smid_default(ioc, smid);
1183 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1184 10*HZ);
1186 if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
1187 pr_err(MPT3SAS_FMT "%s: timeout\n",
1188 ioc->name, __func__);
1189 _debug_dump_mf(mpi_request,
1190 sizeof(Mpi2SmpPassthroughRequest_t)/4);
1191 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
1192 issue_reset = 1;
1193 goto issue_host_reset;
1196 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1197 "phy_error_log - complete\n", ioc->name));
1199 if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
1201 mpi_reply = ioc->transport_cmds.reply;
1203 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1204 "phy_error_log - reply data transfer size(%d)\n",
1205 ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1207 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1208 sizeof(struct phy_error_log_reply))
1209 goto out;
1211 phy_error_log_reply = data_out +
1212 sizeof(struct phy_error_log_request);
1214 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1215 "phy_error_log - function_result(%d)\n",
1216 ioc->name, phy_error_log_reply->function_result));
1218 phy->invalid_dword_count =
1219 be32_to_cpu(phy_error_log_reply->invalid_dword);
1220 phy->running_disparity_error_count =
1221 be32_to_cpu(phy_error_log_reply->running_disparity_error);
1222 phy->loss_of_dword_sync_count =
1223 be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
1224 phy->phy_reset_problem_count =
1225 be32_to_cpu(phy_error_log_reply->phy_reset_problem);
1226 rc = 0;
1227 } else
1228 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1229 "phy_error_log - no reply\n", ioc->name));
1231 issue_host_reset:
1232 if (issue_reset)
1233 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1234 FORCE_BIG_HAMMER);
1235 out:
1236 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
1237 if (data_out)
1238 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1240 mutex_unlock(&ioc->transport_cmds.mutex);
1241 return rc;
1245 * _transport_get_linkerrors - return phy counters for both hba and expanders
1246 * @phy: The sas phy object
1248 * Returns 0 for success, non-zero for failure.
1251 static int
1252 _transport_get_linkerrors(struct sas_phy *phy)
1254 struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1255 unsigned long flags;
1256 Mpi2ConfigReply_t mpi_reply;
1257 Mpi2SasPhyPage1_t phy_pg1;
1259 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1260 if (_transport_sas_node_find_by_sas_address(ioc,
1261 phy->identify.sas_address) == NULL) {
1262 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1263 return -EINVAL;
1265 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1267 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1268 return _transport_get_expander_phy_error_log(ioc, phy);
1270 /* get hba phy error logs */
1271 if ((mpt3sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
1272 phy->number))) {
1273 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1274 ioc->name, __FILE__, __LINE__, __func__);
1275 return -ENXIO;
1278 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1279 pr_info(MPT3SAS_FMT
1280 "phy(%d), ioc_status (0x%04x), loginfo(0x%08x)\n",
1281 ioc->name, phy->number,
1282 le16_to_cpu(mpi_reply.IOCStatus),
1283 le32_to_cpu(mpi_reply.IOCLogInfo));
1285 phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
1286 phy->running_disparity_error_count =
1287 le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
1288 phy->loss_of_dword_sync_count =
1289 le32_to_cpu(phy_pg1.LossDwordSynchCount);
1290 phy->phy_reset_problem_count =
1291 le32_to_cpu(phy_pg1.PhyResetProblemCount);
1292 return 0;
1296 * _transport_get_enclosure_identifier -
1297 * @phy: The sas phy object
1299 * Obtain the enclosure logical id for an expander.
1300 * Returns 0 for success, non-zero for failure.
1302 static int
1303 _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1305 struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1306 struct _sas_device *sas_device;
1307 unsigned long flags;
1308 int rc;
1310 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1311 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
1312 rphy->identify.sas_address);
1313 if (sas_device) {
1314 *identifier = sas_device->enclosure_logical_id;
1315 rc = 0;
1316 } else {
1317 *identifier = 0;
1318 rc = -ENXIO;
1320 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1321 return rc;
1325 * _transport_get_bay_identifier -
1326 * @phy: The sas phy object
1328 * Returns the slot id for a device that resides inside an enclosure.
1330 static int
1331 _transport_get_bay_identifier(struct sas_rphy *rphy)
1333 struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1334 struct _sas_device *sas_device;
1335 unsigned long flags;
1336 int rc;
1338 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1339 sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
1340 rphy->identify.sas_address);
1341 if (sas_device)
1342 rc = sas_device->slot;
1343 else
1344 rc = -ENXIO;
1345 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1346 return rc;
1349 /* phy control request structure */
1350 struct phy_control_request {
1351 u8 smp_frame_type; /* 0x40 */
1352 u8 function; /* 0x91 */
1353 u8 allocated_response_length;
1354 u8 request_length; /* 0x09 */
1355 u16 expander_change_count;
1356 u8 reserved_1[3];
1357 u8 phy_identifier;
1358 u8 phy_operation;
1359 u8 reserved_2[13];
1360 u64 attached_device_name;
1361 u8 programmed_min_physical_link_rate;
1362 u8 programmed_max_physical_link_rate;
1363 u8 reserved_3[6];
1366 /* phy control reply structure */
1367 struct phy_control_reply {
1368 u8 smp_frame_type; /* 0x41 */
1369 u8 function; /* 0x11 */
1370 u8 function_result;
1371 u8 response_length;
1374 #define SMP_PHY_CONTROL_LINK_RESET (0x01)
1375 #define SMP_PHY_CONTROL_HARD_RESET (0x02)
1376 #define SMP_PHY_CONTROL_DISABLE (0x03)
1379 * _transport_expander_phy_control - expander phy control
1380 * @ioc: per adapter object
1381 * @phy: The sas phy object
1383 * Returns 0 for success, non-zero for failure.
1386 static int
1387 _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
1388 struct sas_phy *phy, u8 phy_operation)
1390 Mpi2SmpPassthroughRequest_t *mpi_request;
1391 Mpi2SmpPassthroughReply_t *mpi_reply;
1392 struct phy_control_request *phy_control_request;
1393 struct phy_control_reply *phy_control_reply;
1394 int rc;
1395 u16 smid;
1396 u32 ioc_state;
1397 unsigned long timeleft;
1398 void *psge;
1399 u32 sgl_flags;
1400 u8 issue_reset = 0;
1401 void *data_out = NULL;
1402 dma_addr_t data_out_dma;
1403 u32 sz;
1404 u16 wait_state_count;
1406 if (ioc->shost_recovery || ioc->pci_error_recovery) {
1407 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
1408 __func__, ioc->name);
1409 return -EFAULT;
1412 mutex_lock(&ioc->transport_cmds.mutex);
1414 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1415 pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n",
1416 ioc->name, __func__);
1417 rc = -EAGAIN;
1418 goto out;
1420 ioc->transport_cmds.status = MPT3_CMD_PENDING;
1422 wait_state_count = 0;
1423 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1424 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1425 if (wait_state_count++ == 10) {
1426 pr_err(MPT3SAS_FMT
1427 "%s: failed due to ioc not operational\n",
1428 ioc->name, __func__);
1429 rc = -EFAULT;
1430 goto out;
1432 ssleep(1);
1433 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1434 pr_info(MPT3SAS_FMT
1435 "%s: waiting for operational state(count=%d)\n",
1436 ioc->name, __func__, wait_state_count);
1438 if (wait_state_count)
1439 pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
1440 ioc->name, __func__);
1442 smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
1443 if (!smid) {
1444 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
1445 ioc->name, __func__);
1446 rc = -EAGAIN;
1447 goto out;
1450 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1451 ioc->transport_cmds.smid = smid;
1453 sz = sizeof(struct phy_control_request) +
1454 sizeof(struct phy_control_reply);
1455 data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1456 if (!data_out) {
1457 pr_err("failure at %s:%d/%s()!\n", __FILE__,
1458 __LINE__, __func__);
1459 rc = -ENOMEM;
1460 mpt3sas_base_free_smid(ioc, smid);
1461 goto out;
1464 rc = -EINVAL;
1465 memset(data_out, 0, sz);
1466 phy_control_request = data_out;
1467 phy_control_request->smp_frame_type = 0x40;
1468 phy_control_request->function = 0x91;
1469 phy_control_request->request_length = 9;
1470 phy_control_request->allocated_response_length = 0;
1471 phy_control_request->phy_identifier = phy->number;
1472 phy_control_request->phy_operation = phy_operation;
1473 phy_control_request->programmed_min_physical_link_rate =
1474 phy->minimum_linkrate << 4;
1475 phy_control_request->programmed_max_physical_link_rate =
1476 phy->maximum_linkrate << 4;
1478 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1479 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1480 mpi_request->PhysicalPort = 0xFF;
1481 mpi_request->VF_ID = 0; /* TODO */
1482 mpi_request->VP_ID = 0;
1483 mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1484 mpi_request->RequestDataLength =
1485 cpu_to_le16(sizeof(struct phy_error_log_request));
1486 psge = &mpi_request->SGL;
1488 /* WRITE sgel first */
1489 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1490 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1491 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1492 ioc->base_add_sg_single(psge, sgl_flags |
1493 sizeof(struct phy_control_request), data_out_dma);
1495 /* incr sgel */
1496 psge += ioc->sge_size;
1498 /* READ sgel last */
1499 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1500 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1501 MPI2_SGE_FLAGS_END_OF_LIST);
1502 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1503 ioc->base_add_sg_single(psge, sgl_flags |
1504 sizeof(struct phy_control_reply), data_out_dma +
1505 sizeof(struct phy_control_request));
1507 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1508 "phy_control - send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n",
1509 ioc->name, (unsigned long long)phy->identify.sas_address,
1510 phy->number, phy_operation));
1511 init_completion(&ioc->transport_cmds.done);
1512 mpt3sas_base_put_smid_default(ioc, smid);
1513 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1514 10*HZ);
1516 if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
1517 pr_err(MPT3SAS_FMT "%s: timeout\n",
1518 ioc->name, __func__);
1519 _debug_dump_mf(mpi_request,
1520 sizeof(Mpi2SmpPassthroughRequest_t)/4);
1521 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
1522 issue_reset = 1;
1523 goto issue_host_reset;
1526 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1527 "phy_control - complete\n", ioc->name));
1529 if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
1531 mpi_reply = ioc->transport_cmds.reply;
1533 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1534 "phy_control - reply data transfer size(%d)\n",
1535 ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1537 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1538 sizeof(struct phy_control_reply))
1539 goto out;
1541 phy_control_reply = data_out +
1542 sizeof(struct phy_control_request);
1544 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1545 "phy_control - function_result(%d)\n",
1546 ioc->name, phy_control_reply->function_result));
1548 rc = 0;
1549 } else
1550 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
1551 "phy_control - no reply\n", ioc->name));
1553 issue_host_reset:
1554 if (issue_reset)
1555 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1556 FORCE_BIG_HAMMER);
1557 out:
1558 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
1559 if (data_out)
1560 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1562 mutex_unlock(&ioc->transport_cmds.mutex);
1563 return rc;
1567 * _transport_phy_reset -
1568 * @phy: The sas phy object
1569 * @hard_reset:
1571 * Returns 0 for success, non-zero for failure.
1573 static int
1574 _transport_phy_reset(struct sas_phy *phy, int hard_reset)
1576 struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1577 Mpi2SasIoUnitControlReply_t mpi_reply;
1578 Mpi2SasIoUnitControlRequest_t mpi_request;
1579 unsigned long flags;
1581 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1582 if (_transport_sas_node_find_by_sas_address(ioc,
1583 phy->identify.sas_address) == NULL) {
1584 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1585 return -EINVAL;
1587 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1589 /* handle expander phys */
1590 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1591 return _transport_expander_phy_control(ioc, phy,
1592 (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
1593 SMP_PHY_CONTROL_LINK_RESET);
1595 /* handle hba phys */
1596 memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
1597 mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
1598 mpi_request.Operation = hard_reset ?
1599 MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
1600 mpi_request.PhyNum = phy->number;
1602 if ((mpt3sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
1603 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1604 ioc->name, __FILE__, __LINE__, __func__);
1605 return -ENXIO;
1608 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1609 pr_info(MPT3SAS_FMT
1610 "phy(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
1611 ioc->name, phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1612 le32_to_cpu(mpi_reply.IOCLogInfo));
1614 return 0;
1618 * _transport_phy_enable - enable/disable phys
1619 * @phy: The sas phy object
1620 * @enable: enable phy when true
1622 * Only support sas_host direct attached phys.
1623 * Returns 0 for success, non-zero for failure.
1625 static int
1626 _transport_phy_enable(struct sas_phy *phy, int enable)
1628 struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1629 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1630 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
1631 Mpi2ConfigReply_t mpi_reply;
1632 u16 ioc_status;
1633 u16 sz;
1634 int rc = 0;
1635 unsigned long flags;
1636 int i, discovery_active;
1638 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1639 if (_transport_sas_node_find_by_sas_address(ioc,
1640 phy->identify.sas_address) == NULL) {
1641 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1642 return -EINVAL;
1644 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1646 /* handle expander phys */
1647 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1648 return _transport_expander_phy_control(ioc, phy,
1649 (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
1650 SMP_PHY_CONTROL_DISABLE);
1652 /* handle hba phys */
1654 /* read sas_iounit page 0 */
1655 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
1656 sizeof(Mpi2SasIOUnit0PhyData_t));
1657 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
1658 if (!sas_iounit_pg0) {
1659 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1660 ioc->name, __FILE__, __LINE__, __func__);
1661 rc = -ENOMEM;
1662 goto out;
1664 if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
1665 sas_iounit_pg0, sz))) {
1666 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1667 ioc->name, __FILE__, __LINE__, __func__);
1668 rc = -ENXIO;
1669 goto out;
1671 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1672 MPI2_IOCSTATUS_MASK;
1673 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1674 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1675 ioc->name, __FILE__, __LINE__, __func__);
1676 rc = -EIO;
1677 goto out;
1680 /* unable to enable/disable phys when when discovery is active */
1681 for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) {
1682 if (sas_iounit_pg0->PhyData[i].PortFlags &
1683 MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) {
1684 pr_err(MPT3SAS_FMT "discovery is active on " \
1685 "port = %d, phy = %d: unable to enable/disable "
1686 "phys, try again later!\n", ioc->name,
1687 sas_iounit_pg0->PhyData[i].Port, i);
1688 discovery_active = 1;
1692 if (discovery_active) {
1693 rc = -EAGAIN;
1694 goto out;
1697 /* read sas_iounit page 1 */
1698 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1699 sizeof(Mpi2SasIOUnit1PhyData_t));
1700 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1701 if (!sas_iounit_pg1) {
1702 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1703 ioc->name, __FILE__, __LINE__, __func__);
1704 rc = -ENOMEM;
1705 goto out;
1707 if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1708 sas_iounit_pg1, sz))) {
1709 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1710 ioc->name, __FILE__, __LINE__, __func__);
1711 rc = -ENXIO;
1712 goto out;
1714 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1715 MPI2_IOCSTATUS_MASK;
1716 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1717 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1718 ioc->name, __FILE__, __LINE__, __func__);
1719 rc = -EIO;
1720 goto out;
1723 /* copy Port/PortFlags/PhyFlags from page 0 */
1724 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
1725 sas_iounit_pg1->PhyData[i].Port =
1726 sas_iounit_pg0->PhyData[i].Port;
1727 sas_iounit_pg1->PhyData[i].PortFlags =
1728 (sas_iounit_pg0->PhyData[i].PortFlags &
1729 MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG);
1730 sas_iounit_pg1->PhyData[i].PhyFlags =
1731 (sas_iounit_pg0->PhyData[i].PhyFlags &
1732 (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED +
1733 MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED));
1736 if (enable)
1737 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1738 &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1739 else
1740 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1741 |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1743 mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1745 /* link reset */
1746 if (enable)
1747 _transport_phy_reset(phy, 0);
1749 out:
1750 kfree(sas_iounit_pg1);
1751 kfree(sas_iounit_pg0);
1752 return rc;
1756 * _transport_phy_speed - set phy min/max link rates
1757 * @phy: The sas phy object
1758 * @rates: rates defined in sas_phy_linkrates
1760 * Only support sas_host direct attached phys.
1761 * Returns 0 for success, non-zero for failure.
1763 static int
1764 _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1766 struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1767 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1768 Mpi2SasPhyPage0_t phy_pg0;
1769 Mpi2ConfigReply_t mpi_reply;
1770 u16 ioc_status;
1771 u16 sz;
1772 int i;
1773 int rc = 0;
1774 unsigned long flags;
1776 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1777 if (_transport_sas_node_find_by_sas_address(ioc,
1778 phy->identify.sas_address) == NULL) {
1779 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1780 return -EINVAL;
1782 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1784 if (!rates->minimum_linkrate)
1785 rates->minimum_linkrate = phy->minimum_linkrate;
1786 else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
1787 rates->minimum_linkrate = phy->minimum_linkrate_hw;
1789 if (!rates->maximum_linkrate)
1790 rates->maximum_linkrate = phy->maximum_linkrate;
1791 else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
1792 rates->maximum_linkrate = phy->maximum_linkrate_hw;
1794 /* handle expander phys */
1795 if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
1796 phy->minimum_linkrate = rates->minimum_linkrate;
1797 phy->maximum_linkrate = rates->maximum_linkrate;
1798 return _transport_expander_phy_control(ioc, phy,
1799 SMP_PHY_CONTROL_LINK_RESET);
1802 /* handle hba phys */
1804 /* sas_iounit page 1 */
1805 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1806 sizeof(Mpi2SasIOUnit1PhyData_t));
1807 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1808 if (!sas_iounit_pg1) {
1809 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1810 ioc->name, __FILE__, __LINE__, __func__);
1811 rc = -ENOMEM;
1812 goto out;
1814 if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1815 sas_iounit_pg1, sz))) {
1816 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1817 ioc->name, __FILE__, __LINE__, __func__);
1818 rc = -ENXIO;
1819 goto out;
1821 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1822 MPI2_IOCSTATUS_MASK;
1823 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1824 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1825 ioc->name, __FILE__, __LINE__, __func__);
1826 rc = -EIO;
1827 goto out;
1830 for (i = 0; i < ioc->sas_hba.num_phys; i++) {
1831 if (phy->number != i) {
1832 sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1833 (ioc->sas_hba.phy[i].phy->minimum_linkrate +
1834 (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
1835 } else {
1836 sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1837 (rates->minimum_linkrate +
1838 (rates->maximum_linkrate << 4));
1842 if (mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
1843 sz)) {
1844 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1845 ioc->name, __FILE__, __LINE__, __func__);
1846 rc = -ENXIO;
1847 goto out;
1850 /* link reset */
1851 _transport_phy_reset(phy, 0);
1853 /* read phy page 0, then update the rates in the sas transport phy */
1854 if (!mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
1855 phy->number)) {
1856 phy->minimum_linkrate = _transport_convert_phy_link_rate(
1857 phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1858 phy->maximum_linkrate = _transport_convert_phy_link_rate(
1859 phy_pg0.ProgrammedLinkRate >> 4);
1860 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1861 phy_pg0.NegotiatedLinkRate &
1862 MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1865 out:
1866 kfree(sas_iounit_pg1);
1867 return rc;
1871 * _transport_smp_handler - transport portal for smp passthru
1872 * @shost: shost object
1873 * @rphy: sas transport rphy object
1874 * @req:
1876 * This used primarily for smp_utils.
1877 * Example:
1878 * smp_rep_general /sys/class/bsg/expander-5:0
1880 static int
1881 _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1882 struct request *req)
1884 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1885 Mpi2SmpPassthroughRequest_t *mpi_request;
1886 Mpi2SmpPassthroughReply_t *mpi_reply;
1887 int rc, i;
1888 u16 smid;
1889 u32 ioc_state;
1890 unsigned long timeleft;
1891 void *psge;
1892 u8 issue_reset = 0;
1893 dma_addr_t dma_addr_in = 0;
1894 dma_addr_t dma_addr_out = 0;
1895 dma_addr_t pci_dma_in = 0;
1896 dma_addr_t pci_dma_out = 0;
1897 void *pci_addr_in = NULL;
1898 void *pci_addr_out = NULL;
1899 u16 wait_state_count;
1900 struct request *rsp = req->next_rq;
1901 struct bio_vec *bvec = NULL;
1903 if (!rsp) {
1904 pr_err(MPT3SAS_FMT "%s: the smp response space is missing\n",
1905 ioc->name, __func__);
1906 return -EINVAL;
1909 if (ioc->shost_recovery || ioc->pci_error_recovery) {
1910 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
1911 __func__, ioc->name);
1912 return -EFAULT;
1915 rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1916 if (rc)
1917 return rc;
1919 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1920 pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", ioc->name,
1921 __func__);
1922 rc = -EAGAIN;
1923 goto out;
1925 ioc->transport_cmds.status = MPT3_CMD_PENDING;
1927 /* Check if the request is split across multiple segments */
1928 if (req->bio->bi_vcnt > 1) {
1929 u32 offset = 0;
1931 /* Allocate memory and copy the request */
1932 pci_addr_out = pci_alloc_consistent(ioc->pdev,
1933 blk_rq_bytes(req), &pci_dma_out);
1934 if (!pci_addr_out) {
1935 pr_info(MPT3SAS_FMT "%s(): PCI Addr out = NULL\n",
1936 ioc->name, __func__);
1937 rc = -ENOMEM;
1938 goto out;
1941 bio_for_each_segment(bvec, req->bio, i) {
1942 memcpy(pci_addr_out + offset,
1943 page_address(bvec->bv_page) + bvec->bv_offset,
1944 bvec->bv_len);
1945 offset += bvec->bv_len;
1947 } else {
1948 dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
1949 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
1950 if (!dma_addr_out) {
1951 pr_info(MPT3SAS_FMT "%s(): DMA Addr out = NULL\n",
1952 ioc->name, __func__);
1953 rc = -ENOMEM;
1954 goto free_pci;
1958 /* Check if the response needs to be populated across
1959 * multiple segments */
1960 if (rsp->bio->bi_vcnt > 1) {
1961 pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp),
1962 &pci_dma_in);
1963 if (!pci_addr_in) {
1964 pr_info(MPT3SAS_FMT "%s(): PCI Addr in = NULL\n",
1965 ioc->name, __func__);
1966 rc = -ENOMEM;
1967 goto unmap;
1969 } else {
1970 dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
1971 blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
1972 if (!dma_addr_in) {
1973 pr_info(MPT3SAS_FMT "%s(): DMA Addr in = NULL\n",
1974 ioc->name, __func__);
1975 rc = -ENOMEM;
1976 goto unmap;
1980 wait_state_count = 0;
1981 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1982 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1983 if (wait_state_count++ == 10) {
1984 pr_err(MPT3SAS_FMT
1985 "%s: failed due to ioc not operational\n",
1986 ioc->name, __func__);
1987 rc = -EFAULT;
1988 goto unmap;
1990 ssleep(1);
1991 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
1992 pr_info(MPT3SAS_FMT
1993 "%s: waiting for operational state(count=%d)\n",
1994 ioc->name, __func__, wait_state_count);
1996 if (wait_state_count)
1997 pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
1998 ioc->name, __func__);
2000 smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
2001 if (!smid) {
2002 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
2003 ioc->name, __func__);
2004 rc = -EAGAIN;
2005 goto unmap;
2008 rc = 0;
2009 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
2010 ioc->transport_cmds.smid = smid;
2012 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
2013 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
2014 mpi_request->PhysicalPort = 0xFF;
2015 mpi_request->SASAddress = (rphy) ?
2016 cpu_to_le64(rphy->identify.sas_address) :
2017 cpu_to_le64(ioc->sas_hba.sas_address);
2018 mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
2019 psge = &mpi_request->SGL;
2021 if (req->bio->bi_vcnt > 1)
2022 ioc->build_sg(ioc, psge, pci_dma_out, (blk_rq_bytes(req) - 4),
2023 pci_dma_in, (blk_rq_bytes(rsp) + 4));
2024 else
2025 ioc->build_sg(ioc, psge, dma_addr_out, (blk_rq_bytes(req) - 4),
2026 dma_addr_in, (blk_rq_bytes(rsp) + 4));
2028 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2029 "%s - sending smp request\n", ioc->name, __func__));
2031 init_completion(&ioc->transport_cmds.done);
2032 mpt3sas_base_put_smid_default(ioc, smid);
2033 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
2034 10*HZ);
2036 if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
2037 pr_err(MPT3SAS_FMT "%s : timeout\n",
2038 __func__, ioc->name);
2039 _debug_dump_mf(mpi_request,
2040 sizeof(Mpi2SmpPassthroughRequest_t)/4);
2041 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
2042 issue_reset = 1;
2043 goto issue_host_reset;
2046 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2047 "%s - complete\n", ioc->name, __func__));
2049 if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
2051 mpi_reply = ioc->transport_cmds.reply;
2053 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2054 "%s - reply data transfer size(%d)\n",
2055 ioc->name, __func__,
2056 le16_to_cpu(mpi_reply->ResponseDataLength)));
2058 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
2059 req->sense_len = sizeof(*mpi_reply);
2060 req->resid_len = 0;
2061 rsp->resid_len -=
2062 le16_to_cpu(mpi_reply->ResponseDataLength);
2064 /* check if the resp needs to be copied from the allocated
2065 * pci mem */
2066 if (rsp->bio->bi_vcnt > 1) {
2067 u32 offset = 0;
2068 u32 bytes_to_copy =
2069 le16_to_cpu(mpi_reply->ResponseDataLength);
2070 bio_for_each_segment(bvec, rsp->bio, i) {
2071 if (bytes_to_copy <= bvec->bv_len) {
2072 memcpy(page_address(bvec->bv_page) +
2073 bvec->bv_offset, pci_addr_in +
2074 offset, bytes_to_copy);
2075 break;
2076 } else {
2077 memcpy(page_address(bvec->bv_page) +
2078 bvec->bv_offset, pci_addr_in +
2079 offset, bvec->bv_len);
2080 bytes_to_copy -= bvec->bv_len;
2082 offset += bvec->bv_len;
2085 } else {
2086 dtransportprintk(ioc, pr_info(MPT3SAS_FMT
2087 "%s - no reply\n", ioc->name, __func__));
2088 rc = -ENXIO;
2091 issue_host_reset:
2092 if (issue_reset) {
2093 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2094 FORCE_BIG_HAMMER);
2095 rc = -ETIMEDOUT;
2098 unmap:
2099 if (dma_addr_out)
2100 pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
2101 PCI_DMA_BIDIRECTIONAL);
2102 if (dma_addr_in)
2103 pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
2104 PCI_DMA_BIDIRECTIONAL);
2106 free_pci:
2107 if (pci_addr_out)
2108 pci_free_consistent(ioc->pdev, blk_rq_bytes(req), pci_addr_out,
2109 pci_dma_out);
2111 if (pci_addr_in)
2112 pci_free_consistent(ioc->pdev, blk_rq_bytes(rsp), pci_addr_in,
2113 pci_dma_in);
2115 out:
2116 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
2117 mutex_unlock(&ioc->transport_cmds.mutex);
2118 return rc;
2121 struct sas_function_template mpt3sas_transport_functions = {
2122 .get_linkerrors = _transport_get_linkerrors,
2123 .get_enclosure_identifier = _transport_get_enclosure_identifier,
2124 .get_bay_identifier = _transport_get_bay_identifier,
2125 .phy_reset = _transport_phy_reset,
2126 .phy_enable = _transport_phy_enable,
2127 .set_phy_speed = _transport_phy_speed,
2128 .smp_handler = _transport_smp_handler,
2131 struct scsi_transport_template *mpt3sas_transport_template;