1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Driver for Broadcom MPI3 Storage Controllers
5 * Copyright (C) 2017-2023 Broadcom Inc.
6 * (mailto: mpi3mr-linuxdrv.pdl@broadcom.com)
10 #include <linux/vmalloc.h>
15 * mpi3mr_post_transport_req - Issue transport requests and wait
16 * @mrioc: Adapter instance reference
17 * @request: Properly populated MPI3 request
18 * @request_sz: Size of the MPI3 request
19 * @reply: Pointer to return MPI3 reply
20 * @reply_sz: Size of the MPI3 reply buffer
21 * @timeout: Timeout in seconds
22 * @ioc_status: Pointer to return ioc status
24 * A generic function for posting MPI3 requests from the SAS
25 * transport layer that uses transport command infrastructure.
26 * This blocks for the completion of request for timeout seconds
27 * and if the request times out this function faults the
28 * controller with proper reason code.
30 * On successful completion of the request this function returns
31 * appropriate ioc status from the firmware back to the caller.
33 * Return: 0 on success, non-zero on failure.
35 static int mpi3mr_post_transport_req(struct mpi3mr_ioc
*mrioc
, void *request
,
36 u16 request_sz
, void *reply
, u16 reply_sz
, int timeout
,
41 mutex_lock(&mrioc
->transport_cmds
.mutex
);
42 if (mrioc
->transport_cmds
.state
& MPI3MR_CMD_PENDING
) {
44 ioc_err(mrioc
, "sending transport request failed due to command in use\n");
45 mutex_unlock(&mrioc
->transport_cmds
.mutex
);
48 mrioc
->transport_cmds
.state
= MPI3MR_CMD_PENDING
;
49 mrioc
->transport_cmds
.is_waiting
= 1;
50 mrioc
->transport_cmds
.callback
= NULL
;
51 mrioc
->transport_cmds
.ioc_status
= 0;
52 mrioc
->transport_cmds
.ioc_loginfo
= 0;
54 init_completion(&mrioc
->transport_cmds
.done
);
55 dprint_cfg_info(mrioc
, "posting transport request\n");
56 if (mrioc
->logging_level
& MPI3_DEBUG_TRANSPORT_INFO
)
57 dprint_dump(request
, request_sz
, "transport_req");
58 retval
= mpi3mr_admin_request_post(mrioc
, request
, request_sz
, 1);
60 ioc_err(mrioc
, "posting transport request failed\n");
63 wait_for_completion_timeout(&mrioc
->transport_cmds
.done
,
65 if (!(mrioc
->transport_cmds
.state
& MPI3MR_CMD_COMPLETE
)) {
66 mpi3mr_check_rh_fault_ioc(mrioc
,
67 MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT
);
68 ioc_err(mrioc
, "transport request timed out\n");
72 *ioc_status
= mrioc
->transport_cmds
.ioc_status
&
73 MPI3_IOCSTATUS_STATUS_MASK
;
74 if ((*ioc_status
) != MPI3_IOCSTATUS_SUCCESS
)
75 dprint_transport_err(mrioc
,
76 "transport request returned with ioc_status(0x%04x), log_info(0x%08x)\n",
77 *ioc_status
, mrioc
->transport_cmds
.ioc_loginfo
);
79 if ((reply
) && (mrioc
->transport_cmds
.state
& MPI3MR_CMD_REPLY_VALID
))
80 memcpy((u8
*)reply
, mrioc
->transport_cmds
.reply
, reply_sz
);
83 mrioc
->transport_cmds
.state
= MPI3MR_CMD_NOTUSED
;
84 mutex_unlock(&mrioc
->transport_cmds
.mutex
);
90 /* report manufacture request structure */
91 struct rep_manu_request
{
98 /* report manufacture reply structure */
99 struct rep_manu_reply
{
100 u8 smp_frame_type
; /* 0x41 */
101 u8 function
; /* 0x01 */
104 u16 expander_change_count
;
108 u8 vendor_id
[SAS_EXPANDER_VENDOR_ID_LEN
];
109 u8 product_id
[SAS_EXPANDER_PRODUCT_ID_LEN
];
110 u8 product_rev
[SAS_EXPANDER_PRODUCT_REV_LEN
];
111 u8 component_vendor_id
[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN
];
113 u8 component_revision_id
;
115 u8 vendor_specific
[8];
119 * mpi3mr_report_manufacture - obtain SMP report_manufacture
120 * @mrioc: Adapter instance reference
121 * @sas_address: SAS address of the expander device
122 * @edev: SAS transport layer sas_expander_device object
123 * @port_id: ID of the HBA port
125 * Fills in the sas_expander_device with manufacturing info.
127 * Return: 0 for success, non-zero for failure.
129 static int mpi3mr_report_manufacture(struct mpi3mr_ioc
*mrioc
,
130 u64 sas_address
, struct sas_expander_device
*edev
, u8 port_id
)
132 struct mpi3_smp_passthrough_request mpi_request
;
133 struct mpi3_smp_passthrough_reply mpi_reply
;
134 struct rep_manu_reply
*manufacture_reply
;
135 struct rep_manu_request
*manufacture_request
;
138 void *data_out
= NULL
;
139 dma_addr_t data_out_dma
;
140 dma_addr_t data_in_dma
;
143 u8 sgl_flags
= MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST
;
144 u16 request_sz
= sizeof(struct mpi3_smp_passthrough_request
);
145 u16 reply_sz
= sizeof(struct mpi3_smp_passthrough_reply
);
149 if (mrioc
->reset_in_progress
) {
150 ioc_err(mrioc
, "%s: host reset in progress!\n", __func__
);
154 if (mrioc
->pci_err_recovery
) {
155 ioc_err(mrioc
, "%s: pci error recovery in progress!\n", __func__
);
159 data_out_sz
= sizeof(struct rep_manu_request
);
160 data_in_sz
= sizeof(struct rep_manu_reply
);
161 data_out
= dma_alloc_coherent(&mrioc
->pdev
->dev
,
162 data_out_sz
+ data_in_sz
, &data_out_dma
, GFP_KERNEL
);
168 data_in_dma
= data_out_dma
+ data_out_sz
;
169 manufacture_reply
= data_out
+ data_out_sz
;
171 manufacture_request
= data_out
;
172 manufacture_request
->smp_frame_type
= 0x40;
173 manufacture_request
->function
= 1;
174 manufacture_request
->reserved
= 0;
175 manufacture_request
->request_length
= 0;
177 memset(&mpi_request
, 0, request_sz
);
178 memset(&mpi_reply
, 0, reply_sz
);
179 mpi_request
.host_tag
= cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS
);
180 mpi_request
.function
= MPI3_FUNCTION_SMP_PASSTHROUGH
;
181 mpi_request
.io_unit_port
= (u8
) port_id
;
182 mpi_request
.sas_address
= cpu_to_le64(sas_address
);
184 psge
= &mpi_request
.request_sge
;
185 mpi3mr_add_sg_single(psge
, sgl_flags
, data_out_sz
, data_out_dma
);
187 psge
= &mpi_request
.response_sge
;
188 mpi3mr_add_sg_single(psge
, sgl_flags
, data_in_sz
, data_in_dma
);
190 dprint_transport_info(mrioc
,
191 "sending report manufacturer SMP request to sas_address(0x%016llx), port(%d)\n",
192 (unsigned long long)sas_address
, port_id
);
194 rc
= mpi3mr_post_transport_req(mrioc
, &mpi_request
, request_sz
,
195 &mpi_reply
, reply_sz
,
196 MPI3MR_INTADMCMD_TIMEOUT
, &ioc_status
);
200 dprint_transport_info(mrioc
,
201 "report manufacturer SMP request completed with ioc_status(0x%04x)\n",
204 if (ioc_status
!= MPI3_IOCSTATUS_SUCCESS
) {
209 dprint_transport_info(mrioc
,
210 "report manufacturer - reply data transfer size(%d)\n",
211 le16_to_cpu(mpi_reply
.response_data_length
));
213 if (le16_to_cpu(mpi_reply
.response_data_length
) !=
214 sizeof(struct rep_manu_reply
)) {
219 memtostr(edev
->vendor_id
, manufacture_reply
->vendor_id
);
220 memtostr(edev
->product_id
, manufacture_reply
->product_id
);
221 memtostr(edev
->product_rev
, manufacture_reply
->product_rev
);
222 edev
->level
= manufacture_reply
->sas_format
& 1;
224 memtostr(edev
->component_vendor_id
,
225 manufacture_reply
->component_vendor_id
);
226 tmp
= (u8
*)&manufacture_reply
->component_id
;
227 edev
->component_id
= tmp
[0] << 8 | tmp
[1];
228 edev
->component_revision_id
=
229 manufacture_reply
->component_revision_id
;
234 dma_free_coherent(&mrioc
->pdev
->dev
, data_out_sz
+ data_in_sz
,
235 data_out
, data_out_dma
);
241 * __mpi3mr_expander_find_by_handle - expander search by handle
242 * @mrioc: Adapter instance reference
243 * @handle: Firmware device handle of the expander
245 * Context: The caller should acquire sas_node_lock
247 * This searches for expander device based on handle, then
248 * returns the sas_node object.
250 * Return: Expander sas_node object reference or NULL
252 struct mpi3mr_sas_node
*__mpi3mr_expander_find_by_handle(struct mpi3mr_ioc
255 struct mpi3mr_sas_node
*sas_expander
, *r
;
258 list_for_each_entry(sas_expander
, &mrioc
->sas_expander_list
, list
) {
259 if (sas_expander
->handle
!= handle
)
269 * mpi3mr_is_expander_device - if device is an expander
270 * @device_info: Bitfield providing information about the device
272 * Return: 1 if the device is expander device, else 0.
274 u8
mpi3mr_is_expander_device(u16 device_info
)
276 if ((device_info
& MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK
) ==
277 MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER
)
284 * mpi3mr_get_sas_address - retrieve sas_address for handle
285 * @mrioc: Adapter instance reference
286 * @handle: Firmware device handle
287 * @sas_address: Address to hold sas address
289 * This function issues device page0 read for a given device
290 * handle and gets the SAS address and return it back
292 * Return: 0 for success, non-zero for failure
294 static int mpi3mr_get_sas_address(struct mpi3mr_ioc
*mrioc
, u16 handle
,
297 struct mpi3_device_page0 dev_pg0
;
299 struct mpi3_device0_sas_sata_format
*sasinf
;
303 if ((mpi3mr_cfg_get_dev_pg0(mrioc
, &ioc_status
, &dev_pg0
,
304 sizeof(dev_pg0
), MPI3_DEVICE_PGAD_FORM_HANDLE
,
306 ioc_err(mrioc
, "%s: device page0 read failed\n", __func__
);
310 if (ioc_status
!= MPI3_IOCSTATUS_SUCCESS
) {
311 ioc_err(mrioc
, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
312 handle
, ioc_status
, __FILE__
, __LINE__
, __func__
);
316 if (le16_to_cpu(dev_pg0
.flags
) &
317 MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE
)
318 *sas_address
= mrioc
->sas_hba
.sas_address
;
319 else if (dev_pg0
.device_form
== MPI3_DEVICE_DEVFORM_SAS_SATA
) {
320 sasinf
= &dev_pg0
.device_specific
.sas_sata_format
;
321 *sas_address
= le64_to_cpu(sasinf
->sas_address
);
323 ioc_err(mrioc
, "%s: device_form(%d) is not SAS_SATA\n",
324 __func__
, dev_pg0
.device_form
);
331 * __mpi3mr_get_tgtdev_by_addr - target device search
332 * @mrioc: Adapter instance reference
333 * @sas_address: SAS address of the device
334 * @hba_port: HBA port entry
336 * This searches for target device from sas address and hba port
337 * pointer then return mpi3mr_tgt_dev object.
339 * Return: Valid tget_dev or NULL
341 static struct mpi3mr_tgt_dev
*__mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc
*mrioc
,
342 u64 sas_address
, struct mpi3mr_hba_port
*hba_port
)
344 struct mpi3mr_tgt_dev
*tgtdev
;
346 assert_spin_locked(&mrioc
->tgtdev_lock
);
348 list_for_each_entry(tgtdev
, &mrioc
->tgtdev_list
, list
)
349 if ((tgtdev
->dev_type
== MPI3_DEVICE_DEVFORM_SAS_SATA
) &&
350 (tgtdev
->dev_spec
.sas_sata_inf
.sas_address
== sas_address
)
351 && (tgtdev
->dev_spec
.sas_sata_inf
.hba_port
== hba_port
))
355 mpi3mr_tgtdev_get(tgtdev
);
360 * mpi3mr_get_tgtdev_by_addr - target device search
361 * @mrioc: Adapter instance reference
362 * @sas_address: SAS address of the device
363 * @hba_port: HBA port entry
365 * This searches for target device from sas address and hba port
366 * pointer then return mpi3mr_tgt_dev object.
368 * Context: This function will acquire tgtdev_lock and will
369 * release before returning the mpi3mr_tgt_dev object.
371 * Return: Valid tget_dev or NULL
373 static struct mpi3mr_tgt_dev
*mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc
*mrioc
,
374 u64 sas_address
, struct mpi3mr_hba_port
*hba_port
)
376 struct mpi3mr_tgt_dev
*tgtdev
= NULL
;
382 spin_lock_irqsave(&mrioc
->tgtdev_lock
, flags
);
383 tgtdev
= __mpi3mr_get_tgtdev_by_addr(mrioc
, sas_address
, hba_port
);
384 spin_unlock_irqrestore(&mrioc
->tgtdev_lock
, flags
);
391 * mpi3mr_remove_device_by_sas_address - remove the device
392 * @mrioc: Adapter instance reference
393 * @sas_address: SAS address of the device
394 * @hba_port: HBA port entry
396 * This searches for target device using sas address and hba
397 * port pointer then removes it from the OS.
401 static void mpi3mr_remove_device_by_sas_address(struct mpi3mr_ioc
*mrioc
,
402 u64 sas_address
, struct mpi3mr_hba_port
*hba_port
)
404 struct mpi3mr_tgt_dev
*tgtdev
= NULL
;
406 u8 was_on_tgtdev_list
= 0;
411 spin_lock_irqsave(&mrioc
->tgtdev_lock
, flags
);
412 tgtdev
= __mpi3mr_get_tgtdev_by_addr(mrioc
,
413 sas_address
, hba_port
);
415 if (!list_empty(&tgtdev
->list
)) {
416 list_del_init(&tgtdev
->list
);
417 was_on_tgtdev_list
= 1;
418 mpi3mr_tgtdev_put(tgtdev
);
421 spin_unlock_irqrestore(&mrioc
->tgtdev_lock
, flags
);
422 if (was_on_tgtdev_list
) {
423 if (tgtdev
->host_exposed
)
424 mpi3mr_remove_tgtdev_from_host(mrioc
, tgtdev
);
425 mpi3mr_tgtdev_put(tgtdev
);
430 * __mpi3mr_get_tgtdev_by_addr_and_rphy - target device search
431 * @mrioc: Adapter instance reference
432 * @sas_address: SAS address of the device
433 * @rphy: SAS transport layer rphy object
435 * This searches for target device from sas address and rphy
436 * pointer then return mpi3mr_tgt_dev object.
438 * Return: Valid tget_dev or NULL
440 struct mpi3mr_tgt_dev
*__mpi3mr_get_tgtdev_by_addr_and_rphy(
441 struct mpi3mr_ioc
*mrioc
, u64 sas_address
, struct sas_rphy
*rphy
)
443 struct mpi3mr_tgt_dev
*tgtdev
;
445 assert_spin_locked(&mrioc
->tgtdev_lock
);
447 list_for_each_entry(tgtdev
, &mrioc
->tgtdev_list
, list
)
448 if ((tgtdev
->dev_type
== MPI3_DEVICE_DEVFORM_SAS_SATA
) &&
449 (tgtdev
->dev_spec
.sas_sata_inf
.sas_address
== sas_address
)
450 && (tgtdev
->dev_spec
.sas_sata_inf
.rphy
== rphy
))
454 mpi3mr_tgtdev_get(tgtdev
);
459 * mpi3mr_expander_find_by_sas_address - sas expander search
460 * @mrioc: Adapter instance reference
461 * @sas_address: SAS address of expander
462 * @hba_port: HBA port entry
464 * Return: A valid SAS expander node or NULL.
467 static struct mpi3mr_sas_node
*mpi3mr_expander_find_by_sas_address(
468 struct mpi3mr_ioc
*mrioc
, u64 sas_address
,
469 struct mpi3mr_hba_port
*hba_port
)
471 struct mpi3mr_sas_node
*sas_expander
, *r
= NULL
;
476 list_for_each_entry(sas_expander
, &mrioc
->sas_expander_list
, list
) {
477 if ((sas_expander
->sas_address
!= sas_address
) ||
478 (sas_expander
->hba_port
!= hba_port
))
488 * __mpi3mr_sas_node_find_by_sas_address - sas node search
489 * @mrioc: Adapter instance reference
490 * @sas_address: SAS address of expander or sas host
491 * @hba_port: HBA port entry
492 * Context: Caller should acquire mrioc->sas_node_lock.
494 * If the SAS address indicates the device is direct attached to
495 * the controller (controller's SAS address) then the SAS node
496 * associated with the controller is returned back else the SAS
497 * address and hba port are used to identify the exact expander
498 * and the associated sas_node object is returned. If there is
499 * no match NULL is returned.
501 * Return: A valid SAS node or NULL.
504 static struct mpi3mr_sas_node
*__mpi3mr_sas_node_find_by_sas_address(
505 struct mpi3mr_ioc
*mrioc
, u64 sas_address
,
506 struct mpi3mr_hba_port
*hba_port
)
509 if (mrioc
->sas_hba
.sas_address
== sas_address
)
510 return &mrioc
->sas_hba
;
511 return mpi3mr_expander_find_by_sas_address(mrioc
, sas_address
,
516 * mpi3mr_parent_present - Is parent present for a phy
517 * @mrioc: Adapter instance reference
518 * @phy: SAS transport layer phy object
520 * Return: 0 if parent is present else non-zero
522 static int mpi3mr_parent_present(struct mpi3mr_ioc
*mrioc
, struct sas_phy
*phy
)
525 struct mpi3mr_hba_port
*hba_port
= phy
->hostdata
;
527 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
528 if (__mpi3mr_sas_node_find_by_sas_address(mrioc
,
529 phy
->identify
.sas_address
,
531 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
534 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
539 * mpi3mr_convert_phy_link_rate -
540 * @link_rate: link rate as defined in the MPI header
542 * Convert link_rate from mpi format into sas_transport layer
545 * Return: A valid SAS transport layer defined link rate
547 static enum sas_linkrate
mpi3mr_convert_phy_link_rate(u8 link_rate
)
549 enum sas_linkrate rc
;
552 case MPI3_SAS_NEG_LINK_RATE_1_5
:
553 rc
= SAS_LINK_RATE_1_5_GBPS
;
555 case MPI3_SAS_NEG_LINK_RATE_3_0
:
556 rc
= SAS_LINK_RATE_3_0_GBPS
;
558 case MPI3_SAS_NEG_LINK_RATE_6_0
:
559 rc
= SAS_LINK_RATE_6_0_GBPS
;
561 case MPI3_SAS_NEG_LINK_RATE_12_0
:
562 rc
= SAS_LINK_RATE_12_0_GBPS
;
564 case MPI3_SAS_NEG_LINK_RATE_22_5
:
565 rc
= SAS_LINK_RATE_22_5_GBPS
;
567 case MPI3_SAS_NEG_LINK_RATE_PHY_DISABLED
:
568 rc
= SAS_PHY_DISABLED
;
570 case MPI3_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED
:
571 rc
= SAS_LINK_RATE_FAILED
;
573 case MPI3_SAS_NEG_LINK_RATE_PORT_SELECTOR
:
574 rc
= SAS_SATA_PORT_SELECTOR
;
576 case MPI3_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS
:
577 rc
= SAS_PHY_RESET_IN_PROGRESS
;
579 case MPI3_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE
:
580 case MPI3_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE
:
582 rc
= SAS_LINK_RATE_UNKNOWN
;
589 * mpi3mr_delete_sas_phy - Remove a single phy from port
590 * @mrioc: Adapter instance reference
591 * @mr_sas_port: Internal Port object
592 * @mr_sas_phy: Internal Phy object
593 * @host_node: Flag to indicate this is a host_node
597 static void mpi3mr_delete_sas_phy(struct mpi3mr_ioc
*mrioc
,
598 struct mpi3mr_sas_port
*mr_sas_port
,
599 struct mpi3mr_sas_phy
*mr_sas_phy
, u8 host_node
)
601 u64 sas_address
= mr_sas_port
->remote_identify
.sas_address
;
603 dev_info(&mr_sas_phy
->phy
->dev
,
604 "remove: sas_address(0x%016llx), phy(%d)\n",
605 (unsigned long long) sas_address
, mr_sas_phy
->phy_id
);
607 list_del(&mr_sas_phy
->port_siblings
);
608 mr_sas_port
->num_phys
--;
611 mr_sas_port
->phy_mask
&= ~(1 << mr_sas_phy
->phy_id
);
613 if (mr_sas_port
->lowest_phy
== mr_sas_phy
->phy_id
)
614 mr_sas_port
->lowest_phy
= ffs(mr_sas_port
->phy_mask
) - 1;
616 sas_port_delete_phy(mr_sas_port
->port
, mr_sas_phy
->phy
);
617 mr_sas_phy
->phy_belongs_to_port
= 0;
621 * mpi3mr_add_sas_phy - Adding a single phy to a port
622 * @mrioc: Adapter instance reference
623 * @mr_sas_port: Internal Port object
624 * @mr_sas_phy: Internal Phy object
625 * @host_node: Flag to indicate this is a host_node
629 static void mpi3mr_add_sas_phy(struct mpi3mr_ioc
*mrioc
,
630 struct mpi3mr_sas_port
*mr_sas_port
,
631 struct mpi3mr_sas_phy
*mr_sas_phy
, u8 host_node
)
633 u64 sas_address
= mr_sas_port
->remote_identify
.sas_address
;
635 dev_info(&mr_sas_phy
->phy
->dev
,
636 "add: sas_address(0x%016llx), phy(%d)\n", (unsigned long long)
637 sas_address
, mr_sas_phy
->phy_id
);
639 list_add_tail(&mr_sas_phy
->port_siblings
, &mr_sas_port
->phy_list
);
640 mr_sas_port
->num_phys
++;
642 mr_sas_port
->phy_mask
|= (1 << mr_sas_phy
->phy_id
);
644 if (mr_sas_phy
->phy_id
< mr_sas_port
->lowest_phy
)
645 mr_sas_port
->lowest_phy
= ffs(mr_sas_port
->phy_mask
) - 1;
647 sas_port_add_phy(mr_sas_port
->port
, mr_sas_phy
->phy
);
648 mr_sas_phy
->phy_belongs_to_port
= 1;
652 * mpi3mr_add_phy_to_an_existing_port - add phy to existing port
653 * @mrioc: Adapter instance reference
654 * @mr_sas_node: Internal sas node object (expander or host)
655 * @mr_sas_phy: Internal Phy object *
656 * @sas_address: SAS address of device/expander were phy needs
658 * @hba_port: HBA port entry
662 static void mpi3mr_add_phy_to_an_existing_port(struct mpi3mr_ioc
*mrioc
,
663 struct mpi3mr_sas_node
*mr_sas_node
, struct mpi3mr_sas_phy
*mr_sas_phy
,
664 u64 sas_address
, struct mpi3mr_hba_port
*hba_port
)
666 struct mpi3mr_sas_port
*mr_sas_port
;
667 struct mpi3mr_sas_phy
*srch_phy
;
669 if (mr_sas_phy
->phy_belongs_to_port
== 1)
675 list_for_each_entry(mr_sas_port
, &mr_sas_node
->sas_port_list
,
677 if (mr_sas_port
->remote_identify
.sas_address
!=
680 if (mr_sas_port
->hba_port
!= hba_port
)
682 list_for_each_entry(srch_phy
, &mr_sas_port
->phy_list
,
684 if (srch_phy
== mr_sas_phy
)
687 mpi3mr_add_sas_phy(mrioc
, mr_sas_port
, mr_sas_phy
, mr_sas_node
->host_node
);
693 * mpi3mr_delete_sas_port - helper function to removing a port
694 * @mrioc: Adapter instance reference
695 * @mr_sas_port: Internal Port object
699 static void mpi3mr_delete_sas_port(struct mpi3mr_ioc
*mrioc
,
700 struct mpi3mr_sas_port
*mr_sas_port
)
702 u64 sas_address
= mr_sas_port
->remote_identify
.sas_address
;
703 struct mpi3mr_hba_port
*hba_port
= mr_sas_port
->hba_port
;
704 enum sas_device_type device_type
=
705 mr_sas_port
->remote_identify
.device_type
;
707 dev_info(&mr_sas_port
->port
->dev
,
708 "remove: sas_address(0x%016llx)\n",
709 (unsigned long long) sas_address
);
711 if (device_type
== SAS_END_DEVICE
)
712 mpi3mr_remove_device_by_sas_address(mrioc
, sas_address
,
715 else if (device_type
== SAS_EDGE_EXPANDER_DEVICE
||
716 device_type
== SAS_FANOUT_EXPANDER_DEVICE
)
717 mpi3mr_expander_remove(mrioc
, sas_address
, hba_port
);
721 * mpi3mr_del_phy_from_an_existing_port - del phy from a port
722 * @mrioc: Adapter instance reference
723 * @mr_sas_node: Internal sas node object (expander or host)
724 * @mr_sas_phy: Internal Phy object
728 static void mpi3mr_del_phy_from_an_existing_port(struct mpi3mr_ioc
*mrioc
,
729 struct mpi3mr_sas_node
*mr_sas_node
, struct mpi3mr_sas_phy
*mr_sas_phy
)
731 struct mpi3mr_sas_port
*mr_sas_port
, *next
;
732 struct mpi3mr_sas_phy
*srch_phy
;
734 if (mr_sas_phy
->phy_belongs_to_port
== 0)
737 list_for_each_entry_safe(mr_sas_port
, next
, &mr_sas_node
->sas_port_list
,
739 list_for_each_entry(srch_phy
, &mr_sas_port
->phy_list
,
741 if (srch_phy
!= mr_sas_phy
)
743 if ((mr_sas_port
->num_phys
== 1) &&
744 !mrioc
->reset_in_progress
)
745 mpi3mr_delete_sas_port(mrioc
, mr_sas_port
);
747 mpi3mr_delete_sas_phy(mrioc
, mr_sas_port
,
748 mr_sas_phy
, mr_sas_node
->host_node
);
755 * mpi3mr_sas_port_sanity_check - sanity check while adding port
756 * @mrioc: Adapter instance reference
757 * @mr_sas_node: Internal sas node object (expander or host)
758 * @sas_address: SAS address of device/expander
759 * @hba_port: HBA port entry
761 * Verifies whether the Phys attached to a device with the given
762 * SAS address already belongs to an existing sas port if so
763 * will remove those phys from the sas port
767 static void mpi3mr_sas_port_sanity_check(struct mpi3mr_ioc
*mrioc
,
768 struct mpi3mr_sas_node
*mr_sas_node
, u64 sas_address
,
769 struct mpi3mr_hba_port
*hba_port
)
773 for (i
= 0; i
< mr_sas_node
->num_phys
; i
++) {
774 if ((mr_sas_node
->phy
[i
].remote_identify
.sas_address
!=
775 sas_address
) || (mr_sas_node
->phy
[i
].hba_port
!= hba_port
))
777 if (mr_sas_node
->phy
[i
].phy_belongs_to_port
== 1)
778 mpi3mr_del_phy_from_an_existing_port(mrioc
,
779 mr_sas_node
, &mr_sas_node
->phy
[i
]);
784 * mpi3mr_set_identify - set identify for phys and end devices
785 * @mrioc: Adapter instance reference
786 * @handle: Firmware device handle
787 * @identify: SAS transport layer's identify info
789 * Populates sas identify info for a specific device.
791 * Return: 0 for success, non-zero for failure.
793 static int mpi3mr_set_identify(struct mpi3mr_ioc
*mrioc
, u16 handle
,
794 struct sas_identify
*identify
)
797 struct mpi3_device_page0 device_pg0
;
798 struct mpi3_device0_sas_sata_format
*sasinf
;
802 if (mrioc
->reset_in_progress
) {
803 ioc_err(mrioc
, "%s: host reset in progress!\n", __func__
);
807 if (mrioc
->pci_err_recovery
) {
808 ioc_err(mrioc
, "%s: pci error recovery in progress!\n",
813 if ((mpi3mr_cfg_get_dev_pg0(mrioc
, &ioc_status
, &device_pg0
,
814 sizeof(device_pg0
), MPI3_DEVICE_PGAD_FORM_HANDLE
, handle
))) {
815 ioc_err(mrioc
, "%s: device page0 read failed\n", __func__
);
819 if (ioc_status
!= MPI3_IOCSTATUS_SUCCESS
) {
820 ioc_err(mrioc
, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
821 handle
, ioc_status
, __FILE__
, __LINE__
, __func__
);
825 memset(identify
, 0, sizeof(struct sas_identify
));
826 sasinf
= &device_pg0
.device_specific
.sas_sata_format
;
827 device_info
= le16_to_cpu(sasinf
->device_info
);
830 identify
->sas_address
= le64_to_cpu(sasinf
->sas_address
);
832 /* phy number of the parent device this device is linked to */
833 identify
->phy_identifier
= sasinf
->phy_num
;
836 switch (device_info
& MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK
) {
837 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_NO_DEVICE
:
838 identify
->device_type
= SAS_PHY_UNUSED
;
840 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE
:
841 identify
->device_type
= SAS_END_DEVICE
;
843 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER
:
844 identify
->device_type
= SAS_EDGE_EXPANDER_DEVICE
;
848 /* initiator_port_protocols */
849 if (device_info
& MPI3_SAS_DEVICE_INFO_SSP_INITIATOR
)
850 identify
->initiator_port_protocols
|= SAS_PROTOCOL_SSP
;
851 /* MPI3.0 doesn't have define for SATA INIT so setting both here*/
852 if (device_info
& MPI3_SAS_DEVICE_INFO_STP_INITIATOR
)
853 identify
->initiator_port_protocols
|= (SAS_PROTOCOL_STP
|
855 if (device_info
& MPI3_SAS_DEVICE_INFO_SMP_INITIATOR
)
856 identify
->initiator_port_protocols
|= SAS_PROTOCOL_SMP
;
858 /* target_port_protocols */
859 if (device_info
& MPI3_SAS_DEVICE_INFO_SSP_TARGET
)
860 identify
->target_port_protocols
|= SAS_PROTOCOL_SSP
;
861 /* MPI3.0 doesn't have define for STP Target so setting both here*/
862 if (device_info
& MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET
)
863 identify
->target_port_protocols
|= (SAS_PROTOCOL_STP
|
865 if (device_info
& MPI3_SAS_DEVICE_INFO_SMP_TARGET
)
866 identify
->target_port_protocols
|= SAS_PROTOCOL_SMP
;
871 * mpi3mr_add_host_phy - report sas_host phy to SAS transport
872 * @mrioc: Adapter instance reference
873 * @mr_sas_phy: Internal Phy object
874 * @phy_pg0: SAS phy page 0
875 * @parent_dev: Prent device class object
877 * Return: 0 for success, non-zero for failure.
879 static int mpi3mr_add_host_phy(struct mpi3mr_ioc
*mrioc
,
880 struct mpi3mr_sas_phy
*mr_sas_phy
, struct mpi3_sas_phy_page0 phy_pg0
,
881 struct device
*parent_dev
)
884 int phy_index
= mr_sas_phy
->phy_id
;
887 INIT_LIST_HEAD(&mr_sas_phy
->port_siblings
);
888 phy
= sas_phy_alloc(parent_dev
, phy_index
);
890 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
891 __FILE__
, __LINE__
, __func__
);
894 if ((mpi3mr_set_identify(mrioc
, mr_sas_phy
->handle
,
895 &mr_sas_phy
->identify
))) {
896 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
897 __FILE__
, __LINE__
, __func__
);
901 phy
->identify
= mr_sas_phy
->identify
;
902 mr_sas_phy
->attached_handle
= le16_to_cpu(phy_pg0
.attached_dev_handle
);
903 if (mr_sas_phy
->attached_handle
)
904 mpi3mr_set_identify(mrioc
, mr_sas_phy
->attached_handle
,
905 &mr_sas_phy
->remote_identify
);
906 phy
->identify
.phy_identifier
= mr_sas_phy
->phy_id
;
907 phy
->negotiated_linkrate
= mpi3mr_convert_phy_link_rate(
908 (phy_pg0
.negotiated_link_rate
&
909 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK
) >>
910 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT
);
911 phy
->minimum_linkrate_hw
= mpi3mr_convert_phy_link_rate(
912 phy_pg0
.hw_link_rate
& MPI3_SAS_HWRATE_MIN_RATE_MASK
);
913 phy
->maximum_linkrate_hw
= mpi3mr_convert_phy_link_rate(
914 phy_pg0
.hw_link_rate
>> 4);
915 phy
->minimum_linkrate
= mpi3mr_convert_phy_link_rate(
916 phy_pg0
.programmed_link_rate
& MPI3_SAS_PRATE_MIN_RATE_MASK
);
917 phy
->maximum_linkrate
= mpi3mr_convert_phy_link_rate(
918 phy_pg0
.programmed_link_rate
>> 4);
919 phy
->hostdata
= mr_sas_phy
->hba_port
;
921 if ((sas_phy_add(phy
))) {
922 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
923 __FILE__
, __LINE__
, __func__
);
927 if ((mrioc
->logging_level
& MPI3_DEBUG_TRANSPORT_INFO
))
929 "add: handle(0x%04x), sas_address(0x%016llx)\n"
930 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
931 mr_sas_phy
->handle
, (unsigned long long)
932 mr_sas_phy
->identify
.sas_address
,
933 mr_sas_phy
->attached_handle
,
935 mr_sas_phy
->remote_identify
.sas_address
);
936 mr_sas_phy
->phy
= phy
;
941 * mpi3mr_add_expander_phy - report expander phy to transport
942 * @mrioc: Adapter instance reference
943 * @mr_sas_phy: Internal Phy object
944 * @expander_pg1: SAS Expander page 1
945 * @parent_dev: Parent device class object
947 * Return: 0 for success, non-zero for failure.
949 static int mpi3mr_add_expander_phy(struct mpi3mr_ioc
*mrioc
,
950 struct mpi3mr_sas_phy
*mr_sas_phy
,
951 struct mpi3_sas_expander_page1 expander_pg1
,
952 struct device
*parent_dev
)
955 int phy_index
= mr_sas_phy
->phy_id
;
957 INIT_LIST_HEAD(&mr_sas_phy
->port_siblings
);
958 phy
= sas_phy_alloc(parent_dev
, phy_index
);
960 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
961 __FILE__
, __LINE__
, __func__
);
964 if ((mpi3mr_set_identify(mrioc
, mr_sas_phy
->handle
,
965 &mr_sas_phy
->identify
))) {
966 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
967 __FILE__
, __LINE__
, __func__
);
971 phy
->identify
= mr_sas_phy
->identify
;
972 mr_sas_phy
->attached_handle
=
973 le16_to_cpu(expander_pg1
.attached_dev_handle
);
974 if (mr_sas_phy
->attached_handle
)
975 mpi3mr_set_identify(mrioc
, mr_sas_phy
->attached_handle
,
976 &mr_sas_phy
->remote_identify
);
977 phy
->identify
.phy_identifier
= mr_sas_phy
->phy_id
;
978 phy
->negotiated_linkrate
= mpi3mr_convert_phy_link_rate(
979 (expander_pg1
.negotiated_link_rate
&
980 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK
) >>
981 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT
);
982 phy
->minimum_linkrate_hw
= mpi3mr_convert_phy_link_rate(
983 expander_pg1
.hw_link_rate
& MPI3_SAS_HWRATE_MIN_RATE_MASK
);
984 phy
->maximum_linkrate_hw
= mpi3mr_convert_phy_link_rate(
985 expander_pg1
.hw_link_rate
>> 4);
986 phy
->minimum_linkrate
= mpi3mr_convert_phy_link_rate(
987 expander_pg1
.programmed_link_rate
& MPI3_SAS_PRATE_MIN_RATE_MASK
);
988 phy
->maximum_linkrate
= mpi3mr_convert_phy_link_rate(
989 expander_pg1
.programmed_link_rate
>> 4);
990 phy
->hostdata
= mr_sas_phy
->hba_port
;
992 if ((sas_phy_add(phy
))) {
993 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
994 __FILE__
, __LINE__
, __func__
);
998 if ((mrioc
->logging_level
& MPI3_DEBUG_TRANSPORT_INFO
))
1000 "add: handle(0x%04x), sas_address(0x%016llx)\n"
1001 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
1002 mr_sas_phy
->handle
, (unsigned long long)
1003 mr_sas_phy
->identify
.sas_address
,
1004 mr_sas_phy
->attached_handle
,
1005 (unsigned long long)
1006 mr_sas_phy
->remote_identify
.sas_address
);
1007 mr_sas_phy
->phy
= phy
;
1012 * mpi3mr_alloc_hba_port - alloc hba port object
1013 * @mrioc: Adapter instance reference
1014 * @port_id: Port number
1016 * Alloc memory for hba port object.
1018 static struct mpi3mr_hba_port
*
1019 mpi3mr_alloc_hba_port(struct mpi3mr_ioc
*mrioc
, u16 port_id
)
1021 struct mpi3mr_hba_port
*hba_port
;
1023 hba_port
= kzalloc(sizeof(struct mpi3mr_hba_port
),
1027 hba_port
->port_id
= port_id
;
1028 ioc_info(mrioc
, "hba_port entry: %p, port: %d is added to hba_port list\n",
1029 hba_port
, hba_port
->port_id
);
1030 if (mrioc
->reset_in_progress
||
1031 mrioc
->pci_err_recovery
)
1032 hba_port
->flags
= MPI3MR_HBA_PORT_FLAG_NEW
;
1033 list_add_tail(&hba_port
->list
, &mrioc
->hba_port_table_list
);
1038 * mpi3mr_get_hba_port_by_id - find hba port by id
1039 * @mrioc: Adapter instance reference
1040 * @port_id: Port ID to search
1042 * Return: mpi3mr_hba_port reference for the matched port
1045 struct mpi3mr_hba_port
*mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc
*mrioc
,
1048 struct mpi3mr_hba_port
*port
, *port_next
;
1050 list_for_each_entry_safe(port
, port_next
,
1051 &mrioc
->hba_port_table_list
, list
) {
1052 if (port
->port_id
!= port_id
)
1054 if (port
->flags
& MPI3MR_HBA_PORT_FLAG_DIRTY
)
1063 * mpi3mr_update_links - refreshing SAS phy link changes
1064 * @mrioc: Adapter instance reference
1065 * @sas_address_parent: SAS address of parent expander or host
1066 * @handle: Firmware device handle of attached device
1067 * @phy_number: Phy number
1068 * @link_rate: New link rate
1069 * @hba_port: HBA port entry
1073 void mpi3mr_update_links(struct mpi3mr_ioc
*mrioc
,
1074 u64 sas_address_parent
, u16 handle
, u8 phy_number
, u8 link_rate
,
1075 struct mpi3mr_hba_port
*hba_port
)
1077 unsigned long flags
;
1078 struct mpi3mr_sas_node
*mr_sas_node
;
1079 struct mpi3mr_sas_phy
*mr_sas_phy
;
1081 if (mrioc
->reset_in_progress
|| mrioc
->pci_err_recovery
)
1084 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
1085 mr_sas_node
= __mpi3mr_sas_node_find_by_sas_address(mrioc
,
1086 sas_address_parent
, hba_port
);
1088 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
1092 mr_sas_phy
= &mr_sas_node
->phy
[phy_number
];
1093 mr_sas_phy
->attached_handle
= handle
;
1094 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
1095 if (handle
&& (link_rate
>= MPI3_SAS_NEG_LINK_RATE_1_5
)) {
1096 mpi3mr_set_identify(mrioc
, handle
,
1097 &mr_sas_phy
->remote_identify
);
1098 mpi3mr_add_phy_to_an_existing_port(mrioc
, mr_sas_node
,
1099 mr_sas_phy
, mr_sas_phy
->remote_identify
.sas_address
,
1102 memset(&mr_sas_phy
->remote_identify
, 0, sizeof(struct
1105 if (mr_sas_phy
->phy
)
1106 mr_sas_phy
->phy
->negotiated_linkrate
=
1107 mpi3mr_convert_phy_link_rate(link_rate
);
1109 if ((mrioc
->logging_level
& MPI3_DEBUG_TRANSPORT_INFO
))
1110 dev_info(&mr_sas_phy
->phy
->dev
,
1111 "refresh: parent sas_address(0x%016llx),\n"
1112 "\tlink_rate(0x%02x), phy(%d)\n"
1113 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
1114 (unsigned long long)sas_address_parent
,
1115 link_rate
, phy_number
, handle
, (unsigned long long)
1116 mr_sas_phy
->remote_identify
.sas_address
);
1120 * mpi3mr_sas_host_refresh - refreshing sas host object contents
1121 * @mrioc: Adapter instance reference
1123 * This function refreshes the controllers phy information and
1124 * updates the SAS transport layer with updated information,
1125 * this is executed for each device addition or device info
1130 void mpi3mr_sas_host_refresh(struct mpi3mr_ioc
*mrioc
)
1134 u16 sz
, port_id
, attached_handle
;
1135 struct mpi3_sas_io_unit_page0
*sas_io_unit_pg0
= NULL
;
1137 dprint_transport_info(mrioc
,
1138 "updating handles for sas_host(0x%016llx)\n",
1139 (unsigned long long)mrioc
->sas_hba
.sas_address
);
1141 sz
= offsetof(struct mpi3_sas_io_unit_page0
, phy_data
) +
1142 (mrioc
->sas_hba
.num_phys
*
1143 sizeof(struct mpi3_sas_io_unit0_phy_data
));
1144 sas_io_unit_pg0
= kzalloc(sz
, GFP_KERNEL
);
1145 if (!sas_io_unit_pg0
)
1147 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc
, sas_io_unit_pg0
, sz
)) {
1148 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1149 __FILE__
, __LINE__
, __func__
);
1153 mrioc
->sas_hba
.handle
= 0;
1154 for (i
= 0; i
< mrioc
->sas_hba
.num_phys
; i
++) {
1155 if (sas_io_unit_pg0
->phy_data
[i
].phy_flags
&
1156 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY
|
1157 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY
))
1160 sas_io_unit_pg0
->phy_data
[i
].negotiated_link_rate
>> 4;
1161 if (!mrioc
->sas_hba
.handle
)
1162 mrioc
->sas_hba
.handle
= le16_to_cpu(
1163 sas_io_unit_pg0
->phy_data
[i
].controller_dev_handle
);
1164 port_id
= sas_io_unit_pg0
->phy_data
[i
].io_unit_port
;
1165 if (!(mpi3mr_get_hba_port_by_id(mrioc
, port_id
)))
1166 if (!mpi3mr_alloc_hba_port(mrioc
, port_id
))
1169 mrioc
->sas_hba
.phy
[i
].handle
= mrioc
->sas_hba
.handle
;
1170 attached_handle
= le16_to_cpu(
1171 sas_io_unit_pg0
->phy_data
[i
].attached_dev_handle
);
1172 if (attached_handle
&& link_rate
< MPI3_SAS_NEG_LINK_RATE_1_5
)
1173 link_rate
= MPI3_SAS_NEG_LINK_RATE_1_5
;
1174 mrioc
->sas_hba
.phy
[i
].hba_port
=
1175 mpi3mr_get_hba_port_by_id(mrioc
, port_id
);
1176 mpi3mr_update_links(mrioc
, mrioc
->sas_hba
.sas_address
,
1177 attached_handle
, i
, link_rate
,
1178 mrioc
->sas_hba
.phy
[i
].hba_port
);
1181 kfree(sas_io_unit_pg0
);
1185 * mpi3mr_sas_host_add - create sas host object
1186 * @mrioc: Adapter instance reference
1188 * This function creates the controllers phy information and
1189 * updates the SAS transport layer with updated information,
1190 * this is executed for first device addition or device info
1195 void mpi3mr_sas_host_add(struct mpi3mr_ioc
*mrioc
)
1198 u16 sz
, num_phys
= 1, port_id
, ioc_status
;
1199 struct mpi3_sas_io_unit_page0
*sas_io_unit_pg0
= NULL
;
1200 struct mpi3_sas_phy_page0 phy_pg0
;
1201 struct mpi3_device_page0 dev_pg0
;
1202 struct mpi3_enclosure_page0 encl_pg0
;
1203 struct mpi3_device0_sas_sata_format
*sasinf
;
1205 sz
= offsetof(struct mpi3_sas_io_unit_page0
, phy_data
) +
1206 (num_phys
* sizeof(struct mpi3_sas_io_unit0_phy_data
));
1207 sas_io_unit_pg0
= kzalloc(sz
, GFP_KERNEL
);
1208 if (!sas_io_unit_pg0
)
1211 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc
, sas_io_unit_pg0
, sz
)) {
1212 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1213 __FILE__
, __LINE__
, __func__
);
1216 num_phys
= sas_io_unit_pg0
->num_phys
;
1217 kfree(sas_io_unit_pg0
);
1219 mrioc
->sas_hba
.host_node
= 1;
1220 INIT_LIST_HEAD(&mrioc
->sas_hba
.sas_port_list
);
1221 mrioc
->sas_hba
.parent_dev
= &mrioc
->shost
->shost_gendev
;
1222 mrioc
->sas_hba
.phy
= kcalloc(num_phys
,
1223 sizeof(struct mpi3mr_sas_phy
), GFP_KERNEL
);
1224 if (!mrioc
->sas_hba
.phy
)
1227 mrioc
->sas_hba
.num_phys
= num_phys
;
1229 sz
= offsetof(struct mpi3_sas_io_unit_page0
, phy_data
) +
1230 (num_phys
* sizeof(struct mpi3_sas_io_unit0_phy_data
));
1231 sas_io_unit_pg0
= kzalloc(sz
, GFP_KERNEL
);
1232 if (!sas_io_unit_pg0
)
1235 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc
, sas_io_unit_pg0
, sz
)) {
1236 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1237 __FILE__
, __LINE__
, __func__
);
1241 mrioc
->sas_hba
.handle
= 0;
1242 for (i
= 0; i
< mrioc
->sas_hba
.num_phys
; i
++) {
1243 if (sas_io_unit_pg0
->phy_data
[i
].phy_flags
&
1244 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY
|
1245 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY
))
1247 if (mpi3mr_cfg_get_sas_phy_pg0(mrioc
, &ioc_status
, &phy_pg0
,
1248 sizeof(struct mpi3_sas_phy_page0
),
1249 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER
, i
)) {
1250 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1251 __FILE__
, __LINE__
, __func__
);
1254 if (ioc_status
!= MPI3_IOCSTATUS_SUCCESS
) {
1255 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1256 __FILE__
, __LINE__
, __func__
);
1260 if (!mrioc
->sas_hba
.handle
)
1261 mrioc
->sas_hba
.handle
= le16_to_cpu(
1262 sas_io_unit_pg0
->phy_data
[i
].controller_dev_handle
);
1263 port_id
= sas_io_unit_pg0
->phy_data
[i
].io_unit_port
;
1265 if (!(mpi3mr_get_hba_port_by_id(mrioc
, port_id
)))
1266 if (!mpi3mr_alloc_hba_port(mrioc
, port_id
))
1269 mrioc
->sas_hba
.phy
[i
].handle
= mrioc
->sas_hba
.handle
;
1270 mrioc
->sas_hba
.phy
[i
].phy_id
= i
;
1271 mrioc
->sas_hba
.phy
[i
].hba_port
=
1272 mpi3mr_get_hba_port_by_id(mrioc
, port_id
);
1273 mpi3mr_add_host_phy(mrioc
, &mrioc
->sas_hba
.phy
[i
],
1274 phy_pg0
, mrioc
->sas_hba
.parent_dev
);
1276 if ((mpi3mr_cfg_get_dev_pg0(mrioc
, &ioc_status
, &dev_pg0
,
1277 sizeof(dev_pg0
), MPI3_DEVICE_PGAD_FORM_HANDLE
,
1278 mrioc
->sas_hba
.handle
))) {
1279 ioc_err(mrioc
, "%s: device page0 read failed\n", __func__
);
1282 if (ioc_status
!= MPI3_IOCSTATUS_SUCCESS
) {
1283 ioc_err(mrioc
, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
1284 mrioc
->sas_hba
.handle
, ioc_status
, __FILE__
, __LINE__
,
1288 mrioc
->sas_hba
.enclosure_handle
=
1289 le16_to_cpu(dev_pg0
.enclosure_handle
);
1290 sasinf
= &dev_pg0
.device_specific
.sas_sata_format
;
1291 mrioc
->sas_hba
.sas_address
=
1292 le64_to_cpu(sasinf
->sas_address
);
1294 "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
1295 mrioc
->sas_hba
.handle
,
1296 (unsigned long long) mrioc
->sas_hba
.sas_address
,
1297 mrioc
->sas_hba
.num_phys
);
1299 if (mrioc
->sas_hba
.enclosure_handle
) {
1300 if (!(mpi3mr_cfg_get_enclosure_pg0(mrioc
, &ioc_status
,
1301 &encl_pg0
, sizeof(encl_pg0
),
1302 MPI3_ENCLOS_PGAD_FORM_HANDLE
,
1303 mrioc
->sas_hba
.enclosure_handle
)) &&
1304 (ioc_status
== MPI3_IOCSTATUS_SUCCESS
))
1305 mrioc
->sas_hba
.enclosure_logical_id
=
1306 le64_to_cpu(encl_pg0
.enclosure_logical_id
);
1310 kfree(sas_io_unit_pg0
);
1314 * mpi3mr_sas_port_add - Expose the SAS device to the SAS TL
1315 * @mrioc: Adapter instance reference
1316 * @handle: Firmware device handle of the attached device
1317 * @sas_address_parent: sas address of parent expander or host
1318 * @hba_port: HBA port entry
1320 * This function creates a new sas port object for the given end
1321 * device matching sas address and hba_port and adds it to the
1322 * sas_node's sas_port_list and expose the attached sas device
1323 * to the SAS transport layer through sas_rphy_add.
1325 * Returns a valid mpi3mr_sas_port reference or NULL.
1327 static struct mpi3mr_sas_port
*mpi3mr_sas_port_add(struct mpi3mr_ioc
*mrioc
,
1328 u16 handle
, u64 sas_address_parent
, struct mpi3mr_hba_port
*hba_port
)
1330 struct mpi3mr_sas_phy
*mr_sas_phy
, *next
;
1331 struct mpi3mr_sas_port
*mr_sas_port
;
1332 unsigned long flags
;
1333 struct mpi3mr_sas_node
*mr_sas_node
;
1334 struct sas_rphy
*rphy
;
1335 struct mpi3mr_tgt_dev
*tgtdev
= NULL
;
1337 struct sas_port
*port
;
1340 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1341 __FILE__
, __LINE__
, __func__
);
1345 mr_sas_port
= kzalloc(sizeof(struct mpi3mr_sas_port
), GFP_KERNEL
);
1349 INIT_LIST_HEAD(&mr_sas_port
->port_list
);
1350 INIT_LIST_HEAD(&mr_sas_port
->phy_list
);
1351 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
1352 mr_sas_node
= __mpi3mr_sas_node_find_by_sas_address(mrioc
,
1353 sas_address_parent
, hba_port
);
1354 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
1357 ioc_err(mrioc
, "%s:could not find parent sas_address(0x%016llx)!\n",
1358 __func__
, (unsigned long long)sas_address_parent
);
1362 if ((mpi3mr_set_identify(mrioc
, handle
,
1363 &mr_sas_port
->remote_identify
))) {
1364 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1365 __FILE__
, __LINE__
, __func__
);
1369 if (mr_sas_port
->remote_identify
.device_type
== SAS_PHY_UNUSED
) {
1370 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1371 __FILE__
, __LINE__
, __func__
);
1375 mr_sas_port
->hba_port
= hba_port
;
1376 mpi3mr_sas_port_sanity_check(mrioc
, mr_sas_node
,
1377 mr_sas_port
->remote_identify
.sas_address
, hba_port
);
1379 if (mr_sas_node
->host_node
&& mr_sas_node
->num_phys
>=
1380 sizeof(mr_sas_port
->phy_mask
) * 8)
1381 ioc_info(mrioc
, "max port count %u could be too high\n",
1382 mr_sas_node
->num_phys
);
1384 for (i
= 0; i
< mr_sas_node
->num_phys
; i
++) {
1385 if ((mr_sas_node
->phy
[i
].remote_identify
.sas_address
!=
1386 mr_sas_port
->remote_identify
.sas_address
) ||
1387 (mr_sas_node
->phy
[i
].hba_port
!= hba_port
))
1390 if (mr_sas_node
->host_node
&& (i
>= sizeof(mr_sas_port
->phy_mask
) * 8)) {
1391 ioc_warn(mrioc
, "skipping port %u, max allowed value is %zu\n",
1392 i
, sizeof(mr_sas_port
->phy_mask
) * 8);
1395 list_add_tail(&mr_sas_node
->phy
[i
].port_siblings
,
1396 &mr_sas_port
->phy_list
);
1397 mr_sas_port
->num_phys
++;
1398 if (mr_sas_node
->host_node
)
1399 mr_sas_port
->phy_mask
|= (1 << i
);
1402 if (!mr_sas_port
->num_phys
) {
1403 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1404 __FILE__
, __LINE__
, __func__
);
1408 if (mr_sas_node
->host_node
)
1409 mr_sas_port
->lowest_phy
= ffs(mr_sas_port
->phy_mask
) - 1;
1411 if (mr_sas_port
->remote_identify
.device_type
== SAS_END_DEVICE
) {
1412 tgtdev
= mpi3mr_get_tgtdev_by_addr(mrioc
,
1413 mr_sas_port
->remote_identify
.sas_address
,
1414 mr_sas_port
->hba_port
);
1417 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1418 __FILE__
, __LINE__
, __func__
);
1421 tgtdev
->dev_spec
.sas_sata_inf
.pend_sas_rphy_add
= 1;
1424 if (!mr_sas_node
->parent_dev
) {
1425 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1426 __FILE__
, __LINE__
, __func__
);
1430 port
= sas_port_alloc_num(mr_sas_node
->parent_dev
);
1431 if ((sas_port_add(port
))) {
1432 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1433 __FILE__
, __LINE__
, __func__
);
1437 list_for_each_entry(mr_sas_phy
, &mr_sas_port
->phy_list
,
1439 if ((mrioc
->logging_level
& MPI3_DEBUG_TRANSPORT_INFO
))
1440 dev_info(&port
->dev
,
1441 "add: handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
1442 handle
, (unsigned long long)
1443 mr_sas_port
->remote_identify
.sas_address
,
1444 mr_sas_phy
->phy_id
);
1445 sas_port_add_phy(port
, mr_sas_phy
->phy
);
1446 mr_sas_phy
->phy_belongs_to_port
= 1;
1447 mr_sas_phy
->hba_port
= hba_port
;
1450 mr_sas_port
->port
= port
;
1451 if (mr_sas_port
->remote_identify
.device_type
== SAS_END_DEVICE
) {
1452 rphy
= sas_end_device_alloc(port
);
1453 tgtdev
->dev_spec
.sas_sata_inf
.rphy
= rphy
;
1455 rphy
= sas_expander_alloc(port
,
1456 mr_sas_port
->remote_identify
.device_type
);
1458 rphy
->identify
= mr_sas_port
->remote_identify
;
1460 if (mrioc
->current_event
)
1461 mrioc
->current_event
->pending_at_sml
= 1;
1463 if ((sas_rphy_add(rphy
))) {
1464 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1465 __FILE__
, __LINE__
, __func__
);
1467 if (mr_sas_port
->remote_identify
.device_type
== SAS_END_DEVICE
) {
1468 tgtdev
->dev_spec
.sas_sata_inf
.pend_sas_rphy_add
= 0;
1469 tgtdev
->dev_spec
.sas_sata_inf
.sas_transport_attached
= 1;
1470 mpi3mr_tgtdev_put(tgtdev
);
1473 dev_info(&rphy
->dev
,
1474 "%s: added: handle(0x%04x), sas_address(0x%016llx)\n",
1475 __func__
, handle
, (unsigned long long)
1476 mr_sas_port
->remote_identify
.sas_address
);
1478 mr_sas_port
->rphy
= rphy
;
1479 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
1480 list_add_tail(&mr_sas_port
->port_list
, &mr_sas_node
->sas_port_list
);
1481 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
1483 if (mrioc
->current_event
) {
1484 mrioc
->current_event
->pending_at_sml
= 0;
1485 if (mrioc
->current_event
->discard
)
1486 mpi3mr_print_device_event_notice(mrioc
, true);
1489 /* fill in report manufacture */
1490 if (mr_sas_port
->remote_identify
.device_type
==
1491 SAS_EDGE_EXPANDER_DEVICE
||
1492 mr_sas_port
->remote_identify
.device_type
==
1493 SAS_FANOUT_EXPANDER_DEVICE
)
1494 mpi3mr_report_manufacture(mrioc
,
1495 mr_sas_port
->remote_identify
.sas_address
,
1496 rphy_to_expander_device(rphy
), hba_port
->port_id
);
1501 list_for_each_entry_safe(mr_sas_phy
, next
, &mr_sas_port
->phy_list
,
1503 list_del(&mr_sas_phy
->port_siblings
);
1509 * mpi3mr_sas_port_remove - remove port from the list
1510 * @mrioc: Adapter instance reference
1511 * @sas_address: SAS address of attached device
1512 * @sas_address_parent: SAS address of parent expander or host
1513 * @hba_port: HBA port entry
1515 * Removing object and freeing associated memory from the
1520 static void mpi3mr_sas_port_remove(struct mpi3mr_ioc
*mrioc
, u64 sas_address
,
1521 u64 sas_address_parent
, struct mpi3mr_hba_port
*hba_port
)
1524 unsigned long flags
;
1525 struct mpi3mr_sas_port
*mr_sas_port
, *next
;
1526 struct mpi3mr_sas_node
*mr_sas_node
;
1528 struct mpi3mr_sas_phy
*mr_sas_phy
, *next_phy
;
1529 struct mpi3mr_hba_port
*srch_port
, *hba_port_next
= NULL
;
1534 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
1535 mr_sas_node
= __mpi3mr_sas_node_find_by_sas_address(mrioc
,
1536 sas_address_parent
, hba_port
);
1538 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
1541 list_for_each_entry_safe(mr_sas_port
, next
, &mr_sas_node
->sas_port_list
,
1543 if (mr_sas_port
->remote_identify
.sas_address
!= sas_address
)
1545 if (mr_sas_port
->hba_port
!= hba_port
)
1548 list_del(&mr_sas_port
->port_list
);
1554 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
1558 if (mr_sas_node
->host_node
) {
1559 list_for_each_entry_safe(srch_port
, hba_port_next
,
1560 &mrioc
->hba_port_table_list
, list
) {
1561 if (srch_port
!= hba_port
)
1564 "removing hba_port entry: %p port: %d from hba_port list\n",
1565 srch_port
, srch_port
->port_id
);
1566 list_del(&hba_port
->list
);
1572 for (i
= 0; i
< mr_sas_node
->num_phys
; i
++) {
1573 if (mr_sas_node
->phy
[i
].remote_identify
.sas_address
==
1575 memset(&mr_sas_node
->phy
[i
].remote_identify
, 0,
1576 sizeof(struct sas_identify
));
1579 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
1581 if (mrioc
->current_event
)
1582 mrioc
->current_event
->pending_at_sml
= 1;
1584 list_for_each_entry_safe(mr_sas_phy
, next_phy
,
1585 &mr_sas_port
->phy_list
, port_siblings
) {
1586 if ((!mrioc
->stop_drv_processing
) &&
1587 (mrioc
->logging_level
& MPI3_DEBUG_TRANSPORT_INFO
))
1588 dev_info(&mr_sas_port
->port
->dev
,
1589 "remove: sas_address(0x%016llx), phy(%d)\n",
1590 (unsigned long long)
1591 mr_sas_port
->remote_identify
.sas_address
,
1592 mr_sas_phy
->phy_id
);
1593 mr_sas_phy
->phy_belongs_to_port
= 0;
1594 if (!mrioc
->stop_drv_processing
)
1595 sas_port_delete_phy(mr_sas_port
->port
,
1597 list_del(&mr_sas_phy
->port_siblings
);
1599 if (!mrioc
->stop_drv_processing
)
1600 sas_port_delete(mr_sas_port
->port
);
1601 ioc_info(mrioc
, "%s: removed sas_address(0x%016llx)\n",
1602 __func__
, (unsigned long long)sas_address
);
1604 if (mrioc
->current_event
) {
1605 mrioc
->current_event
->pending_at_sml
= 0;
1606 if (mrioc
->current_event
->discard
)
1607 mpi3mr_print_device_event_notice(mrioc
, false);
1614 * struct host_port - host port details
1615 * @sas_address: SAS Address of the attached device
1616 * @phy_mask: phy mask of host port
1617 * @handle: Device Handle of attached device
1618 * @iounit_port_id: port ID
1619 * @used: host port is already matched with sas port from sas_port_list
1620 * @lowest_phy: lowest phy ID of host port
1632 * mpi3mr_update_mr_sas_port - update sas port objects during reset
1633 * @mrioc: Adapter instance reference
1634 * @h_port: host_port object
1635 * @mr_sas_port: sas_port objects which needs to be updated
1637 * Update the port ID of sas port object. Also add the phys if new phys got
1638 * added to current sas port and remove the phys if some phys are moved
1639 * out of the current sas port.
1644 mpi3mr_update_mr_sas_port(struct mpi3mr_ioc
*mrioc
, struct host_port
*h_port
,
1645 struct mpi3mr_sas_port
*mr_sas_port
)
1647 struct mpi3mr_sas_phy
*mr_sas_phy
;
1649 u64 phys_to_be_added
, phys_to_be_removed
;
1653 mr_sas_port
->marked_responding
= 1;
1655 dev_info(&mr_sas_port
->port
->dev
,
1656 "sas_address(0x%016llx), old: port_id %d phy_mask 0x%llx, new: port_id %d phy_mask:0x%llx\n",
1657 mr_sas_port
->remote_identify
.sas_address
,
1658 mr_sas_port
->hba_port
->port_id
, mr_sas_port
->phy_mask
,
1659 h_port
->iounit_port_id
, h_port
->phy_mask
);
1661 mr_sas_port
->hba_port
->port_id
= h_port
->iounit_port_id
;
1662 mr_sas_port
->hba_port
->flags
&= ~MPI3MR_HBA_PORT_FLAG_DIRTY
;
1664 /* Get the newly added phys bit map & removed phys bit map */
1665 phy_mask_xor
= mr_sas_port
->phy_mask
^ h_port
->phy_mask
;
1666 phys_to_be_added
= h_port
->phy_mask
& phy_mask_xor
;
1667 phys_to_be_removed
= mr_sas_port
->phy_mask
& phy_mask_xor
;
1670 * Register these new phys to current mr_sas_port's port.
1671 * if these phys are previously registered with another port
1672 * then delete these phys from that port first.
1674 for_each_set_bit(i
, (ulong
*) &phys_to_be_added
, BITS_PER_TYPE(u64
)) {
1675 mr_sas_phy
= &mrioc
->sas_hba
.phy
[i
];
1676 if (mr_sas_phy
->phy_belongs_to_port
)
1677 mpi3mr_del_phy_from_an_existing_port(mrioc
,
1678 &mrioc
->sas_hba
, mr_sas_phy
);
1679 mpi3mr_add_phy_to_an_existing_port(mrioc
,
1680 &mrioc
->sas_hba
, mr_sas_phy
,
1681 mr_sas_port
->remote_identify
.sas_address
,
1682 mr_sas_port
->hba_port
);
1685 /* Delete the phys which are not part of current mr_sas_port's port. */
1686 for_each_set_bit(i
, (ulong
*) &phys_to_be_removed
, BITS_PER_TYPE(u64
)) {
1687 mr_sas_phy
= &mrioc
->sas_hba
.phy
[i
];
1688 if (mr_sas_phy
->phy_belongs_to_port
)
1689 mpi3mr_del_phy_from_an_existing_port(mrioc
,
1690 &mrioc
->sas_hba
, mr_sas_phy
);
1695 * mpi3mr_refresh_sas_ports - update host's sas ports during reset
1696 * @mrioc: Adapter instance reference
1698 * Update the host's sas ports during reset by checking whether
1699 * sas ports are still intact or not. Add/remove phys if any hba
1700 * phys are (moved in)/(moved out) of sas port. Also update
1701 * io_unit_port if it got changed during reset.
1706 mpi3mr_refresh_sas_ports(struct mpi3mr_ioc
*mrioc
)
1708 struct host_port
*h_port
= NULL
;
1709 int i
, j
, found
, host_port_count
= 0, port_idx
;
1710 u16 sz
, attached_handle
, ioc_status
;
1711 struct mpi3_sas_io_unit_page0
*sas_io_unit_pg0
= NULL
;
1712 struct mpi3_device_page0 dev_pg0
;
1713 struct mpi3_device0_sas_sata_format
*sasinf
;
1714 struct mpi3mr_sas_port
*mr_sas_port
;
1716 sz
= offsetof(struct mpi3_sas_io_unit_page0
, phy_data
) +
1717 (mrioc
->sas_hba
.num_phys
*
1718 sizeof(struct mpi3_sas_io_unit0_phy_data
));
1719 sas_io_unit_pg0
= kzalloc(sz
, GFP_KERNEL
);
1720 if (!sas_io_unit_pg0
)
1722 h_port
= kcalloc(64, sizeof(struct host_port
), GFP_KERNEL
);
1726 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc
, sas_io_unit_pg0
, sz
)) {
1727 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
1728 __FILE__
, __LINE__
, __func__
);
1732 /* Create a new expander port table */
1733 for (i
= 0; i
< mrioc
->sas_hba
.num_phys
; i
++) {
1734 attached_handle
= le16_to_cpu(
1735 sas_io_unit_pg0
->phy_data
[i
].attached_dev_handle
);
1736 if (!attached_handle
)
1739 for (j
= 0; j
< host_port_count
; j
++) {
1740 if (h_port
[j
].handle
== attached_handle
) {
1741 h_port
[j
].phy_mask
|= (1 << i
);
1748 if ((mpi3mr_cfg_get_dev_pg0(mrioc
, &ioc_status
, &dev_pg0
,
1749 sizeof(dev_pg0
), MPI3_DEVICE_PGAD_FORM_HANDLE
,
1750 attached_handle
))) {
1752 "failed to read dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1753 attached_handle
, __FILE__
, __LINE__
, __func__
);
1756 if (ioc_status
!= MPI3_IOCSTATUS_SUCCESS
) {
1758 "ioc_status(0x%x) while reading dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1759 ioc_status
, attached_handle
,
1760 __FILE__
, __LINE__
, __func__
);
1763 sasinf
= &dev_pg0
.device_specific
.sas_sata_format
;
1765 port_idx
= host_port_count
;
1766 h_port
[port_idx
].sas_address
= le64_to_cpu(sasinf
->sas_address
);
1767 h_port
[port_idx
].handle
= attached_handle
;
1768 h_port
[port_idx
].phy_mask
= (1 << i
);
1769 h_port
[port_idx
].iounit_port_id
= sas_io_unit_pg0
->phy_data
[i
].io_unit_port
;
1770 h_port
[port_idx
].lowest_phy
= sasinf
->phy_num
;
1771 h_port
[port_idx
].used
= 0;
1775 if (!host_port_count
)
1778 if (mrioc
->logging_level
& MPI3_DEBUG_RESET
) {
1779 ioc_info(mrioc
, "Host port details before reset\n");
1780 list_for_each_entry(mr_sas_port
, &mrioc
->sas_hba
.sas_port_list
,
1783 "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1784 mr_sas_port
->hba_port
->port_id
,
1785 mr_sas_port
->remote_identify
.sas_address
,
1786 mr_sas_port
->phy_mask
, mr_sas_port
->lowest_phy
);
1789 ioc_info(mrioc
, "Host port details after reset\n");
1790 for (i
= 0; i
< host_port_count
; i
++) {
1792 "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1793 h_port
[i
].iounit_port_id
, h_port
[i
].sas_address
,
1794 h_port
[i
].phy_mask
, h_port
[i
].lowest_phy
);
1798 /* mark all host sas port entries as dirty */
1799 list_for_each_entry(mr_sas_port
, &mrioc
->sas_hba
.sas_port_list
,
1801 mr_sas_port
->marked_responding
= 0;
1802 mr_sas_port
->hba_port
->flags
|= MPI3MR_HBA_PORT_FLAG_DIRTY
;
1805 /* First check for matching lowest phy */
1806 for (i
= 0; i
< host_port_count
; i
++) {
1808 list_for_each_entry(mr_sas_port
, &mrioc
->sas_hba
.sas_port_list
,
1810 if (mr_sas_port
->marked_responding
)
1812 if (h_port
[i
].sas_address
!= mr_sas_port
->remote_identify
.sas_address
)
1814 if (h_port
[i
].lowest_phy
== mr_sas_port
->lowest_phy
) {
1815 mpi3mr_update_mr_sas_port(mrioc
, &h_port
[i
], mr_sas_port
);
1821 /* In case if lowest phy is got enabled or disabled during reset */
1822 for (i
= 0; i
< host_port_count
; i
++) {
1826 list_for_each_entry(mr_sas_port
, &mrioc
->sas_hba
.sas_port_list
,
1828 if (mr_sas_port
->marked_responding
)
1830 if (h_port
[i
].sas_address
!= mr_sas_port
->remote_identify
.sas_address
)
1832 if (h_port
[i
].phy_mask
& mr_sas_port
->phy_mask
) {
1833 mpi3mr_update_mr_sas_port(mrioc
, &h_port
[i
], mr_sas_port
);
1839 /* In case if expander cable is removed & connected to another HBA port during reset */
1840 for (i
= 0; i
< host_port_count
; i
++) {
1844 list_for_each_entry(mr_sas_port
, &mrioc
->sas_hba
.sas_port_list
,
1846 if (mr_sas_port
->marked_responding
)
1848 if (h_port
[i
].sas_address
!= mr_sas_port
->remote_identify
.sas_address
)
1850 mpi3mr_update_mr_sas_port(mrioc
, &h_port
[i
], mr_sas_port
);
1856 kfree(sas_io_unit_pg0
);
1860 * mpi3mr_refresh_expanders - Refresh expander device exposure
1861 * @mrioc: Adapter instance reference
1863 * This is executed post controller reset to identify any
1864 * missing expander devices during reset and remove from the upper layers
1865 * or expose any newly detected expander device to the upper layers.
1870 mpi3mr_refresh_expanders(struct mpi3mr_ioc
*mrioc
)
1872 struct mpi3mr_sas_node
*sas_expander
, *sas_expander_next
;
1873 struct mpi3_sas_expander_page0 expander_pg0
;
1874 u16 ioc_status
, handle
;
1877 unsigned long flags
;
1878 struct mpi3mr_hba_port
*hba_port
;
1880 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
1881 list_for_each_entry(sas_expander
, &mrioc
->sas_expander_list
, list
) {
1882 sas_expander
->non_responding
= 1;
1884 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
1886 sas_expander
= NULL
;
1890 /* Search for responding expander devices and add them if they are newly got added */
1892 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc
, &ioc_status
, &expander_pg0
,
1893 sizeof(struct mpi3_sas_expander_page0
),
1894 MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE
, handle
))) {
1896 "failed to read exp pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1897 handle
, __FILE__
, __LINE__
, __func__
);
1901 if (ioc_status
!= MPI3_IOCSTATUS_SUCCESS
) {
1903 "ioc_status(0x%x) while reading exp pg0 for handle:(0x%04x), %s:%d/%s()!\n",
1904 ioc_status
, handle
, __FILE__
, __LINE__
, __func__
);
1908 handle
= le16_to_cpu(expander_pg0
.dev_handle
);
1909 sas_address
= le64_to_cpu(expander_pg0
.sas_address
);
1910 hba_port
= mpi3mr_get_hba_port_by_id(mrioc
, expander_pg0
.io_unit_port
);
1913 mpi3mr_sas_host_refresh(mrioc
);
1914 mpi3mr_expander_add(mrioc
, handle
);
1918 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
1920 mpi3mr_expander_find_by_sas_address(mrioc
,
1921 sas_address
, hba_port
);
1922 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
1924 if (!sas_expander
) {
1925 mpi3mr_sas_host_refresh(mrioc
);
1926 mpi3mr_expander_add(mrioc
, handle
);
1930 sas_expander
->non_responding
= 0;
1931 if (sas_expander
->handle
== handle
)
1934 sas_expander
->handle
= handle
;
1935 for (i
= 0 ; i
< sas_expander
->num_phys
; i
++)
1936 sas_expander
->phy
[i
].handle
= handle
;
1940 * Delete non responding expander devices and the corresponding
1941 * hba_port if the non responding expander device's parent device
1944 sas_expander
= NULL
;
1945 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
1946 list_for_each_entry_safe_reverse(sas_expander
, sas_expander_next
,
1947 &mrioc
->sas_expander_list
, list
) {
1948 if (sas_expander
->non_responding
) {
1949 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
1950 mpi3mr_expander_node_remove(mrioc
, sas_expander
);
1951 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
1954 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
1958 * mpi3mr_expander_node_add - insert an expander to the list.
1959 * @mrioc: Adapter instance reference
1960 * @sas_expander: Expander sas node
1961 * Context: This function will acquire sas_node_lock.
1963 * Adding new object to the ioc->sas_expander_list.
1967 static void mpi3mr_expander_node_add(struct mpi3mr_ioc
*mrioc
,
1968 struct mpi3mr_sas_node
*sas_expander
)
1970 unsigned long flags
;
1972 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
1973 list_add_tail(&sas_expander
->list
, &mrioc
->sas_expander_list
);
1974 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
1978 * mpi3mr_expander_add - Create expander object
1979 * @mrioc: Adapter instance reference
1980 * @handle: Expander firmware device handle
1982 * This function creating expander object, stored in
1983 * sas_expander_list and expose it to the SAS transport
1986 * Return: 0 for success, non-zero for failure.
1988 int mpi3mr_expander_add(struct mpi3mr_ioc
*mrioc
, u16 handle
)
1990 struct mpi3mr_sas_node
*sas_expander
;
1991 struct mpi3mr_enclosure_node
*enclosure_dev
;
1992 struct mpi3_sas_expander_page0 expander_pg0
;
1993 struct mpi3_sas_expander_page1 expander_pg1
;
1994 u16 ioc_status
, parent_handle
, temp_handle
;
1995 u64 sas_address
, sas_address_parent
= 0;
1997 unsigned long flags
;
1998 u8 port_id
, link_rate
;
1999 struct mpi3mr_sas_port
*mr_sas_port
= NULL
;
2000 struct mpi3mr_hba_port
*hba_port
;
2007 if (mrioc
->reset_in_progress
|| mrioc
->pci_err_recovery
)
2010 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc
, &ioc_status
, &expander_pg0
,
2011 sizeof(expander_pg0
), MPI3_SAS_EXPAND_PGAD_FORM_HANDLE
, handle
))) {
2012 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2013 __FILE__
, __LINE__
, __func__
);
2017 if (ioc_status
!= MPI3_IOCSTATUS_SUCCESS
) {
2018 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2019 __FILE__
, __LINE__
, __func__
);
2023 parent_handle
= le16_to_cpu(expander_pg0
.parent_dev_handle
);
2024 if (mpi3mr_get_sas_address(mrioc
, parent_handle
, &sas_address_parent
)
2026 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2027 __FILE__
, __LINE__
, __func__
);
2031 port_id
= expander_pg0
.io_unit_port
;
2032 hba_port
= mpi3mr_get_hba_port_by_id(mrioc
, port_id
);
2034 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2035 __FILE__
, __LINE__
, __func__
);
2039 if (sas_address_parent
!= mrioc
->sas_hba
.sas_address
) {
2040 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
2042 mpi3mr_expander_find_by_sas_address(mrioc
,
2043 sas_address_parent
, hba_port
);
2044 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
2045 if (!sas_expander
) {
2046 rc
= mpi3mr_expander_add(mrioc
, parent_handle
);
2051 * When there is a parent expander present, update it's
2052 * phys where child expander is connected with the link
2053 * speed, attached dev handle and sas address.
2055 for (i
= 0 ; i
< sas_expander
->num_phys
; i
++) {
2057 (i
<< MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT
) |
2059 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc
,
2060 &ioc_status
, &expander_pg1
,
2061 sizeof(expander_pg1
),
2062 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM
,
2064 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2065 __FILE__
, __LINE__
, __func__
);
2069 if (ioc_status
!= MPI3_IOCSTATUS_SUCCESS
) {
2070 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2071 __FILE__
, __LINE__
, __func__
);
2075 temp_handle
= le16_to_cpu(
2076 expander_pg1
.attached_dev_handle
);
2077 if (temp_handle
!= handle
)
2079 link_rate
= (expander_pg1
.negotiated_link_rate
&
2080 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK
) >>
2081 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT
;
2082 mpi3mr_update_links(mrioc
, sas_address_parent
,
2083 handle
, i
, link_rate
, hba_port
);
2088 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
2089 sas_address
= le64_to_cpu(expander_pg0
.sas_address
);
2090 sas_expander
= mpi3mr_expander_find_by_sas_address(mrioc
,
2091 sas_address
, hba_port
);
2092 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
2097 sas_expander
= kzalloc(sizeof(struct mpi3mr_sas_node
),
2102 sas_expander
->handle
= handle
;
2103 sas_expander
->num_phys
= expander_pg0
.num_phys
;
2104 sas_expander
->sas_address_parent
= sas_address_parent
;
2105 sas_expander
->sas_address
= sas_address
;
2106 sas_expander
->hba_port
= hba_port
;
2109 "expander_add: handle(0x%04x), parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
2110 handle
, parent_handle
, (unsigned long long)
2111 sas_expander
->sas_address
, sas_expander
->num_phys
);
2113 if (!sas_expander
->num_phys
) {
2117 sas_expander
->phy
= kcalloc(sas_expander
->num_phys
,
2118 sizeof(struct mpi3mr_sas_phy
), GFP_KERNEL
);
2119 if (!sas_expander
->phy
) {
2124 INIT_LIST_HEAD(&sas_expander
->sas_port_list
);
2125 mr_sas_port
= mpi3mr_sas_port_add(mrioc
, handle
, sas_address_parent
,
2126 sas_expander
->hba_port
);
2128 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2129 __FILE__
, __LINE__
, __func__
);
2133 sas_expander
->parent_dev
= &mr_sas_port
->rphy
->dev
;
2134 sas_expander
->rphy
= mr_sas_port
->rphy
;
2136 for (i
= 0 ; i
< sas_expander
->num_phys
; i
++) {
2137 phynum_handle
= (i
<< MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT
) |
2139 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc
, &ioc_status
,
2140 &expander_pg1
, sizeof(expander_pg1
),
2141 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM
,
2143 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2144 __FILE__
, __LINE__
, __func__
);
2148 if (ioc_status
!= MPI3_IOCSTATUS_SUCCESS
) {
2149 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2150 __FILE__
, __LINE__
, __func__
);
2155 sas_expander
->phy
[i
].handle
= handle
;
2156 sas_expander
->phy
[i
].phy_id
= i
;
2157 sas_expander
->phy
[i
].hba_port
= hba_port
;
2159 if ((mpi3mr_add_expander_phy(mrioc
, &sas_expander
->phy
[i
],
2160 expander_pg1
, sas_expander
->parent_dev
))) {
2161 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2162 __FILE__
, __LINE__
, __func__
);
2168 if (sas_expander
->enclosure_handle
) {
2170 mpi3mr_enclosure_find_by_handle(mrioc
,
2171 sas_expander
->enclosure_handle
);
2173 sas_expander
->enclosure_logical_id
= le64_to_cpu(
2174 enclosure_dev
->pg0
.enclosure_logical_id
);
2177 mpi3mr_expander_node_add(mrioc
, sas_expander
);
2183 mpi3mr_sas_port_remove(mrioc
,
2184 sas_expander
->sas_address
,
2185 sas_address_parent
, sas_expander
->hba_port
);
2186 kfree(sas_expander
->phy
);
2187 kfree(sas_expander
);
2192 * mpi3mr_expander_node_remove - recursive removal of expander.
2193 * @mrioc: Adapter instance reference
2194 * @sas_expander: Expander device object
2196 * Removes expander object and freeing associated memory from
2197 * the sas_expander_list and removes the same from SAS TL, if
2198 * one of the attached device is an expander then it recursively
2199 * removes the expander device too.
2203 void mpi3mr_expander_node_remove(struct mpi3mr_ioc
*mrioc
,
2204 struct mpi3mr_sas_node
*sas_expander
)
2206 struct mpi3mr_sas_port
*mr_sas_port
, *next
;
2207 unsigned long flags
;
2210 /* remove sibling ports attached to this expander */
2211 list_for_each_entry_safe(mr_sas_port
, next
,
2212 &sas_expander
->sas_port_list
, port_list
) {
2213 if (mrioc
->reset_in_progress
|| mrioc
->pci_err_recovery
)
2215 if (mr_sas_port
->remote_identify
.device_type
==
2217 mpi3mr_remove_device_by_sas_address(mrioc
,
2218 mr_sas_port
->remote_identify
.sas_address
,
2219 mr_sas_port
->hba_port
);
2220 else if (mr_sas_port
->remote_identify
.device_type
==
2221 SAS_EDGE_EXPANDER_DEVICE
||
2222 mr_sas_port
->remote_identify
.device_type
==
2223 SAS_FANOUT_EXPANDER_DEVICE
)
2224 mpi3mr_expander_remove(mrioc
,
2225 mr_sas_port
->remote_identify
.sas_address
,
2226 mr_sas_port
->hba_port
);
2229 port_id
= sas_expander
->hba_port
->port_id
;
2230 mpi3mr_sas_port_remove(mrioc
, sas_expander
->sas_address
,
2231 sas_expander
->sas_address_parent
, sas_expander
->hba_port
);
2233 ioc_info(mrioc
, "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
2234 sas_expander
->handle
, (unsigned long long)
2235 sas_expander
->sas_address
, port_id
);
2237 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
2238 list_del(&sas_expander
->list
);
2239 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
2241 kfree(sas_expander
->phy
);
2242 kfree(sas_expander
);
2246 * mpi3mr_expander_remove - Remove expander object
2247 * @mrioc: Adapter instance reference
2248 * @sas_address: Remove expander sas_address
2249 * @hba_port: HBA port reference
2251 * This function remove expander object, stored in
2252 * mrioc->sas_expander_list and removes it from the SAS TL by
2253 * calling mpi3mr_expander_node_remove().
2257 void mpi3mr_expander_remove(struct mpi3mr_ioc
*mrioc
, u64 sas_address
,
2258 struct mpi3mr_hba_port
*hba_port
)
2260 struct mpi3mr_sas_node
*sas_expander
;
2261 unsigned long flags
;
2263 if (mrioc
->reset_in_progress
|| mrioc
->pci_err_recovery
)
2269 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
2270 sas_expander
= mpi3mr_expander_find_by_sas_address(mrioc
, sas_address
,
2272 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
2274 mpi3mr_expander_node_remove(mrioc
, sas_expander
);
2279 * mpi3mr_get_sas_negotiated_logical_linkrate - get linkrate
2280 * @mrioc: Adapter instance reference
2281 * @tgtdev: Target device
2283 * This function identifies whether the target device is
2284 * attached directly or through expander and issues sas phy
2285 * page0 or expander phy page1 and gets the link rate, if there
2286 * is any failure in reading the pages then this returns link
2289 * Return: logical link rate.
2291 static u8
mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc
*mrioc
,
2292 struct mpi3mr_tgt_dev
*tgtdev
)
2294 u8 link_rate
= MPI3_SAS_NEG_LINK_RATE_1_5
, phy_number
;
2295 struct mpi3_sas_expander_page1 expander_pg1
;
2296 struct mpi3_sas_phy_page0 phy_pg0
;
2300 phy_number
= tgtdev
->dev_spec
.sas_sata_inf
.phy_id
;
2301 if (!(tgtdev
->devpg0_flag
& MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED
)) {
2302 phynum_handle
= ((phy_number
<<MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT
)
2303 | tgtdev
->parent_handle
);
2304 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc
, &ioc_status
,
2305 &expander_pg1
, sizeof(expander_pg1
),
2306 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM
,
2308 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2309 __FILE__
, __LINE__
, __func__
);
2312 if (ioc_status
!= MPI3_IOCSTATUS_SUCCESS
) {
2313 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2314 __FILE__
, __LINE__
, __func__
);
2317 link_rate
= (expander_pg1
.negotiated_link_rate
&
2318 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK
) >>
2319 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT
;
2322 if (mpi3mr_cfg_get_sas_phy_pg0(mrioc
, &ioc_status
, &phy_pg0
,
2323 sizeof(struct mpi3_sas_phy_page0
),
2324 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER
, phy_number
)) {
2325 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2326 __FILE__
, __LINE__
, __func__
);
2329 if (ioc_status
!= MPI3_IOCSTATUS_SUCCESS
) {
2330 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2331 __FILE__
, __LINE__
, __func__
);
2334 link_rate
= (phy_pg0
.negotiated_link_rate
&
2335 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK
) >>
2336 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT
;
2342 * mpi3mr_report_tgtdev_to_sas_transport - expose dev to SAS TL
2343 * @mrioc: Adapter instance reference
2344 * @tgtdev: Target device
2346 * This function exposes the target device after
2347 * preparing host_phy, setting up link rate etc.
2349 * Return: 0 on success, non-zero for failure.
2351 int mpi3mr_report_tgtdev_to_sas_transport(struct mpi3mr_ioc
*mrioc
,
2352 struct mpi3mr_tgt_dev
*tgtdev
)
2355 u8 link_rate
, parent_phy_number
;
2356 u64 sas_address_parent
, sas_address
;
2357 struct mpi3mr_hba_port
*hba_port
;
2360 if ((tgtdev
->dev_type
!= MPI3_DEVICE_DEVFORM_SAS_SATA
) ||
2361 !mrioc
->sas_transport_enabled
)
2364 sas_address
= tgtdev
->dev_spec
.sas_sata_inf
.sas_address
;
2365 if (!mrioc
->sas_hba
.num_phys
)
2366 mpi3mr_sas_host_add(mrioc
);
2368 mpi3mr_sas_host_refresh(mrioc
);
2370 if (mpi3mr_get_sas_address(mrioc
, tgtdev
->parent_handle
,
2371 &sas_address_parent
) != 0) {
2372 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2373 __FILE__
, __LINE__
, __func__
);
2376 tgtdev
->dev_spec
.sas_sata_inf
.sas_address_parent
= sas_address_parent
;
2378 parent_phy_number
= tgtdev
->dev_spec
.sas_sata_inf
.phy_id
;
2379 port_id
= tgtdev
->io_unit_port
;
2381 hba_port
= mpi3mr_get_hba_port_by_id(mrioc
, port_id
);
2383 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2384 __FILE__
, __LINE__
, __func__
);
2387 tgtdev
->dev_spec
.sas_sata_inf
.hba_port
= hba_port
;
2389 link_rate
= mpi3mr_get_sas_negotiated_logical_linkrate(mrioc
, tgtdev
);
2391 mpi3mr_update_links(mrioc
, sas_address_parent
, tgtdev
->dev_handle
,
2392 parent_phy_number
, link_rate
, hba_port
);
2394 tgtdev
->host_exposed
= 1;
2395 if (!mpi3mr_sas_port_add(mrioc
, tgtdev
->dev_handle
,
2396 sas_address_parent
, hba_port
)) {
2398 } else if ((!tgtdev
->starget
) && (!mrioc
->is_driver_loading
)) {
2399 mpi3mr_sas_port_remove(mrioc
, sas_address
,
2400 sas_address_parent
, hba_port
);
2404 tgtdev
->dev_spec
.sas_sata_inf
.hba_port
= NULL
;
2405 tgtdev
->host_exposed
= 0;
2411 * mpi3mr_remove_tgtdev_from_sas_transport - remove from SAS TL
2412 * @mrioc: Adapter instance reference
2413 * @tgtdev: Target device
2415 * This function removes the target device
2419 void mpi3mr_remove_tgtdev_from_sas_transport(struct mpi3mr_ioc
*mrioc
,
2420 struct mpi3mr_tgt_dev
*tgtdev
)
2422 u64 sas_address_parent
, sas_address
;
2423 struct mpi3mr_hba_port
*hba_port
;
2425 if ((tgtdev
->dev_type
!= MPI3_DEVICE_DEVFORM_SAS_SATA
) ||
2426 !mrioc
->sas_transport_enabled
)
2429 hba_port
= tgtdev
->dev_spec
.sas_sata_inf
.hba_port
;
2430 sas_address
= tgtdev
->dev_spec
.sas_sata_inf
.sas_address
;
2431 sas_address_parent
= tgtdev
->dev_spec
.sas_sata_inf
.sas_address_parent
;
2432 mpi3mr_sas_port_remove(mrioc
, sas_address
, sas_address_parent
,
2434 tgtdev
->host_exposed
= 0;
2435 tgtdev
->dev_spec
.sas_sata_inf
.hba_port
= NULL
;
2439 * mpi3mr_get_port_id_by_sas_phy - Get port ID of the given phy
2440 * @phy: SAS transport layer phy object
2442 * Return: Port number for valid ID else 0xFFFF
2444 static inline u8
mpi3mr_get_port_id_by_sas_phy(struct sas_phy
*phy
)
2447 struct mpi3mr_hba_port
*hba_port
= phy
->hostdata
;
2450 port_id
= hba_port
->port_id
;
2456 * mpi3mr_get_port_id_by_rphy - Get Port number from SAS rphy
2458 * @mrioc: Adapter instance reference
2459 * @rphy: SAS transport layer remote phy object
2461 * Retrieves HBA port number in which the device pointed by the
2462 * rphy object is attached with.
2464 * Return: Valid port number on success else OxFFFF.
2466 static u8
mpi3mr_get_port_id_by_rphy(struct mpi3mr_ioc
*mrioc
, struct sas_rphy
*rphy
)
2468 struct mpi3mr_sas_node
*sas_expander
;
2469 struct mpi3mr_tgt_dev
*tgtdev
;
2470 unsigned long flags
;
2476 if (rphy
->identify
.device_type
== SAS_EDGE_EXPANDER_DEVICE
||
2477 rphy
->identify
.device_type
== SAS_FANOUT_EXPANDER_DEVICE
) {
2478 spin_lock_irqsave(&mrioc
->sas_node_lock
, flags
);
2479 list_for_each_entry(sas_expander
, &mrioc
->sas_expander_list
,
2481 if (sas_expander
->rphy
== rphy
) {
2482 port_id
= sas_expander
->hba_port
->port_id
;
2486 spin_unlock_irqrestore(&mrioc
->sas_node_lock
, flags
);
2487 } else if (rphy
->identify
.device_type
== SAS_END_DEVICE
) {
2488 spin_lock_irqsave(&mrioc
->tgtdev_lock
, flags
);
2490 tgtdev
= __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc
,
2491 rphy
->identify
.sas_address
, rphy
);
2492 if (tgtdev
&& tgtdev
->dev_spec
.sas_sata_inf
.hba_port
) {
2494 tgtdev
->dev_spec
.sas_sata_inf
.hba_port
->port_id
;
2495 mpi3mr_tgtdev_put(tgtdev
);
2497 spin_unlock_irqrestore(&mrioc
->tgtdev_lock
, flags
);
2502 static inline struct mpi3mr_ioc
*phy_to_mrioc(struct sas_phy
*phy
)
2504 struct Scsi_Host
*shost
= dev_to_shost(phy
->dev
.parent
);
2506 return shost_priv(shost
);
2509 static inline struct mpi3mr_ioc
*rphy_to_mrioc(struct sas_rphy
*rphy
)
2511 struct Scsi_Host
*shost
= dev_to_shost(rphy
->dev
.parent
->parent
);
2513 return shost_priv(shost
);
2516 /* report phy error log structure */
2517 struct phy_error_log_request
{
2518 u8 smp_frame_type
; /* 0x40 */
2519 u8 function
; /* 0x11 */
2520 u8 allocated_response_length
;
2521 u8 request_length
; /* 02 */
2527 /* report phy error log reply structure */
2528 struct phy_error_log_reply
{
2529 u8 smp_frame_type
; /* 0x41 */
2530 u8 function
; /* 0x11 */
2533 __be16 expander_change_count
;
2537 __be32 invalid_dword
;
2538 __be32 running_disparity_error
;
2539 __be32 loss_of_dword_sync
;
2540 __be32 phy_reset_problem
;
2545 * mpi3mr_get_expander_phy_error_log - return expander counters:
2546 * @mrioc: Adapter instance reference
2547 * @phy: The SAS transport layer phy object
2549 * Return: 0 for success, non-zero for failure.
2552 static int mpi3mr_get_expander_phy_error_log(struct mpi3mr_ioc
*mrioc
,
2553 struct sas_phy
*phy
)
2555 struct mpi3_smp_passthrough_request mpi_request
;
2556 struct mpi3_smp_passthrough_reply mpi_reply
;
2557 struct phy_error_log_request
*phy_error_log_request
;
2558 struct phy_error_log_reply
*phy_error_log_reply
;
2561 void *data_out
= NULL
;
2562 dma_addr_t data_out_dma
, data_in_dma
;
2563 u32 data_out_sz
, data_in_sz
, sz
;
2564 u8 sgl_flags
= MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST
;
2565 u16 request_sz
= sizeof(struct mpi3_smp_passthrough_request
);
2566 u16 reply_sz
= sizeof(struct mpi3_smp_passthrough_reply
);
2569 if (mrioc
->reset_in_progress
) {
2570 ioc_err(mrioc
, "%s: host reset in progress!\n", __func__
);
2574 if (mrioc
->pci_err_recovery
) {
2575 ioc_err(mrioc
, "%s: pci error recovery in progress!\n", __func__
);
2579 data_out_sz
= sizeof(struct phy_error_log_request
);
2580 data_in_sz
= sizeof(struct phy_error_log_reply
);
2581 sz
= data_out_sz
+ data_in_sz
;
2582 data_out
= dma_alloc_coherent(&mrioc
->pdev
->dev
, sz
, &data_out_dma
,
2589 data_in_dma
= data_out_dma
+ data_out_sz
;
2590 phy_error_log_reply
= data_out
+ data_out_sz
;
2593 memset(data_out
, 0, sz
);
2594 phy_error_log_request
= data_out
;
2595 phy_error_log_request
->smp_frame_type
= 0x40;
2596 phy_error_log_request
->function
= 0x11;
2597 phy_error_log_request
->request_length
= 2;
2598 phy_error_log_request
->allocated_response_length
= 0;
2599 phy_error_log_request
->phy_identifier
= phy
->number
;
2601 memset(&mpi_request
, 0, request_sz
);
2602 memset(&mpi_reply
, 0, reply_sz
);
2603 mpi_request
.host_tag
= cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS
);
2604 mpi_request
.function
= MPI3_FUNCTION_SMP_PASSTHROUGH
;
2605 mpi_request
.io_unit_port
= (u8
) mpi3mr_get_port_id_by_sas_phy(phy
);
2606 mpi_request
.sas_address
= cpu_to_le64(phy
->identify
.sas_address
);
2608 psge
= &mpi_request
.request_sge
;
2609 mpi3mr_add_sg_single(psge
, sgl_flags
, data_out_sz
, data_out_dma
);
2611 psge
= &mpi_request
.response_sge
;
2612 mpi3mr_add_sg_single(psge
, sgl_flags
, data_in_sz
, data_in_dma
);
2614 dprint_transport_info(mrioc
,
2615 "sending phy error log SMP request to sas_address(0x%016llx), phy_id(%d)\n",
2616 (unsigned long long)phy
->identify
.sas_address
, phy
->number
);
2618 if (mpi3mr_post_transport_req(mrioc
, &mpi_request
, request_sz
,
2619 &mpi_reply
, reply_sz
, MPI3MR_INTADMCMD_TIMEOUT
, &ioc_status
))
2622 dprint_transport_info(mrioc
,
2623 "phy error log SMP request completed with ioc_status(0x%04x)\n",
2626 if (ioc_status
== MPI3_IOCSTATUS_SUCCESS
) {
2627 dprint_transport_info(mrioc
,
2628 "phy error log - reply data transfer size(%d)\n",
2629 le16_to_cpu(mpi_reply
.response_data_length
));
2631 if (le16_to_cpu(mpi_reply
.response_data_length
) !=
2632 sizeof(struct phy_error_log_reply
))
2635 dprint_transport_info(mrioc
,
2636 "phy error log - function_result(%d)\n",
2637 phy_error_log_reply
->function_result
);
2639 phy
->invalid_dword_count
=
2640 be32_to_cpu(phy_error_log_reply
->invalid_dword
);
2641 phy
->running_disparity_error_count
=
2642 be32_to_cpu(phy_error_log_reply
->running_disparity_error
);
2643 phy
->loss_of_dword_sync_count
=
2644 be32_to_cpu(phy_error_log_reply
->loss_of_dword_sync
);
2645 phy
->phy_reset_problem_count
=
2646 be32_to_cpu(phy_error_log_reply
->phy_reset_problem
);
2652 dma_free_coherent(&mrioc
->pdev
->dev
, sz
, data_out
,
2659 * mpi3mr_transport_get_linkerrors - return phy error counters
2660 * @phy: The SAS transport layer phy object
2662 * This function retrieves the phy error log information of the
2663 * HBA or expander for which the phy belongs to
2665 * Return: 0 for success, non-zero for failure.
2667 static int mpi3mr_transport_get_linkerrors(struct sas_phy
*phy
)
2669 struct mpi3mr_ioc
*mrioc
= phy_to_mrioc(phy
);
2670 struct mpi3_sas_phy_page1 phy_pg1
;
2674 rc
= mpi3mr_parent_present(mrioc
, phy
);
2678 if (phy
->identify
.sas_address
!= mrioc
->sas_hba
.sas_address
)
2679 return mpi3mr_get_expander_phy_error_log(mrioc
, phy
);
2681 memset(&phy_pg1
, 0, sizeof(struct mpi3_sas_phy_page1
));
2682 /* get hba phy error logs */
2683 if ((mpi3mr_cfg_get_sas_phy_pg1(mrioc
, &ioc_status
, &phy_pg1
,
2684 sizeof(struct mpi3_sas_phy_page1
),
2685 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER
, phy
->number
))) {
2686 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2687 __FILE__
, __LINE__
, __func__
);
2691 if (ioc_status
!= MPI3_IOCSTATUS_SUCCESS
) {
2692 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
2693 __FILE__
, __LINE__
, __func__
);
2696 phy
->invalid_dword_count
= le32_to_cpu(phy_pg1
.invalid_dword_count
);
2697 phy
->running_disparity_error_count
=
2698 le32_to_cpu(phy_pg1
.running_disparity_error_count
);
2699 phy
->loss_of_dword_sync_count
=
2700 le32_to_cpu(phy_pg1
.loss_dword_synch_count
);
2701 phy
->phy_reset_problem_count
=
2702 le32_to_cpu(phy_pg1
.phy_reset_problem_count
);
2707 * mpi3mr_transport_get_enclosure_identifier - Get Enclosure ID
2708 * @rphy: The SAS transport layer remote phy object
2709 * @identifier: Enclosure identifier to be returned
2711 * Returns the enclosure id for the device pointed by the remote
2714 * Return: 0 on success or -ENXIO
2717 mpi3mr_transport_get_enclosure_identifier(struct sas_rphy
*rphy
,
2720 struct mpi3mr_ioc
*mrioc
= rphy_to_mrioc(rphy
);
2721 struct mpi3mr_tgt_dev
*tgtdev
= NULL
;
2722 unsigned long flags
;
2725 spin_lock_irqsave(&mrioc
->tgtdev_lock
, flags
);
2726 tgtdev
= __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc
,
2727 rphy
->identify
.sas_address
, rphy
);
2730 tgtdev
->enclosure_logical_id
;
2732 mpi3mr_tgtdev_put(tgtdev
);
2737 spin_unlock_irqrestore(&mrioc
->tgtdev_lock
, flags
);
2743 * mpi3mr_transport_get_bay_identifier - Get bay ID
2744 * @rphy: The SAS transport layer remote phy object
2746 * Returns the slot id for the device pointed by the remote phy
2749 * Return: Valid slot ID on success or -ENXIO
2752 mpi3mr_transport_get_bay_identifier(struct sas_rphy
*rphy
)
2754 struct mpi3mr_ioc
*mrioc
= rphy_to_mrioc(rphy
);
2755 struct mpi3mr_tgt_dev
*tgtdev
= NULL
;
2756 unsigned long flags
;
2759 spin_lock_irqsave(&mrioc
->tgtdev_lock
, flags
);
2760 tgtdev
= __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc
,
2761 rphy
->identify
.sas_address
, rphy
);
2764 mpi3mr_tgtdev_put(tgtdev
);
2767 spin_unlock_irqrestore(&mrioc
->tgtdev_lock
, flags
);
2772 /* phy control request structure */
2773 struct phy_control_request
{
2774 u8 smp_frame_type
; /* 0x40 */
2775 u8 function
; /* 0x91 */
2776 u8 allocated_response_length
;
2777 u8 request_length
; /* 0x09 */
2778 u16 expander_change_count
;
2783 u64 attached_device_name
;
2784 u8 programmed_min_physical_link_rate
;
2785 u8 programmed_max_physical_link_rate
;
2789 /* phy control reply structure */
2790 struct phy_control_reply
{
2791 u8 smp_frame_type
; /* 0x41 */
2792 u8 function
; /* 0x11 */
2797 #define SMP_PHY_CONTROL_LINK_RESET (0x01)
2798 #define SMP_PHY_CONTROL_HARD_RESET (0x02)
2799 #define SMP_PHY_CONTROL_DISABLE (0x03)
2802 * mpi3mr_expander_phy_control - expander phy control
2803 * @mrioc: Adapter instance reference
2804 * @phy: The SAS transport layer phy object
2805 * @phy_operation: The phy operation to be executed
2807 * Issues SMP passthru phy control request to execute a specific
2808 * phy operation for a given expander device.
2810 * Return: 0 for success, non-zero for failure.
2813 mpi3mr_expander_phy_control(struct mpi3mr_ioc
*mrioc
,
2814 struct sas_phy
*phy
, u8 phy_operation
)
2816 struct mpi3_smp_passthrough_request mpi_request
;
2817 struct mpi3_smp_passthrough_reply mpi_reply
;
2818 struct phy_control_request
*phy_control_request
;
2819 struct phy_control_reply
*phy_control_reply
;
2822 void *data_out
= NULL
;
2823 dma_addr_t data_out_dma
;
2824 dma_addr_t data_in_dma
;
2827 u8 sgl_flags
= MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST
;
2828 u16 request_sz
= sizeof(struct mpi3_smp_passthrough_request
);
2829 u16 reply_sz
= sizeof(struct mpi3_smp_passthrough_reply
);
2833 if (mrioc
->reset_in_progress
) {
2834 ioc_err(mrioc
, "%s: host reset in progress!\n", __func__
);
2838 if (mrioc
->pci_err_recovery
) {
2839 ioc_err(mrioc
, "%s: pci error recovery in progress!\n",
2844 data_out_sz
= sizeof(struct phy_control_request
);
2845 data_in_sz
= sizeof(struct phy_control_reply
);
2846 sz
= data_out_sz
+ data_in_sz
;
2847 data_out
= dma_alloc_coherent(&mrioc
->pdev
->dev
, sz
, &data_out_dma
,
2854 data_in_dma
= data_out_dma
+ data_out_sz
;
2855 phy_control_reply
= data_out
+ data_out_sz
;
2858 memset(data_out
, 0, sz
);
2860 phy_control_request
= data_out
;
2861 phy_control_request
->smp_frame_type
= 0x40;
2862 phy_control_request
->function
= 0x91;
2863 phy_control_request
->request_length
= 9;
2864 phy_control_request
->allocated_response_length
= 0;
2865 phy_control_request
->phy_identifier
= phy
->number
;
2866 phy_control_request
->phy_operation
= phy_operation
;
2867 phy_control_request
->programmed_min_physical_link_rate
=
2868 phy
->minimum_linkrate
<< 4;
2869 phy_control_request
->programmed_max_physical_link_rate
=
2870 phy
->maximum_linkrate
<< 4;
2872 memset(&mpi_request
, 0, request_sz
);
2873 memset(&mpi_reply
, 0, reply_sz
);
2874 mpi_request
.host_tag
= cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS
);
2875 mpi_request
.function
= MPI3_FUNCTION_SMP_PASSTHROUGH
;
2876 mpi_request
.io_unit_port
= (u8
) mpi3mr_get_port_id_by_sas_phy(phy
);
2877 mpi_request
.sas_address
= cpu_to_le64(phy
->identify
.sas_address
);
2879 psge
= &mpi_request
.request_sge
;
2880 mpi3mr_add_sg_single(psge
, sgl_flags
, data_out_sz
, data_out_dma
);
2882 psge
= &mpi_request
.response_sge
;
2883 mpi3mr_add_sg_single(psge
, sgl_flags
, data_in_sz
, data_in_dma
);
2885 dprint_transport_info(mrioc
,
2886 "sending phy control SMP request to sas_address(0x%016llx), phy_id(%d) opcode(%d)\n",
2887 (unsigned long long)phy
->identify
.sas_address
, phy
->number
,
2890 if (mpi3mr_post_transport_req(mrioc
, &mpi_request
, request_sz
,
2891 &mpi_reply
, reply_sz
, MPI3MR_INTADMCMD_TIMEOUT
, &ioc_status
))
2894 dprint_transport_info(mrioc
,
2895 "phy control SMP request completed with ioc_status(0x%04x)\n",
2898 if (ioc_status
== MPI3_IOCSTATUS_SUCCESS
) {
2899 dprint_transport_info(mrioc
,
2900 "phy control - reply data transfer size(%d)\n",
2901 le16_to_cpu(mpi_reply
.response_data_length
));
2903 if (le16_to_cpu(mpi_reply
.response_data_length
) !=
2904 sizeof(struct phy_control_reply
))
2906 dprint_transport_info(mrioc
,
2907 "phy control - function_result(%d)\n",
2908 phy_control_reply
->function_result
);
2913 dma_free_coherent(&mrioc
->pdev
->dev
, sz
, data_out
,
2920 * mpi3mr_transport_phy_reset - Reset a given phy
2921 * @phy: The SAS transport layer phy object
2922 * @hard_reset: Flag to indicate the type of reset
2924 * Return: 0 for success, non-zero for failure.
2927 mpi3mr_transport_phy_reset(struct sas_phy
*phy
, int hard_reset
)
2929 struct mpi3mr_ioc
*mrioc
= phy_to_mrioc(phy
);
2930 struct mpi3_iounit_control_request mpi_request
;
2931 struct mpi3_iounit_control_reply mpi_reply
;
2932 u16 request_sz
= sizeof(struct mpi3_iounit_control_request
);
2933 u16 reply_sz
= sizeof(struct mpi3_iounit_control_reply
);
2937 rc
= mpi3mr_parent_present(mrioc
, phy
);
2941 /* handle expander phys */
2942 if (phy
->identify
.sas_address
!= mrioc
->sas_hba
.sas_address
)
2943 return mpi3mr_expander_phy_control(mrioc
, phy
,
2944 (hard_reset
== 1) ? SMP_PHY_CONTROL_HARD_RESET
:
2945 SMP_PHY_CONTROL_LINK_RESET
);
2947 /* handle hba phys */
2948 memset(&mpi_request
, 0, request_sz
);
2949 mpi_request
.host_tag
= cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS
);
2950 mpi_request
.function
= MPI3_FUNCTION_IO_UNIT_CONTROL
;
2951 mpi_request
.operation
= MPI3_CTRL_OP_SAS_PHY_CONTROL
;
2952 mpi_request
.param8
[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_ACTION_INDEX
] =
2953 (hard_reset
? MPI3_CTRL_ACTION_HARD_RESET
:
2954 MPI3_CTRL_ACTION_LINK_RESET
);
2955 mpi_request
.param8
[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_PHY_INDEX
] =
2958 dprint_transport_info(mrioc
,
2959 "sending phy reset request to sas_address(0x%016llx), phy_id(%d) hard_reset(%d)\n",
2960 (unsigned long long)phy
->identify
.sas_address
, phy
->number
,
2963 if (mpi3mr_post_transport_req(mrioc
, &mpi_request
, request_sz
,
2964 &mpi_reply
, reply_sz
, MPI3MR_INTADMCMD_TIMEOUT
, &ioc_status
)) {
2969 dprint_transport_info(mrioc
,
2970 "phy reset request completed with ioc_status(0x%04x)\n",
2977 * mpi3mr_transport_phy_enable - enable/disable phys
2978 * @phy: The SAS transport layer phy object
2979 * @enable: flag to enable/disable, enable phy when true
2981 * This function enables/disables a given by executing required
2982 * configuration page changes or expander phy control command
2984 * Return: 0 for success, non-zero for failure.
2987 mpi3mr_transport_phy_enable(struct sas_phy
*phy
, int enable
)
2989 struct mpi3mr_ioc
*mrioc
= phy_to_mrioc(phy
);
2990 struct mpi3_sas_io_unit_page0
*sas_io_unit_pg0
= NULL
;
2991 struct mpi3_sas_io_unit_page1
*sas_io_unit_pg1
= NULL
;
2994 int i
, discovery_active
;
2996 rc
= mpi3mr_parent_present(mrioc
, phy
);
3000 /* handle expander phys */
3001 if (phy
->identify
.sas_address
!= mrioc
->sas_hba
.sas_address
)
3002 return mpi3mr_expander_phy_control(mrioc
, phy
,
3003 (enable
== 1) ? SMP_PHY_CONTROL_LINK_RESET
:
3004 SMP_PHY_CONTROL_DISABLE
);
3006 /* handle hba phys */
3007 sz
= offsetof(struct mpi3_sas_io_unit_page0
, phy_data
) +
3008 (mrioc
->sas_hba
.num_phys
*
3009 sizeof(struct mpi3_sas_io_unit0_phy_data
));
3010 sas_io_unit_pg0
= kzalloc(sz
, GFP_KERNEL
);
3011 if (!sas_io_unit_pg0
) {
3015 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc
, sas_io_unit_pg0
, sz
)) {
3016 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
3017 __FILE__
, __LINE__
, __func__
);
3022 /* unable to enable/disable phys when discovery is active */
3023 for (i
= 0, discovery_active
= 0; i
< mrioc
->sas_hba
.num_phys
; i
++) {
3024 if (sas_io_unit_pg0
->phy_data
[i
].port_flags
&
3025 MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS
) {
3027 "discovery is active on port = %d, phy = %d\n"
3028 "\tunable to enable/disable phys, try again later!\n",
3029 sas_io_unit_pg0
->phy_data
[i
].io_unit_port
, i
);
3030 discovery_active
= 1;
3034 if (discovery_active
) {
3039 if ((sas_io_unit_pg0
->phy_data
[phy
->number
].phy_flags
&
3040 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY
|
3041 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY
))) {
3042 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
3043 __FILE__
, __LINE__
, __func__
);
3048 /* read sas_iounit page 1 */
3049 sz
= offsetof(struct mpi3_sas_io_unit_page1
, phy_data
) +
3050 (mrioc
->sas_hba
.num_phys
*
3051 sizeof(struct mpi3_sas_io_unit1_phy_data
));
3052 sas_io_unit_pg1
= kzalloc(sz
, GFP_KERNEL
);
3053 if (!sas_io_unit_pg1
) {
3058 if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc
, sas_io_unit_pg1
, sz
)) {
3059 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
3060 __FILE__
, __LINE__
, __func__
);
3066 sas_io_unit_pg1
->phy_data
[phy
->number
].phy_flags
3067 &= ~MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE
;
3069 sas_io_unit_pg1
->phy_data
[phy
->number
].phy_flags
3070 |= MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE
;
3072 mpi3mr_cfg_set_sas_io_unit_pg1(mrioc
, sas_io_unit_pg1
, sz
);
3076 mpi3mr_transport_phy_reset(phy
, 0);
3079 kfree(sas_io_unit_pg1
);
3080 kfree(sas_io_unit_pg0
);
3085 * mpi3mr_transport_phy_speed - set phy min/max speed
3086 * @phy: The SAS transport later phy object
3087 * @rates: Rates defined as in sas_phy_linkrates
3089 * This function sets the link rates given in the rates
3090 * argument to the given phy by executing required configuration
3091 * page changes or expander phy control command
3093 * Return: 0 for success, non-zero for failure.
3096 mpi3mr_transport_phy_speed(struct sas_phy
*phy
, struct sas_phy_linkrates
*rates
)
3098 struct mpi3mr_ioc
*mrioc
= phy_to_mrioc(phy
);
3099 struct mpi3_sas_io_unit_page1
*sas_io_unit_pg1
= NULL
;
3100 struct mpi3_sas_phy_page0 phy_pg0
;
3104 rc
= mpi3mr_parent_present(mrioc
, phy
);
3108 if (!rates
->minimum_linkrate
)
3109 rates
->minimum_linkrate
= phy
->minimum_linkrate
;
3110 else if (rates
->minimum_linkrate
< phy
->minimum_linkrate_hw
)
3111 rates
->minimum_linkrate
= phy
->minimum_linkrate_hw
;
3113 if (!rates
->maximum_linkrate
)
3114 rates
->maximum_linkrate
= phy
->maximum_linkrate
;
3115 else if (rates
->maximum_linkrate
> phy
->maximum_linkrate_hw
)
3116 rates
->maximum_linkrate
= phy
->maximum_linkrate_hw
;
3118 /* handle expander phys */
3119 if (phy
->identify
.sas_address
!= mrioc
->sas_hba
.sas_address
) {
3120 phy
->minimum_linkrate
= rates
->minimum_linkrate
;
3121 phy
->maximum_linkrate
= rates
->maximum_linkrate
;
3122 return mpi3mr_expander_phy_control(mrioc
, phy
,
3123 SMP_PHY_CONTROL_LINK_RESET
);
3126 /* handle hba phys */
3127 sz
= offsetof(struct mpi3_sas_io_unit_page1
, phy_data
) +
3128 (mrioc
->sas_hba
.num_phys
*
3129 sizeof(struct mpi3_sas_io_unit1_phy_data
));
3130 sas_io_unit_pg1
= kzalloc(sz
, GFP_KERNEL
);
3131 if (!sas_io_unit_pg1
) {
3136 if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc
, sas_io_unit_pg1
, sz
)) {
3137 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
3138 __FILE__
, __LINE__
, __func__
);
3143 sas_io_unit_pg1
->phy_data
[phy
->number
].max_min_link_rate
=
3144 (rates
->minimum_linkrate
+ (rates
->maximum_linkrate
<< 4));
3146 if (mpi3mr_cfg_set_sas_io_unit_pg1(mrioc
, sas_io_unit_pg1
, sz
)) {
3147 ioc_err(mrioc
, "failure at %s:%d/%s()!\n",
3148 __FILE__
, __LINE__
, __func__
);
3154 mpi3mr_transport_phy_reset(phy
, 0);
3156 /* read phy page 0, then update the rates in the sas transport phy */
3157 if (!mpi3mr_cfg_get_sas_phy_pg0(mrioc
, &ioc_status
, &phy_pg0
,
3158 sizeof(struct mpi3_sas_phy_page0
),
3159 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER
, phy
->number
) &&
3160 (ioc_status
== MPI3_IOCSTATUS_SUCCESS
)) {
3161 phy
->minimum_linkrate
= mpi3mr_convert_phy_link_rate(
3162 phy_pg0
.programmed_link_rate
&
3163 MPI3_SAS_PRATE_MIN_RATE_MASK
);
3164 phy
->maximum_linkrate
= mpi3mr_convert_phy_link_rate(
3165 phy_pg0
.programmed_link_rate
>> 4);
3166 phy
->negotiated_linkrate
=
3167 mpi3mr_convert_phy_link_rate(
3168 (phy_pg0
.negotiated_link_rate
&
3169 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK
)
3170 >> MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT
);
3174 kfree(sas_io_unit_pg1
);
3179 * mpi3mr_map_smp_buffer - map BSG dma buffer
3180 * @dev: Generic device reference
3181 * @buf: BSG buffer pointer
3182 * @dma_addr: Physical address holder
3183 * @dma_len: Mapped DMA buffer length.
3184 * @p: Virtual address holder
3186 * This function maps the DMAable buffer
3188 * Return: 0 on success, non-zero on failure
3191 mpi3mr_map_smp_buffer(struct device
*dev
, struct bsg_buffer
*buf
,
3192 dma_addr_t
*dma_addr
, size_t *dma_len
, void **p
)
3194 /* Check if the request is split across multiple segments */
3195 if (buf
->sg_cnt
> 1) {
3196 *p
= dma_alloc_coherent(dev
, buf
->payload_len
, dma_addr
,
3200 *dma_len
= buf
->payload_len
;
3202 if (!dma_map_sg(dev
, buf
->sg_list
, 1, DMA_BIDIRECTIONAL
))
3204 *dma_addr
= sg_dma_address(buf
->sg_list
);
3205 *dma_len
= sg_dma_len(buf
->sg_list
);
3213 * mpi3mr_unmap_smp_buffer - unmap BSG dma buffer
3214 * @dev: Generic device reference
3215 * @buf: BSG buffer pointer
3216 * @dma_addr: Physical address to be unmapped
3217 * @p: Virtual address
3219 * This function unmaps the DMAable buffer
3222 mpi3mr_unmap_smp_buffer(struct device
*dev
, struct bsg_buffer
*buf
,
3223 dma_addr_t dma_addr
, void *p
)
3226 dma_free_coherent(dev
, buf
->payload_len
, p
, dma_addr
);
3228 dma_unmap_sg(dev
, buf
->sg_list
, 1, DMA_BIDIRECTIONAL
);
3232 * mpi3mr_transport_smp_handler - handler for smp passthru
3233 * @job: BSG job reference
3234 * @shost: SCSI host object reference
3235 * @rphy: SAS transport rphy object pointing the expander
3237 * This is used primarily by smp utils for sending the SMP
3238 * commands to the expanders attached to the controller
3241 mpi3mr_transport_smp_handler(struct bsg_job
*job
, struct Scsi_Host
*shost
,
3242 struct sas_rphy
*rphy
)
3244 struct mpi3mr_ioc
*mrioc
= shost_priv(shost
);
3245 struct mpi3_smp_passthrough_request mpi_request
;
3246 struct mpi3_smp_passthrough_reply mpi_reply
;
3249 dma_addr_t dma_addr_in
;
3250 dma_addr_t dma_addr_out
;
3251 void *addr_in
= NULL
;
3252 void *addr_out
= NULL
;
3255 unsigned int reslen
= 0;
3256 u16 request_sz
= sizeof(struct mpi3_smp_passthrough_request
);
3257 u16 reply_sz
= sizeof(struct mpi3_smp_passthrough_reply
);
3258 u8 sgl_flags
= MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST
;
3261 if (mrioc
->reset_in_progress
) {
3262 ioc_err(mrioc
, "%s: host reset in progress!\n", __func__
);
3267 if (mrioc
->pci_err_recovery
) {
3268 ioc_err(mrioc
, "%s: pci error recovery in progress!\n", __func__
);
3273 rc
= mpi3mr_map_smp_buffer(&mrioc
->pdev
->dev
, &job
->request_payload
,
3274 &dma_addr_out
, &dma_len_out
, &addr_out
);
3279 sg_copy_to_buffer(job
->request_payload
.sg_list
,
3280 job
->request_payload
.sg_cnt
, addr_out
,
3281 job
->request_payload
.payload_len
);
3283 rc
= mpi3mr_map_smp_buffer(&mrioc
->pdev
->dev
, &job
->reply_payload
,
3284 &dma_addr_in
, &dma_len_in
, &addr_in
);
3288 memset(&mpi_request
, 0, request_sz
);
3289 memset(&mpi_reply
, 0, reply_sz
);
3290 mpi_request
.host_tag
= cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS
);
3291 mpi_request
.function
= MPI3_FUNCTION_SMP_PASSTHROUGH
;
3292 mpi_request
.io_unit_port
= (u8
) mpi3mr_get_port_id_by_rphy(mrioc
, rphy
);
3293 mpi_request
.sas_address
= ((rphy
) ?
3294 cpu_to_le64(rphy
->identify
.sas_address
) :
3295 cpu_to_le64(mrioc
->sas_hba
.sas_address
));
3296 psge
= &mpi_request
.request_sge
;
3297 mpi3mr_add_sg_single(psge
, sgl_flags
, dma_len_out
- 4, dma_addr_out
);
3299 psge
= &mpi_request
.response_sge
;
3300 mpi3mr_add_sg_single(psge
, sgl_flags
, dma_len_in
- 4, dma_addr_in
);
3302 dprint_transport_info(mrioc
, "sending SMP request\n");
3304 rc
= mpi3mr_post_transport_req(mrioc
, &mpi_request
, request_sz
,
3305 &mpi_reply
, reply_sz
,
3306 MPI3MR_INTADMCMD_TIMEOUT
, &ioc_status
);
3310 dprint_transport_info(mrioc
,
3311 "SMP request completed with ioc_status(0x%04x)\n", ioc_status
);
3313 dprint_transport_info(mrioc
,
3314 "SMP request - reply data transfer size(%d)\n",
3315 le16_to_cpu(mpi_reply
.response_data_length
));
3317 memcpy(job
->reply
, &mpi_reply
, reply_sz
);
3318 job
->reply_len
= reply_sz
;
3319 reslen
= le16_to_cpu(mpi_reply
.response_data_length
);
3322 sg_copy_from_buffer(job
->reply_payload
.sg_list
,
3323 job
->reply_payload
.sg_cnt
, addr_in
,
3324 job
->reply_payload
.payload_len
);
3328 mpi3mr_unmap_smp_buffer(&mrioc
->pdev
->dev
, &job
->reply_payload
,
3329 dma_addr_in
, addr_in
);
3331 mpi3mr_unmap_smp_buffer(&mrioc
->pdev
->dev
, &job
->request_payload
,
3332 dma_addr_out
, addr_out
);
3334 bsg_job_done(job
, rc
, reslen
);
3337 struct sas_function_template mpi3mr_transport_functions
= {
3338 .get_linkerrors
= mpi3mr_transport_get_linkerrors
,
3339 .get_enclosure_identifier
= mpi3mr_transport_get_enclosure_identifier
,
3340 .get_bay_identifier
= mpi3mr_transport_get_bay_identifier
,
3341 .phy_reset
= mpi3mr_transport_phy_reset
,
3342 .phy_enable
= mpi3mr_transport_phy_enable
,
3343 .set_phy_speed
= mpi3mr_transport_phy_speed
,
3344 .smp_handler
= mpi3mr_transport_smp_handler
,
3347 struct scsi_transport_template
*mpi3mr_transport_template
;