2 * SAS Transport Layer for MPT (Message Passing Technology) based controllers
4 * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c
5 * Copyright (C) 2007-2014 LSI Corporation
6 * Copyright (C) 20013-2014 Avago Technologies
7 * (mailto: MPT-FusionLinux.pdl@avagotech.com)
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
20 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
21 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
22 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
23 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
24 * solely responsible for determining the appropriateness of using and
25 * distributing the Program and assumes all risks associated with its
26 * exercise of rights under this Agreement, including but not limited to
27 * the risks and costs of program errors, damage to or loss of data,
28 * programs or equipment, and unavailability or interruption of operations.
30 * DISCLAIMER OF LIABILITY
31 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
35 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
37 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
45 #include <linux/module.h>
46 #include <linux/kernel.h>
47 #include <linux/init.h>
48 #include <linux/errno.h>
49 #include <linux/sched.h>
50 #include <linux/workqueue.h>
51 #include <linux/delay.h>
52 #include <linux/pci.h>
53 #include <linux/slab.h>
55 #include <scsi/scsi.h>
56 #include <scsi/scsi_cmnd.h>
57 #include <scsi/scsi_device.h>
58 #include <scsi/scsi_host.h>
59 #include <scsi/scsi_transport_sas.h>
60 #include <scsi/scsi_dbg.h>
62 #include "mpt2sas_base.h"
64 * _transport_sas_node_find_by_sas_address - sas node search
65 * @ioc: per adapter object
66 * @sas_address: sas address of expander or sas host
67 * Context: Calling function should acquire ioc->sas_node_lock.
69 * Search for either hba phys or expander device based on handle, then returns
70 * the sas_node object.
72 static struct _sas_node
*
73 _transport_sas_node_find_by_sas_address(struct MPT2SAS_ADAPTER
*ioc
,
76 if (ioc
->sas_hba
.sas_address
== sas_address
)
79 return mpt2sas_scsih_expander_find_by_sas_address(ioc
,
84 * _transport_convert_phy_link_rate -
85 * @link_rate: link rate returned from mpt firmware
87 * Convert link_rate from mpi fusion into sas_transport form.
89 static enum sas_linkrate
90 _transport_convert_phy_link_rate(u8 link_rate
)
95 case MPI2_SAS_NEG_LINK_RATE_1_5
:
96 rc
= SAS_LINK_RATE_1_5_GBPS
;
98 case MPI2_SAS_NEG_LINK_RATE_3_0
:
99 rc
= SAS_LINK_RATE_3_0_GBPS
;
101 case MPI2_SAS_NEG_LINK_RATE_6_0
:
102 rc
= SAS_LINK_RATE_6_0_GBPS
;
104 case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED
:
105 rc
= SAS_PHY_DISABLED
;
107 case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED
:
108 rc
= SAS_LINK_RATE_FAILED
;
110 case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR
:
111 rc
= SAS_SATA_PORT_SELECTOR
;
113 case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS
:
114 rc
= SAS_PHY_RESET_IN_PROGRESS
;
117 case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE
:
118 case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE
:
119 rc
= SAS_LINK_RATE_UNKNOWN
;
126 * _transport_set_identify - set identify for phys and end devices
127 * @ioc: per adapter object
128 * @handle: device handle
129 * @identify: sas identify info
131 * Populates sas identify info.
133 * Returns 0 for success, non-zero for failure.
136 _transport_set_identify(struct MPT2SAS_ADAPTER
*ioc
, u16 handle
,
137 struct sas_identify
*identify
)
139 Mpi2SasDevicePage0_t sas_device_pg0
;
140 Mpi2ConfigReply_t mpi_reply
;
144 if (ioc
->shost_recovery
|| ioc
->pci_error_recovery
) {
145 printk(MPT2SAS_INFO_FMT
"%s: host reset in progress!\n",
146 __func__
, ioc
->name
);
150 if ((mpt2sas_config_get_sas_device_pg0(ioc
, &mpi_reply
, &sas_device_pg0
,
151 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE
, handle
))) {
152 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
154 ioc
->name
, __FILE__
, __LINE__
, __func__
);
158 ioc_status
= le16_to_cpu(mpi_reply
.IOCStatus
) &
160 if (ioc_status
!= MPI2_IOCSTATUS_SUCCESS
) {
161 printk(MPT2SAS_ERR_FMT
"handle(0x%04x), ioc_status(0x%04x)"
162 "\nfailure at %s:%d/%s()!\n", ioc
->name
, handle
, ioc_status
,
163 __FILE__
, __LINE__
, __func__
);
167 memset(identify
, 0, sizeof(struct sas_identify
));
168 device_info
= le32_to_cpu(sas_device_pg0
.DeviceInfo
);
171 identify
->sas_address
= le64_to_cpu(sas_device_pg0
.SASAddress
);
173 /* phy number of the parent device this device is linked to */
174 identify
->phy_identifier
= sas_device_pg0
.PhyNum
;
177 switch (device_info
& MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE
) {
178 case MPI2_SAS_DEVICE_INFO_NO_DEVICE
:
179 identify
->device_type
= SAS_PHY_UNUSED
;
181 case MPI2_SAS_DEVICE_INFO_END_DEVICE
:
182 identify
->device_type
= SAS_END_DEVICE
;
184 case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER
:
185 identify
->device_type
= SAS_EDGE_EXPANDER_DEVICE
;
187 case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER
:
188 identify
->device_type
= SAS_FANOUT_EXPANDER_DEVICE
;
192 /* initiator_port_protocols */
193 if (device_info
& MPI2_SAS_DEVICE_INFO_SSP_INITIATOR
)
194 identify
->initiator_port_protocols
|= SAS_PROTOCOL_SSP
;
195 if (device_info
& MPI2_SAS_DEVICE_INFO_STP_INITIATOR
)
196 identify
->initiator_port_protocols
|= SAS_PROTOCOL_STP
;
197 if (device_info
& MPI2_SAS_DEVICE_INFO_SMP_INITIATOR
)
198 identify
->initiator_port_protocols
|= SAS_PROTOCOL_SMP
;
199 if (device_info
& MPI2_SAS_DEVICE_INFO_SATA_HOST
)
200 identify
->initiator_port_protocols
|= SAS_PROTOCOL_SATA
;
202 /* target_port_protocols */
203 if (device_info
& MPI2_SAS_DEVICE_INFO_SSP_TARGET
)
204 identify
->target_port_protocols
|= SAS_PROTOCOL_SSP
;
205 if (device_info
& MPI2_SAS_DEVICE_INFO_STP_TARGET
)
206 identify
->target_port_protocols
|= SAS_PROTOCOL_STP
;
207 if (device_info
& MPI2_SAS_DEVICE_INFO_SMP_TARGET
)
208 identify
->target_port_protocols
|= SAS_PROTOCOL_SMP
;
209 if (device_info
& MPI2_SAS_DEVICE_INFO_SATA_DEVICE
)
210 identify
->target_port_protocols
|= SAS_PROTOCOL_SATA
;
216 * mpt2sas_transport_done - internal transport layer callback handler.
217 * @ioc: per adapter object
218 * @smid: system request message index
219 * @msix_index: MSIX table index supplied by the OS
220 * @reply: reply message frame(lower 32bit addr)
222 * Callback handler when sending internal generated transport cmds.
223 * The callback index passed is `ioc->transport_cb_idx`
225 * Return 1 meaning mf should be freed from _base_interrupt
226 * 0 means the mf is freed from this function.
229 mpt2sas_transport_done(struct MPT2SAS_ADAPTER
*ioc
, u16 smid
, u8 msix_index
,
232 MPI2DefaultReply_t
*mpi_reply
;
234 mpi_reply
= mpt2sas_base_get_reply_virt_addr(ioc
, reply
);
235 if (ioc
->transport_cmds
.status
== MPT2_CMD_NOT_USED
)
237 if (ioc
->transport_cmds
.smid
!= smid
)
239 ioc
->transport_cmds
.status
|= MPT2_CMD_COMPLETE
;
241 memcpy(ioc
->transport_cmds
.reply
, mpi_reply
,
242 mpi_reply
->MsgLength
*4);
243 ioc
->transport_cmds
.status
|= MPT2_CMD_REPLY_VALID
;
245 ioc
->transport_cmds
.status
&= ~MPT2_CMD_PENDING
;
246 complete(&ioc
->transport_cmds
.done
);
250 /* report manufacture request structure */
251 struct rep_manu_request
{
258 /* report manufacture reply structure */
259 struct rep_manu_reply
{
260 u8 smp_frame_type
; /* 0x41 */
261 u8 function
; /* 0x01 */
264 u16 expander_change_count
;
268 u8 vendor_id
[SAS_EXPANDER_VENDOR_ID_LEN
];
269 u8 product_id
[SAS_EXPANDER_PRODUCT_ID_LEN
];
270 u8 product_rev
[SAS_EXPANDER_PRODUCT_REV_LEN
];
271 u8 component_vendor_id
[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN
];
273 u8 component_revision_id
;
275 u8 vendor_specific
[8];
279 * _transport_expander_report_manufacture - obtain SMP report_manufacture
280 * @ioc: per adapter object
281 * @sas_address: expander sas address
282 * @edev: the sas_expander_device object
284 * Fills in the sas_expander_device object when SMP port is created.
286 * Returns 0 for success, non-zero for failure.
289 _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER
*ioc
,
290 u64 sas_address
, struct sas_expander_device
*edev
)
292 Mpi2SmpPassthroughRequest_t
*mpi_request
;
293 Mpi2SmpPassthroughReply_t
*mpi_reply
;
294 struct rep_manu_reply
*manufacture_reply
;
295 struct rep_manu_request
*manufacture_request
;
299 unsigned long timeleft
;
303 void *data_out
= NULL
;
304 dma_addr_t data_out_dma
;
306 u16 wait_state_count
;
308 if (ioc
->shost_recovery
|| ioc
->pci_error_recovery
) {
309 printk(MPT2SAS_INFO_FMT
"%s: host reset in progress!\n",
310 __func__
, ioc
->name
);
314 mutex_lock(&ioc
->transport_cmds
.mutex
);
316 if (ioc
->transport_cmds
.status
!= MPT2_CMD_NOT_USED
) {
317 printk(MPT2SAS_ERR_FMT
"%s: transport_cmds in use\n",
318 ioc
->name
, __func__
);
322 ioc
->transport_cmds
.status
= MPT2_CMD_PENDING
;
324 wait_state_count
= 0;
325 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
326 while (ioc_state
!= MPI2_IOC_STATE_OPERATIONAL
) {
327 if (wait_state_count
++ == 10) {
328 printk(MPT2SAS_ERR_FMT
329 "%s: failed due to ioc not operational\n",
330 ioc
->name
, __func__
);
335 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
336 printk(MPT2SAS_INFO_FMT
"%s: waiting for "
337 "operational state(count=%d)\n", ioc
->name
,
338 __func__
, wait_state_count
);
340 if (wait_state_count
)
341 printk(MPT2SAS_INFO_FMT
"%s: ioc is operational\n",
342 ioc
->name
, __func__
);
344 smid
= mpt2sas_base_get_smid(ioc
, ioc
->transport_cb_idx
);
346 printk(MPT2SAS_ERR_FMT
"%s: failed obtaining a smid\n",
347 ioc
->name
, __func__
);
353 mpi_request
= mpt2sas_base_get_msg_frame(ioc
, smid
);
354 ioc
->transport_cmds
.smid
= smid
;
356 sz
= sizeof(struct rep_manu_request
) + sizeof(struct rep_manu_reply
);
357 data_out
= pci_alloc_consistent(ioc
->pdev
, sz
, &data_out_dma
);
360 printk(KERN_ERR
"failure at %s:%d/%s()!\n", __FILE__
,
363 mpt2sas_base_free_smid(ioc
, smid
);
367 manufacture_request
= data_out
;
368 manufacture_request
->smp_frame_type
= 0x40;
369 manufacture_request
->function
= 1;
370 manufacture_request
->reserved
= 0;
371 manufacture_request
->request_length
= 0;
373 memset(mpi_request
, 0, sizeof(Mpi2SmpPassthroughRequest_t
));
374 mpi_request
->Function
= MPI2_FUNCTION_SMP_PASSTHROUGH
;
375 mpi_request
->PhysicalPort
= 0xFF;
376 mpi_request
->VF_ID
= 0; /* TODO */
377 mpi_request
->VP_ID
= 0;
378 mpi_request
->SASAddress
= cpu_to_le64(sas_address
);
379 mpi_request
->RequestDataLength
=
380 cpu_to_le16(sizeof(struct rep_manu_request
));
381 psge
= &mpi_request
->SGL
;
383 /* WRITE sgel first */
384 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
385 MPI2_SGE_FLAGS_END_OF_BUFFER
| MPI2_SGE_FLAGS_HOST_TO_IOC
);
386 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
387 ioc
->base_add_sg_single(psge
, sgl_flags
|
388 sizeof(struct rep_manu_request
), data_out_dma
);
391 psge
+= ioc
->sge_size
;
394 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
395 MPI2_SGE_FLAGS_LAST_ELEMENT
| MPI2_SGE_FLAGS_END_OF_BUFFER
|
396 MPI2_SGE_FLAGS_END_OF_LIST
);
397 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
398 ioc
->base_add_sg_single(psge
, sgl_flags
|
399 sizeof(struct rep_manu_reply
), data_out_dma
+
400 sizeof(struct rep_manu_request
));
402 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"report_manufacture - "
403 "send to sas_addr(0x%016llx)\n", ioc
->name
,
404 (unsigned long long)sas_address
));
405 init_completion(&ioc
->transport_cmds
.done
);
406 mpt2sas_base_put_smid_default(ioc
, smid
);
407 timeleft
= wait_for_completion_timeout(&ioc
->transport_cmds
.done
,
410 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_COMPLETE
)) {
411 printk(MPT2SAS_ERR_FMT
"%s: timeout\n",
412 ioc
->name
, __func__
);
413 _debug_dump_mf(mpi_request
,
414 sizeof(Mpi2SmpPassthroughRequest_t
)/4);
415 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_RESET
))
417 goto issue_host_reset
;
420 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"report_manufacture - "
421 "complete\n", ioc
->name
));
423 if (ioc
->transport_cmds
.status
& MPT2_CMD_REPLY_VALID
) {
426 mpi_reply
= ioc
->transport_cmds
.reply
;
428 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
429 "report_manufacture - reply data transfer size(%d)\n",
430 ioc
->name
, le16_to_cpu(mpi_reply
->ResponseDataLength
)));
432 if (le16_to_cpu(mpi_reply
->ResponseDataLength
) !=
433 sizeof(struct rep_manu_reply
))
436 manufacture_reply
= data_out
+ sizeof(struct rep_manu_request
);
437 strncpy(edev
->vendor_id
, manufacture_reply
->vendor_id
,
438 SAS_EXPANDER_VENDOR_ID_LEN
);
439 strncpy(edev
->product_id
, manufacture_reply
->product_id
,
440 SAS_EXPANDER_PRODUCT_ID_LEN
);
441 strncpy(edev
->product_rev
, manufacture_reply
->product_rev
,
442 SAS_EXPANDER_PRODUCT_REV_LEN
);
443 edev
->level
= manufacture_reply
->sas_format
& 1;
445 strncpy(edev
->component_vendor_id
,
446 manufacture_reply
->component_vendor_id
,
447 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN
);
448 tmp
= (u8
*)&manufacture_reply
->component_id
;
449 edev
->component_id
= tmp
[0] << 8 | tmp
[1];
450 edev
->component_revision_id
=
451 manufacture_reply
->component_revision_id
;
454 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
455 "report_manufacture - no reply\n", ioc
->name
));
459 mpt2sas_base_hard_reset_handler(ioc
, CAN_SLEEP
,
462 ioc
->transport_cmds
.status
= MPT2_CMD_NOT_USED
;
464 pci_free_consistent(ioc
->pdev
, sz
, data_out
, data_out_dma
);
466 mutex_unlock(&ioc
->transport_cmds
.mutex
);
471 * _transport_delete_port - helper function to removing a port
472 * @ioc: per adapter object
473 * @mpt2sas_port: mpt2sas per port object
478 _transport_delete_port(struct MPT2SAS_ADAPTER
*ioc
,
479 struct _sas_port
*mpt2sas_port
)
481 u64 sas_address
= mpt2sas_port
->remote_identify
.sas_address
;
482 enum sas_device_type device_type
=
483 mpt2sas_port
->remote_identify
.device_type
;
485 dev_printk(KERN_INFO
, &mpt2sas_port
->port
->dev
,
486 "remove: sas_addr(0x%016llx)\n",
487 (unsigned long long) sas_address
);
489 ioc
->logging_level
|= MPT_DEBUG_TRANSPORT
;
490 if (device_type
== SAS_END_DEVICE
)
491 mpt2sas_device_remove_by_sas_address(ioc
, sas_address
);
492 else if (device_type
== SAS_EDGE_EXPANDER_DEVICE
||
493 device_type
== SAS_FANOUT_EXPANDER_DEVICE
)
494 mpt2sas_expander_remove(ioc
, sas_address
);
495 ioc
->logging_level
&= ~MPT_DEBUG_TRANSPORT
;
499 * _transport_delete_phy - helper function to removing single phy from port
500 * @ioc: per adapter object
501 * @mpt2sas_port: mpt2sas per port object
502 * @mpt2sas_phy: mpt2sas per phy object
507 _transport_delete_phy(struct MPT2SAS_ADAPTER
*ioc
,
508 struct _sas_port
*mpt2sas_port
, struct _sas_phy
*mpt2sas_phy
)
510 u64 sas_address
= mpt2sas_port
->remote_identify
.sas_address
;
512 dev_printk(KERN_INFO
, &mpt2sas_phy
->phy
->dev
,
513 "remove: sas_addr(0x%016llx), phy(%d)\n",
514 (unsigned long long) sas_address
, mpt2sas_phy
->phy_id
);
516 list_del(&mpt2sas_phy
->port_siblings
);
517 mpt2sas_port
->num_phys
--;
518 sas_port_delete_phy(mpt2sas_port
->port
, mpt2sas_phy
->phy
);
519 mpt2sas_phy
->phy_belongs_to_port
= 0;
523 * _transport_add_phy - helper function to adding single phy to port
524 * @ioc: per adapter object
525 * @mpt2sas_port: mpt2sas per port object
526 * @mpt2sas_phy: mpt2sas per phy object
531 _transport_add_phy(struct MPT2SAS_ADAPTER
*ioc
, struct _sas_port
*mpt2sas_port
,
532 struct _sas_phy
*mpt2sas_phy
)
534 u64 sas_address
= mpt2sas_port
->remote_identify
.sas_address
;
536 dev_printk(KERN_INFO
, &mpt2sas_phy
->phy
->dev
,
537 "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
538 sas_address
, mpt2sas_phy
->phy_id
);
540 list_add_tail(&mpt2sas_phy
->port_siblings
, &mpt2sas_port
->phy_list
);
541 mpt2sas_port
->num_phys
++;
542 sas_port_add_phy(mpt2sas_port
->port
, mpt2sas_phy
->phy
);
543 mpt2sas_phy
->phy_belongs_to_port
= 1;
547 * _transport_add_phy_to_an_existing_port - adding new phy to existing port
548 * @ioc: per adapter object
549 * @sas_node: sas node object (either expander or sas host)
550 * @mpt2sas_phy: mpt2sas per phy object
551 * @sas_address: sas address of device/expander were phy needs to be added to
556 _transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER
*ioc
,
557 struct _sas_node
*sas_node
, struct _sas_phy
*mpt2sas_phy
, u64 sas_address
)
559 struct _sas_port
*mpt2sas_port
;
560 struct _sas_phy
*phy_srch
;
562 if (mpt2sas_phy
->phy_belongs_to_port
== 1)
565 list_for_each_entry(mpt2sas_port
, &sas_node
->sas_port_list
,
567 if (mpt2sas_port
->remote_identify
.sas_address
!=
570 list_for_each_entry(phy_srch
, &mpt2sas_port
->phy_list
,
572 if (phy_srch
== mpt2sas_phy
)
575 _transport_add_phy(ioc
, mpt2sas_port
, mpt2sas_phy
);
582 * _transport_del_phy_from_an_existing_port - delete phy from existing port
583 * @ioc: per adapter object
584 * @sas_node: sas node object (either expander or sas host)
585 * @mpt2sas_phy: mpt2sas per phy object
590 _transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER
*ioc
,
591 struct _sas_node
*sas_node
, struct _sas_phy
*mpt2sas_phy
)
593 struct _sas_port
*mpt2sas_port
, *next
;
594 struct _sas_phy
*phy_srch
;
596 if (mpt2sas_phy
->phy_belongs_to_port
== 0)
599 list_for_each_entry_safe(mpt2sas_port
, next
, &sas_node
->sas_port_list
,
601 list_for_each_entry(phy_srch
, &mpt2sas_port
->phy_list
,
603 if (phy_srch
!= mpt2sas_phy
)
605 if (mpt2sas_port
->num_phys
== 1)
606 _transport_delete_port(ioc
, mpt2sas_port
);
608 _transport_delete_phy(ioc
, mpt2sas_port
,
616 * _transport_sanity_check - sanity check when adding a new port
617 * @ioc: per adapter object
618 * @sas_node: sas node object (either expander or sas host)
619 * @sas_address: sas address of device being added
621 * See the explanation above from _transport_delete_duplicate_port
624 _transport_sanity_check(struct MPT2SAS_ADAPTER
*ioc
, struct _sas_node
*sas_node
,
629 for (i
= 0; i
< sas_node
->num_phys
; i
++) {
630 if (sas_node
->phy
[i
].remote_identify
.sas_address
!= sas_address
)
632 if (sas_node
->phy
[i
].phy_belongs_to_port
== 1)
633 _transport_del_phy_from_an_existing_port(ioc
, sas_node
,
639 * mpt2sas_transport_port_add - insert port to the list
640 * @ioc: per adapter object
641 * @handle: handle of attached device
642 * @sas_address: sas address of parent expander or sas host
643 * Context: This function will acquire ioc->sas_node_lock.
645 * Adding new port object to the sas_node->sas_port_list.
647 * Returns mpt2sas_port.
650 mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER
*ioc
, u16 handle
,
653 struct _sas_phy
*mpt2sas_phy
, *next
;
654 struct _sas_port
*mpt2sas_port
;
656 struct _sas_node
*sas_node
;
657 struct sas_rphy
*rphy
;
659 struct sas_port
*port
;
661 mpt2sas_port
= kzalloc(sizeof(struct _sas_port
),
664 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
665 ioc
->name
, __FILE__
, __LINE__
, __func__
);
669 INIT_LIST_HEAD(&mpt2sas_port
->port_list
);
670 INIT_LIST_HEAD(&mpt2sas_port
->phy_list
);
671 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
672 sas_node
= _transport_sas_node_find_by_sas_address(ioc
, sas_address
);
673 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
676 printk(MPT2SAS_ERR_FMT
"%s: Could not find "
677 "parent sas_address(0x%016llx)!\n", ioc
->name
,
678 __func__
, (unsigned long long)sas_address
);
682 if ((_transport_set_identify(ioc
, handle
,
683 &mpt2sas_port
->remote_identify
))) {
684 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
685 ioc
->name
, __FILE__
, __LINE__
, __func__
);
689 if (mpt2sas_port
->remote_identify
.device_type
== SAS_PHY_UNUSED
) {
690 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
691 ioc
->name
, __FILE__
, __LINE__
, __func__
);
695 _transport_sanity_check(ioc
, sas_node
,
696 mpt2sas_port
->remote_identify
.sas_address
);
698 for (i
= 0; i
< sas_node
->num_phys
; i
++) {
699 if (sas_node
->phy
[i
].remote_identify
.sas_address
!=
700 mpt2sas_port
->remote_identify
.sas_address
)
702 list_add_tail(&sas_node
->phy
[i
].port_siblings
,
703 &mpt2sas_port
->phy_list
);
704 mpt2sas_port
->num_phys
++;
707 if (!mpt2sas_port
->num_phys
) {
708 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
709 ioc
->name
, __FILE__
, __LINE__
, __func__
);
713 port
= sas_port_alloc_num(sas_node
->parent_dev
);
714 if ((sas_port_add(port
))) {
715 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
716 ioc
->name
, __FILE__
, __LINE__
, __func__
);
720 list_for_each_entry(mpt2sas_phy
, &mpt2sas_port
->phy_list
,
722 if ((ioc
->logging_level
& MPT_DEBUG_TRANSPORT
))
723 dev_printk(KERN_INFO
, &port
->dev
, "add: handle(0x%04x)"
724 ", sas_addr(0x%016llx), phy(%d)\n", handle
,
726 mpt2sas_port
->remote_identify
.sas_address
,
727 mpt2sas_phy
->phy_id
);
728 sas_port_add_phy(port
, mpt2sas_phy
->phy
);
729 mpt2sas_phy
->phy_belongs_to_port
= 1;
732 mpt2sas_port
->port
= port
;
733 if (mpt2sas_port
->remote_identify
.device_type
== SAS_END_DEVICE
)
734 rphy
= sas_end_device_alloc(port
);
736 rphy
= sas_expander_alloc(port
,
737 mpt2sas_port
->remote_identify
.device_type
);
739 rphy
->identify
= mpt2sas_port
->remote_identify
;
740 if ((sas_rphy_add(rphy
))) {
741 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
742 ioc
->name
, __FILE__
, __LINE__
, __func__
);
744 if ((ioc
->logging_level
& MPT_DEBUG_TRANSPORT
))
745 dev_printk(KERN_INFO
, &rphy
->dev
, "add: handle(0x%04x), "
746 "sas_addr(0x%016llx)\n", handle
,
748 mpt2sas_port
->remote_identify
.sas_address
);
749 mpt2sas_port
->rphy
= rphy
;
750 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
751 list_add_tail(&mpt2sas_port
->port_list
, &sas_node
->sas_port_list
);
752 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
754 /* fill in report manufacture */
755 if (mpt2sas_port
->remote_identify
.device_type
==
756 MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER
||
757 mpt2sas_port
->remote_identify
.device_type
==
758 MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER
)
759 _transport_expander_report_manufacture(ioc
,
760 mpt2sas_port
->remote_identify
.sas_address
,
761 rphy_to_expander_device(rphy
));
766 list_for_each_entry_safe(mpt2sas_phy
, next
, &mpt2sas_port
->phy_list
,
768 list_del(&mpt2sas_phy
->port_siblings
);
774 * mpt2sas_transport_port_remove - remove port from the list
775 * @ioc: per adapter object
776 * @sas_address: sas address of attached device
777 * @sas_address_parent: sas address of parent expander or sas host
778 * Context: This function will acquire ioc->sas_node_lock.
780 * Removing object and freeing associated memory from the
781 * ioc->sas_port_list.
786 mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER
*ioc
, u64 sas_address
,
787 u64 sas_address_parent
)
791 struct _sas_port
*mpt2sas_port
, *next
;
792 struct _sas_node
*sas_node
;
794 struct _sas_phy
*mpt2sas_phy
, *next_phy
;
796 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
797 sas_node
= _transport_sas_node_find_by_sas_address(ioc
,
800 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
803 list_for_each_entry_safe(mpt2sas_port
, next
, &sas_node
->sas_port_list
,
805 if (mpt2sas_port
->remote_identify
.sas_address
!= sas_address
)
808 list_del(&mpt2sas_port
->port_list
);
813 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
817 for (i
= 0; i
< sas_node
->num_phys
; i
++) {
818 if (sas_node
->phy
[i
].remote_identify
.sas_address
== sas_address
)
819 memset(&sas_node
->phy
[i
].remote_identify
, 0 ,
820 sizeof(struct sas_identify
));
823 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
824 list_for_each_entry_safe(mpt2sas_phy
, next_phy
,
825 &mpt2sas_port
->phy_list
, port_siblings
) {
826 if ((ioc
->logging_level
& MPT_DEBUG_TRANSPORT
))
827 dev_printk(KERN_INFO
, &mpt2sas_port
->port
->dev
,
828 "remove: sas_addr(0x%016llx), phy(%d)\n",
830 mpt2sas_port
->remote_identify
.sas_address
,
831 mpt2sas_phy
->phy_id
);
832 mpt2sas_phy
->phy_belongs_to_port
= 0;
833 sas_port_delete_phy(mpt2sas_port
->port
, mpt2sas_phy
->phy
);
834 list_del(&mpt2sas_phy
->port_siblings
);
836 sas_port_delete(mpt2sas_port
->port
);
841 * mpt2sas_transport_add_host_phy - report sas_host phy to transport
842 * @ioc: per adapter object
843 * @mpt2sas_phy: mpt2sas per phy object
844 * @phy_pg0: sas phy page 0
845 * @parent_dev: parent device class object
847 * Returns 0 for success, non-zero for failure.
850 mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER
*ioc
, struct _sas_phy
851 *mpt2sas_phy
, Mpi2SasPhyPage0_t phy_pg0
, struct device
*parent_dev
)
854 int phy_index
= mpt2sas_phy
->phy_id
;
857 INIT_LIST_HEAD(&mpt2sas_phy
->port_siblings
);
858 phy
= sas_phy_alloc(parent_dev
, phy_index
);
860 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
861 ioc
->name
, __FILE__
, __LINE__
, __func__
);
864 if ((_transport_set_identify(ioc
, mpt2sas_phy
->handle
,
865 &mpt2sas_phy
->identify
))) {
866 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
867 ioc
->name
, __FILE__
, __LINE__
, __func__
);
870 phy
->identify
= mpt2sas_phy
->identify
;
871 mpt2sas_phy
->attached_handle
= le16_to_cpu(phy_pg0
.AttachedDevHandle
);
872 if (mpt2sas_phy
->attached_handle
)
873 _transport_set_identify(ioc
, mpt2sas_phy
->attached_handle
,
874 &mpt2sas_phy
->remote_identify
);
875 phy
->identify
.phy_identifier
= mpt2sas_phy
->phy_id
;
876 phy
->negotiated_linkrate
= _transport_convert_phy_link_rate(
877 phy_pg0
.NegotiatedLinkRate
& MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL
);
878 phy
->minimum_linkrate_hw
= _transport_convert_phy_link_rate(
879 phy_pg0
.HwLinkRate
& MPI2_SAS_HWRATE_MIN_RATE_MASK
);
880 phy
->maximum_linkrate_hw
= _transport_convert_phy_link_rate(
881 phy_pg0
.HwLinkRate
>> 4);
882 phy
->minimum_linkrate
= _transport_convert_phy_link_rate(
883 phy_pg0
.ProgrammedLinkRate
& MPI2_SAS_PRATE_MIN_RATE_MASK
);
884 phy
->maximum_linkrate
= _transport_convert_phy_link_rate(
885 phy_pg0
.ProgrammedLinkRate
>> 4);
887 if ((sas_phy_add(phy
))) {
888 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
889 ioc
->name
, __FILE__
, __LINE__
, __func__
);
893 if ((ioc
->logging_level
& MPT_DEBUG_TRANSPORT
))
894 dev_printk(KERN_INFO
, &phy
->dev
,
895 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
896 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
897 mpt2sas_phy
->handle
, (unsigned long long)
898 mpt2sas_phy
->identify
.sas_address
,
899 mpt2sas_phy
->attached_handle
,
901 mpt2sas_phy
->remote_identify
.sas_address
);
902 mpt2sas_phy
->phy
= phy
;
908 * mpt2sas_transport_add_expander_phy - report expander phy to transport
909 * @ioc: per adapter object
910 * @mpt2sas_phy: mpt2sas per phy object
911 * @expander_pg1: expander page 1
912 * @parent_dev: parent device class object
914 * Returns 0 for success, non-zero for failure.
917 mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER
*ioc
, struct _sas_phy
918 *mpt2sas_phy
, Mpi2ExpanderPage1_t expander_pg1
, struct device
*parent_dev
)
921 int phy_index
= mpt2sas_phy
->phy_id
;
923 INIT_LIST_HEAD(&mpt2sas_phy
->port_siblings
);
924 phy
= sas_phy_alloc(parent_dev
, phy_index
);
926 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
927 ioc
->name
, __FILE__
, __LINE__
, __func__
);
930 if ((_transport_set_identify(ioc
, mpt2sas_phy
->handle
,
931 &mpt2sas_phy
->identify
))) {
932 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
933 ioc
->name
, __FILE__
, __LINE__
, __func__
);
936 phy
->identify
= mpt2sas_phy
->identify
;
937 mpt2sas_phy
->attached_handle
=
938 le16_to_cpu(expander_pg1
.AttachedDevHandle
);
939 if (mpt2sas_phy
->attached_handle
)
940 _transport_set_identify(ioc
, mpt2sas_phy
->attached_handle
,
941 &mpt2sas_phy
->remote_identify
);
942 phy
->identify
.phy_identifier
= mpt2sas_phy
->phy_id
;
943 phy
->negotiated_linkrate
= _transport_convert_phy_link_rate(
944 expander_pg1
.NegotiatedLinkRate
&
945 MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL
);
946 phy
->minimum_linkrate_hw
= _transport_convert_phy_link_rate(
947 expander_pg1
.HwLinkRate
& MPI2_SAS_HWRATE_MIN_RATE_MASK
);
948 phy
->maximum_linkrate_hw
= _transport_convert_phy_link_rate(
949 expander_pg1
.HwLinkRate
>> 4);
950 phy
->minimum_linkrate
= _transport_convert_phy_link_rate(
951 expander_pg1
.ProgrammedLinkRate
& MPI2_SAS_PRATE_MIN_RATE_MASK
);
952 phy
->maximum_linkrate
= _transport_convert_phy_link_rate(
953 expander_pg1
.ProgrammedLinkRate
>> 4);
955 if ((sas_phy_add(phy
))) {
956 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
957 ioc
->name
, __FILE__
, __LINE__
, __func__
);
961 if ((ioc
->logging_level
& MPT_DEBUG_TRANSPORT
))
962 dev_printk(KERN_INFO
, &phy
->dev
,
963 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
964 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
965 mpt2sas_phy
->handle
, (unsigned long long)
966 mpt2sas_phy
->identify
.sas_address
,
967 mpt2sas_phy
->attached_handle
,
969 mpt2sas_phy
->remote_identify
.sas_address
);
970 mpt2sas_phy
->phy
= phy
;
975 * mpt2sas_transport_update_links - refreshing phy link changes
976 * @ioc: per adapter object
977 * @sas_address: sas address of parent expander or sas host
978 * @handle: attached device handle
979 * @phy_numberv: phy number
980 * @link_rate: new link rate
985 mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER
*ioc
,
986 u64 sas_address
, u16 handle
, u8 phy_number
, u8 link_rate
)
989 struct _sas_node
*sas_node
;
990 struct _sas_phy
*mpt2sas_phy
;
992 if (ioc
->shost_recovery
|| ioc
->pci_error_recovery
)
995 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
996 sas_node
= _transport_sas_node_find_by_sas_address(ioc
, sas_address
);
998 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1002 mpt2sas_phy
= &sas_node
->phy
[phy_number
];
1003 mpt2sas_phy
->attached_handle
= handle
;
1004 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1005 if (handle
&& (link_rate
>= MPI2_SAS_NEG_LINK_RATE_1_5
)) {
1006 _transport_set_identify(ioc
, handle
,
1007 &mpt2sas_phy
->remote_identify
);
1008 _transport_add_phy_to_an_existing_port(ioc
, sas_node
,
1009 mpt2sas_phy
, mpt2sas_phy
->remote_identify
.sas_address
);
1011 memset(&mpt2sas_phy
->remote_identify
, 0 , sizeof(struct
1014 if (mpt2sas_phy
->phy
)
1015 mpt2sas_phy
->phy
->negotiated_linkrate
=
1016 _transport_convert_phy_link_rate(link_rate
);
1018 if ((ioc
->logging_level
& MPT_DEBUG_TRANSPORT
))
1019 dev_printk(KERN_INFO
, &mpt2sas_phy
->phy
->dev
,
1020 "refresh: parent sas_addr(0x%016llx),\n"
1021 "\tlink_rate(0x%02x), phy(%d)\n"
1022 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
1023 (unsigned long long)sas_address
,
1024 link_rate
, phy_number
, handle
, (unsigned long long)
1025 mpt2sas_phy
->remote_identify
.sas_address
);
1028 static inline void *
1029 phy_to_ioc(struct sas_phy
*phy
)
1031 struct Scsi_Host
*shost
= dev_to_shost(phy
->dev
.parent
);
1032 return shost_priv(shost
);
1035 static inline void *
1036 rphy_to_ioc(struct sas_rphy
*rphy
)
1038 struct Scsi_Host
*shost
= dev_to_shost(rphy
->dev
.parent
->parent
);
1039 return shost_priv(shost
);
1043 /* report phy error log structure */
1044 struct phy_error_log_request
{
1045 u8 smp_frame_type
; /* 0x40 */
1046 u8 function
; /* 0x11 */
1047 u8 allocated_response_length
;
1048 u8 request_length
; /* 02 */
1054 /* report phy error log reply structure */
1055 struct phy_error_log_reply
{
1056 u8 smp_frame_type
; /* 0x41 */
1057 u8 function
; /* 0x11 */
1060 __be16 expander_change_count
;
1064 __be32 invalid_dword
;
1065 __be32 running_disparity_error
;
1066 __be32 loss_of_dword_sync
;
1067 __be32 phy_reset_problem
;
1071 * _transport_get_expander_phy_error_log - return expander counters
1072 * @ioc: per adapter object
1073 * @phy: The sas phy object
1075 * Returns 0 for success, non-zero for failure.
1079 _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER
*ioc
,
1080 struct sas_phy
*phy
)
1082 Mpi2SmpPassthroughRequest_t
*mpi_request
;
1083 Mpi2SmpPassthroughReply_t
*mpi_reply
;
1084 struct phy_error_log_request
*phy_error_log_request
;
1085 struct phy_error_log_reply
*phy_error_log_reply
;
1089 unsigned long timeleft
;
1093 void *data_out
= NULL
;
1094 dma_addr_t data_out_dma
;
1096 u16 wait_state_count
;
1098 if (ioc
->shost_recovery
|| ioc
->pci_error_recovery
) {
1099 printk(MPT2SAS_INFO_FMT
"%s: host reset in progress!\n",
1100 __func__
, ioc
->name
);
1104 mutex_lock(&ioc
->transport_cmds
.mutex
);
1106 if (ioc
->transport_cmds
.status
!= MPT2_CMD_NOT_USED
) {
1107 printk(MPT2SAS_ERR_FMT
"%s: transport_cmds in use\n",
1108 ioc
->name
, __func__
);
1112 ioc
->transport_cmds
.status
= MPT2_CMD_PENDING
;
1114 wait_state_count
= 0;
1115 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
1116 while (ioc_state
!= MPI2_IOC_STATE_OPERATIONAL
) {
1117 if (wait_state_count
++ == 10) {
1118 printk(MPT2SAS_ERR_FMT
1119 "%s: failed due to ioc not operational\n",
1120 ioc
->name
, __func__
);
1125 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
1126 printk(MPT2SAS_INFO_FMT
"%s: waiting for "
1127 "operational state(count=%d)\n", ioc
->name
,
1128 __func__
, wait_state_count
);
1130 if (wait_state_count
)
1131 printk(MPT2SAS_INFO_FMT
"%s: ioc is operational\n",
1132 ioc
->name
, __func__
);
1134 smid
= mpt2sas_base_get_smid(ioc
, ioc
->transport_cb_idx
);
1136 printk(MPT2SAS_ERR_FMT
"%s: failed obtaining a smid\n",
1137 ioc
->name
, __func__
);
1142 mpi_request
= mpt2sas_base_get_msg_frame(ioc
, smid
);
1143 ioc
->transport_cmds
.smid
= smid
;
1145 sz
= sizeof(struct phy_error_log_request
) +
1146 sizeof(struct phy_error_log_reply
);
1147 data_out
= pci_alloc_consistent(ioc
->pdev
, sz
, &data_out_dma
);
1149 printk(KERN_ERR
"failure at %s:%d/%s()!\n", __FILE__
,
1150 __LINE__
, __func__
);
1152 mpt2sas_base_free_smid(ioc
, smid
);
1157 memset(data_out
, 0, sz
);
1158 phy_error_log_request
= data_out
;
1159 phy_error_log_request
->smp_frame_type
= 0x40;
1160 phy_error_log_request
->function
= 0x11;
1161 phy_error_log_request
->request_length
= 2;
1162 phy_error_log_request
->allocated_response_length
= 0;
1163 phy_error_log_request
->phy_identifier
= phy
->number
;
1165 memset(mpi_request
, 0, sizeof(Mpi2SmpPassthroughRequest_t
));
1166 mpi_request
->Function
= MPI2_FUNCTION_SMP_PASSTHROUGH
;
1167 mpi_request
->PhysicalPort
= 0xFF;
1168 mpi_request
->VF_ID
= 0; /* TODO */
1169 mpi_request
->VP_ID
= 0;
1170 mpi_request
->SASAddress
= cpu_to_le64(phy
->identify
.sas_address
);
1171 mpi_request
->RequestDataLength
=
1172 cpu_to_le16(sizeof(struct phy_error_log_request
));
1173 psge
= &mpi_request
->SGL
;
1175 /* WRITE sgel first */
1176 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
1177 MPI2_SGE_FLAGS_END_OF_BUFFER
| MPI2_SGE_FLAGS_HOST_TO_IOC
);
1178 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
1179 ioc
->base_add_sg_single(psge
, sgl_flags
|
1180 sizeof(struct phy_error_log_request
), data_out_dma
);
1183 psge
+= ioc
->sge_size
;
1185 /* READ sgel last */
1186 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
1187 MPI2_SGE_FLAGS_LAST_ELEMENT
| MPI2_SGE_FLAGS_END_OF_BUFFER
|
1188 MPI2_SGE_FLAGS_END_OF_LIST
);
1189 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
1190 ioc
->base_add_sg_single(psge
, sgl_flags
|
1191 sizeof(struct phy_error_log_reply
), data_out_dma
+
1192 sizeof(struct phy_error_log_request
));
1194 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"phy_error_log - "
1195 "send to sas_addr(0x%016llx), phy(%d)\n", ioc
->name
,
1196 (unsigned long long)phy
->identify
.sas_address
, phy
->number
));
1197 init_completion(&ioc
->transport_cmds
.done
);
1198 mpt2sas_base_put_smid_default(ioc
, smid
);
1199 timeleft
= wait_for_completion_timeout(&ioc
->transport_cmds
.done
,
1202 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_COMPLETE
)) {
1203 printk(MPT2SAS_ERR_FMT
"%s: timeout\n",
1204 ioc
->name
, __func__
);
1205 _debug_dump_mf(mpi_request
,
1206 sizeof(Mpi2SmpPassthroughRequest_t
)/4);
1207 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_RESET
))
1209 goto issue_host_reset
;
1212 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"phy_error_log - "
1213 "complete\n", ioc
->name
));
1215 if (ioc
->transport_cmds
.status
& MPT2_CMD_REPLY_VALID
) {
1217 mpi_reply
= ioc
->transport_cmds
.reply
;
1219 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1220 "phy_error_log - reply data transfer size(%d)\n",
1221 ioc
->name
, le16_to_cpu(mpi_reply
->ResponseDataLength
)));
1223 if (le16_to_cpu(mpi_reply
->ResponseDataLength
) !=
1224 sizeof(struct phy_error_log_reply
))
1227 phy_error_log_reply
= data_out
+
1228 sizeof(struct phy_error_log_request
);
1230 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1231 "phy_error_log - function_result(%d)\n",
1232 ioc
->name
, phy_error_log_reply
->function_result
));
1234 phy
->invalid_dword_count
=
1235 be32_to_cpu(phy_error_log_reply
->invalid_dword
);
1236 phy
->running_disparity_error_count
=
1237 be32_to_cpu(phy_error_log_reply
->running_disparity_error
);
1238 phy
->loss_of_dword_sync_count
=
1239 be32_to_cpu(phy_error_log_reply
->loss_of_dword_sync
);
1240 phy
->phy_reset_problem_count
=
1241 be32_to_cpu(phy_error_log_reply
->phy_reset_problem
);
1244 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1245 "phy_error_log - no reply\n", ioc
->name
));
1249 mpt2sas_base_hard_reset_handler(ioc
, CAN_SLEEP
,
1252 ioc
->transport_cmds
.status
= MPT2_CMD_NOT_USED
;
1254 pci_free_consistent(ioc
->pdev
, sz
, data_out
, data_out_dma
);
1256 mutex_unlock(&ioc
->transport_cmds
.mutex
);
1261 * _transport_get_linkerrors - return phy counters for both hba and expanders
1262 * @phy: The sas phy object
1264 * Returns 0 for success, non-zero for failure.
1268 _transport_get_linkerrors(struct sas_phy
*phy
)
1270 struct MPT2SAS_ADAPTER
*ioc
= phy_to_ioc(phy
);
1271 unsigned long flags
;
1272 Mpi2ConfigReply_t mpi_reply
;
1273 Mpi2SasPhyPage1_t phy_pg1
;
1275 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
1276 if (_transport_sas_node_find_by_sas_address(ioc
,
1277 phy
->identify
.sas_address
) == NULL
) {
1278 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1281 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1283 if (phy
->identify
.sas_address
!= ioc
->sas_hba
.sas_address
)
1284 return _transport_get_expander_phy_error_log(ioc
, phy
);
1286 /* get hba phy error logs */
1287 if ((mpt2sas_config_get_phy_pg1(ioc
, &mpi_reply
, &phy_pg1
,
1289 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1290 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1294 if (mpi_reply
.IOCStatus
|| mpi_reply
.IOCLogInfo
)
1295 printk(MPT2SAS_INFO_FMT
"phy(%d), ioc_status"
1296 "(0x%04x), loginfo(0x%08x)\n", ioc
->name
,
1297 phy
->number
, le16_to_cpu(mpi_reply
.IOCStatus
),
1298 le32_to_cpu(mpi_reply
.IOCLogInfo
));
1300 phy
->invalid_dword_count
= le32_to_cpu(phy_pg1
.InvalidDwordCount
);
1301 phy
->running_disparity_error_count
=
1302 le32_to_cpu(phy_pg1
.RunningDisparityErrorCount
);
1303 phy
->loss_of_dword_sync_count
=
1304 le32_to_cpu(phy_pg1
.LossDwordSynchCount
);
1305 phy
->phy_reset_problem_count
=
1306 le32_to_cpu(phy_pg1
.PhyResetProblemCount
);
1311 * _transport_get_enclosure_identifier -
1312 * @phy: The sas phy object
1314 * Obtain the enclosure logical id for an expander.
1315 * Returns 0 for success, non-zero for failure.
1318 _transport_get_enclosure_identifier(struct sas_rphy
*rphy
, u64
*identifier
)
1320 struct MPT2SAS_ADAPTER
*ioc
= rphy_to_ioc(rphy
);
1321 struct _sas_device
*sas_device
;
1322 unsigned long flags
;
1325 spin_lock_irqsave(&ioc
->sas_device_lock
, flags
);
1326 sas_device
= mpt2sas_scsih_sas_device_find_by_sas_address(ioc
,
1327 rphy
->identify
.sas_address
);
1329 *identifier
= sas_device
->enclosure_logical_id
;
1335 spin_unlock_irqrestore(&ioc
->sas_device_lock
, flags
);
1340 * _transport_get_bay_identifier -
1341 * @phy: The sas phy object
1343 * Returns the slot id for a device that resides inside an enclosure.
1346 _transport_get_bay_identifier(struct sas_rphy
*rphy
)
1348 struct MPT2SAS_ADAPTER
*ioc
= rphy_to_ioc(rphy
);
1349 struct _sas_device
*sas_device
;
1350 unsigned long flags
;
1353 spin_lock_irqsave(&ioc
->sas_device_lock
, flags
);
1354 sas_device
= mpt2sas_scsih_sas_device_find_by_sas_address(ioc
,
1355 rphy
->identify
.sas_address
);
1357 rc
= sas_device
->slot
;
1360 spin_unlock_irqrestore(&ioc
->sas_device_lock
, flags
);
1364 /* phy control request structure */
1365 struct phy_control_request
{
1366 u8 smp_frame_type
; /* 0x40 */
1367 u8 function
; /* 0x91 */
1368 u8 allocated_response_length
;
1369 u8 request_length
; /* 0x09 */
1370 u16 expander_change_count
;
1375 u64 attached_device_name
;
1376 u8 programmed_min_physical_link_rate
;
1377 u8 programmed_max_physical_link_rate
;
1381 /* phy control reply structure */
1382 struct phy_control_reply
{
1383 u8 smp_frame_type
; /* 0x41 */
1384 u8 function
; /* 0x11 */
1389 #define SMP_PHY_CONTROL_LINK_RESET (0x01)
1390 #define SMP_PHY_CONTROL_HARD_RESET (0x02)
1391 #define SMP_PHY_CONTROL_DISABLE (0x03)
1394 * _transport_expander_phy_control - expander phy control
1395 * @ioc: per adapter object
1396 * @phy: The sas phy object
1398 * Returns 0 for success, non-zero for failure.
1402 _transport_expander_phy_control(struct MPT2SAS_ADAPTER
*ioc
,
1403 struct sas_phy
*phy
, u8 phy_operation
)
1405 Mpi2SmpPassthroughRequest_t
*mpi_request
;
1406 Mpi2SmpPassthroughReply_t
*mpi_reply
;
1407 struct phy_control_request
*phy_control_request
;
1408 struct phy_control_reply
*phy_control_reply
;
1412 unsigned long timeleft
;
1416 void *data_out
= NULL
;
1417 dma_addr_t data_out_dma
;
1419 u16 wait_state_count
;
1421 if (ioc
->shost_recovery
) {
1422 printk(MPT2SAS_INFO_FMT
"%s: host reset in progress!\n",
1423 __func__
, ioc
->name
);
1427 mutex_lock(&ioc
->transport_cmds
.mutex
);
1429 if (ioc
->transport_cmds
.status
!= MPT2_CMD_NOT_USED
) {
1430 printk(MPT2SAS_ERR_FMT
"%s: transport_cmds in use\n",
1431 ioc
->name
, __func__
);
1435 ioc
->transport_cmds
.status
= MPT2_CMD_PENDING
;
1437 wait_state_count
= 0;
1438 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
1439 while (ioc_state
!= MPI2_IOC_STATE_OPERATIONAL
) {
1440 if (wait_state_count
++ == 10) {
1441 printk(MPT2SAS_ERR_FMT
1442 "%s: failed due to ioc not operational\n",
1443 ioc
->name
, __func__
);
1448 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
1449 printk(MPT2SAS_INFO_FMT
"%s: waiting for "
1450 "operational state(count=%d)\n", ioc
->name
,
1451 __func__
, wait_state_count
);
1453 if (wait_state_count
)
1454 printk(MPT2SAS_INFO_FMT
"%s: ioc is operational\n",
1455 ioc
->name
, __func__
);
1457 smid
= mpt2sas_base_get_smid(ioc
, ioc
->transport_cb_idx
);
1459 printk(MPT2SAS_ERR_FMT
"%s: failed obtaining a smid\n",
1460 ioc
->name
, __func__
);
1465 mpi_request
= mpt2sas_base_get_msg_frame(ioc
, smid
);
1466 ioc
->transport_cmds
.smid
= smid
;
1468 sz
= sizeof(struct phy_control_request
) +
1469 sizeof(struct phy_control_reply
);
1470 data_out
= pci_alloc_consistent(ioc
->pdev
, sz
, &data_out_dma
);
1472 printk(KERN_ERR
"failure at %s:%d/%s()!\n", __FILE__
,
1473 __LINE__
, __func__
);
1475 mpt2sas_base_free_smid(ioc
, smid
);
1480 memset(data_out
, 0, sz
);
1481 phy_control_request
= data_out
;
1482 phy_control_request
->smp_frame_type
= 0x40;
1483 phy_control_request
->function
= 0x91;
1484 phy_control_request
->request_length
= 9;
1485 phy_control_request
->allocated_response_length
= 0;
1486 phy_control_request
->phy_identifier
= phy
->number
;
1487 phy_control_request
->phy_operation
= phy_operation
;
1488 phy_control_request
->programmed_min_physical_link_rate
=
1489 phy
->minimum_linkrate
<< 4;
1490 phy_control_request
->programmed_max_physical_link_rate
=
1491 phy
->maximum_linkrate
<< 4;
1493 memset(mpi_request
, 0, sizeof(Mpi2SmpPassthroughRequest_t
));
1494 mpi_request
->Function
= MPI2_FUNCTION_SMP_PASSTHROUGH
;
1495 mpi_request
->PhysicalPort
= 0xFF;
1496 mpi_request
->VF_ID
= 0; /* TODO */
1497 mpi_request
->VP_ID
= 0;
1498 mpi_request
->SASAddress
= cpu_to_le64(phy
->identify
.sas_address
);
1499 mpi_request
->RequestDataLength
=
1500 cpu_to_le16(sizeof(struct phy_error_log_request
));
1501 psge
= &mpi_request
->SGL
;
1503 /* WRITE sgel first */
1504 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
1505 MPI2_SGE_FLAGS_END_OF_BUFFER
| MPI2_SGE_FLAGS_HOST_TO_IOC
);
1506 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
1507 ioc
->base_add_sg_single(psge
, sgl_flags
|
1508 sizeof(struct phy_control_request
), data_out_dma
);
1511 psge
+= ioc
->sge_size
;
1513 /* READ sgel last */
1514 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
1515 MPI2_SGE_FLAGS_LAST_ELEMENT
| MPI2_SGE_FLAGS_END_OF_BUFFER
|
1516 MPI2_SGE_FLAGS_END_OF_LIST
);
1517 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
1518 ioc
->base_add_sg_single(psge
, sgl_flags
|
1519 sizeof(struct phy_control_reply
), data_out_dma
+
1520 sizeof(struct phy_control_request
));
1522 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"phy_control - "
1523 "send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", ioc
->name
,
1524 (unsigned long long)phy
->identify
.sas_address
, phy
->number
,
1527 init_completion(&ioc
->transport_cmds
.done
);
1528 mpt2sas_base_put_smid_default(ioc
, smid
);
1529 timeleft
= wait_for_completion_timeout(&ioc
->transport_cmds
.done
,
1532 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_COMPLETE
)) {
1533 printk(MPT2SAS_ERR_FMT
"%s: timeout\n",
1534 ioc
->name
, __func__
);
1535 _debug_dump_mf(mpi_request
,
1536 sizeof(Mpi2SmpPassthroughRequest_t
)/4);
1537 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_RESET
))
1539 goto issue_host_reset
;
1542 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"phy_control - "
1543 "complete\n", ioc
->name
));
1545 if (ioc
->transport_cmds
.status
& MPT2_CMD_REPLY_VALID
) {
1547 mpi_reply
= ioc
->transport_cmds
.reply
;
1549 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1550 "phy_control - reply data transfer size(%d)\n",
1551 ioc
->name
, le16_to_cpu(mpi_reply
->ResponseDataLength
)));
1553 if (le16_to_cpu(mpi_reply
->ResponseDataLength
) !=
1554 sizeof(struct phy_control_reply
))
1557 phy_control_reply
= data_out
+
1558 sizeof(struct phy_control_request
);
1560 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1561 "phy_control - function_result(%d)\n",
1562 ioc
->name
, phy_control_reply
->function_result
));
1566 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1567 "phy_control - no reply\n", ioc
->name
));
1571 mpt2sas_base_hard_reset_handler(ioc
, CAN_SLEEP
,
1574 ioc
->transport_cmds
.status
= MPT2_CMD_NOT_USED
;
1576 pci_free_consistent(ioc
->pdev
, sz
, data_out
, data_out_dma
);
1578 mutex_unlock(&ioc
->transport_cmds
.mutex
);
1583 * _transport_phy_reset -
1584 * @phy: The sas phy object
1587 * Returns 0 for success, non-zero for failure.
1590 _transport_phy_reset(struct sas_phy
*phy
, int hard_reset
)
1592 struct MPT2SAS_ADAPTER
*ioc
= phy_to_ioc(phy
);
1593 Mpi2SasIoUnitControlReply_t mpi_reply
;
1594 Mpi2SasIoUnitControlRequest_t mpi_request
;
1595 unsigned long flags
;
1597 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
1598 if (_transport_sas_node_find_by_sas_address(ioc
,
1599 phy
->identify
.sas_address
) == NULL
) {
1600 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1603 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1605 /* handle expander phys */
1606 if (phy
->identify
.sas_address
!= ioc
->sas_hba
.sas_address
)
1607 return _transport_expander_phy_control(ioc
, phy
,
1608 (hard_reset
== 1) ? SMP_PHY_CONTROL_HARD_RESET
:
1609 SMP_PHY_CONTROL_LINK_RESET
);
1611 /* handle hba phys */
1612 memset(&mpi_request
, 0, sizeof(Mpi2SasIoUnitControlReply_t
));
1613 mpi_request
.Function
= MPI2_FUNCTION_SAS_IO_UNIT_CONTROL
;
1614 mpi_request
.Operation
= hard_reset
?
1615 MPI2_SAS_OP_PHY_HARD_RESET
: MPI2_SAS_OP_PHY_LINK_RESET
;
1616 mpi_request
.PhyNum
= phy
->number
;
1618 if ((mpt2sas_base_sas_iounit_control(ioc
, &mpi_reply
, &mpi_request
))) {
1619 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1620 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1624 if (mpi_reply
.IOCStatus
|| mpi_reply
.IOCLogInfo
)
1625 printk(MPT2SAS_INFO_FMT
"phy(%d), ioc_status"
1626 "(0x%04x), loginfo(0x%08x)\n", ioc
->name
,
1627 phy
->number
, le16_to_cpu(mpi_reply
.IOCStatus
),
1628 le32_to_cpu(mpi_reply
.IOCLogInfo
));
1634 * _transport_phy_enable - enable/disable phys
1635 * @phy: The sas phy object
1636 * @enable: enable phy when true
1638 * Only support sas_host direct attached phys.
1639 * Returns 0 for success, non-zero for failure.
1642 _transport_phy_enable(struct sas_phy
*phy
, int enable
)
1644 struct MPT2SAS_ADAPTER
*ioc
= phy_to_ioc(phy
);
1645 Mpi2SasIOUnitPage1_t
*sas_iounit_pg1
= NULL
;
1646 Mpi2SasIOUnitPage0_t
*sas_iounit_pg0
= NULL
;
1647 Mpi2ConfigReply_t mpi_reply
;
1651 unsigned long flags
;
1652 int i
, discovery_active
;
1654 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
1655 if (_transport_sas_node_find_by_sas_address(ioc
,
1656 phy
->identify
.sas_address
) == NULL
) {
1657 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1660 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1662 /* handle expander phys */
1663 if (phy
->identify
.sas_address
!= ioc
->sas_hba
.sas_address
)
1664 return _transport_expander_phy_control(ioc
, phy
,
1665 (enable
== 1) ? SMP_PHY_CONTROL_LINK_RESET
:
1666 SMP_PHY_CONTROL_DISABLE
);
1668 /* handle hba phys */
1670 /* read sas_iounit page 0 */
1671 sz
= offsetof(Mpi2SasIOUnitPage0_t
, PhyData
) + (ioc
->sas_hba
.num_phys
*
1672 sizeof(Mpi2SasIOUnit0PhyData_t
));
1673 sas_iounit_pg0
= kzalloc(sz
, GFP_KERNEL
);
1674 if (!sas_iounit_pg0
) {
1675 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1676 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1680 if ((mpt2sas_config_get_sas_iounit_pg0(ioc
, &mpi_reply
,
1681 sas_iounit_pg0
, sz
))) {
1682 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1683 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1687 ioc_status
= le16_to_cpu(mpi_reply
.IOCStatus
) &
1688 MPI2_IOCSTATUS_MASK
;
1689 if (ioc_status
!= MPI2_IOCSTATUS_SUCCESS
) {
1690 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1691 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1696 /* unable to enable/disable phys when when discovery is active */
1697 for (i
= 0, discovery_active
= 0; i
< ioc
->sas_hba
.num_phys
; i
++) {
1698 if (sas_iounit_pg0
->PhyData
[i
].PortFlags
&
1699 MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS
) {
1700 printk(MPT2SAS_ERR_FMT
"discovery is active on "
1701 "port = %d, phy = %d: unable to enable/disable "
1702 "phys, try again later!\n", ioc
->name
,
1703 sas_iounit_pg0
->PhyData
[i
].Port
, i
);
1704 discovery_active
= 1;
1708 if (discovery_active
) {
1713 /* read sas_iounit page 1 */
1714 sz
= offsetof(Mpi2SasIOUnitPage1_t
, PhyData
) + (ioc
->sas_hba
.num_phys
*
1715 sizeof(Mpi2SasIOUnit1PhyData_t
));
1716 sas_iounit_pg1
= kzalloc(sz
, GFP_KERNEL
);
1717 if (!sas_iounit_pg1
) {
1718 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1719 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1723 if ((mpt2sas_config_get_sas_iounit_pg1(ioc
, &mpi_reply
,
1724 sas_iounit_pg1
, sz
))) {
1725 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1726 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1730 ioc_status
= le16_to_cpu(mpi_reply
.IOCStatus
) &
1731 MPI2_IOCSTATUS_MASK
;
1732 if (ioc_status
!= MPI2_IOCSTATUS_SUCCESS
) {
1733 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1734 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1738 /* copy Port/PortFlags/PhyFlags from page 0 */
1739 for (i
= 0; i
< ioc
->sas_hba
.num_phys
; i
++) {
1740 sas_iounit_pg1
->PhyData
[i
].Port
=
1741 sas_iounit_pg0
->PhyData
[i
].Port
;
1742 sas_iounit_pg1
->PhyData
[i
].PortFlags
=
1743 (sas_iounit_pg0
->PhyData
[i
].PortFlags
&
1744 MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG
);
1745 sas_iounit_pg1
->PhyData
[i
].PhyFlags
=
1746 (sas_iounit_pg0
->PhyData
[i
].PhyFlags
&
1747 (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED
+
1748 MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED
));
1751 sas_iounit_pg1
->PhyData
[phy
->number
].PhyFlags
1752 &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE
;
1754 sas_iounit_pg1
->PhyData
[phy
->number
].PhyFlags
1755 |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE
;
1757 mpt2sas_config_set_sas_iounit_pg1(ioc
, &mpi_reply
, sas_iounit_pg1
, sz
);
1761 _transport_phy_reset(phy
, 0);
1764 kfree(sas_iounit_pg1
);
1765 kfree(sas_iounit_pg0
);
1770 * _transport_phy_speed - set phy min/max link rates
1771 * @phy: The sas phy object
1772 * @rates: rates defined in sas_phy_linkrates
1774 * Only support sas_host direct attached phys.
1775 * Returns 0 for success, non-zero for failure.
1778 _transport_phy_speed(struct sas_phy
*phy
, struct sas_phy_linkrates
*rates
)
1780 struct MPT2SAS_ADAPTER
*ioc
= phy_to_ioc(phy
);
1781 Mpi2SasIOUnitPage1_t
*sas_iounit_pg1
= NULL
;
1782 Mpi2SasPhyPage0_t phy_pg0
;
1783 Mpi2ConfigReply_t mpi_reply
;
1788 unsigned long flags
;
1790 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
1791 if (_transport_sas_node_find_by_sas_address(ioc
,
1792 phy
->identify
.sas_address
) == NULL
) {
1793 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1796 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1798 if (!rates
->minimum_linkrate
)
1799 rates
->minimum_linkrate
= phy
->minimum_linkrate
;
1800 else if (rates
->minimum_linkrate
< phy
->minimum_linkrate_hw
)
1801 rates
->minimum_linkrate
= phy
->minimum_linkrate_hw
;
1803 if (!rates
->maximum_linkrate
)
1804 rates
->maximum_linkrate
= phy
->maximum_linkrate
;
1805 else if (rates
->maximum_linkrate
> phy
->maximum_linkrate_hw
)
1806 rates
->maximum_linkrate
= phy
->maximum_linkrate_hw
;
1808 /* handle expander phys */
1809 if (phy
->identify
.sas_address
!= ioc
->sas_hba
.sas_address
) {
1810 phy
->minimum_linkrate
= rates
->minimum_linkrate
;
1811 phy
->maximum_linkrate
= rates
->maximum_linkrate
;
1812 return _transport_expander_phy_control(ioc
, phy
,
1813 SMP_PHY_CONTROL_LINK_RESET
);
1816 /* handle hba phys */
1818 /* sas_iounit page 1 */
1819 sz
= offsetof(Mpi2SasIOUnitPage1_t
, PhyData
) + (ioc
->sas_hba
.num_phys
*
1820 sizeof(Mpi2SasIOUnit1PhyData_t
));
1821 sas_iounit_pg1
= kzalloc(sz
, GFP_KERNEL
);
1822 if (!sas_iounit_pg1
) {
1823 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1824 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1828 if ((mpt2sas_config_get_sas_iounit_pg1(ioc
, &mpi_reply
,
1829 sas_iounit_pg1
, sz
))) {
1830 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1831 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1835 ioc_status
= le16_to_cpu(mpi_reply
.IOCStatus
) &
1836 MPI2_IOCSTATUS_MASK
;
1837 if (ioc_status
!= MPI2_IOCSTATUS_SUCCESS
) {
1838 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1839 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1844 for (i
= 0; i
< ioc
->sas_hba
.num_phys
; i
++) {
1845 if (phy
->number
!= i
) {
1846 sas_iounit_pg1
->PhyData
[i
].MaxMinLinkRate
=
1847 (ioc
->sas_hba
.phy
[i
].phy
->minimum_linkrate
+
1848 (ioc
->sas_hba
.phy
[i
].phy
->maximum_linkrate
<< 4));
1850 sas_iounit_pg1
->PhyData
[i
].MaxMinLinkRate
=
1851 (rates
->minimum_linkrate
+
1852 (rates
->maximum_linkrate
<< 4));
1856 if (mpt2sas_config_set_sas_iounit_pg1(ioc
, &mpi_reply
, sas_iounit_pg1
,
1858 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1859 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1865 _transport_phy_reset(phy
, 0);
1867 /* read phy page 0, then update the rates in the sas transport phy */
1868 if (!mpt2sas_config_get_phy_pg0(ioc
, &mpi_reply
, &phy_pg0
,
1870 phy
->minimum_linkrate
= _transport_convert_phy_link_rate(
1871 phy_pg0
.ProgrammedLinkRate
& MPI2_SAS_PRATE_MIN_RATE_MASK
);
1872 phy
->maximum_linkrate
= _transport_convert_phy_link_rate(
1873 phy_pg0
.ProgrammedLinkRate
>> 4);
1874 phy
->negotiated_linkrate
= _transport_convert_phy_link_rate(
1875 phy_pg0
.NegotiatedLinkRate
&
1876 MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL
);
1880 kfree(sas_iounit_pg1
);
1886 * _transport_smp_handler - transport portal for smp passthru
1887 * @shost: shost object
1888 * @rphy: sas transport rphy object
1891 * This used primarily for smp_utils.
1893 * smp_rep_general /sys/class/bsg/expander-5:0
1896 _transport_smp_handler(struct Scsi_Host
*shost
, struct sas_rphy
*rphy
,
1897 struct request
*req
)
1899 struct MPT2SAS_ADAPTER
*ioc
= shost_priv(shost
);
1900 Mpi2SmpPassthroughRequest_t
*mpi_request
;
1901 Mpi2SmpPassthroughReply_t
*mpi_reply
;
1905 unsigned long timeleft
;
1909 dma_addr_t dma_addr_in
= 0;
1910 dma_addr_t dma_addr_out
= 0;
1911 dma_addr_t pci_dma_in
= 0;
1912 dma_addr_t pci_dma_out
= 0;
1913 void *pci_addr_in
= NULL
;
1914 void *pci_addr_out
= NULL
;
1915 u16 wait_state_count
;
1916 struct request
*rsp
= req
->next_rq
;
1917 struct bio_vec bvec
;
1918 struct bvec_iter iter
;
1921 printk(MPT2SAS_ERR_FMT
"%s: the smp response space is "
1922 "missing\n", ioc
->name
, __func__
);
1925 if (ioc
->shost_recovery
|| ioc
->pci_error_recovery
) {
1926 printk(MPT2SAS_INFO_FMT
"%s: host reset in progress!\n",
1927 __func__
, ioc
->name
);
1931 rc
= mutex_lock_interruptible(&ioc
->transport_cmds
.mutex
);
1935 if (ioc
->transport_cmds
.status
!= MPT2_CMD_NOT_USED
) {
1936 printk(MPT2SAS_ERR_FMT
"%s: transport_cmds in use\n", ioc
->name
,
1941 ioc
->transport_cmds
.status
= MPT2_CMD_PENDING
;
1943 /* Check if the request is split across multiple segments */
1944 if (bio_multiple_segments(req
->bio
)) {
1947 /* Allocate memory and copy the request */
1948 pci_addr_out
= pci_alloc_consistent(ioc
->pdev
,
1949 blk_rq_bytes(req
), &pci_dma_out
);
1950 if (!pci_addr_out
) {
1951 printk(MPT2SAS_INFO_FMT
"%s(): PCI Addr out = NULL\n",
1952 ioc
->name
, __func__
);
1957 bio_for_each_segment(bvec
, req
->bio
, iter
) {
1958 memcpy(pci_addr_out
+ offset
,
1959 page_address(bvec
.bv_page
) + bvec
.bv_offset
,
1961 offset
+= bvec
.bv_len
;
1964 dma_addr_out
= pci_map_single(ioc
->pdev
, bio_data(req
->bio
),
1965 blk_rq_bytes(req
), PCI_DMA_BIDIRECTIONAL
);
1966 if (!dma_addr_out
) {
1967 printk(MPT2SAS_INFO_FMT
"%s(): DMA Addr out = NULL\n",
1968 ioc
->name
, __func__
);
1974 /* Check if the response needs to be populated across
1975 * multiple segments */
1976 if (bio_multiple_segments(rsp
->bio
)) {
1977 pci_addr_in
= pci_alloc_consistent(ioc
->pdev
, blk_rq_bytes(rsp
),
1980 printk(MPT2SAS_INFO_FMT
"%s(): PCI Addr in = NULL\n",
1981 ioc
->name
, __func__
);
1986 dma_addr_in
= pci_map_single(ioc
->pdev
, bio_data(rsp
->bio
),
1987 blk_rq_bytes(rsp
), PCI_DMA_BIDIRECTIONAL
);
1989 printk(MPT2SAS_INFO_FMT
"%s(): DMA Addr in = NULL\n",
1990 ioc
->name
, __func__
);
1996 wait_state_count
= 0;
1997 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
1998 while (ioc_state
!= MPI2_IOC_STATE_OPERATIONAL
) {
1999 if (wait_state_count
++ == 10) {
2000 printk(MPT2SAS_ERR_FMT
2001 "%s: failed due to ioc not operational\n",
2002 ioc
->name
, __func__
);
2007 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
2008 printk(MPT2SAS_INFO_FMT
"%s: waiting for "
2009 "operational state(count=%d)\n", ioc
->name
,
2010 __func__
, wait_state_count
);
2012 if (wait_state_count
)
2013 printk(MPT2SAS_INFO_FMT
"%s: ioc is operational\n",
2014 ioc
->name
, __func__
);
2016 smid
= mpt2sas_base_get_smid(ioc
, ioc
->transport_cb_idx
);
2018 printk(MPT2SAS_ERR_FMT
"%s: failed obtaining a smid\n",
2019 ioc
->name
, __func__
);
2025 mpi_request
= mpt2sas_base_get_msg_frame(ioc
, smid
);
2026 ioc
->transport_cmds
.smid
= smid
;
2028 memset(mpi_request
, 0, sizeof(Mpi2SmpPassthroughRequest_t
));
2029 mpi_request
->Function
= MPI2_FUNCTION_SMP_PASSTHROUGH
;
2030 mpi_request
->PhysicalPort
= 0xFF;
2031 mpi_request
->VF_ID
= 0; /* TODO */
2032 mpi_request
->VP_ID
= 0;
2033 mpi_request
->SASAddress
= (rphy
) ?
2034 cpu_to_le64(rphy
->identify
.sas_address
) :
2035 cpu_to_le64(ioc
->sas_hba
.sas_address
);
2036 mpi_request
->RequestDataLength
= cpu_to_le16(blk_rq_bytes(req
) - 4);
2037 psge
= &mpi_request
->SGL
;
2039 /* WRITE sgel first */
2040 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
2041 MPI2_SGE_FLAGS_END_OF_BUFFER
| MPI2_SGE_FLAGS_HOST_TO_IOC
);
2042 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
2043 if (bio_multiple_segments(req
->bio
)) {
2044 ioc
->base_add_sg_single(psge
, sgl_flags
|
2045 (blk_rq_bytes(req
) - 4), pci_dma_out
);
2047 ioc
->base_add_sg_single(psge
, sgl_flags
|
2048 (blk_rq_bytes(req
) - 4), dma_addr_out
);
2052 psge
+= ioc
->sge_size
;
2054 /* READ sgel last */
2055 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
2056 MPI2_SGE_FLAGS_LAST_ELEMENT
| MPI2_SGE_FLAGS_END_OF_BUFFER
|
2057 MPI2_SGE_FLAGS_END_OF_LIST
);
2058 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
2059 if (bio_multiple_segments(rsp
->bio
)) {
2060 ioc
->base_add_sg_single(psge
, sgl_flags
|
2061 (blk_rq_bytes(rsp
) + 4), pci_dma_in
);
2063 ioc
->base_add_sg_single(psge
, sgl_flags
|
2064 (blk_rq_bytes(rsp
) + 4), dma_addr_in
);
2067 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"%s - "
2068 "sending smp request\n", ioc
->name
, __func__
));
2070 init_completion(&ioc
->transport_cmds
.done
);
2071 mpt2sas_base_put_smid_default(ioc
, smid
);
2072 timeleft
= wait_for_completion_timeout(&ioc
->transport_cmds
.done
,
2075 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_COMPLETE
)) {
2076 printk(MPT2SAS_ERR_FMT
"%s : timeout\n",
2077 __func__
, ioc
->name
);
2078 _debug_dump_mf(mpi_request
,
2079 sizeof(Mpi2SmpPassthroughRequest_t
)/4);
2080 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_RESET
))
2082 goto issue_host_reset
;
2085 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"%s - "
2086 "complete\n", ioc
->name
, __func__
));
2088 if (ioc
->transport_cmds
.status
& MPT2_CMD_REPLY_VALID
) {
2090 mpi_reply
= ioc
->transport_cmds
.reply
;
2092 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
2093 "%s - reply data transfer size(%d)\n",
2094 ioc
->name
, __func__
,
2095 le16_to_cpu(mpi_reply
->ResponseDataLength
)));
2097 memcpy(req
->sense
, mpi_reply
, sizeof(*mpi_reply
));
2098 req
->sense_len
= sizeof(*mpi_reply
);
2101 le16_to_cpu(mpi_reply
->ResponseDataLength
);
2102 /* check if the resp needs to be copied from the allocated
2104 if (bio_multiple_segments(rsp
->bio
)) {
2107 le16_to_cpu(mpi_reply
->ResponseDataLength
);
2108 bio_for_each_segment(bvec
, rsp
->bio
, iter
) {
2109 if (bytes_to_copy
<= bvec
.bv_len
) {
2110 memcpy(page_address(bvec
.bv_page
) +
2111 bvec
.bv_offset
, pci_addr_in
+
2112 offset
, bytes_to_copy
);
2115 memcpy(page_address(bvec
.bv_page
) +
2116 bvec
.bv_offset
, pci_addr_in
+
2117 offset
, bvec
.bv_len
);
2118 bytes_to_copy
-= bvec
.bv_len
;
2120 offset
+= bvec
.bv_len
;
2124 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
2125 "%s - no reply\n", ioc
->name
, __func__
));
2131 mpt2sas_base_hard_reset_handler(ioc
, CAN_SLEEP
,
2138 pci_unmap_single(ioc
->pdev
, dma_addr_out
, blk_rq_bytes(req
),
2139 PCI_DMA_BIDIRECTIONAL
);
2141 pci_unmap_single(ioc
->pdev
, dma_addr_in
, blk_rq_bytes(rsp
),
2142 PCI_DMA_BIDIRECTIONAL
);
2146 pci_free_consistent(ioc
->pdev
, blk_rq_bytes(req
), pci_addr_out
,
2150 pci_free_consistent(ioc
->pdev
, blk_rq_bytes(rsp
), pci_addr_in
,
2154 ioc
->transport_cmds
.status
= MPT2_CMD_NOT_USED
;
2155 mutex_unlock(&ioc
->transport_cmds
.mutex
);
2159 struct sas_function_template mpt2sas_transport_functions
= {
2160 .get_linkerrors
= _transport_get_linkerrors
,
2161 .get_enclosure_identifier
= _transport_get_enclosure_identifier
,
2162 .get_bay_identifier
= _transport_get_bay_identifier
,
2163 .phy_reset
= _transport_phy_reset
,
2164 .phy_enable
= _transport_phy_enable
,
2165 .set_phy_speed
= _transport_phy_speed
,
2166 .smp_handler
= _transport_smp_handler
,
2169 struct scsi_transport_template
*mpt2sas_transport_template
;