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-2010 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.
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,
44 #include <linux/module.h>
45 #include <linux/kernel.h>
46 #include <linux/init.h>
47 #include <linux/errno.h>
48 #include <linux/sched.h>
49 #include <linux/workqueue.h>
50 #include <linux/delay.h>
51 #include <linux/pci.h>
52 #include <linux/slab.h>
54 #include <scsi/scsi.h>
55 #include <scsi/scsi_cmnd.h>
56 #include <scsi/scsi_device.h>
57 #include <scsi/scsi_host.h>
58 #include <scsi/scsi_transport_sas.h>
59 #include <scsi/scsi_dbg.h>
61 #include "mpt2sas_base.h"
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 MPT2SAS_ADAPTER
*ioc
,
75 if (ioc
->sas_hba
.sas_address
== sas_address
)
78 return mpt2sas_scsih_expander_find_by_sas_address(ioc
,
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
)
94 case MPI2_SAS_NEG_LINK_RATE_1_5
:
95 rc
= SAS_LINK_RATE_1_5_GBPS
;
97 case MPI2_SAS_NEG_LINK_RATE_3_0
:
98 rc
= SAS_LINK_RATE_3_0_GBPS
;
100 case MPI2_SAS_NEG_LINK_RATE_6_0
:
101 rc
= SAS_LINK_RATE_6_0_GBPS
;
103 case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED
:
104 rc
= SAS_PHY_DISABLED
;
106 case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED
:
107 rc
= SAS_LINK_RATE_FAILED
;
109 case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR
:
110 rc
= SAS_SATA_PORT_SELECTOR
;
112 case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS
:
113 rc
= SAS_PHY_RESET_IN_PROGRESS
;
116 case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE
:
117 case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE
:
118 rc
= SAS_LINK_RATE_UNKNOWN
;
125 * _transport_set_identify - set identify for phys and end devices
126 * @ioc: per adapter object
127 * @handle: device handle
128 * @identify: sas identify info
130 * Populates sas identify info.
132 * Returns 0 for success, non-zero for failure.
135 _transport_set_identify(struct MPT2SAS_ADAPTER
*ioc
, u16 handle
,
136 struct sas_identify
*identify
)
138 Mpi2SasDevicePage0_t sas_device_pg0
;
139 Mpi2ConfigReply_t mpi_reply
;
143 if (ioc
->shost_recovery
|| ioc
->pci_error_recovery
) {
144 printk(MPT2SAS_INFO_FMT
"%s: host reset in progress!\n",
145 __func__
, ioc
->name
);
149 if ((mpt2sas_config_get_sas_device_pg0(ioc
, &mpi_reply
, &sas_device_pg0
,
150 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE
, handle
))) {
151 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
153 ioc
->name
, __FILE__
, __LINE__
, __func__
);
157 ioc_status
= le16_to_cpu(mpi_reply
.IOCStatus
) &
159 if (ioc_status
!= MPI2_IOCSTATUS_SUCCESS
) {
160 printk(MPT2SAS_ERR_FMT
"handle(0x%04x), ioc_status(0x%04x)"
161 "\nfailure at %s:%d/%s()!\n", ioc
->name
, handle
, ioc_status
,
162 __FILE__
, __LINE__
, __func__
);
166 memset(identify
, 0, sizeof(*identify
));
167 device_info
= le32_to_cpu(sas_device_pg0
.DeviceInfo
);
170 identify
->sas_address
= le64_to_cpu(sas_device_pg0
.SASAddress
);
173 switch (device_info
& MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE
) {
174 case MPI2_SAS_DEVICE_INFO_NO_DEVICE
:
175 identify
->device_type
= SAS_PHY_UNUSED
;
177 case MPI2_SAS_DEVICE_INFO_END_DEVICE
:
178 identify
->device_type
= SAS_END_DEVICE
;
180 case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER
:
181 identify
->device_type
= SAS_EDGE_EXPANDER_DEVICE
;
183 case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER
:
184 identify
->device_type
= SAS_FANOUT_EXPANDER_DEVICE
;
188 /* initiator_port_protocols */
189 if (device_info
& MPI2_SAS_DEVICE_INFO_SSP_INITIATOR
)
190 identify
->initiator_port_protocols
|= SAS_PROTOCOL_SSP
;
191 if (device_info
& MPI2_SAS_DEVICE_INFO_STP_INITIATOR
)
192 identify
->initiator_port_protocols
|= SAS_PROTOCOL_STP
;
193 if (device_info
& MPI2_SAS_DEVICE_INFO_SMP_INITIATOR
)
194 identify
->initiator_port_protocols
|= SAS_PROTOCOL_SMP
;
195 if (device_info
& MPI2_SAS_DEVICE_INFO_SATA_HOST
)
196 identify
->initiator_port_protocols
|= SAS_PROTOCOL_SATA
;
198 /* target_port_protocols */
199 if (device_info
& MPI2_SAS_DEVICE_INFO_SSP_TARGET
)
200 identify
->target_port_protocols
|= SAS_PROTOCOL_SSP
;
201 if (device_info
& MPI2_SAS_DEVICE_INFO_STP_TARGET
)
202 identify
->target_port_protocols
|= SAS_PROTOCOL_STP
;
203 if (device_info
& MPI2_SAS_DEVICE_INFO_SMP_TARGET
)
204 identify
->target_port_protocols
|= SAS_PROTOCOL_SMP
;
205 if (device_info
& MPI2_SAS_DEVICE_INFO_SATA_DEVICE
)
206 identify
->target_port_protocols
|= SAS_PROTOCOL_SATA
;
212 * mpt2sas_transport_done - internal transport layer callback handler.
213 * @ioc: per adapter object
214 * @smid: system request message index
215 * @msix_index: MSIX table index supplied by the OS
216 * @reply: reply message frame(lower 32bit addr)
218 * Callback handler when sending internal generated transport cmds.
219 * The callback index passed is `ioc->transport_cb_idx`
221 * Return 1 meaning mf should be freed from _base_interrupt
222 * 0 means the mf is freed from this function.
225 mpt2sas_transport_done(struct MPT2SAS_ADAPTER
*ioc
, u16 smid
, u8 msix_index
,
228 MPI2DefaultReply_t
*mpi_reply
;
230 mpi_reply
= mpt2sas_base_get_reply_virt_addr(ioc
, reply
);
231 if (ioc
->transport_cmds
.status
== MPT2_CMD_NOT_USED
)
233 if (ioc
->transport_cmds
.smid
!= smid
)
235 ioc
->transport_cmds
.status
|= MPT2_CMD_COMPLETE
;
237 memcpy(ioc
->transport_cmds
.reply
, mpi_reply
,
238 mpi_reply
->MsgLength
*4);
239 ioc
->transport_cmds
.status
|= MPT2_CMD_REPLY_VALID
;
241 ioc
->transport_cmds
.status
&= ~MPT2_CMD_PENDING
;
242 complete(&ioc
->transport_cmds
.done
);
246 /* report manufacture request structure */
247 struct rep_manu_request
{
254 /* report manufacture reply structure */
255 struct rep_manu_reply
{
256 u8 smp_frame_type
; /* 0x41 */
257 u8 function
; /* 0x01 */
260 u16 expander_change_count
;
264 u8 vendor_id
[SAS_EXPANDER_VENDOR_ID_LEN
];
265 u8 product_id
[SAS_EXPANDER_PRODUCT_ID_LEN
];
266 u8 product_rev
[SAS_EXPANDER_PRODUCT_REV_LEN
];
267 u8 component_vendor_id
[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN
];
269 u8 component_revision_id
;
271 u8 vendor_specific
[8];
275 * _transport_expander_report_manufacture - obtain SMP report_manufacture
276 * @ioc: per adapter object
277 * @sas_address: expander sas address
278 * @edev: the sas_expander_device object
280 * Fills in the sas_expander_device object when SMP port is created.
282 * Returns 0 for success, non-zero for failure.
285 _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER
*ioc
,
286 u64 sas_address
, struct sas_expander_device
*edev
)
288 Mpi2SmpPassthroughRequest_t
*mpi_request
;
289 Mpi2SmpPassthroughReply_t
*mpi_reply
;
290 struct rep_manu_reply
*manufacture_reply
;
291 struct rep_manu_request
*manufacture_request
;
295 unsigned long timeleft
;
299 void *data_out
= NULL
;
300 dma_addr_t data_out_dma
;
302 u16 wait_state_count
;
304 if (ioc
->shost_recovery
|| ioc
->pci_error_recovery
) {
305 printk(MPT2SAS_INFO_FMT
"%s: host reset in progress!\n",
306 __func__
, ioc
->name
);
310 mutex_lock(&ioc
->transport_cmds
.mutex
);
312 if (ioc
->transport_cmds
.status
!= MPT2_CMD_NOT_USED
) {
313 printk(MPT2SAS_ERR_FMT
"%s: transport_cmds in use\n",
314 ioc
->name
, __func__
);
318 ioc
->transport_cmds
.status
= MPT2_CMD_PENDING
;
320 wait_state_count
= 0;
321 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
322 while (ioc_state
!= MPI2_IOC_STATE_OPERATIONAL
) {
323 if (wait_state_count
++ == 10) {
324 printk(MPT2SAS_ERR_FMT
325 "%s: failed due to ioc not operational\n",
326 ioc
->name
, __func__
);
331 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
332 printk(MPT2SAS_INFO_FMT
"%s: waiting for "
333 "operational state(count=%d)\n", ioc
->name
,
334 __func__
, wait_state_count
);
336 if (wait_state_count
)
337 printk(MPT2SAS_INFO_FMT
"%s: ioc is operational\n",
338 ioc
->name
, __func__
);
340 smid
= mpt2sas_base_get_smid(ioc
, ioc
->transport_cb_idx
);
342 printk(MPT2SAS_ERR_FMT
"%s: failed obtaining a smid\n",
343 ioc
->name
, __func__
);
349 mpi_request
= mpt2sas_base_get_msg_frame(ioc
, smid
);
350 ioc
->transport_cmds
.smid
= smid
;
352 sz
= sizeof(struct rep_manu_request
) + sizeof(struct rep_manu_reply
);
353 data_out
= pci_alloc_consistent(ioc
->pdev
, sz
, &data_out_dma
);
356 printk(KERN_ERR
"failure at %s:%d/%s()!\n", __FILE__
,
359 mpt2sas_base_free_smid(ioc
, smid
);
363 manufacture_request
= data_out
;
364 manufacture_request
->smp_frame_type
= 0x40;
365 manufacture_request
->function
= 1;
366 manufacture_request
->reserved
= 0;
367 manufacture_request
->request_length
= 0;
369 memset(mpi_request
, 0, sizeof(Mpi2SmpPassthroughRequest_t
));
370 mpi_request
->Function
= MPI2_FUNCTION_SMP_PASSTHROUGH
;
371 mpi_request
->PhysicalPort
= 0xFF;
372 mpi_request
->VF_ID
= 0; /* TODO */
373 mpi_request
->VP_ID
= 0;
374 mpi_request
->SASAddress
= cpu_to_le64(sas_address
);
375 mpi_request
->RequestDataLength
=
376 cpu_to_le16(sizeof(struct rep_manu_request
));
377 psge
= &mpi_request
->SGL
;
379 /* WRITE sgel first */
380 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
381 MPI2_SGE_FLAGS_END_OF_BUFFER
| MPI2_SGE_FLAGS_HOST_TO_IOC
);
382 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
383 ioc
->base_add_sg_single(psge
, sgl_flags
|
384 sizeof(struct rep_manu_request
), data_out_dma
);
387 psge
+= ioc
->sge_size
;
390 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
391 MPI2_SGE_FLAGS_LAST_ELEMENT
| MPI2_SGE_FLAGS_END_OF_BUFFER
|
392 MPI2_SGE_FLAGS_END_OF_LIST
);
393 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
394 ioc
->base_add_sg_single(psge
, sgl_flags
|
395 sizeof(struct rep_manu_reply
), data_out_dma
+
396 sizeof(struct rep_manu_request
));
398 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"report_manufacture - "
399 "send to sas_addr(0x%016llx)\n", ioc
->name
,
400 (unsigned long long)sas_address
));
401 init_completion(&ioc
->transport_cmds
.done
);
402 mpt2sas_base_put_smid_default(ioc
, smid
);
403 timeleft
= wait_for_completion_timeout(&ioc
->transport_cmds
.done
,
406 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_COMPLETE
)) {
407 printk(MPT2SAS_ERR_FMT
"%s: timeout\n",
408 ioc
->name
, __func__
);
409 _debug_dump_mf(mpi_request
,
410 sizeof(Mpi2SmpPassthroughRequest_t
)/4);
411 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_RESET
))
413 goto issue_host_reset
;
416 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"report_manufacture - "
417 "complete\n", ioc
->name
));
419 if (ioc
->transport_cmds
.status
& MPT2_CMD_REPLY_VALID
) {
422 mpi_reply
= ioc
->transport_cmds
.reply
;
424 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
425 "report_manufacture - reply data transfer size(%d)\n",
426 ioc
->name
, le16_to_cpu(mpi_reply
->ResponseDataLength
)));
428 if (le16_to_cpu(mpi_reply
->ResponseDataLength
) !=
429 sizeof(struct rep_manu_reply
))
432 manufacture_reply
= data_out
+ sizeof(struct rep_manu_request
);
433 strncpy(edev
->vendor_id
, manufacture_reply
->vendor_id
,
434 SAS_EXPANDER_VENDOR_ID_LEN
);
435 strncpy(edev
->product_id
, manufacture_reply
->product_id
,
436 SAS_EXPANDER_PRODUCT_ID_LEN
);
437 strncpy(edev
->product_rev
, manufacture_reply
->product_rev
,
438 SAS_EXPANDER_PRODUCT_REV_LEN
);
439 edev
->level
= manufacture_reply
->sas_format
& 1;
441 strncpy(edev
->component_vendor_id
,
442 manufacture_reply
->component_vendor_id
,
443 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN
);
444 tmp
= (u8
*)&manufacture_reply
->component_id
;
445 edev
->component_id
= tmp
[0] << 8 | tmp
[1];
446 edev
->component_revision_id
=
447 manufacture_reply
->component_revision_id
;
450 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
451 "report_manufacture - no reply\n", ioc
->name
));
455 mpt2sas_base_hard_reset_handler(ioc
, CAN_SLEEP
,
458 ioc
->transport_cmds
.status
= MPT2_CMD_NOT_USED
;
460 pci_free_consistent(ioc
->pdev
, sz
, data_out
, data_out_dma
);
462 mutex_unlock(&ioc
->transport_cmds
.mutex
);
467 * _transport_delete_port - helper function to removing a port
468 * @ioc: per adapter object
469 * @mpt2sas_port: mpt2sas per port object
474 _transport_delete_port(struct MPT2SAS_ADAPTER
*ioc
,
475 struct _sas_port
*mpt2sas_port
)
477 u64 sas_address
= mpt2sas_port
->remote_identify
.sas_address
;
478 enum sas_device_type device_type
=
479 mpt2sas_port
->remote_identify
.device_type
;
481 dev_printk(KERN_INFO
, &mpt2sas_port
->port
->dev
,
482 "remove: sas_addr(0x%016llx)\n",
483 (unsigned long long) sas_address
);
485 ioc
->logging_level
|= MPT_DEBUG_TRANSPORT
;
486 if (device_type
== SAS_END_DEVICE
)
487 mpt2sas_device_remove(ioc
, sas_address
);
488 else if (device_type
== SAS_EDGE_EXPANDER_DEVICE
||
489 device_type
== SAS_FANOUT_EXPANDER_DEVICE
)
490 mpt2sas_expander_remove(ioc
, sas_address
);
491 ioc
->logging_level
&= ~MPT_DEBUG_TRANSPORT
;
495 * _transport_delete_phy - helper function to removing single phy from port
496 * @ioc: per adapter object
497 * @mpt2sas_port: mpt2sas per port object
498 * @mpt2sas_phy: mpt2sas per phy object
503 _transport_delete_phy(struct MPT2SAS_ADAPTER
*ioc
,
504 struct _sas_port
*mpt2sas_port
, struct _sas_phy
*mpt2sas_phy
)
506 u64 sas_address
= mpt2sas_port
->remote_identify
.sas_address
;
508 dev_printk(KERN_INFO
, &mpt2sas_phy
->phy
->dev
,
509 "remove: sas_addr(0x%016llx), phy(%d)\n",
510 (unsigned long long) sas_address
, mpt2sas_phy
->phy_id
);
512 list_del(&mpt2sas_phy
->port_siblings
);
513 mpt2sas_port
->num_phys
--;
514 sas_port_delete_phy(mpt2sas_port
->port
, mpt2sas_phy
->phy
);
515 mpt2sas_phy
->phy_belongs_to_port
= 0;
519 * _transport_add_phy - helper function to adding single phy to port
520 * @ioc: per adapter object
521 * @mpt2sas_port: mpt2sas per port object
522 * @mpt2sas_phy: mpt2sas per phy object
527 _transport_add_phy(struct MPT2SAS_ADAPTER
*ioc
, struct _sas_port
*mpt2sas_port
,
528 struct _sas_phy
*mpt2sas_phy
)
530 u64 sas_address
= mpt2sas_port
->remote_identify
.sas_address
;
532 dev_printk(KERN_INFO
, &mpt2sas_phy
->phy
->dev
,
533 "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
534 sas_address
, mpt2sas_phy
->phy_id
);
536 list_add_tail(&mpt2sas_phy
->port_siblings
, &mpt2sas_port
->phy_list
);
537 mpt2sas_port
->num_phys
++;
538 sas_port_add_phy(mpt2sas_port
->port
, mpt2sas_phy
->phy
);
539 mpt2sas_phy
->phy_belongs_to_port
= 1;
543 * _transport_add_phy_to_an_existing_port - adding new phy to existing port
544 * @ioc: per adapter object
545 * @sas_node: sas node object (either expander or sas host)
546 * @mpt2sas_phy: mpt2sas per phy object
547 * @sas_address: sas address of device/expander were phy needs to be added to
552 _transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER
*ioc
,
553 struct _sas_node
*sas_node
, struct _sas_phy
*mpt2sas_phy
, u64 sas_address
)
555 struct _sas_port
*mpt2sas_port
;
556 struct _sas_phy
*phy_srch
;
558 if (mpt2sas_phy
->phy_belongs_to_port
== 1)
561 list_for_each_entry(mpt2sas_port
, &sas_node
->sas_port_list
,
563 if (mpt2sas_port
->remote_identify
.sas_address
!=
566 list_for_each_entry(phy_srch
, &mpt2sas_port
->phy_list
,
568 if (phy_srch
== mpt2sas_phy
)
571 _transport_add_phy(ioc
, mpt2sas_port
, mpt2sas_phy
);
578 * _transport_del_phy_from_an_existing_port - delete phy from existing port
579 * @ioc: per adapter object
580 * @sas_node: sas node object (either expander or sas host)
581 * @mpt2sas_phy: mpt2sas per phy object
586 _transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER
*ioc
,
587 struct _sas_node
*sas_node
, struct _sas_phy
*mpt2sas_phy
)
589 struct _sas_port
*mpt2sas_port
, *next
;
590 struct _sas_phy
*phy_srch
;
592 if (mpt2sas_phy
->phy_belongs_to_port
== 0)
595 list_for_each_entry_safe(mpt2sas_port
, next
, &sas_node
->sas_port_list
,
597 list_for_each_entry(phy_srch
, &mpt2sas_port
->phy_list
,
599 if (phy_srch
!= mpt2sas_phy
)
601 if (mpt2sas_port
->num_phys
== 1)
602 _transport_delete_port(ioc
, mpt2sas_port
);
604 _transport_delete_phy(ioc
, mpt2sas_port
,
612 * _transport_sanity_check - sanity check when adding a new port
613 * @ioc: per adapter object
614 * @sas_node: sas node object (either expander or sas host)
615 * @sas_address: sas address of device being added
617 * See the explanation above from _transport_delete_duplicate_port
620 _transport_sanity_check(struct MPT2SAS_ADAPTER
*ioc
, struct _sas_node
*sas_node
,
625 for (i
= 0; i
< sas_node
->num_phys
; i
++) {
626 if (sas_node
->phy
[i
].remote_identify
.sas_address
!= sas_address
)
628 if (sas_node
->phy
[i
].phy_belongs_to_port
== 1)
629 _transport_del_phy_from_an_existing_port(ioc
, sas_node
,
635 * mpt2sas_transport_port_add - insert port to the list
636 * @ioc: per adapter object
637 * @handle: handle of attached device
638 * @sas_address: sas address of parent expander or sas host
639 * Context: This function will acquire ioc->sas_node_lock.
641 * Adding new port object to the sas_node->sas_port_list.
643 * Returns mpt2sas_port.
646 mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER
*ioc
, u16 handle
,
649 struct _sas_phy
*mpt2sas_phy
, *next
;
650 struct _sas_port
*mpt2sas_port
;
652 struct _sas_node
*sas_node
;
653 struct sas_rphy
*rphy
;
655 struct sas_port
*port
;
657 mpt2sas_port
= kzalloc(sizeof(struct _sas_port
),
660 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
661 ioc
->name
, __FILE__
, __LINE__
, __func__
);
665 INIT_LIST_HEAD(&mpt2sas_port
->port_list
);
666 INIT_LIST_HEAD(&mpt2sas_port
->phy_list
);
667 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
668 sas_node
= _transport_sas_node_find_by_sas_address(ioc
, sas_address
);
669 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
672 printk(MPT2SAS_ERR_FMT
"%s: Could not find "
673 "parent sas_address(0x%016llx)!\n", ioc
->name
,
674 __func__
, (unsigned long long)sas_address
);
678 if ((_transport_set_identify(ioc
, handle
,
679 &mpt2sas_port
->remote_identify
))) {
680 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
681 ioc
->name
, __FILE__
, __LINE__
, __func__
);
685 if (mpt2sas_port
->remote_identify
.device_type
== SAS_PHY_UNUSED
) {
686 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
687 ioc
->name
, __FILE__
, __LINE__
, __func__
);
691 _transport_sanity_check(ioc
, sas_node
,
692 mpt2sas_port
->remote_identify
.sas_address
);
694 for (i
= 0; i
< sas_node
->num_phys
; i
++) {
695 if (sas_node
->phy
[i
].remote_identify
.sas_address
!=
696 mpt2sas_port
->remote_identify
.sas_address
)
698 list_add_tail(&sas_node
->phy
[i
].port_siblings
,
699 &mpt2sas_port
->phy_list
);
700 mpt2sas_port
->num_phys
++;
703 if (!mpt2sas_port
->num_phys
) {
704 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
705 ioc
->name
, __FILE__
, __LINE__
, __func__
);
709 port
= sas_port_alloc_num(sas_node
->parent_dev
);
710 if ((sas_port_add(port
))) {
711 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
712 ioc
->name
, __FILE__
, __LINE__
, __func__
);
716 list_for_each_entry(mpt2sas_phy
, &mpt2sas_port
->phy_list
,
718 if ((ioc
->logging_level
& MPT_DEBUG_TRANSPORT
))
719 dev_printk(KERN_INFO
, &port
->dev
, "add: handle(0x%04x)"
720 ", sas_addr(0x%016llx), phy(%d)\n", handle
,
722 mpt2sas_port
->remote_identify
.sas_address
,
723 mpt2sas_phy
->phy_id
);
724 sas_port_add_phy(port
, mpt2sas_phy
->phy
);
725 mpt2sas_phy
->phy_belongs_to_port
= 1;
728 mpt2sas_port
->port
= port
;
729 if (mpt2sas_port
->remote_identify
.device_type
== SAS_END_DEVICE
)
730 rphy
= sas_end_device_alloc(port
);
732 rphy
= sas_expander_alloc(port
,
733 mpt2sas_port
->remote_identify
.device_type
);
735 rphy
->identify
= mpt2sas_port
->remote_identify
;
736 if ((sas_rphy_add(rphy
))) {
737 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
738 ioc
->name
, __FILE__
, __LINE__
, __func__
);
740 if ((ioc
->logging_level
& MPT_DEBUG_TRANSPORT
))
741 dev_printk(KERN_INFO
, &rphy
->dev
, "add: handle(0x%04x), "
742 "sas_addr(0x%016llx)\n", handle
,
744 mpt2sas_port
->remote_identify
.sas_address
);
745 mpt2sas_port
->rphy
= rphy
;
746 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
747 list_add_tail(&mpt2sas_port
->port_list
, &sas_node
->sas_port_list
);
748 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
750 /* fill in report manufacture */
751 if (mpt2sas_port
->remote_identify
.device_type
==
752 MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER
||
753 mpt2sas_port
->remote_identify
.device_type
==
754 MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER
)
755 _transport_expander_report_manufacture(ioc
,
756 mpt2sas_port
->remote_identify
.sas_address
,
757 rphy_to_expander_device(rphy
));
762 list_for_each_entry_safe(mpt2sas_phy
, next
, &mpt2sas_port
->phy_list
,
764 list_del(&mpt2sas_phy
->port_siblings
);
770 * mpt2sas_transport_port_remove - remove port from the list
771 * @ioc: per adapter object
772 * @sas_address: sas address of attached device
773 * @sas_address_parent: sas address of parent expander or sas host
774 * Context: This function will acquire ioc->sas_node_lock.
776 * Removing object and freeing associated memory from the
777 * ioc->sas_port_list.
782 mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER
*ioc
, u64 sas_address
,
783 u64 sas_address_parent
)
787 struct _sas_port
*mpt2sas_port
, *next
;
788 struct _sas_node
*sas_node
;
790 struct _sas_phy
*mpt2sas_phy
, *next_phy
;
792 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
793 sas_node
= _transport_sas_node_find_by_sas_address(ioc
,
795 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
798 list_for_each_entry_safe(mpt2sas_port
, next
, &sas_node
->sas_port_list
,
800 if (mpt2sas_port
->remote_identify
.sas_address
!= sas_address
)
803 list_del(&mpt2sas_port
->port_list
);
810 for (i
= 0; i
< sas_node
->num_phys
; i
++) {
811 if (sas_node
->phy
[i
].remote_identify
.sas_address
== sas_address
)
812 memset(&sas_node
->phy
[i
].remote_identify
, 0 ,
813 sizeof(struct sas_identify
));
816 list_for_each_entry_safe(mpt2sas_phy
, next_phy
,
817 &mpt2sas_port
->phy_list
, port_siblings
) {
818 if ((ioc
->logging_level
& MPT_DEBUG_TRANSPORT
))
819 dev_printk(KERN_INFO
, &mpt2sas_port
->port
->dev
,
820 "remove: sas_addr(0x%016llx), phy(%d)\n",
822 mpt2sas_port
->remote_identify
.sas_address
,
823 mpt2sas_phy
->phy_id
);
824 mpt2sas_phy
->phy_belongs_to_port
= 0;
825 sas_port_delete_phy(mpt2sas_port
->port
, mpt2sas_phy
->phy
);
826 list_del(&mpt2sas_phy
->port_siblings
);
828 sas_port_delete(mpt2sas_port
->port
);
833 * mpt2sas_transport_add_host_phy - report sas_host phy to transport
834 * @ioc: per adapter object
835 * @mpt2sas_phy: mpt2sas per phy object
836 * @phy_pg0: sas phy page 0
837 * @parent_dev: parent device class object
839 * Returns 0 for success, non-zero for failure.
842 mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER
*ioc
, struct _sas_phy
843 *mpt2sas_phy
, Mpi2SasPhyPage0_t phy_pg0
, struct device
*parent_dev
)
846 int phy_index
= mpt2sas_phy
->phy_id
;
849 INIT_LIST_HEAD(&mpt2sas_phy
->port_siblings
);
850 phy
= sas_phy_alloc(parent_dev
, phy_index
);
852 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
853 ioc
->name
, __FILE__
, __LINE__
, __func__
);
856 if ((_transport_set_identify(ioc
, mpt2sas_phy
->handle
,
857 &mpt2sas_phy
->identify
))) {
858 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
859 ioc
->name
, __FILE__
, __LINE__
, __func__
);
862 phy
->identify
= mpt2sas_phy
->identify
;
863 mpt2sas_phy
->attached_handle
= le16_to_cpu(phy_pg0
.AttachedDevHandle
);
864 if (mpt2sas_phy
->attached_handle
)
865 _transport_set_identify(ioc
, mpt2sas_phy
->attached_handle
,
866 &mpt2sas_phy
->remote_identify
);
867 phy
->identify
.phy_identifier
= mpt2sas_phy
->phy_id
;
868 phy
->negotiated_linkrate
= _transport_convert_phy_link_rate(
869 phy_pg0
.NegotiatedLinkRate
& MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL
);
870 phy
->minimum_linkrate_hw
= _transport_convert_phy_link_rate(
871 phy_pg0
.HwLinkRate
& MPI2_SAS_HWRATE_MIN_RATE_MASK
);
872 phy
->maximum_linkrate_hw
= _transport_convert_phy_link_rate(
873 phy_pg0
.HwLinkRate
>> 4);
874 phy
->minimum_linkrate
= _transport_convert_phy_link_rate(
875 phy_pg0
.ProgrammedLinkRate
& MPI2_SAS_PRATE_MIN_RATE_MASK
);
876 phy
->maximum_linkrate
= _transport_convert_phy_link_rate(
877 phy_pg0
.ProgrammedLinkRate
>> 4);
879 if ((sas_phy_add(phy
))) {
880 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
881 ioc
->name
, __FILE__
, __LINE__
, __func__
);
885 if ((ioc
->logging_level
& MPT_DEBUG_TRANSPORT
))
886 dev_printk(KERN_INFO
, &phy
->dev
,
887 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
888 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
889 mpt2sas_phy
->handle
, (unsigned long long)
890 mpt2sas_phy
->identify
.sas_address
,
891 mpt2sas_phy
->attached_handle
,
893 mpt2sas_phy
->remote_identify
.sas_address
);
894 mpt2sas_phy
->phy
= phy
;
900 * mpt2sas_transport_add_expander_phy - report expander phy to transport
901 * @ioc: per adapter object
902 * @mpt2sas_phy: mpt2sas per phy object
903 * @expander_pg1: expander page 1
904 * @parent_dev: parent device class object
906 * Returns 0 for success, non-zero for failure.
909 mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER
*ioc
, struct _sas_phy
910 *mpt2sas_phy
, Mpi2ExpanderPage1_t expander_pg1
, struct device
*parent_dev
)
913 int phy_index
= mpt2sas_phy
->phy_id
;
915 INIT_LIST_HEAD(&mpt2sas_phy
->port_siblings
);
916 phy
= sas_phy_alloc(parent_dev
, phy_index
);
918 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
919 ioc
->name
, __FILE__
, __LINE__
, __func__
);
922 if ((_transport_set_identify(ioc
, mpt2sas_phy
->handle
,
923 &mpt2sas_phy
->identify
))) {
924 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
925 ioc
->name
, __FILE__
, __LINE__
, __func__
);
928 phy
->identify
= mpt2sas_phy
->identify
;
929 mpt2sas_phy
->attached_handle
=
930 le16_to_cpu(expander_pg1
.AttachedDevHandle
);
931 if (mpt2sas_phy
->attached_handle
)
932 _transport_set_identify(ioc
, mpt2sas_phy
->attached_handle
,
933 &mpt2sas_phy
->remote_identify
);
934 phy
->identify
.phy_identifier
= mpt2sas_phy
->phy_id
;
935 phy
->negotiated_linkrate
= _transport_convert_phy_link_rate(
936 expander_pg1
.NegotiatedLinkRate
&
937 MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL
);
938 phy
->minimum_linkrate_hw
= _transport_convert_phy_link_rate(
939 expander_pg1
.HwLinkRate
& MPI2_SAS_HWRATE_MIN_RATE_MASK
);
940 phy
->maximum_linkrate_hw
= _transport_convert_phy_link_rate(
941 expander_pg1
.HwLinkRate
>> 4);
942 phy
->minimum_linkrate
= _transport_convert_phy_link_rate(
943 expander_pg1
.ProgrammedLinkRate
& MPI2_SAS_PRATE_MIN_RATE_MASK
);
944 phy
->maximum_linkrate
= _transport_convert_phy_link_rate(
945 expander_pg1
.ProgrammedLinkRate
>> 4);
947 if ((sas_phy_add(phy
))) {
948 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
949 ioc
->name
, __FILE__
, __LINE__
, __func__
);
953 if ((ioc
->logging_level
& MPT_DEBUG_TRANSPORT
))
954 dev_printk(KERN_INFO
, &phy
->dev
,
955 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
956 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
957 mpt2sas_phy
->handle
, (unsigned long long)
958 mpt2sas_phy
->identify
.sas_address
,
959 mpt2sas_phy
->attached_handle
,
961 mpt2sas_phy
->remote_identify
.sas_address
);
962 mpt2sas_phy
->phy
= phy
;
967 * mpt2sas_transport_update_links - refreshing phy link changes
968 * @ioc: per adapter object
969 * @sas_address: sas address of parent expander or sas host
970 * @handle: attached device handle
971 * @phy_numberv: phy number
972 * @link_rate: new link rate
977 mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER
*ioc
,
978 u64 sas_address
, u16 handle
, u8 phy_number
, u8 link_rate
)
981 struct _sas_node
*sas_node
;
982 struct _sas_phy
*mpt2sas_phy
;
984 if (ioc
->shost_recovery
|| ioc
->pci_error_recovery
)
987 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
988 sas_node
= _transport_sas_node_find_by_sas_address(ioc
, sas_address
);
989 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
993 mpt2sas_phy
= &sas_node
->phy
[phy_number
];
994 mpt2sas_phy
->attached_handle
= handle
;
995 if (handle
&& (link_rate
>= MPI2_SAS_NEG_LINK_RATE_1_5
)) {
996 _transport_set_identify(ioc
, handle
,
997 &mpt2sas_phy
->remote_identify
);
998 _transport_add_phy_to_an_existing_port(ioc
, sas_node
,
999 mpt2sas_phy
, mpt2sas_phy
->remote_identify
.sas_address
);
1001 memset(&mpt2sas_phy
->remote_identify
, 0 , sizeof(struct
1004 if (mpt2sas_phy
->phy
)
1005 mpt2sas_phy
->phy
->negotiated_linkrate
=
1006 _transport_convert_phy_link_rate(link_rate
);
1008 if ((ioc
->logging_level
& MPT_DEBUG_TRANSPORT
))
1009 dev_printk(KERN_INFO
, &mpt2sas_phy
->phy
->dev
,
1010 "refresh: parent sas_addr(0x%016llx),\n"
1011 "\tlink_rate(0x%02x), phy(%d)\n"
1012 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
1013 (unsigned long long)sas_address
,
1014 link_rate
, phy_number
, handle
, (unsigned long long)
1015 mpt2sas_phy
->remote_identify
.sas_address
);
1018 static inline void *
1019 phy_to_ioc(struct sas_phy
*phy
)
1021 struct Scsi_Host
*shost
= dev_to_shost(phy
->dev
.parent
);
1022 return shost_priv(shost
);
1025 static inline void *
1026 rphy_to_ioc(struct sas_rphy
*rphy
)
1028 struct Scsi_Host
*shost
= dev_to_shost(rphy
->dev
.parent
->parent
);
1029 return shost_priv(shost
);
1033 /* report phy error log structure */
1034 struct phy_error_log_request
{
1035 u8 smp_frame_type
; /* 0x40 */
1036 u8 function
; /* 0x11 */
1037 u8 allocated_response_length
;
1038 u8 request_length
; /* 02 */
1044 /* report phy error log reply structure */
1045 struct phy_error_log_reply
{
1046 u8 smp_frame_type
; /* 0x41 */
1047 u8 function
; /* 0x11 */
1050 __be16 expander_change_count
;
1054 __be32 invalid_dword
;
1055 __be32 running_disparity_error
;
1056 __be32 loss_of_dword_sync
;
1057 __be32 phy_reset_problem
;
1061 * _transport_get_expander_phy_error_log - return expander counters
1062 * @ioc: per adapter object
1063 * @phy: The sas phy object
1065 * Returns 0 for success, non-zero for failure.
1069 _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER
*ioc
,
1070 struct sas_phy
*phy
)
1072 Mpi2SmpPassthroughRequest_t
*mpi_request
;
1073 Mpi2SmpPassthroughReply_t
*mpi_reply
;
1074 struct phy_error_log_request
*phy_error_log_request
;
1075 struct phy_error_log_reply
*phy_error_log_reply
;
1079 unsigned long timeleft
;
1083 void *data_out
= NULL
;
1084 dma_addr_t data_out_dma
;
1086 u16 wait_state_count
;
1088 if (ioc
->shost_recovery
|| ioc
->pci_error_recovery
) {
1089 printk(MPT2SAS_INFO_FMT
"%s: host reset in progress!\n",
1090 __func__
, ioc
->name
);
1094 mutex_lock(&ioc
->transport_cmds
.mutex
);
1096 if (ioc
->transport_cmds
.status
!= MPT2_CMD_NOT_USED
) {
1097 printk(MPT2SAS_ERR_FMT
"%s: transport_cmds in use\n",
1098 ioc
->name
, __func__
);
1102 ioc
->transport_cmds
.status
= MPT2_CMD_PENDING
;
1104 wait_state_count
= 0;
1105 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
1106 while (ioc_state
!= MPI2_IOC_STATE_OPERATIONAL
) {
1107 if (wait_state_count
++ == 10) {
1108 printk(MPT2SAS_ERR_FMT
1109 "%s: failed due to ioc not operational\n",
1110 ioc
->name
, __func__
);
1115 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
1116 printk(MPT2SAS_INFO_FMT
"%s: waiting for "
1117 "operational state(count=%d)\n", ioc
->name
,
1118 __func__
, wait_state_count
);
1120 if (wait_state_count
)
1121 printk(MPT2SAS_INFO_FMT
"%s: ioc is operational\n",
1122 ioc
->name
, __func__
);
1124 smid
= mpt2sas_base_get_smid(ioc
, ioc
->transport_cb_idx
);
1126 printk(MPT2SAS_ERR_FMT
"%s: failed obtaining a smid\n",
1127 ioc
->name
, __func__
);
1132 mpi_request
= mpt2sas_base_get_msg_frame(ioc
, smid
);
1133 ioc
->transport_cmds
.smid
= smid
;
1135 sz
= sizeof(struct phy_error_log_request
) +
1136 sizeof(struct phy_error_log_reply
);
1137 data_out
= pci_alloc_consistent(ioc
->pdev
, sz
, &data_out_dma
);
1139 printk(KERN_ERR
"failure at %s:%d/%s()!\n", __FILE__
,
1140 __LINE__
, __func__
);
1142 mpt2sas_base_free_smid(ioc
, smid
);
1147 memset(data_out
, 0, sz
);
1148 phy_error_log_request
= data_out
;
1149 phy_error_log_request
->smp_frame_type
= 0x40;
1150 phy_error_log_request
->function
= 0x11;
1151 phy_error_log_request
->request_length
= 2;
1152 phy_error_log_request
->allocated_response_length
= 0;
1153 phy_error_log_request
->phy_identifier
= phy
->number
;
1155 memset(mpi_request
, 0, sizeof(Mpi2SmpPassthroughRequest_t
));
1156 mpi_request
->Function
= MPI2_FUNCTION_SMP_PASSTHROUGH
;
1157 mpi_request
->PhysicalPort
= 0xFF;
1158 mpi_request
->VF_ID
= 0; /* TODO */
1159 mpi_request
->VP_ID
= 0;
1160 mpi_request
->SASAddress
= cpu_to_le64(phy
->identify
.sas_address
);
1161 mpi_request
->RequestDataLength
=
1162 cpu_to_le16(sizeof(struct phy_error_log_request
));
1163 psge
= &mpi_request
->SGL
;
1165 /* WRITE sgel first */
1166 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
1167 MPI2_SGE_FLAGS_END_OF_BUFFER
| MPI2_SGE_FLAGS_HOST_TO_IOC
);
1168 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
1169 ioc
->base_add_sg_single(psge
, sgl_flags
|
1170 sizeof(struct phy_error_log_request
), data_out_dma
);
1173 psge
+= ioc
->sge_size
;
1175 /* READ sgel last */
1176 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
1177 MPI2_SGE_FLAGS_LAST_ELEMENT
| MPI2_SGE_FLAGS_END_OF_BUFFER
|
1178 MPI2_SGE_FLAGS_END_OF_LIST
);
1179 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
1180 ioc
->base_add_sg_single(psge
, sgl_flags
|
1181 sizeof(struct phy_error_log_reply
), data_out_dma
+
1182 sizeof(struct phy_error_log_request
));
1184 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"phy_error_log - "
1185 "send to sas_addr(0x%016llx), phy(%d)\n", ioc
->name
,
1186 (unsigned long long)phy
->identify
.sas_address
, phy
->number
));
1187 init_completion(&ioc
->transport_cmds
.done
);
1188 mpt2sas_base_put_smid_default(ioc
, smid
);
1189 timeleft
= wait_for_completion_timeout(&ioc
->transport_cmds
.done
,
1192 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_COMPLETE
)) {
1193 printk(MPT2SAS_ERR_FMT
"%s: timeout\n",
1194 ioc
->name
, __func__
);
1195 _debug_dump_mf(mpi_request
,
1196 sizeof(Mpi2SmpPassthroughRequest_t
)/4);
1197 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_RESET
))
1199 goto issue_host_reset
;
1202 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"phy_error_log - "
1203 "complete\n", ioc
->name
));
1205 if (ioc
->transport_cmds
.status
& MPT2_CMD_REPLY_VALID
) {
1207 mpi_reply
= ioc
->transport_cmds
.reply
;
1209 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1210 "phy_error_log - reply data transfer size(%d)\n",
1211 ioc
->name
, le16_to_cpu(mpi_reply
->ResponseDataLength
)));
1213 if (le16_to_cpu(mpi_reply
->ResponseDataLength
) !=
1214 sizeof(struct phy_error_log_reply
))
1217 phy_error_log_reply
= data_out
+
1218 sizeof(struct phy_error_log_request
);
1220 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1221 "phy_error_log - function_result(%d)\n",
1222 ioc
->name
, phy_error_log_reply
->function_result
));
1224 phy
->invalid_dword_count
=
1225 be32_to_cpu(phy_error_log_reply
->invalid_dword
);
1226 phy
->running_disparity_error_count
=
1227 be32_to_cpu(phy_error_log_reply
->running_disparity_error
);
1228 phy
->loss_of_dword_sync_count
=
1229 be32_to_cpu(phy_error_log_reply
->loss_of_dword_sync
);
1230 phy
->phy_reset_problem_count
=
1231 be32_to_cpu(phy_error_log_reply
->phy_reset_problem
);
1234 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1235 "phy_error_log - no reply\n", ioc
->name
));
1239 mpt2sas_base_hard_reset_handler(ioc
, CAN_SLEEP
,
1242 ioc
->transport_cmds
.status
= MPT2_CMD_NOT_USED
;
1244 pci_free_consistent(ioc
->pdev
, sz
, data_out
, data_out_dma
);
1246 mutex_unlock(&ioc
->transport_cmds
.mutex
);
1251 * _transport_get_linkerrors - return phy counters for both hba and expanders
1252 * @phy: The sas phy object
1254 * Returns 0 for success, non-zero for failure.
1258 _transport_get_linkerrors(struct sas_phy
*phy
)
1260 struct MPT2SAS_ADAPTER
*ioc
= phy_to_ioc(phy
);
1261 unsigned long flags
;
1262 Mpi2ConfigReply_t mpi_reply
;
1263 Mpi2SasPhyPage1_t phy_pg1
;
1265 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
1266 if (_transport_sas_node_find_by_sas_address(ioc
,
1267 phy
->identify
.sas_address
) == NULL
) {
1268 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1271 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1273 if (phy
->identify
.sas_address
!= ioc
->sas_hba
.sas_address
)
1274 return _transport_get_expander_phy_error_log(ioc
, phy
);
1276 /* get hba phy error logs */
1277 if ((mpt2sas_config_get_phy_pg1(ioc
, &mpi_reply
, &phy_pg1
,
1279 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1280 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1284 if (mpi_reply
.IOCStatus
|| mpi_reply
.IOCLogInfo
)
1285 printk(MPT2SAS_INFO_FMT
"phy(%d), ioc_status"
1286 "(0x%04x), loginfo(0x%08x)\n", ioc
->name
,
1287 phy
->number
, le16_to_cpu(mpi_reply
.IOCStatus
),
1288 le32_to_cpu(mpi_reply
.IOCLogInfo
));
1290 phy
->invalid_dword_count
= le32_to_cpu(phy_pg1
.InvalidDwordCount
);
1291 phy
->running_disparity_error_count
=
1292 le32_to_cpu(phy_pg1
.RunningDisparityErrorCount
);
1293 phy
->loss_of_dword_sync_count
=
1294 le32_to_cpu(phy_pg1
.LossDwordSynchCount
);
1295 phy
->phy_reset_problem_count
=
1296 le32_to_cpu(phy_pg1
.PhyResetProblemCount
);
1301 * _transport_get_enclosure_identifier -
1302 * @phy: The sas phy object
1304 * Obtain the enclosure logical id for an expander.
1305 * Returns 0 for success, non-zero for failure.
1308 _transport_get_enclosure_identifier(struct sas_rphy
*rphy
, u64
*identifier
)
1310 struct MPT2SAS_ADAPTER
*ioc
= rphy_to_ioc(rphy
);
1311 struct _sas_device
*sas_device
;
1312 unsigned long flags
;
1314 spin_lock_irqsave(&ioc
->sas_device_lock
, flags
);
1315 sas_device
= mpt2sas_scsih_sas_device_find_by_sas_address(ioc
,
1316 rphy
->identify
.sas_address
);
1317 spin_unlock_irqrestore(&ioc
->sas_device_lock
, flags
);
1322 *identifier
= sas_device
->enclosure_logical_id
;
1327 * _transport_get_bay_identifier -
1328 * @phy: The sas phy object
1330 * Returns the slot id for a device that resides inside an enclosure.
1333 _transport_get_bay_identifier(struct sas_rphy
*rphy
)
1335 struct MPT2SAS_ADAPTER
*ioc
= rphy_to_ioc(rphy
);
1336 struct _sas_device
*sas_device
;
1337 unsigned long flags
;
1339 spin_lock_irqsave(&ioc
->sas_device_lock
, flags
);
1340 sas_device
= mpt2sas_scsih_sas_device_find_by_sas_address(ioc
,
1341 rphy
->identify
.sas_address
);
1342 spin_unlock_irqrestore(&ioc
->sas_device_lock
, flags
);
1347 return sas_device
->slot
;
1350 /* phy control request structure */
1351 struct phy_control_request
{
1352 u8 smp_frame_type
; /* 0x40 */
1353 u8 function
; /* 0x91 */
1354 u8 allocated_response_length
;
1355 u8 request_length
; /* 0x09 */
1356 u16 expander_change_count
;
1361 u64 attached_device_name
;
1362 u8 programmed_min_physical_link_rate
;
1363 u8 programmed_max_physical_link_rate
;
1367 /* phy control reply structure */
1368 struct phy_control_reply
{
1369 u8 smp_frame_type
; /* 0x41 */
1370 u8 function
; /* 0x11 */
1375 #define SMP_PHY_CONTROL_LINK_RESET (0x01)
1376 #define SMP_PHY_CONTROL_HARD_RESET (0x02)
1377 #define SMP_PHY_CONTROL_DISABLE (0x03)
1380 * _transport_expander_phy_control - expander phy control
1381 * @ioc: per adapter object
1382 * @phy: The sas phy object
1384 * Returns 0 for success, non-zero for failure.
1388 _transport_expander_phy_control(struct MPT2SAS_ADAPTER
*ioc
,
1389 struct sas_phy
*phy
, u8 phy_operation
)
1391 Mpi2SmpPassthroughRequest_t
*mpi_request
;
1392 Mpi2SmpPassthroughReply_t
*mpi_reply
;
1393 struct phy_control_request
*phy_control_request
;
1394 struct phy_control_reply
*phy_control_reply
;
1398 unsigned long timeleft
;
1402 void *data_out
= NULL
;
1403 dma_addr_t data_out_dma
;
1405 u16 wait_state_count
;
1407 if (ioc
->shost_recovery
) {
1408 printk(MPT2SAS_INFO_FMT
"%s: host reset in progress!\n",
1409 __func__
, ioc
->name
);
1413 mutex_lock(&ioc
->transport_cmds
.mutex
);
1415 if (ioc
->transport_cmds
.status
!= MPT2_CMD_NOT_USED
) {
1416 printk(MPT2SAS_ERR_FMT
"%s: transport_cmds in use\n",
1417 ioc
->name
, __func__
);
1421 ioc
->transport_cmds
.status
= MPT2_CMD_PENDING
;
1423 wait_state_count
= 0;
1424 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
1425 while (ioc_state
!= MPI2_IOC_STATE_OPERATIONAL
) {
1426 if (wait_state_count
++ == 10) {
1427 printk(MPT2SAS_ERR_FMT
1428 "%s: failed due to ioc not operational\n",
1429 ioc
->name
, __func__
);
1434 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
1435 printk(MPT2SAS_INFO_FMT
"%s: waiting for "
1436 "operational state(count=%d)\n", ioc
->name
,
1437 __func__
, wait_state_count
);
1439 if (wait_state_count
)
1440 printk(MPT2SAS_INFO_FMT
"%s: ioc is operational\n",
1441 ioc
->name
, __func__
);
1443 smid
= mpt2sas_base_get_smid(ioc
, ioc
->transport_cb_idx
);
1445 printk(MPT2SAS_ERR_FMT
"%s: failed obtaining a smid\n",
1446 ioc
->name
, __func__
);
1451 mpi_request
= mpt2sas_base_get_msg_frame(ioc
, smid
);
1452 ioc
->transport_cmds
.smid
= smid
;
1454 sz
= sizeof(struct phy_control_request
) +
1455 sizeof(struct phy_control_reply
);
1456 data_out
= pci_alloc_consistent(ioc
->pdev
, sz
, &data_out_dma
);
1458 printk(KERN_ERR
"failure at %s:%d/%s()!\n", __FILE__
,
1459 __LINE__
, __func__
);
1461 mpt2sas_base_free_smid(ioc
, smid
);
1466 memset(data_out
, 0, sz
);
1467 phy_control_request
= data_out
;
1468 phy_control_request
->smp_frame_type
= 0x40;
1469 phy_control_request
->function
= 0x91;
1470 phy_control_request
->request_length
= 9;
1471 phy_control_request
->allocated_response_length
= 0;
1472 phy_control_request
->phy_identifier
= phy
->number
;
1473 phy_control_request
->phy_operation
= phy_operation
;
1474 phy_control_request
->programmed_min_physical_link_rate
=
1475 phy
->minimum_linkrate
<< 4;
1476 phy_control_request
->programmed_max_physical_link_rate
=
1477 phy
->maximum_linkrate
<< 4;
1479 memset(mpi_request
, 0, sizeof(Mpi2SmpPassthroughRequest_t
));
1480 mpi_request
->Function
= MPI2_FUNCTION_SMP_PASSTHROUGH
;
1481 mpi_request
->PhysicalPort
= 0xFF;
1482 mpi_request
->VF_ID
= 0; /* TODO */
1483 mpi_request
->VP_ID
= 0;
1484 mpi_request
->SASAddress
= cpu_to_le64(phy
->identify
.sas_address
);
1485 mpi_request
->RequestDataLength
=
1486 cpu_to_le16(sizeof(struct phy_error_log_request
));
1487 psge
= &mpi_request
->SGL
;
1489 /* WRITE sgel first */
1490 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
1491 MPI2_SGE_FLAGS_END_OF_BUFFER
| MPI2_SGE_FLAGS_HOST_TO_IOC
);
1492 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
1493 ioc
->base_add_sg_single(psge
, sgl_flags
|
1494 sizeof(struct phy_control_request
), data_out_dma
);
1497 psge
+= ioc
->sge_size
;
1499 /* READ sgel last */
1500 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
1501 MPI2_SGE_FLAGS_LAST_ELEMENT
| MPI2_SGE_FLAGS_END_OF_BUFFER
|
1502 MPI2_SGE_FLAGS_END_OF_LIST
);
1503 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
1504 ioc
->base_add_sg_single(psge
, sgl_flags
|
1505 sizeof(struct phy_control_reply
), data_out_dma
+
1506 sizeof(struct phy_control_request
));
1508 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"phy_control - "
1509 "send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", ioc
->name
,
1510 (unsigned long long)phy
->identify
.sas_address
, phy
->number
,
1513 init_completion(&ioc
->transport_cmds
.done
);
1514 mpt2sas_base_put_smid_default(ioc
, smid
);
1515 timeleft
= wait_for_completion_timeout(&ioc
->transport_cmds
.done
,
1518 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_COMPLETE
)) {
1519 printk(MPT2SAS_ERR_FMT
"%s: timeout\n",
1520 ioc
->name
, __func__
);
1521 _debug_dump_mf(mpi_request
,
1522 sizeof(Mpi2SmpPassthroughRequest_t
)/4);
1523 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_RESET
))
1525 goto issue_host_reset
;
1528 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"phy_control - "
1529 "complete\n", ioc
->name
));
1531 if (ioc
->transport_cmds
.status
& MPT2_CMD_REPLY_VALID
) {
1533 mpi_reply
= ioc
->transport_cmds
.reply
;
1535 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1536 "phy_control - reply data transfer size(%d)\n",
1537 ioc
->name
, le16_to_cpu(mpi_reply
->ResponseDataLength
)));
1539 if (le16_to_cpu(mpi_reply
->ResponseDataLength
) !=
1540 sizeof(struct phy_control_reply
))
1543 phy_control_reply
= data_out
+
1544 sizeof(struct phy_control_request
);
1546 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1547 "phy_control - function_result(%d)\n",
1548 ioc
->name
, phy_control_reply
->function_result
));
1552 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1553 "phy_control - no reply\n", ioc
->name
));
1557 mpt2sas_base_hard_reset_handler(ioc
, CAN_SLEEP
,
1560 ioc
->transport_cmds
.status
= MPT2_CMD_NOT_USED
;
1562 pci_free_consistent(ioc
->pdev
, sz
, data_out
, data_out_dma
);
1564 mutex_unlock(&ioc
->transport_cmds
.mutex
);
1569 * _transport_phy_reset -
1570 * @phy: The sas phy object
1573 * Returns 0 for success, non-zero for failure.
1576 _transport_phy_reset(struct sas_phy
*phy
, int hard_reset
)
1578 struct MPT2SAS_ADAPTER
*ioc
= phy_to_ioc(phy
);
1579 Mpi2SasIoUnitControlReply_t mpi_reply
;
1580 Mpi2SasIoUnitControlRequest_t mpi_request
;
1581 unsigned long flags
;
1583 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
1584 if (_transport_sas_node_find_by_sas_address(ioc
,
1585 phy
->identify
.sas_address
) == NULL
) {
1586 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1589 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1591 /* handle expander phys */
1592 if (phy
->identify
.sas_address
!= ioc
->sas_hba
.sas_address
)
1593 return _transport_expander_phy_control(ioc
, phy
,
1594 (hard_reset
== 1) ? SMP_PHY_CONTROL_HARD_RESET
:
1595 SMP_PHY_CONTROL_LINK_RESET
);
1597 /* handle hba phys */
1598 memset(&mpi_request
, 0, sizeof(Mpi2SasIoUnitControlReply_t
));
1599 mpi_request
.Function
= MPI2_FUNCTION_SAS_IO_UNIT_CONTROL
;
1600 mpi_request
.Operation
= hard_reset
?
1601 MPI2_SAS_OP_PHY_HARD_RESET
: MPI2_SAS_OP_PHY_LINK_RESET
;
1602 mpi_request
.PhyNum
= phy
->number
;
1604 if ((mpt2sas_base_sas_iounit_control(ioc
, &mpi_reply
, &mpi_request
))) {
1605 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1606 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1610 if (mpi_reply
.IOCStatus
|| mpi_reply
.IOCLogInfo
)
1611 printk(MPT2SAS_INFO_FMT
"phy(%d), ioc_status"
1612 "(0x%04x), loginfo(0x%08x)\n", ioc
->name
,
1613 phy
->number
, le16_to_cpu(mpi_reply
.IOCStatus
),
1614 le32_to_cpu(mpi_reply
.IOCLogInfo
));
1620 * _transport_phy_enable - enable/disable phys
1621 * @phy: The sas phy object
1622 * @enable: enable phy when true
1624 * Only support sas_host direct attached phys.
1625 * Returns 0 for success, non-zero for failure.
1628 _transport_phy_enable(struct sas_phy
*phy
, int enable
)
1630 struct MPT2SAS_ADAPTER
*ioc
= phy_to_ioc(phy
);
1631 Mpi2SasIOUnitPage1_t
*sas_iounit_pg1
= NULL
;
1632 Mpi2ConfigReply_t mpi_reply
;
1636 unsigned long flags
;
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
);
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 /* sas_iounit page 1 */
1655 sz
= offsetof(Mpi2SasIOUnitPage1_t
, PhyData
) + (ioc
->sas_hba
.num_phys
*
1656 sizeof(Mpi2SasIOUnit1PhyData_t
));
1657 sas_iounit_pg1
= kzalloc(sz
, GFP_KERNEL
);
1658 if (!sas_iounit_pg1
) {
1659 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1660 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1664 if ((mpt2sas_config_get_sas_iounit_pg1(ioc
, &mpi_reply
,
1665 sas_iounit_pg1
, sz
))) {
1666 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1667 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1671 ioc_status
= le16_to_cpu(mpi_reply
.IOCStatus
) &
1672 MPI2_IOCSTATUS_MASK
;
1673 if (ioc_status
!= MPI2_IOCSTATUS_SUCCESS
) {
1674 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1675 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1681 sas_iounit_pg1
->PhyData
[phy
->number
].PhyFlags
1682 &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE
;
1684 sas_iounit_pg1
->PhyData
[phy
->number
].PhyFlags
1685 |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE
;
1687 mpt2sas_config_set_sas_iounit_pg1(ioc
, &mpi_reply
, sas_iounit_pg1
, sz
);
1691 _transport_phy_reset(phy
, 0);
1694 kfree(sas_iounit_pg1
);
1699 * _transport_phy_speed - set phy min/max link rates
1700 * @phy: The sas phy object
1701 * @rates: rates defined in sas_phy_linkrates
1703 * Only support sas_host direct attached phys.
1704 * Returns 0 for success, non-zero for failure.
1707 _transport_phy_speed(struct sas_phy
*phy
, struct sas_phy_linkrates
*rates
)
1709 struct MPT2SAS_ADAPTER
*ioc
= phy_to_ioc(phy
);
1710 Mpi2SasIOUnitPage1_t
*sas_iounit_pg1
= NULL
;
1711 Mpi2SasPhyPage0_t phy_pg0
;
1712 Mpi2ConfigReply_t mpi_reply
;
1717 unsigned long flags
;
1719 spin_lock_irqsave(&ioc
->sas_node_lock
, flags
);
1720 if (_transport_sas_node_find_by_sas_address(ioc
,
1721 phy
->identify
.sas_address
) == NULL
) {
1722 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1725 spin_unlock_irqrestore(&ioc
->sas_node_lock
, flags
);
1727 if (!rates
->minimum_linkrate
)
1728 rates
->minimum_linkrate
= phy
->minimum_linkrate
;
1729 else if (rates
->minimum_linkrate
< phy
->minimum_linkrate_hw
)
1730 rates
->minimum_linkrate
= phy
->minimum_linkrate_hw
;
1732 if (!rates
->maximum_linkrate
)
1733 rates
->maximum_linkrate
= phy
->maximum_linkrate
;
1734 else if (rates
->maximum_linkrate
> phy
->maximum_linkrate_hw
)
1735 rates
->maximum_linkrate
= phy
->maximum_linkrate_hw
;
1737 /* handle expander phys */
1738 if (phy
->identify
.sas_address
!= ioc
->sas_hba
.sas_address
) {
1739 phy
->minimum_linkrate
= rates
->minimum_linkrate
;
1740 phy
->maximum_linkrate
= rates
->maximum_linkrate
;
1741 return _transport_expander_phy_control(ioc
, phy
,
1742 SMP_PHY_CONTROL_LINK_RESET
);
1745 /* handle hba phys */
1747 /* sas_iounit page 1 */
1748 sz
= offsetof(Mpi2SasIOUnitPage1_t
, PhyData
) + (ioc
->sas_hba
.num_phys
*
1749 sizeof(Mpi2SasIOUnit1PhyData_t
));
1750 sas_iounit_pg1
= kzalloc(sz
, GFP_KERNEL
);
1751 if (!sas_iounit_pg1
) {
1752 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1753 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1757 if ((mpt2sas_config_get_sas_iounit_pg1(ioc
, &mpi_reply
,
1758 sas_iounit_pg1
, sz
))) {
1759 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1760 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1764 ioc_status
= le16_to_cpu(mpi_reply
.IOCStatus
) &
1765 MPI2_IOCSTATUS_MASK
;
1766 if (ioc_status
!= MPI2_IOCSTATUS_SUCCESS
) {
1767 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1768 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1773 for (i
= 0; i
< ioc
->sas_hba
.num_phys
; i
++) {
1774 if (phy
->number
!= i
) {
1775 sas_iounit_pg1
->PhyData
[i
].MaxMinLinkRate
=
1776 (ioc
->sas_hba
.phy
[i
].phy
->minimum_linkrate
+
1777 (ioc
->sas_hba
.phy
[i
].phy
->maximum_linkrate
<< 4));
1779 sas_iounit_pg1
->PhyData
[i
].MaxMinLinkRate
=
1780 (rates
->minimum_linkrate
+
1781 (rates
->maximum_linkrate
<< 4));
1785 if (mpt2sas_config_set_sas_iounit_pg1(ioc
, &mpi_reply
, sas_iounit_pg1
,
1787 printk(MPT2SAS_ERR_FMT
"failure at %s:%d/%s()!\n",
1788 ioc
->name
, __FILE__
, __LINE__
, __func__
);
1794 _transport_phy_reset(phy
, 0);
1796 /* read phy page 0, then update the rates in the sas transport phy */
1797 if (!mpt2sas_config_get_phy_pg0(ioc
, &mpi_reply
, &phy_pg0
,
1799 phy
->minimum_linkrate
= _transport_convert_phy_link_rate(
1800 phy_pg0
.ProgrammedLinkRate
& MPI2_SAS_PRATE_MIN_RATE_MASK
);
1801 phy
->maximum_linkrate
= _transport_convert_phy_link_rate(
1802 phy_pg0
.ProgrammedLinkRate
>> 4);
1803 phy
->negotiated_linkrate
= _transport_convert_phy_link_rate(
1804 phy_pg0
.NegotiatedLinkRate
&
1805 MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL
);
1809 kfree(sas_iounit_pg1
);
1815 * _transport_smp_handler - transport portal for smp passthru
1816 * @shost: shost object
1817 * @rphy: sas transport rphy object
1820 * This used primarily for smp_utils.
1822 * smp_rep_general /sys/class/bsg/expander-5:0
1825 _transport_smp_handler(struct Scsi_Host
*shost
, struct sas_rphy
*rphy
,
1826 struct request
*req
)
1828 struct MPT2SAS_ADAPTER
*ioc
= shost_priv(shost
);
1829 Mpi2SmpPassthroughRequest_t
*mpi_request
;
1830 Mpi2SmpPassthroughReply_t
*mpi_reply
;
1834 unsigned long timeleft
;
1838 dma_addr_t dma_addr_in
= 0;
1839 dma_addr_t dma_addr_out
= 0;
1840 u16 wait_state_count
;
1841 struct request
*rsp
= req
->next_rq
;
1844 printk(MPT2SAS_ERR_FMT
"%s: the smp response space is "
1845 "missing\n", ioc
->name
, __func__
);
1849 /* do we need to support multiple segments? */
1850 if (req
->bio
->bi_vcnt
> 1 || rsp
->bio
->bi_vcnt
> 1) {
1851 printk(MPT2SAS_ERR_FMT
"%s: multiple segments req %u %u, "
1852 "rsp %u %u\n", ioc
->name
, __func__
, req
->bio
->bi_vcnt
,
1853 blk_rq_bytes(req
), rsp
->bio
->bi_vcnt
, blk_rq_bytes(rsp
));
1857 if (ioc
->shost_recovery
) {
1858 printk(MPT2SAS_INFO_FMT
"%s: host reset in progress!\n",
1859 __func__
, ioc
->name
);
1863 rc
= mutex_lock_interruptible(&ioc
->transport_cmds
.mutex
);
1867 if (ioc
->transport_cmds
.status
!= MPT2_CMD_NOT_USED
) {
1868 printk(MPT2SAS_ERR_FMT
"%s: transport_cmds in use\n", ioc
->name
,
1873 ioc
->transport_cmds
.status
= MPT2_CMD_PENDING
;
1875 wait_state_count
= 0;
1876 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
1877 while (ioc_state
!= MPI2_IOC_STATE_OPERATIONAL
) {
1878 if (wait_state_count
++ == 10) {
1879 printk(MPT2SAS_ERR_FMT
1880 "%s: failed due to ioc not operational\n",
1881 ioc
->name
, __func__
);
1886 ioc_state
= mpt2sas_base_get_iocstate(ioc
, 1);
1887 printk(MPT2SAS_INFO_FMT
"%s: waiting for "
1888 "operational state(count=%d)\n", ioc
->name
,
1889 __func__
, wait_state_count
);
1891 if (wait_state_count
)
1892 printk(MPT2SAS_INFO_FMT
"%s: ioc is operational\n",
1893 ioc
->name
, __func__
);
1895 smid
= mpt2sas_base_get_smid(ioc
, ioc
->transport_cb_idx
);
1897 printk(MPT2SAS_ERR_FMT
"%s: failed obtaining a smid\n",
1898 ioc
->name
, __func__
);
1904 mpi_request
= mpt2sas_base_get_msg_frame(ioc
, smid
);
1905 ioc
->transport_cmds
.smid
= smid
;
1907 memset(mpi_request
, 0, sizeof(Mpi2SmpPassthroughRequest_t
));
1908 mpi_request
->Function
= MPI2_FUNCTION_SMP_PASSTHROUGH
;
1909 mpi_request
->PhysicalPort
= 0xFF;
1910 mpi_request
->VF_ID
= 0; /* TODO */
1911 mpi_request
->VP_ID
= 0;
1912 mpi_request
->SASAddress
= (rphy
) ?
1913 cpu_to_le64(rphy
->identify
.sas_address
) :
1914 cpu_to_le64(ioc
->sas_hba
.sas_address
);
1915 mpi_request
->RequestDataLength
= cpu_to_le16(blk_rq_bytes(req
) - 4);
1916 psge
= &mpi_request
->SGL
;
1918 /* WRITE sgel first */
1919 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
1920 MPI2_SGE_FLAGS_END_OF_BUFFER
| MPI2_SGE_FLAGS_HOST_TO_IOC
);
1921 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
1922 dma_addr_out
= pci_map_single(ioc
->pdev
, bio_data(req
->bio
),
1923 blk_rq_bytes(req
), PCI_DMA_BIDIRECTIONAL
);
1924 if (!dma_addr_out
) {
1925 mpt2sas_base_free_smid(ioc
, smid
);
1929 ioc
->base_add_sg_single(psge
, sgl_flags
| (blk_rq_bytes(req
) - 4),
1933 psge
+= ioc
->sge_size
;
1935 /* READ sgel last */
1936 sgl_flags
= (MPI2_SGE_FLAGS_SIMPLE_ELEMENT
|
1937 MPI2_SGE_FLAGS_LAST_ELEMENT
| MPI2_SGE_FLAGS_END_OF_BUFFER
|
1938 MPI2_SGE_FLAGS_END_OF_LIST
);
1939 sgl_flags
= sgl_flags
<< MPI2_SGE_FLAGS_SHIFT
;
1940 dma_addr_in
= pci_map_single(ioc
->pdev
, bio_data(rsp
->bio
),
1941 blk_rq_bytes(rsp
), PCI_DMA_BIDIRECTIONAL
);
1943 mpt2sas_base_free_smid(ioc
, smid
);
1947 ioc
->base_add_sg_single(psge
, sgl_flags
| (blk_rq_bytes(rsp
) + 4),
1950 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"%s - "
1951 "sending smp request\n", ioc
->name
, __func__
));
1953 init_completion(&ioc
->transport_cmds
.done
);
1954 mpt2sas_base_put_smid_default(ioc
, smid
);
1955 timeleft
= wait_for_completion_timeout(&ioc
->transport_cmds
.done
,
1958 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_COMPLETE
)) {
1959 printk(MPT2SAS_ERR_FMT
"%s : timeout\n",
1960 __func__
, ioc
->name
);
1961 _debug_dump_mf(mpi_request
,
1962 sizeof(Mpi2SmpPassthroughRequest_t
)/4);
1963 if (!(ioc
->transport_cmds
.status
& MPT2_CMD_RESET
))
1965 goto issue_host_reset
;
1968 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
"%s - "
1969 "complete\n", ioc
->name
, __func__
));
1971 if (ioc
->transport_cmds
.status
& MPT2_CMD_REPLY_VALID
) {
1973 mpi_reply
= ioc
->transport_cmds
.reply
;
1975 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1976 "%s - reply data transfer size(%d)\n",
1977 ioc
->name
, __func__
,
1978 le16_to_cpu(mpi_reply
->ResponseDataLength
)));
1980 memcpy(req
->sense
, mpi_reply
, sizeof(*mpi_reply
));
1981 req
->sense_len
= sizeof(*mpi_reply
);
1984 le16_to_cpu(mpi_reply
->ResponseDataLength
);
1986 dtransportprintk(ioc
, printk(MPT2SAS_INFO_FMT
1987 "%s - no reply\n", ioc
->name
, __func__
));
1993 mpt2sas_base_hard_reset_handler(ioc
, CAN_SLEEP
,
2000 pci_unmap_single(ioc
->pdev
, dma_addr_out
, blk_rq_bytes(req
),
2001 PCI_DMA_BIDIRECTIONAL
);
2003 pci_unmap_single(ioc
->pdev
, dma_addr_in
, blk_rq_bytes(rsp
),
2004 PCI_DMA_BIDIRECTIONAL
);
2007 ioc
->transport_cmds
.status
= MPT2_CMD_NOT_USED
;
2008 mutex_unlock(&ioc
->transport_cmds
.mutex
);
2012 struct sas_function_template mpt2sas_transport_functions
= {
2013 .get_linkerrors
= _transport_get_linkerrors
,
2014 .get_enclosure_identifier
= _transport_get_enclosure_identifier
,
2015 .get_bay_identifier
= _transport_get_bay_identifier
,
2016 .phy_reset
= _transport_phy_reset
,
2017 .phy_enable
= _transport_phy_enable
,
2018 .set_phy_speed
= _transport_phy_speed
,
2019 .smp_handler
= _transport_smp_handler
,
2022 struct scsi_transport_template
*mpt2sas_transport_template
;