1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Driver for Broadcom MPI3 Storage Controllers
5 * Copyright (C) 2017-2023 Broadcom Inc.
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
596 static void mpi3mr_delete_sas_phy(struct mpi3mr_ioc *mrioc,
597 struct mpi3mr_sas_port *mr_sas_port,
598 struct mpi3mr_sas_phy *mr_sas_phy)
600 u64 sas_address = mr_sas_port->remote_identify.sas_address;
602 dev_info(&mr_sas_phy->phy->dev,
603 "remove: sas_address(0x%016llx), phy(%d)\n",
604 (unsigned long long) sas_address, mr_sas_phy->phy_id);
606 list_del(&mr_sas_phy->port_siblings);
607 mr_sas_port->num_phys--;
608 mr_sas_port->phy_mask &= ~(1 << mr_sas_phy->phy_id);
609 if (mr_sas_port->lowest_phy == mr_sas_phy->phy_id)
610 mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
611 sas_port_delete_phy(mr_sas_port->port, mr_sas_phy->phy);
612 mr_sas_phy->phy_belongs_to_port = 0;
616 * mpi3mr_add_sas_phy - Adding a single phy to a port
617 * @mrioc: Adapter instance reference
618 * @mr_sas_port: Internal Port object
619 * @mr_sas_phy: Internal Phy object
623 static void mpi3mr_add_sas_phy(struct mpi3mr_ioc *mrioc,
624 struct mpi3mr_sas_port *mr_sas_port,
625 struct mpi3mr_sas_phy *mr_sas_phy)
627 u64 sas_address = mr_sas_port->remote_identify.sas_address;
629 dev_info(&mr_sas_phy->phy->dev,
630 "add: sas_address(0x%016llx), phy(%d)\n", (unsigned long long)
631 sas_address, mr_sas_phy->phy_id);
633 list_add_tail(&mr_sas_phy->port_siblings, &mr_sas_port->phy_list);
634 mr_sas_port->num_phys++;
635 mr_sas_port->phy_mask |= (1 << mr_sas_phy->phy_id);
636 if (mr_sas_phy->phy_id < mr_sas_port->lowest_phy)
637 mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
638 sas_port_add_phy(mr_sas_port->port, mr_sas_phy->phy);
639 mr_sas_phy->phy_belongs_to_port = 1;
643 * mpi3mr_add_phy_to_an_existing_port - add phy to existing port
644 * @mrioc: Adapter instance reference
645 * @mr_sas_node: Internal sas node object (expander or host)
646 * @mr_sas_phy: Internal Phy object *
647 * @sas_address: SAS address of device/expander were phy needs
649 * @hba_port: HBA port entry
653 static void mpi3mr_add_phy_to_an_existing_port(struct mpi3mr_ioc *mrioc,
654 struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy,
655 u64 sas_address, struct mpi3mr_hba_port *hba_port)
657 struct mpi3mr_sas_port *mr_sas_port;
658 struct mpi3mr_sas_phy *srch_phy;
660 if (mr_sas_phy->phy_belongs_to_port == 1)
666 list_for_each_entry(mr_sas_port, &mr_sas_node->sas_port_list,
668 if (mr_sas_port->remote_identify.sas_address !=
671 if (mr_sas_port->hba_port != hba_port)
673 list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
675 if (srch_phy == mr_sas_phy)
678 mpi3mr_add_sas_phy(mrioc, mr_sas_port, mr_sas_phy);
684 * mpi3mr_delete_sas_port - helper function to removing a port
685 * @mrioc: Adapter instance reference
686 * @mr_sas_port: Internal Port object
690 static void mpi3mr_delete_sas_port(struct mpi3mr_ioc *mrioc,
691 struct mpi3mr_sas_port *mr_sas_port)
693 u64 sas_address = mr_sas_port->remote_identify.sas_address;
694 struct mpi3mr_hba_port *hba_port = mr_sas_port->hba_port;
695 enum sas_device_type device_type =
696 mr_sas_port->remote_identify.device_type;
698 dev_info(&mr_sas_port->port->dev,
699 "remove: sas_address(0x%016llx)\n",
700 (unsigned long long) sas_address);
702 if (device_type == SAS_END_DEVICE)
703 mpi3mr_remove_device_by_sas_address(mrioc, sas_address,
706 else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
707 device_type == SAS_FANOUT_EXPANDER_DEVICE)
708 mpi3mr_expander_remove(mrioc, sas_address, hba_port);
712 * mpi3mr_del_phy_from_an_existing_port - del phy from a port
713 * @mrioc: Adapter instance reference
714 * @mr_sas_node: Internal sas node object (expander or host)
715 * @mr_sas_phy: Internal Phy object
719 static void mpi3mr_del_phy_from_an_existing_port(struct mpi3mr_ioc *mrioc,
720 struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy)
722 struct mpi3mr_sas_port *mr_sas_port, *next;
723 struct mpi3mr_sas_phy *srch_phy;
725 if (mr_sas_phy->phy_belongs_to_port == 0)
728 list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
730 list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
732 if (srch_phy != mr_sas_phy)
734 if ((mr_sas_port->num_phys == 1) &&
735 !mrioc->reset_in_progress)
736 mpi3mr_delete_sas_port(mrioc, mr_sas_port);
738 mpi3mr_delete_sas_phy(mrioc, mr_sas_port,
746 * mpi3mr_sas_port_sanity_check - sanity check while adding port
747 * @mrioc: Adapter instance reference
748 * @mr_sas_node: Internal sas node object (expander or host)
749 * @sas_address: SAS address of device/expander
750 * @hba_port: HBA port entry
752 * Verifies whether the Phys attached to a device with the given
753 * SAS address already belongs to an existing sas port if so
754 * will remove those phys from the sas port
758 static void mpi3mr_sas_port_sanity_check(struct mpi3mr_ioc *mrioc,
759 struct mpi3mr_sas_node *mr_sas_node, u64 sas_address,
760 struct mpi3mr_hba_port *hba_port)
764 for (i = 0; i < mr_sas_node->num_phys; i++) {
765 if ((mr_sas_node->phy[i].remote_identify.sas_address !=
766 sas_address) || (mr_sas_node->phy[i].hba_port != hba_port))
768 if (mr_sas_node->phy[i].phy_belongs_to_port == 1)
769 mpi3mr_del_phy_from_an_existing_port(mrioc,
770 mr_sas_node, &mr_sas_node->phy[i]);
775 * mpi3mr_set_identify - set identify for phys and end devices
776 * @mrioc: Adapter instance reference
777 * @handle: Firmware device handle
778 * @identify: SAS transport layer's identify info
780 * Populates sas identify info for a specific device.
782 * Return: 0 for success, non-zero for failure.
784 static int mpi3mr_set_identify(struct mpi3mr_ioc *mrioc, u16 handle,
785 struct sas_identify *identify)
788 struct mpi3_device_page0 device_pg0;
789 struct mpi3_device0_sas_sata_format *sasinf;
793 if (mrioc->reset_in_progress) {
794 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
798 if (mrioc->pci_err_recovery) {
799 ioc_err(mrioc, "%s: pci error recovery in progress!\n",
804 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &device_pg0,
805 sizeof(device_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, handle))) {
806 ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
810 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
811 ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
812 handle, ioc_status, __FILE__, __LINE__, __func__);
816 memset(identify, 0, sizeof(struct sas_identify));
817 sasinf = &device_pg0.device_specific.sas_sata_format;
818 device_info = le16_to_cpu(sasinf->device_info);
821 identify->sas_address = le64_to_cpu(sasinf->sas_address);
823 /* phy number of the parent device this device is linked to */
824 identify->phy_identifier = sasinf->phy_num;
827 switch (device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) {
828 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_NO_DEVICE:
829 identify->device_type = SAS_PHY_UNUSED;
831 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE:
832 identify->device_type = SAS_END_DEVICE;
834 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER:
835 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
839 /* initiator_port_protocols */
840 if (device_info & MPI3_SAS_DEVICE_INFO_SSP_INITIATOR)
841 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
842 /* MPI3.0 doesn't have define for SATA INIT so setting both here*/
843 if (device_info & MPI3_SAS_DEVICE_INFO_STP_INITIATOR)
844 identify->initiator_port_protocols |= (SAS_PROTOCOL_STP |
846 if (device_info & MPI3_SAS_DEVICE_INFO_SMP_INITIATOR)
847 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
849 /* target_port_protocols */
850 if (device_info & MPI3_SAS_DEVICE_INFO_SSP_TARGET)
851 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
852 /* MPI3.0 doesn't have define for STP Target so setting both here*/
853 if (device_info & MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET)
854 identify->target_port_protocols |= (SAS_PROTOCOL_STP |
856 if (device_info & MPI3_SAS_DEVICE_INFO_SMP_TARGET)
857 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
862 * mpi3mr_add_host_phy - report sas_host phy to SAS transport
863 * @mrioc: Adapter instance reference
864 * @mr_sas_phy: Internal Phy object
865 * @phy_pg0: SAS phy page 0
866 * @parent_dev: Prent device class object
868 * Return: 0 for success, non-zero for failure.
870 static int mpi3mr_add_host_phy(struct mpi3mr_ioc *mrioc,
871 struct mpi3mr_sas_phy *mr_sas_phy, struct mpi3_sas_phy_page0 phy_pg0,
872 struct device *parent_dev)
875 int phy_index = mr_sas_phy->phy_id;
878 INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
879 phy = sas_phy_alloc(parent_dev, phy_index);
881 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
882 __FILE__, __LINE__, __func__);
885 if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle,
886 &mr_sas_phy->identify))) {
887 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
888 __FILE__, __LINE__, __func__);
892 phy->identify = mr_sas_phy->identify;
893 mr_sas_phy->attached_handle = le16_to_cpu(phy_pg0.attached_dev_handle);
894 if (mr_sas_phy->attached_handle)
895 mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle,
896 &mr_sas_phy->remote_identify);
897 phy->identify.phy_identifier = mr_sas_phy->phy_id;
898 phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate(
899 (phy_pg0.negotiated_link_rate &
900 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
901 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
902 phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate(
903 phy_pg0.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK);
904 phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate(
905 phy_pg0.hw_link_rate >> 4);
906 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
907 phy_pg0.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK);
908 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
909 phy_pg0.programmed_link_rate >> 4);
910 phy->hostdata = mr_sas_phy->hba_port;
912 if ((sas_phy_add(phy))) {
913 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
914 __FILE__, __LINE__, __func__);
918 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
920 "add: handle(0x%04x), sas_address(0x%016llx)\n"
921 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
922 mr_sas_phy->handle, (unsigned long long)
923 mr_sas_phy->identify.sas_address,
924 mr_sas_phy->attached_handle,
926 mr_sas_phy->remote_identify.sas_address);
927 mr_sas_phy->phy = phy;
932 * mpi3mr_add_expander_phy - report expander phy to transport
933 * @mrioc: Adapter instance reference
934 * @mr_sas_phy: Internal Phy object
935 * @expander_pg1: SAS Expander page 1
936 * @parent_dev: Parent device class object
938 * Return: 0 for success, non-zero for failure.
940 static int mpi3mr_add_expander_phy(struct mpi3mr_ioc *mrioc,
941 struct mpi3mr_sas_phy *mr_sas_phy,
942 struct mpi3_sas_expander_page1 expander_pg1,
943 struct device *parent_dev)
946 int phy_index = mr_sas_phy->phy_id;
948 INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
949 phy = sas_phy_alloc(parent_dev, phy_index);
951 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
952 __FILE__, __LINE__, __func__);
955 if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle,
956 &mr_sas_phy->identify))) {
957 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
958 __FILE__, __LINE__, __func__);
962 phy->identify = mr_sas_phy->identify;
963 mr_sas_phy->attached_handle =
964 le16_to_cpu(expander_pg1.attached_dev_handle);
965 if (mr_sas_phy->attached_handle)
966 mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle,
967 &mr_sas_phy->remote_identify);
968 phy->identify.phy_identifier = mr_sas_phy->phy_id;
969 phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate(
970 (expander_pg1.negotiated_link_rate &
971 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
972 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
973 phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate(
974 expander_pg1.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK);
975 phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate(
976 expander_pg1.hw_link_rate >> 4);
977 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
978 expander_pg1.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK);
979 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
980 expander_pg1.programmed_link_rate >> 4);
981 phy->hostdata = mr_sas_phy->hba_port;
983 if ((sas_phy_add(phy))) {
984 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
985 __FILE__, __LINE__, __func__);
989 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
991 "add: handle(0x%04x), sas_address(0x%016llx)\n"
992 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
993 mr_sas_phy->handle, (unsigned long long)
994 mr_sas_phy->identify.sas_address,
995 mr_sas_phy->attached_handle,
997 mr_sas_phy->remote_identify.sas_address);
998 mr_sas_phy->phy = phy;
1003 * mpi3mr_alloc_hba_port - alloc hba port object
1004 * @mrioc: Adapter instance reference
1005 * @port_id: Port number
1007 * Alloc memory for hba port object.
1009 static struct mpi3mr_hba_port *
1010 mpi3mr_alloc_hba_port(struct mpi3mr_ioc *mrioc, u16 port_id)
1012 struct mpi3mr_hba_port *hba_port;
1014 hba_port = kzalloc(sizeof(struct mpi3mr_hba_port),
1018 hba_port->port_id = port_id;
1019 ioc_info(mrioc, "hba_port entry: %p, port: %d is added to hba_port list\n",
1020 hba_port, hba_port->port_id);
1021 if (mrioc->reset_in_progress ||
1022 mrioc->pci_err_recovery)
1023 hba_port->flags = MPI3MR_HBA_PORT_FLAG_NEW;
1024 list_add_tail(&hba_port->list, &mrioc->hba_port_table_list);
1029 * mpi3mr_get_hba_port_by_id - find hba port by id
1030 * @mrioc: Adapter instance reference
1031 * @port_id - Port ID to search
1033 * Return: mpi3mr_hba_port reference for the matched port
1036 struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc,
1039 struct mpi3mr_hba_port *port, *port_next;
1041 list_for_each_entry_safe(port, port_next,
1042 &mrioc->hba_port_table_list, list) {
1043 if (port->port_id != port_id)
1045 if (port->flags & MPI3MR_HBA_PORT_FLAG_DIRTY)
1054 * mpi3mr_update_links - refreshing SAS phy link changes
1055 * @mrioc: Adapter instance reference
1056 * @sas_address_parent: SAS address of parent expander or host
1057 * @handle: Firmware device handle of attached device
1058 * @phy_number: Phy number
1059 * @link_rate: New link rate
1060 * @hba_port: HBA port entry
1064 void mpi3mr_update_links(struct mpi3mr_ioc *mrioc,
1065 u64 sas_address_parent, u16 handle, u8 phy_number, u8 link_rate,
1066 struct mpi3mr_hba_port *hba_port)
1068 unsigned long flags;
1069 struct mpi3mr_sas_node *mr_sas_node;
1070 struct mpi3mr_sas_phy *mr_sas_phy;
1072 if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
1075 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1076 mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1077 sas_address_parent, hba_port);
1079 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1083 mr_sas_phy = &mr_sas_node->phy[phy_number];
1084 mr_sas_phy->attached_handle = handle;
1085 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1086 if (handle && (link_rate >= MPI3_SAS_NEG_LINK_RATE_1_5)) {
1087 mpi3mr_set_identify(mrioc, handle,
1088 &mr_sas_phy->remote_identify);
1089 mpi3mr_add_phy_to_an_existing_port(mrioc, mr_sas_node,
1090 mr_sas_phy, mr_sas_phy->remote_identify.sas_address,
1093 memset(&mr_sas_phy->remote_identify, 0, sizeof(struct
1096 if (mr_sas_phy->phy)
1097 mr_sas_phy->phy->negotiated_linkrate =
1098 mpi3mr_convert_phy_link_rate(link_rate);
1100 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1101 dev_info(&mr_sas_phy->phy->dev,
1102 "refresh: parent sas_address(0x%016llx),\n"
1103 "\tlink_rate(0x%02x), phy(%d)\n"
1104 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
1105 (unsigned long long)sas_address_parent,
1106 link_rate, phy_number, handle, (unsigned long long)
1107 mr_sas_phy->remote_identify.sas_address);
1111 * mpi3mr_sas_host_refresh - refreshing sas host object contents
1112 * @mrioc: Adapter instance reference
1114 * This function refreshes the controllers phy information and
1115 * updates the SAS transport layer with updated information,
1116 * this is executed for each device addition or device info
1121 void mpi3mr_sas_host_refresh(struct mpi3mr_ioc *mrioc)
1125 u16 sz, port_id, attached_handle;
1126 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1128 dprint_transport_info(mrioc,
1129 "updating handles for sas_host(0x%016llx)\n",
1130 (unsigned long long)mrioc->sas_hba.sas_address);
1132 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1133 (mrioc->sas_hba.num_phys *
1134 sizeof(struct mpi3_sas_io_unit0_phy_data));
1135 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1136 if (!sas_io_unit_pg0)
1138 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1139 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1140 __FILE__, __LINE__, __func__);
1144 mrioc->sas_hba.handle = 0;
1145 for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1146 if (sas_io_unit_pg0->phy_data[i].phy_flags &
1147 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
1148 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))
1151 sas_io_unit_pg0->phy_data[i].negotiated_link_rate >> 4;
1152 if (!mrioc->sas_hba.handle)
1153 mrioc->sas_hba.handle = le16_to_cpu(
1154 sas_io_unit_pg0->phy_data[i].controller_dev_handle);
1155 port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1156 if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
1157 if (!mpi3mr_alloc_hba_port(mrioc, port_id))
1160 mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle;
1161 attached_handle = le16_to_cpu(
1162 sas_io_unit_pg0->phy_data[i].attached_dev_handle);
1163 if (attached_handle && link_rate < MPI3_SAS_NEG_LINK_RATE_1_5)
1164 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5;
1165 mrioc->sas_hba.phy[i].hba_port =
1166 mpi3mr_get_hba_port_by_id(mrioc, port_id);
1167 mpi3mr_update_links(mrioc, mrioc->sas_hba.sas_address,
1168 attached_handle, i, link_rate,
1169 mrioc->sas_hba.phy[i].hba_port);
1172 kfree(sas_io_unit_pg0);
1176 * mpi3mr_sas_host_add - create sas host object
1177 * @mrioc: Adapter instance reference
1179 * This function creates the controllers phy information and
1180 * updates the SAS transport layer with updated information,
1181 * this is executed for first device addition or device info
1186 void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc)
1189 u16 sz, num_phys = 1, port_id, ioc_status;
1190 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1191 struct mpi3_sas_phy_page0 phy_pg0;
1192 struct mpi3_device_page0 dev_pg0;
1193 struct mpi3_enclosure_page0 encl_pg0;
1194 struct mpi3_device0_sas_sata_format *sasinf;
1196 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1197 (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data));
1198 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1199 if (!sas_io_unit_pg0)
1202 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1203 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1204 __FILE__, __LINE__, __func__);
1207 num_phys = sas_io_unit_pg0->num_phys;
1208 kfree(sas_io_unit_pg0);
1210 mrioc->sas_hba.host_node = 1;
1211 INIT_LIST_HEAD(&mrioc->sas_hba.sas_port_list);
1212 mrioc->sas_hba.parent_dev = &mrioc->shost->shost_gendev;
1213 mrioc->sas_hba.phy = kcalloc(num_phys,
1214 sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
1215 if (!mrioc->sas_hba.phy)
1218 mrioc->sas_hba.num_phys = num_phys;
1220 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1221 (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data));
1222 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1223 if (!sas_io_unit_pg0)
1226 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1227 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1228 __FILE__, __LINE__, __func__);
1232 mrioc->sas_hba.handle = 0;
1233 for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1234 if (sas_io_unit_pg0->phy_data[i].phy_flags &
1235 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
1236 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))
1238 if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
1239 sizeof(struct mpi3_sas_phy_page0),
1240 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, i)) {
1241 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1242 __FILE__, __LINE__, __func__);
1245 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1246 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1247 __FILE__, __LINE__, __func__);
1251 if (!mrioc->sas_hba.handle)
1252 mrioc->sas_hba.handle = le16_to_cpu(
1253 sas_io_unit_pg0->phy_data[i].controller_dev_handle);
1254 port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1256 if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
1257 if (!mpi3mr_alloc_hba_port(mrioc, port_id))
1260 mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle;
1261 mrioc->sas_hba.phy[i].phy_id = i;
1262 mrioc->sas_hba.phy[i].hba_port =
1263 mpi3mr_get_hba_port_by_id(mrioc, port_id);
1264 mpi3mr_add_host_phy(mrioc, &mrioc->sas_hba.phy[i],
1265 phy_pg0, mrioc->sas_hba.parent_dev);
1267 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
1268 sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
1269 mrioc->sas_hba.handle))) {
1270 ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
1273 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1274 ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
1275 mrioc->sas_hba.handle, ioc_status, __FILE__, __LINE__,
1279 mrioc->sas_hba.enclosure_handle =
1280 le16_to_cpu(dev_pg0.enclosure_handle);
1281 sasinf = &dev_pg0.device_specific.sas_sata_format;
1282 mrioc->sas_hba.sas_address =
1283 le64_to_cpu(sasinf->sas_address);
1285 "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
1286 mrioc->sas_hba.handle,
1287 (unsigned long long) mrioc->sas_hba.sas_address,
1288 mrioc->sas_hba.num_phys);
1290 if (mrioc->sas_hba.enclosure_handle) {
1291 if (!(mpi3mr_cfg_get_enclosure_pg0(mrioc, &ioc_status,
1292 &encl_pg0, sizeof(encl_pg0),
1293 MPI3_ENCLOS_PGAD_FORM_HANDLE,
1294 mrioc->sas_hba.enclosure_handle)) &&
1295 (ioc_status == MPI3_IOCSTATUS_SUCCESS))
1296 mrioc->sas_hba.enclosure_logical_id =
1297 le64_to_cpu(encl_pg0.enclosure_logical_id);
1301 kfree(sas_io_unit_pg0);
1305 * mpi3mr_sas_port_add - Expose the SAS device to the SAS TL
1306 * @mrioc: Adapter instance reference
1307 * @handle: Firmware device handle of the attached device
1308 * @sas_address_parent: sas address of parent expander or host
1309 * @hba_port: HBA port entry
1311 * This function creates a new sas port object for the given end
1312 * device matching sas address and hba_port and adds it to the
1313 * sas_node's sas_port_list and expose the attached sas device
1314 * to the SAS transport layer through sas_rphy_add.
1316 * Returns a valid mpi3mr_sas_port reference or NULL.
1318 static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
1319 u16 handle, u64 sas_address_parent, struct mpi3mr_hba_port *hba_port)
1321 struct mpi3mr_sas_phy *mr_sas_phy, *next;
1322 struct mpi3mr_sas_port *mr_sas_port;
1323 unsigned long flags;
1324 struct mpi3mr_sas_node *mr_sas_node;
1325 struct sas_rphy *rphy;
1326 struct mpi3mr_tgt_dev *tgtdev = NULL;
1328 struct sas_port *port;
1331 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1332 __FILE__, __LINE__, __func__);
1336 mr_sas_port = kzalloc(sizeof(struct mpi3mr_sas_port), GFP_KERNEL);
1340 INIT_LIST_HEAD(&mr_sas_port->port_list);
1341 INIT_LIST_HEAD(&mr_sas_port->phy_list);
1342 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1343 mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1344 sas_address_parent, hba_port);
1345 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1348 ioc_err(mrioc, "%s:could not find parent sas_address(0x%016llx)!\n",
1349 __func__, (unsigned long long)sas_address_parent);
1353 if ((mpi3mr_set_identify(mrioc, handle,
1354 &mr_sas_port->remote_identify))) {
1355 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1356 __FILE__, __LINE__, __func__);
1360 if (mr_sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
1361 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1362 __FILE__, __LINE__, __func__);
1366 mr_sas_port->hba_port = hba_port;
1367 mpi3mr_sas_port_sanity_check(mrioc, mr_sas_node,
1368 mr_sas_port->remote_identify.sas_address, hba_port);
1370 if (mr_sas_node->num_phys >= sizeof(mr_sas_port->phy_mask) * 8)
1371 ioc_info(mrioc, "max port count %u could be too high\n",
1372 mr_sas_node->num_phys);
1374 for (i = 0; i < mr_sas_node->num_phys; i++) {
1375 if ((mr_sas_node->phy[i].remote_identify.sas_address !=
1376 mr_sas_port->remote_identify.sas_address) ||
1377 (mr_sas_node->phy[i].hba_port != hba_port))
1380 if (i >= sizeof(mr_sas_port->phy_mask) * 8) {
1381 ioc_warn(mrioc, "skipping port %u, max allowed value is %zu\n",
1382 i, sizeof(mr_sas_port->phy_mask) * 8);
1385 list_add_tail(&mr_sas_node->phy[i].port_siblings,
1386 &mr_sas_port->phy_list);
1387 mr_sas_port->num_phys++;
1388 mr_sas_port->phy_mask |= (1 << i);
1391 if (!mr_sas_port->num_phys) {
1392 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1393 __FILE__, __LINE__, __func__);
1397 mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
1399 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1400 tgtdev = mpi3mr_get_tgtdev_by_addr(mrioc,
1401 mr_sas_port->remote_identify.sas_address,
1402 mr_sas_port->hba_port);
1405 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1406 __FILE__, __LINE__, __func__);
1409 tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 1;
1412 if (!mr_sas_node->parent_dev) {
1413 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1414 __FILE__, __LINE__, __func__);
1418 port = sas_port_alloc_num(mr_sas_node->parent_dev);
1419 if ((sas_port_add(port))) {
1420 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1421 __FILE__, __LINE__, __func__);
1425 list_for_each_entry(mr_sas_phy, &mr_sas_port->phy_list,
1427 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1428 dev_info(&port->dev,
1429 "add: handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
1430 handle, (unsigned long long)
1431 mr_sas_port->remote_identify.sas_address,
1432 mr_sas_phy->phy_id);
1433 sas_port_add_phy(port, mr_sas_phy->phy);
1434 mr_sas_phy->phy_belongs_to_port = 1;
1435 mr_sas_phy->hba_port = hba_port;
1438 mr_sas_port->port = port;
1439 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1440 rphy = sas_end_device_alloc(port);
1441 tgtdev->dev_spec.sas_sata_inf.rphy = rphy;
1443 rphy = sas_expander_alloc(port,
1444 mr_sas_port->remote_identify.device_type);
1446 rphy->identify = mr_sas_port->remote_identify;
1448 if (mrioc->current_event)
1449 mrioc->current_event->pending_at_sml = 1;
1451 if ((sas_rphy_add(rphy))) {
1452 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1453 __FILE__, __LINE__, __func__);
1455 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1456 tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 0;
1457 tgtdev->dev_spec.sas_sata_inf.sas_transport_attached = 1;
1458 mpi3mr_tgtdev_put(tgtdev);
1461 dev_info(&rphy->dev,
1462 "%s: added: handle(0x%04x), sas_address(0x%016llx)\n",
1463 __func__, handle, (unsigned long long)
1464 mr_sas_port->remote_identify.sas_address);
1466 mr_sas_port->rphy = rphy;
1467 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1468 list_add_tail(&mr_sas_port->port_list, &mr_sas_node->sas_port_list);
1469 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1471 if (mrioc->current_event) {
1472 mrioc->current_event->pending_at_sml = 0;
1473 if (mrioc->current_event->discard)
1474 mpi3mr_print_device_event_notice(mrioc, true);
1477 /* fill in report manufacture */
1478 if (mr_sas_port->remote_identify.device_type ==
1479 SAS_EDGE_EXPANDER_DEVICE ||
1480 mr_sas_port->remote_identify.device_type ==
1481 SAS_FANOUT_EXPANDER_DEVICE)
1482 mpi3mr_report_manufacture(mrioc,
1483 mr_sas_port->remote_identify.sas_address,
1484 rphy_to_expander_device(rphy), hba_port->port_id);
1489 list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list,
1491 list_del(&mr_sas_phy->port_siblings);
1497 * mpi3mr_sas_port_remove - remove port from the list
1498 * @mrioc: Adapter instance reference
1499 * @sas_address: SAS address of attached device
1500 * @sas_address_parent: SAS address of parent expander or host
1501 * @hba_port: HBA port entry
1503 * Removing object and freeing associated memory from the
1508 static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
1509 u64 sas_address_parent, struct mpi3mr_hba_port *hba_port)
1512 unsigned long flags;
1513 struct mpi3mr_sas_port *mr_sas_port, *next;
1514 struct mpi3mr_sas_node *mr_sas_node;
1516 struct mpi3mr_sas_phy *mr_sas_phy, *next_phy;
1517 struct mpi3mr_hba_port *srch_port, *hba_port_next = NULL;
1522 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1523 mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1524 sas_address_parent, hba_port);
1526 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1529 list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
1531 if (mr_sas_port->remote_identify.sas_address != sas_address)
1533 if (mr_sas_port->hba_port != hba_port)
1536 list_del(&mr_sas_port->port_list);
1542 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1546 if (mr_sas_node->host_node) {
1547 list_for_each_entry_safe(srch_port, hba_port_next,
1548 &mrioc->hba_port_table_list, list) {
1549 if (srch_port != hba_port)
1552 "removing hba_port entry: %p port: %d from hba_port list\n",
1553 srch_port, srch_port->port_id);
1554 list_del(&hba_port->list);
1560 for (i = 0; i < mr_sas_node->num_phys; i++) {
1561 if (mr_sas_node->phy[i].remote_identify.sas_address ==
1563 memset(&mr_sas_node->phy[i].remote_identify, 0,
1564 sizeof(struct sas_identify));
1567 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1569 if (mrioc->current_event)
1570 mrioc->current_event->pending_at_sml = 1;
1572 list_for_each_entry_safe(mr_sas_phy, next_phy,
1573 &mr_sas_port->phy_list, port_siblings) {
1574 if ((!mrioc->stop_drv_processing) &&
1575 (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1576 dev_info(&mr_sas_port->port->dev,
1577 "remove: sas_address(0x%016llx), phy(%d)\n",
1578 (unsigned long long)
1579 mr_sas_port->remote_identify.sas_address,
1580 mr_sas_phy->phy_id);
1581 mr_sas_phy->phy_belongs_to_port = 0;
1582 if (!mrioc->stop_drv_processing)
1583 sas_port_delete_phy(mr_sas_port->port,
1585 list_del(&mr_sas_phy->port_siblings);
1587 if (!mrioc->stop_drv_processing)
1588 sas_port_delete(mr_sas_port->port);
1589 ioc_info(mrioc, "%s: removed sas_address(0x%016llx)\n",
1590 __func__, (unsigned long long)sas_address);
1592 if (mrioc->current_event) {
1593 mrioc->current_event->pending_at_sml = 0;
1594 if (mrioc->current_event->discard)
1595 mpi3mr_print_device_event_notice(mrioc, false);
1602 * struct host_port - host port details
1603 * @sas_address: SAS Address of the attached device
1604 * @phy_mask: phy mask of host port
1605 * @handle: Device Handle of attached device
1606 * @iounit_port_id: port ID
1607 * @used: host port is already matched with sas port from sas_port_list
1608 * @lowest_phy: lowest phy ID of host port
1620 * mpi3mr_update_mr_sas_port - update sas port objects during reset
1621 * @mrioc: Adapter instance reference
1622 * @h_port: host_port object
1623 * @mr_sas_port: sas_port objects which needs to be updated
1625 * Update the port ID of sas port object. Also add the phys if new phys got
1626 * added to current sas port and remove the phys if some phys are moved
1627 * out of the current sas port.
1632 mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
1633 struct mpi3mr_sas_port *mr_sas_port)
1635 struct mpi3mr_sas_phy *mr_sas_phy;
1637 u64 phys_to_be_added, phys_to_be_removed;
1641 mr_sas_port->marked_responding = 1;
1643 dev_info(&mr_sas_port->port->dev,
1644 "sas_address(0x%016llx), old: port_id %d phy_mask 0x%llx, new: port_id %d phy_mask:0x%llx\n",
1645 mr_sas_port->remote_identify.sas_address,
1646 mr_sas_port->hba_port->port_id, mr_sas_port->phy_mask,
1647 h_port->iounit_port_id, h_port->phy_mask);
1649 mr_sas_port->hba_port->port_id = h_port->iounit_port_id;
1650 mr_sas_port->hba_port->flags &= ~MPI3MR_HBA_PORT_FLAG_DIRTY;
1652 /* Get the newly added phys bit map & removed phys bit map */
1653 phy_mask_xor = mr_sas_port->phy_mask ^ h_port->phy_mask;
1654 phys_to_be_added = h_port->phy_mask & phy_mask_xor;
1655 phys_to_be_removed = mr_sas_port->phy_mask & phy_mask_xor;
1658 * Register these new phys to current mr_sas_port's port.
1659 * if these phys are previously registered with another port
1660 * then delete these phys from that port first.
1662 for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u64)) {
1663 mr_sas_phy = &mrioc->sas_hba.phy[i];
1664 if (mr_sas_phy->phy_belongs_to_port)
1665 mpi3mr_del_phy_from_an_existing_port(mrioc,
1666 &mrioc->sas_hba, mr_sas_phy);
1667 mpi3mr_add_phy_to_an_existing_port(mrioc,
1668 &mrioc->sas_hba, mr_sas_phy,
1669 mr_sas_port->remote_identify.sas_address,
1670 mr_sas_port->hba_port);
1673 /* Delete the phys which are not part of current mr_sas_port's port. */
1674 for_each_set_bit(i, (ulong *) &phys_to_be_removed, 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);
1683 * mpi3mr_refresh_sas_ports - update host's sas ports during reset
1684 * @mrioc: Adapter instance reference
1686 * Update the host's sas ports during reset by checking whether
1687 * sas ports are still intact or not. Add/remove phys if any hba
1688 * phys are (moved in)/(moved out) of sas port. Also update
1689 * io_unit_port if it got changed during reset.
1694 mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
1696 struct host_port *h_port = NULL;
1697 int i, j, found, host_port_count = 0, port_idx;
1698 u16 sz, attached_handle, ioc_status;
1699 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1700 struct mpi3_device_page0 dev_pg0;
1701 struct mpi3_device0_sas_sata_format *sasinf;
1702 struct mpi3mr_sas_port *mr_sas_port;
1704 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1705 (mrioc->sas_hba.num_phys *
1706 sizeof(struct mpi3_sas_io_unit0_phy_data));
1707 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1708 if (!sas_io_unit_pg0)
1710 h_port = kcalloc(64, sizeof(struct host_port), GFP_KERNEL);
1714 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1715 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1716 __FILE__, __LINE__, __func__);
1720 /* Create a new expander port table */
1721 for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1722 attached_handle = le16_to_cpu(
1723 sas_io_unit_pg0->phy_data[i].attached_dev_handle);
1724 if (!attached_handle)
1727 for (j = 0; j < host_port_count; j++) {
1728 if (h_port[j].handle == attached_handle) {
1729 h_port[j].phy_mask |= (1 << i);
1736 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
1737 sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
1738 attached_handle))) {
1740 "failed to read dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1741 attached_handle, __FILE__, __LINE__, __func__);
1744 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1746 "ioc_status(0x%x) while reading dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1747 ioc_status, attached_handle,
1748 __FILE__, __LINE__, __func__);
1751 sasinf = &dev_pg0.device_specific.sas_sata_format;
1753 port_idx = host_port_count;
1754 h_port[port_idx].sas_address = le64_to_cpu(sasinf->sas_address);
1755 h_port[port_idx].handle = attached_handle;
1756 h_port[port_idx].phy_mask = (1 << i);
1757 h_port[port_idx].iounit_port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1758 h_port[port_idx].lowest_phy = sasinf->phy_num;
1759 h_port[port_idx].used = 0;
1763 if (!host_port_count)
1766 if (mrioc->logging_level & MPI3_DEBUG_RESET) {
1767 ioc_info(mrioc, "Host port details before reset\n");
1768 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1771 "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1772 mr_sas_port->hba_port->port_id,
1773 mr_sas_port->remote_identify.sas_address,
1774 mr_sas_port->phy_mask, mr_sas_port->lowest_phy);
1777 ioc_info(mrioc, "Host port details after reset\n");
1778 for (i = 0; i < host_port_count; i++) {
1780 "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1781 h_port[i].iounit_port_id, h_port[i].sas_address,
1782 h_port[i].phy_mask, h_port[i].lowest_phy);
1786 /* mark all host sas port entries as dirty */
1787 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1789 mr_sas_port->marked_responding = 0;
1790 mr_sas_port->hba_port->flags |= MPI3MR_HBA_PORT_FLAG_DIRTY;
1793 /* First check for matching lowest phy */
1794 for (i = 0; i < host_port_count; i++) {
1796 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1798 if (mr_sas_port->marked_responding)
1800 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1802 if (h_port[i].lowest_phy == mr_sas_port->lowest_phy) {
1803 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1809 /* In case if lowest phy is got enabled or disabled during reset */
1810 for (i = 0; i < host_port_count; i++) {
1814 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1816 if (mr_sas_port->marked_responding)
1818 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1820 if (h_port[i].phy_mask & mr_sas_port->phy_mask) {
1821 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1827 /* In case if expander cable is removed & connected to another HBA port during reset */
1828 for (i = 0; i < host_port_count; i++) {
1832 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1834 if (mr_sas_port->marked_responding)
1836 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1838 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1844 kfree(sas_io_unit_pg0);
1848 * mpi3mr_refresh_expanders - Refresh expander device exposure
1849 * @mrioc: Adapter instance reference
1851 * This is executed post controller reset to identify any
1852 * missing expander devices during reset and remove from the upper layers
1853 * or expose any newly detected expander device to the upper layers.
1858 mpi3mr_refresh_expanders(struct mpi3mr_ioc *mrioc)
1860 struct mpi3mr_sas_node *sas_expander, *sas_expander_next;
1861 struct mpi3_sas_expander_page0 expander_pg0;
1862 u16 ioc_status, handle;
1865 unsigned long flags;
1866 struct mpi3mr_hba_port *hba_port;
1868 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1869 list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
1870 sas_expander->non_responding = 1;
1872 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1874 sas_expander = NULL;
1878 /* Search for responding expander devices and add them if they are newly got added */
1880 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
1881 sizeof(struct mpi3_sas_expander_page0),
1882 MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
1884 "failed to read exp pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1885 handle, __FILE__, __LINE__, __func__);
1889 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1891 "ioc_status(0x%x) while reading exp pg0 for handle:(0x%04x), %s:%d/%s()!\n",
1892 ioc_status, handle, __FILE__, __LINE__, __func__);
1896 handle = le16_to_cpu(expander_pg0.dev_handle);
1897 sas_address = le64_to_cpu(expander_pg0.sas_address);
1898 hba_port = mpi3mr_get_hba_port_by_id(mrioc, expander_pg0.io_unit_port);
1901 mpi3mr_sas_host_refresh(mrioc);
1902 mpi3mr_expander_add(mrioc, handle);
1906 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1908 mpi3mr_expander_find_by_sas_address(mrioc,
1909 sas_address, hba_port);
1910 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1912 if (!sas_expander) {
1913 mpi3mr_sas_host_refresh(mrioc);
1914 mpi3mr_expander_add(mrioc, handle);
1918 sas_expander->non_responding = 0;
1919 if (sas_expander->handle == handle)
1922 sas_expander->handle = handle;
1923 for (i = 0 ; i < sas_expander->num_phys ; i++)
1924 sas_expander->phy[i].handle = handle;
1928 * Delete non responding expander devices and the corresponding
1929 * hba_port if the non responding expander device's parent device
1932 sas_expander = NULL;
1933 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1934 list_for_each_entry_safe_reverse(sas_expander, sas_expander_next,
1935 &mrioc->sas_expander_list, list) {
1936 if (sas_expander->non_responding) {
1937 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1938 mpi3mr_expander_node_remove(mrioc, sas_expander);
1939 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1942 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1946 * mpi3mr_expander_node_add - insert an expander to the list.
1947 * @mrioc: Adapter instance reference
1948 * @sas_expander: Expander sas node
1949 * Context: This function will acquire sas_node_lock.
1951 * Adding new object to the ioc->sas_expander_list.
1955 static void mpi3mr_expander_node_add(struct mpi3mr_ioc *mrioc,
1956 struct mpi3mr_sas_node *sas_expander)
1958 unsigned long flags;
1960 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1961 list_add_tail(&sas_expander->list, &mrioc->sas_expander_list);
1962 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1966 * mpi3mr_expander_add - Create expander object
1967 * @mrioc: Adapter instance reference
1968 * @handle: Expander firmware device handle
1970 * This function creating expander object, stored in
1971 * sas_expander_list and expose it to the SAS transport
1974 * Return: 0 for success, non-zero for failure.
1976 int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle)
1978 struct mpi3mr_sas_node *sas_expander;
1979 struct mpi3mr_enclosure_node *enclosure_dev;
1980 struct mpi3_sas_expander_page0 expander_pg0;
1981 struct mpi3_sas_expander_page1 expander_pg1;
1982 u16 ioc_status, parent_handle, temp_handle;
1983 u64 sas_address, sas_address_parent = 0;
1985 unsigned long flags;
1986 u8 port_id, link_rate;
1987 struct mpi3mr_sas_port *mr_sas_port = NULL;
1988 struct mpi3mr_hba_port *hba_port;
1995 if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
1998 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
1999 sizeof(expander_pg0), MPI3_SAS_EXPAND_PGAD_FORM_HANDLE, handle))) {
2000 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2001 __FILE__, __LINE__, __func__);
2005 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2006 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2007 __FILE__, __LINE__, __func__);
2011 parent_handle = le16_to_cpu(expander_pg0.parent_dev_handle);
2012 if (mpi3mr_get_sas_address(mrioc, parent_handle, &sas_address_parent)
2014 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2015 __FILE__, __LINE__, __func__);
2019 port_id = expander_pg0.io_unit_port;
2020 hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
2022 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2023 __FILE__, __LINE__, __func__);
2027 if (sas_address_parent != mrioc->sas_hba.sas_address) {
2028 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2030 mpi3mr_expander_find_by_sas_address(mrioc,
2031 sas_address_parent, hba_port);
2032 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2033 if (!sas_expander) {
2034 rc = mpi3mr_expander_add(mrioc, parent_handle);
2039 * When there is a parent expander present, update it's
2040 * phys where child expander is connected with the link
2041 * speed, attached dev handle and sas address.
2043 for (i = 0 ; i < sas_expander->num_phys ; i++) {
2045 (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2047 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc,
2048 &ioc_status, &expander_pg1,
2049 sizeof(expander_pg1),
2050 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2052 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2053 __FILE__, __LINE__, __func__);
2057 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2058 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2059 __FILE__, __LINE__, __func__);
2063 temp_handle = le16_to_cpu(
2064 expander_pg1.attached_dev_handle);
2065 if (temp_handle != handle)
2067 link_rate = (expander_pg1.negotiated_link_rate &
2068 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2069 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2070 mpi3mr_update_links(mrioc, sas_address_parent,
2071 handle, i, link_rate, hba_port);
2076 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2077 sas_address = le64_to_cpu(expander_pg0.sas_address);
2078 sas_expander = mpi3mr_expander_find_by_sas_address(mrioc,
2079 sas_address, hba_port);
2080 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2085 sas_expander = kzalloc(sizeof(struct mpi3mr_sas_node),
2090 sas_expander->handle = handle;
2091 sas_expander->num_phys = expander_pg0.num_phys;
2092 sas_expander->sas_address_parent = sas_address_parent;
2093 sas_expander->sas_address = sas_address;
2094 sas_expander->hba_port = hba_port;
2097 "expander_add: handle(0x%04x), parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
2098 handle, parent_handle, (unsigned long long)
2099 sas_expander->sas_address, sas_expander->num_phys);
2101 if (!sas_expander->num_phys) {
2105 sas_expander->phy = kcalloc(sas_expander->num_phys,
2106 sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
2107 if (!sas_expander->phy) {
2112 INIT_LIST_HEAD(&sas_expander->sas_port_list);
2113 mr_sas_port = mpi3mr_sas_port_add(mrioc, handle, sas_address_parent,
2114 sas_expander->hba_port);
2116 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2117 __FILE__, __LINE__, __func__);
2121 sas_expander->parent_dev = &mr_sas_port->rphy->dev;
2122 sas_expander->rphy = mr_sas_port->rphy;
2124 for (i = 0 ; i < sas_expander->num_phys ; i++) {
2125 phynum_handle = (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2127 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2128 &expander_pg1, sizeof(expander_pg1),
2129 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2131 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2132 __FILE__, __LINE__, __func__);
2136 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2137 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2138 __FILE__, __LINE__, __func__);
2143 sas_expander->phy[i].handle = handle;
2144 sas_expander->phy[i].phy_id = i;
2145 sas_expander->phy[i].hba_port = hba_port;
2147 if ((mpi3mr_add_expander_phy(mrioc, &sas_expander->phy[i],
2148 expander_pg1, sas_expander->parent_dev))) {
2149 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2150 __FILE__, __LINE__, __func__);
2156 if (sas_expander->enclosure_handle) {
2158 mpi3mr_enclosure_find_by_handle(mrioc,
2159 sas_expander->enclosure_handle);
2161 sas_expander->enclosure_logical_id = le64_to_cpu(
2162 enclosure_dev->pg0.enclosure_logical_id);
2165 mpi3mr_expander_node_add(mrioc, sas_expander);
2171 mpi3mr_sas_port_remove(mrioc,
2172 sas_expander->sas_address,
2173 sas_address_parent, sas_expander->hba_port);
2174 kfree(sas_expander->phy);
2175 kfree(sas_expander);
2180 * mpi3mr_expander_node_remove - recursive removal of expander.
2181 * @mrioc: Adapter instance reference
2182 * @sas_expander: Expander device object
2184 * Removes expander object and freeing associated memory from
2185 * the sas_expander_list and removes the same from SAS TL, if
2186 * one of the attached device is an expander then it recursively
2187 * removes the expander device too.
2191 void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
2192 struct mpi3mr_sas_node *sas_expander)
2194 struct mpi3mr_sas_port *mr_sas_port, *next;
2195 unsigned long flags;
2198 /* remove sibling ports attached to this expander */
2199 list_for_each_entry_safe(mr_sas_port, next,
2200 &sas_expander->sas_port_list, port_list) {
2201 if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
2203 if (mr_sas_port->remote_identify.device_type ==
2205 mpi3mr_remove_device_by_sas_address(mrioc,
2206 mr_sas_port->remote_identify.sas_address,
2207 mr_sas_port->hba_port);
2208 else if (mr_sas_port->remote_identify.device_type ==
2209 SAS_EDGE_EXPANDER_DEVICE ||
2210 mr_sas_port->remote_identify.device_type ==
2211 SAS_FANOUT_EXPANDER_DEVICE)
2212 mpi3mr_expander_remove(mrioc,
2213 mr_sas_port->remote_identify.sas_address,
2214 mr_sas_port->hba_port);
2217 port_id = sas_expander->hba_port->port_id;
2218 mpi3mr_sas_port_remove(mrioc, sas_expander->sas_address,
2219 sas_expander->sas_address_parent, sas_expander->hba_port);
2221 ioc_info(mrioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
2222 sas_expander->handle, (unsigned long long)
2223 sas_expander->sas_address, port_id);
2225 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2226 list_del(&sas_expander->list);
2227 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2229 kfree(sas_expander->phy);
2230 kfree(sas_expander);
2234 * mpi3mr_expander_remove - Remove expander object
2235 * @mrioc: Adapter instance reference
2236 * @sas_address: Remove expander sas_address
2237 * @hba_port: HBA port reference
2239 * This function remove expander object, stored in
2240 * mrioc->sas_expander_list and removes it from the SAS TL by
2241 * calling mpi3mr_expander_node_remove().
2245 void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
2246 struct mpi3mr_hba_port *hba_port)
2248 struct mpi3mr_sas_node *sas_expander;
2249 unsigned long flags;
2251 if (mrioc->reset_in_progress || mrioc->pci_err_recovery)
2257 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2258 sas_expander = mpi3mr_expander_find_by_sas_address(mrioc, sas_address,
2260 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2262 mpi3mr_expander_node_remove(mrioc, sas_expander);
2267 * mpi3mr_get_sas_negotiated_logical_linkrate - get linkrate
2268 * @mrioc: Adapter instance reference
2269 * @tgtdev: Target device
2271 * This function identifies whether the target device is
2272 * attached directly or through expander and issues sas phy
2273 * page0 or expander phy page1 and gets the link rate, if there
2274 * is any failure in reading the pages then this returns link
2277 * Return: logical link rate.
2279 static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc,
2280 struct mpi3mr_tgt_dev *tgtdev)
2282 u8 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5, phy_number;
2283 struct mpi3_sas_expander_page1 expander_pg1;
2284 struct mpi3_sas_phy_page0 phy_pg0;
2288 phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2289 if (!(tgtdev->devpg0_flag & MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED)) {
2290 phynum_handle = ((phy_number<<MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT)
2291 | tgtdev->parent_handle);
2292 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2293 &expander_pg1, sizeof(expander_pg1),
2294 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2296 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2297 __FILE__, __LINE__, __func__);
2300 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2301 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2302 __FILE__, __LINE__, __func__);
2305 link_rate = (expander_pg1.negotiated_link_rate &
2306 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2307 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2310 if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
2311 sizeof(struct mpi3_sas_phy_page0),
2312 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy_number)) {
2313 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2314 __FILE__, __LINE__, __func__);
2317 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2318 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2319 __FILE__, __LINE__, __func__);
2322 link_rate = (phy_pg0.negotiated_link_rate &
2323 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2324 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2330 * mpi3mr_report_tgtdev_to_sas_transport - expose dev to SAS TL
2331 * @mrioc: Adapter instance reference
2332 * @tgtdev: Target device
2334 * This function exposes the target device after
2335 * preparing host_phy, setting up link rate etc.
2337 * Return: 0 on success, non-zero for failure.
2339 int mpi3mr_report_tgtdev_to_sas_transport(struct mpi3mr_ioc *mrioc,
2340 struct mpi3mr_tgt_dev *tgtdev)
2343 u8 link_rate, parent_phy_number;
2344 u64 sas_address_parent, sas_address;
2345 struct mpi3mr_hba_port *hba_port;
2348 if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2349 !mrioc->sas_transport_enabled)
2352 sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2353 if (!mrioc->sas_hba.num_phys)
2354 mpi3mr_sas_host_add(mrioc);
2356 mpi3mr_sas_host_refresh(mrioc);
2358 if (mpi3mr_get_sas_address(mrioc, tgtdev->parent_handle,
2359 &sas_address_parent) != 0) {
2360 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2361 __FILE__, __LINE__, __func__);
2364 tgtdev->dev_spec.sas_sata_inf.sas_address_parent = sas_address_parent;
2366 parent_phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2367 port_id = tgtdev->io_unit_port;
2369 hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
2371 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2372 __FILE__, __LINE__, __func__);
2375 tgtdev->dev_spec.sas_sata_inf.hba_port = hba_port;
2377 link_rate = mpi3mr_get_sas_negotiated_logical_linkrate(mrioc, tgtdev);
2379 mpi3mr_update_links(mrioc, sas_address_parent, tgtdev->dev_handle,
2380 parent_phy_number, link_rate, hba_port);
2382 tgtdev->host_exposed = 1;
2383 if (!mpi3mr_sas_port_add(mrioc, tgtdev->dev_handle,
2384 sas_address_parent, hba_port)) {
2386 } else if ((!tgtdev->starget) && (!mrioc->is_driver_loading)) {
2387 mpi3mr_sas_port_remove(mrioc, sas_address,
2388 sas_address_parent, hba_port);
2392 tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2393 tgtdev->host_exposed = 0;
2399 * mpi3mr_remove_tgtdev_from_sas_transport - remove from SAS TL
2400 * @mrioc: Adapter instance reference
2401 * @tgtdev: Target device
2403 * This function removes the target device
2407 void mpi3mr_remove_tgtdev_from_sas_transport(struct mpi3mr_ioc *mrioc,
2408 struct mpi3mr_tgt_dev *tgtdev)
2410 u64 sas_address_parent, sas_address;
2411 struct mpi3mr_hba_port *hba_port;
2413 if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2414 !mrioc->sas_transport_enabled)
2417 hba_port = tgtdev->dev_spec.sas_sata_inf.hba_port;
2418 sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2419 sas_address_parent = tgtdev->dev_spec.sas_sata_inf.sas_address_parent;
2420 mpi3mr_sas_port_remove(mrioc, sas_address, sas_address_parent,
2422 tgtdev->host_exposed = 0;
2423 tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2427 * mpi3mr_get_port_id_by_sas_phy - Get port ID of the given phy
2428 * @phy: SAS transport layer phy object
2430 * Return: Port number for valid ID else 0xFFFF
2432 static inline u8 mpi3mr_get_port_id_by_sas_phy(struct sas_phy *phy)
2435 struct mpi3mr_hba_port *hba_port = phy->hostdata;
2438 port_id = hba_port->port_id;
2444 * mpi3mr_get_port_id_by_rphy - Get Port number from SAS rphy
2446 * @mrioc: Adapter instance reference
2447 * @rphy: SAS transport layer remote phy object
2449 * Retrieves HBA port number in which the device pointed by the
2450 * rphy object is attached with.
2452 * Return: Valid port number on success else OxFFFF.
2454 static u8 mpi3mr_get_port_id_by_rphy(struct mpi3mr_ioc *mrioc, struct sas_rphy *rphy)
2456 struct mpi3mr_sas_node *sas_expander;
2457 struct mpi3mr_tgt_dev *tgtdev;
2458 unsigned long flags;
2464 if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
2465 rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) {
2466 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2467 list_for_each_entry(sas_expander, &mrioc->sas_expander_list,
2469 if (sas_expander->rphy == rphy) {
2470 port_id = sas_expander->hba_port->port_id;
2474 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2475 } else if (rphy->identify.device_type == SAS_END_DEVICE) {
2476 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2478 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2479 rphy->identify.sas_address, rphy);
2480 if (tgtdev && tgtdev->dev_spec.sas_sata_inf.hba_port) {
2482 tgtdev->dev_spec.sas_sata_inf.hba_port->port_id;
2483 mpi3mr_tgtdev_put(tgtdev);
2485 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2490 static inline struct mpi3mr_ioc *phy_to_mrioc(struct sas_phy *phy)
2492 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
2494 return shost_priv(shost);
2497 static inline struct mpi3mr_ioc *rphy_to_mrioc(struct sas_rphy *rphy)
2499 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
2501 return shost_priv(shost);
2504 /* report phy error log structure */
2505 struct phy_error_log_request {
2506 u8 smp_frame_type; /* 0x40 */
2507 u8 function; /* 0x11 */
2508 u8 allocated_response_length;
2509 u8 request_length; /* 02 */
2515 /* report phy error log reply structure */
2516 struct phy_error_log_reply {
2517 u8 smp_frame_type; /* 0x41 */
2518 u8 function; /* 0x11 */
2521 __be16 expander_change_count;
2525 __be32 invalid_dword;
2526 __be32 running_disparity_error;
2527 __be32 loss_of_dword_sync;
2528 __be32 phy_reset_problem;
2533 * mpi3mr_get_expander_phy_error_log - return expander counters:
2534 * @mrioc: Adapter instance reference
2535 * @phy: The SAS transport layer phy object
2537 * Return: 0 for success, non-zero for failure.
2540 static int mpi3mr_get_expander_phy_error_log(struct mpi3mr_ioc *mrioc,
2541 struct sas_phy *phy)
2543 struct mpi3_smp_passthrough_request mpi_request;
2544 struct mpi3_smp_passthrough_reply mpi_reply;
2545 struct phy_error_log_request *phy_error_log_request;
2546 struct phy_error_log_reply *phy_error_log_reply;
2549 void *data_out = NULL;
2550 dma_addr_t data_out_dma, data_in_dma;
2551 u32 data_out_sz, data_in_sz, sz;
2552 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2553 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2554 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2557 if (mrioc->reset_in_progress) {
2558 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2562 if (mrioc->pci_err_recovery) {
2563 ioc_err(mrioc, "%s: pci error recovery in progress!\n", __func__);
2567 data_out_sz = sizeof(struct phy_error_log_request);
2568 data_in_sz = sizeof(struct phy_error_log_reply);
2569 sz = data_out_sz + data_in_sz;
2570 data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2577 data_in_dma = data_out_dma + data_out_sz;
2578 phy_error_log_reply = data_out + data_out_sz;
2581 memset(data_out, 0, sz);
2582 phy_error_log_request = data_out;
2583 phy_error_log_request->smp_frame_type = 0x40;
2584 phy_error_log_request->function = 0x11;
2585 phy_error_log_request->request_length = 2;
2586 phy_error_log_request->allocated_response_length = 0;
2587 phy_error_log_request->phy_identifier = phy->number;
2589 memset(&mpi_request, 0, request_sz);
2590 memset(&mpi_reply, 0, reply_sz);
2591 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2592 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2593 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2594 mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2596 psge = &mpi_request.request_sge;
2597 mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2599 psge = &mpi_request.response_sge;
2600 mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2602 dprint_transport_info(mrioc,
2603 "sending phy error log SMP request to sas_address(0x%016llx), phy_id(%d)\n",
2604 (unsigned long long)phy->identify.sas_address, phy->number);
2606 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2607 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2610 dprint_transport_info(mrioc,
2611 "phy error log SMP request completed with ioc_status(0x%04x)\n",
2614 if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2615 dprint_transport_info(mrioc,
2616 "phy error log - reply data transfer size(%d)\n",
2617 le16_to_cpu(mpi_reply.response_data_length));
2619 if (le16_to_cpu(mpi_reply.response_data_length) !=
2620 sizeof(struct phy_error_log_reply))
2623 dprint_transport_info(mrioc,
2624 "phy error log - function_result(%d)\n",
2625 phy_error_log_reply->function_result);
2627 phy->invalid_dword_count =
2628 be32_to_cpu(phy_error_log_reply->invalid_dword);
2629 phy->running_disparity_error_count =
2630 be32_to_cpu(phy_error_log_reply->running_disparity_error);
2631 phy->loss_of_dword_sync_count =
2632 be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
2633 phy->phy_reset_problem_count =
2634 be32_to_cpu(phy_error_log_reply->phy_reset_problem);
2640 dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2647 * mpi3mr_transport_get_linkerrors - return phy error counters
2648 * @phy: The SAS transport layer phy object
2650 * This function retrieves the phy error log information of the
2651 * HBA or expander for which the phy belongs to
2653 * Return: 0 for success, non-zero for failure.
2655 static int mpi3mr_transport_get_linkerrors(struct sas_phy *phy)
2657 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2658 struct mpi3_sas_phy_page1 phy_pg1;
2662 rc = mpi3mr_parent_present(mrioc, phy);
2666 if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2667 return mpi3mr_get_expander_phy_error_log(mrioc, phy);
2669 memset(&phy_pg1, 0, sizeof(struct mpi3_sas_phy_page1));
2670 /* get hba phy error logs */
2671 if ((mpi3mr_cfg_get_sas_phy_pg1(mrioc, &ioc_status, &phy_pg1,
2672 sizeof(struct mpi3_sas_phy_page1),
2673 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number))) {
2674 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2675 __FILE__, __LINE__, __func__);
2679 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2680 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2681 __FILE__, __LINE__, __func__);
2684 phy->invalid_dword_count = le32_to_cpu(phy_pg1.invalid_dword_count);
2685 phy->running_disparity_error_count =
2686 le32_to_cpu(phy_pg1.running_disparity_error_count);
2687 phy->loss_of_dword_sync_count =
2688 le32_to_cpu(phy_pg1.loss_dword_synch_count);
2689 phy->phy_reset_problem_count =
2690 le32_to_cpu(phy_pg1.phy_reset_problem_count);
2695 * mpi3mr_transport_get_enclosure_identifier - Get Enclosure ID
2696 * @rphy: The SAS transport layer remote phy object
2697 * @identifier: Enclosure identifier to be returned
2699 * Returns the enclosure id for the device pointed by the remote
2702 * Return: 0 on success or -ENXIO
2705 mpi3mr_transport_get_enclosure_identifier(struct sas_rphy *rphy,
2708 struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2709 struct mpi3mr_tgt_dev *tgtdev = NULL;
2710 unsigned long flags;
2713 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2714 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2715 rphy->identify.sas_address, rphy);
2718 tgtdev->enclosure_logical_id;
2720 mpi3mr_tgtdev_put(tgtdev);
2725 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2731 * mpi3mr_transport_get_bay_identifier - Get bay ID
2732 * @rphy: The SAS transport layer remote phy object
2734 * Returns the slot id for the device pointed by the remote phy
2737 * Return: Valid slot ID on success or -ENXIO
2740 mpi3mr_transport_get_bay_identifier(struct sas_rphy *rphy)
2742 struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2743 struct mpi3mr_tgt_dev *tgtdev = NULL;
2744 unsigned long flags;
2747 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2748 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2749 rphy->identify.sas_address, rphy);
2752 mpi3mr_tgtdev_put(tgtdev);
2755 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2760 /* phy control request structure */
2761 struct phy_control_request {
2762 u8 smp_frame_type; /* 0x40 */
2763 u8 function; /* 0x91 */
2764 u8 allocated_response_length;
2765 u8 request_length; /* 0x09 */
2766 u16 expander_change_count;
2771 u64 attached_device_name;
2772 u8 programmed_min_physical_link_rate;
2773 u8 programmed_max_physical_link_rate;
2777 /* phy control reply structure */
2778 struct phy_control_reply {
2779 u8 smp_frame_type; /* 0x41 */
2780 u8 function; /* 0x11 */
2785 #define SMP_PHY_CONTROL_LINK_RESET (0x01)
2786 #define SMP_PHY_CONTROL_HARD_RESET (0x02)
2787 #define SMP_PHY_CONTROL_DISABLE (0x03)
2790 * mpi3mr_expander_phy_control - expander phy control
2791 * @mrioc: Adapter instance reference
2792 * @phy: The SAS transport layer phy object
2793 * @phy_operation: The phy operation to be executed
2795 * Issues SMP passthru phy control request to execute a specific
2796 * phy operation for a given expander device.
2798 * Return: 0 for success, non-zero for failure.
2801 mpi3mr_expander_phy_control(struct mpi3mr_ioc *mrioc,
2802 struct sas_phy *phy, u8 phy_operation)
2804 struct mpi3_smp_passthrough_request mpi_request;
2805 struct mpi3_smp_passthrough_reply mpi_reply;
2806 struct phy_control_request *phy_control_request;
2807 struct phy_control_reply *phy_control_reply;
2810 void *data_out = NULL;
2811 dma_addr_t data_out_dma;
2812 dma_addr_t data_in_dma;
2815 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2816 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2817 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2821 if (mrioc->reset_in_progress) {
2822 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2826 if (mrioc->pci_err_recovery) {
2827 ioc_err(mrioc, "%s: pci error recovery in progress!\n",
2832 data_out_sz = sizeof(struct phy_control_request);
2833 data_in_sz = sizeof(struct phy_control_reply);
2834 sz = data_out_sz + data_in_sz;
2835 data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2842 data_in_dma = data_out_dma + data_out_sz;
2843 phy_control_reply = data_out + data_out_sz;
2846 memset(data_out, 0, sz);
2848 phy_control_request = data_out;
2849 phy_control_request->smp_frame_type = 0x40;
2850 phy_control_request->function = 0x91;
2851 phy_control_request->request_length = 9;
2852 phy_control_request->allocated_response_length = 0;
2853 phy_control_request->phy_identifier = phy->number;
2854 phy_control_request->phy_operation = phy_operation;
2855 phy_control_request->programmed_min_physical_link_rate =
2856 phy->minimum_linkrate << 4;
2857 phy_control_request->programmed_max_physical_link_rate =
2858 phy->maximum_linkrate << 4;
2860 memset(&mpi_request, 0, request_sz);
2861 memset(&mpi_reply, 0, reply_sz);
2862 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2863 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2864 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2865 mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2867 psge = &mpi_request.request_sge;
2868 mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2870 psge = &mpi_request.response_sge;
2871 mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2873 dprint_transport_info(mrioc,
2874 "sending phy control SMP request to sas_address(0x%016llx), phy_id(%d) opcode(%d)\n",
2875 (unsigned long long)phy->identify.sas_address, phy->number,
2878 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2879 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2882 dprint_transport_info(mrioc,
2883 "phy control SMP request completed with ioc_status(0x%04x)\n",
2886 if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2887 dprint_transport_info(mrioc,
2888 "phy control - reply data transfer size(%d)\n",
2889 le16_to_cpu(mpi_reply.response_data_length));
2891 if (le16_to_cpu(mpi_reply.response_data_length) !=
2892 sizeof(struct phy_control_reply))
2894 dprint_transport_info(mrioc,
2895 "phy control - function_result(%d)\n",
2896 phy_control_reply->function_result);
2901 dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2908 * mpi3mr_transport_phy_reset - Reset a given phy
2909 * @phy: The SAS transport layer phy object
2910 * @hard_reset: Flag to indicate the type of reset
2912 * Return: 0 for success, non-zero for failure.
2915 mpi3mr_transport_phy_reset(struct sas_phy *phy, int hard_reset)
2917 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2918 struct mpi3_iounit_control_request mpi_request;
2919 struct mpi3_iounit_control_reply mpi_reply;
2920 u16 request_sz = sizeof(struct mpi3_iounit_control_request);
2921 u16 reply_sz = sizeof(struct mpi3_iounit_control_reply);
2925 rc = mpi3mr_parent_present(mrioc, phy);
2929 /* handle expander phys */
2930 if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2931 return mpi3mr_expander_phy_control(mrioc, phy,
2932 (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
2933 SMP_PHY_CONTROL_LINK_RESET);
2935 /* handle hba phys */
2936 memset(&mpi_request, 0, request_sz);
2937 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2938 mpi_request.function = MPI3_FUNCTION_IO_UNIT_CONTROL;
2939 mpi_request.operation = MPI3_CTRL_OP_SAS_PHY_CONTROL;
2940 mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_ACTION_INDEX] =
2941 (hard_reset ? MPI3_CTRL_ACTION_HARD_RESET :
2942 MPI3_CTRL_ACTION_LINK_RESET);
2943 mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_PHY_INDEX] =
2946 dprint_transport_info(mrioc,
2947 "sending phy reset request to sas_address(0x%016llx), phy_id(%d) hard_reset(%d)\n",
2948 (unsigned long long)phy->identify.sas_address, phy->number,
2951 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2952 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) {
2957 dprint_transport_info(mrioc,
2958 "phy reset request completed with ioc_status(0x%04x)\n",
2965 * mpi3mr_transport_phy_enable - enable/disable phys
2966 * @phy: The SAS transport layer phy object
2967 * @enable: flag to enable/disable, enable phy when true
2969 * This function enables/disables a given by executing required
2970 * configuration page changes or expander phy control command
2972 * Return: 0 for success, non-zero for failure.
2975 mpi3mr_transport_phy_enable(struct sas_phy *phy, int enable)
2977 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2978 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
2979 struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
2982 int i, discovery_active;
2984 rc = mpi3mr_parent_present(mrioc, phy);
2988 /* handle expander phys */
2989 if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2990 return mpi3mr_expander_phy_control(mrioc, phy,
2991 (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
2992 SMP_PHY_CONTROL_DISABLE);
2994 /* handle hba phys */
2995 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
2996 (mrioc->sas_hba.num_phys *
2997 sizeof(struct mpi3_sas_io_unit0_phy_data));
2998 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
2999 if (!sas_io_unit_pg0) {
3003 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
3004 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3005 __FILE__, __LINE__, __func__);
3010 /* unable to enable/disable phys when discovery is active */
3011 for (i = 0, discovery_active = 0; i < mrioc->sas_hba.num_phys ; i++) {
3012 if (sas_io_unit_pg0->phy_data[i].port_flags &
3013 MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS) {
3015 "discovery is active on port = %d, phy = %d\n"
3016 "\tunable to enable/disable phys, try again later!\n",
3017 sas_io_unit_pg0->phy_data[i].io_unit_port, i);
3018 discovery_active = 1;
3022 if (discovery_active) {
3027 if ((sas_io_unit_pg0->phy_data[phy->number].phy_flags &
3028 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
3029 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))) {
3030 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3031 __FILE__, __LINE__, __func__);
3036 /* read sas_iounit page 1 */
3037 sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3038 (mrioc->sas_hba.num_phys *
3039 sizeof(struct mpi3_sas_io_unit1_phy_data));
3040 sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3041 if (!sas_io_unit_pg1) {
3046 if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3047 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3048 __FILE__, __LINE__, __func__);
3054 sas_io_unit_pg1->phy_data[phy->number].phy_flags
3055 &= ~MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3057 sas_io_unit_pg1->phy_data[phy->number].phy_flags
3058 |= MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3060 mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz);
3064 mpi3mr_transport_phy_reset(phy, 0);
3067 kfree(sas_io_unit_pg1);
3068 kfree(sas_io_unit_pg0);
3073 * mpi3mr_transport_phy_speed - set phy min/max speed
3074 * @phy: The SAS transport later phy object
3075 * @rates: Rates defined as in sas_phy_linkrates
3077 * This function sets the link rates given in the rates
3078 * argument to the given phy by executing required configuration
3079 * page changes or expander phy control command
3081 * Return: 0 for success, non-zero for failure.
3084 mpi3mr_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
3086 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
3087 struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
3088 struct mpi3_sas_phy_page0 phy_pg0;
3092 rc = mpi3mr_parent_present(mrioc, phy);
3096 if (!rates->minimum_linkrate)
3097 rates->minimum_linkrate = phy->minimum_linkrate;
3098 else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
3099 rates->minimum_linkrate = phy->minimum_linkrate_hw;
3101 if (!rates->maximum_linkrate)
3102 rates->maximum_linkrate = phy->maximum_linkrate;
3103 else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
3104 rates->maximum_linkrate = phy->maximum_linkrate_hw;
3106 /* handle expander phys */
3107 if (phy->identify.sas_address != mrioc->sas_hba.sas_address) {
3108 phy->minimum_linkrate = rates->minimum_linkrate;
3109 phy->maximum_linkrate = rates->maximum_linkrate;
3110 return mpi3mr_expander_phy_control(mrioc, phy,
3111 SMP_PHY_CONTROL_LINK_RESET);
3114 /* handle hba phys */
3115 sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3116 (mrioc->sas_hba.num_phys *
3117 sizeof(struct mpi3_sas_io_unit1_phy_data));
3118 sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3119 if (!sas_io_unit_pg1) {
3124 if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3125 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3126 __FILE__, __LINE__, __func__);
3131 sas_io_unit_pg1->phy_data[phy->number].max_min_link_rate =
3132 (rates->minimum_linkrate + (rates->maximum_linkrate << 4));
3134 if (mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3135 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3136 __FILE__, __LINE__, __func__);
3142 mpi3mr_transport_phy_reset(phy, 0);
3144 /* read phy page 0, then update the rates in the sas transport phy */
3145 if (!mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
3146 sizeof(struct mpi3_sas_phy_page0),
3147 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number) &&
3148 (ioc_status == MPI3_IOCSTATUS_SUCCESS)) {
3149 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
3150 phy_pg0.programmed_link_rate &
3151 MPI3_SAS_PRATE_MIN_RATE_MASK);
3152 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
3153 phy_pg0.programmed_link_rate >> 4);
3154 phy->negotiated_linkrate =
3155 mpi3mr_convert_phy_link_rate(
3156 (phy_pg0.negotiated_link_rate &
3157 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK)
3158 >> MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
3162 kfree(sas_io_unit_pg1);
3167 * mpi3mr_map_smp_buffer - map BSG dma buffer
3168 * @dev: Generic device reference
3169 * @buf: BSG buffer pointer
3170 * @dma_addr: Physical address holder
3171 * @dma_len: Mapped DMA buffer length.
3172 * @p: Virtual address holder
3174 * This function maps the DMAable buffer
3176 * Return: 0 on success, non-zero on failure
3179 mpi3mr_map_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3180 dma_addr_t *dma_addr, size_t *dma_len, void **p)
3182 /* Check if the request is split across multiple segments */
3183 if (buf->sg_cnt > 1) {
3184 *p = dma_alloc_coherent(dev, buf->payload_len, dma_addr,
3188 *dma_len = buf->payload_len;
3190 if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
3192 *dma_addr = sg_dma_address(buf->sg_list);
3193 *dma_len = sg_dma_len(buf->sg_list);
3201 * mpi3mr_unmap_smp_buffer - unmap BSG dma buffer
3202 * @dev: Generic device reference
3203 * @buf: BSG buffer pointer
3204 * @dma_addr: Physical address to be unmapped
3205 * @p: Virtual address
3207 * This function unmaps the DMAable buffer
3210 mpi3mr_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3211 dma_addr_t dma_addr, void *p)
3214 dma_free_coherent(dev, buf->payload_len, p, dma_addr);
3216 dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL);
3220 * mpi3mr_transport_smp_handler - handler for smp passthru
3221 * @job: BSG job reference
3222 * @shost: SCSI host object reference
3223 * @rphy: SAS transport rphy object pointing the expander
3225 * This is used primarily by smp utils for sending the SMP
3226 * commands to the expanders attached to the controller
3229 mpi3mr_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
3230 struct sas_rphy *rphy)
3232 struct mpi3mr_ioc *mrioc = shost_priv(shost);
3233 struct mpi3_smp_passthrough_request mpi_request;
3234 struct mpi3_smp_passthrough_reply mpi_reply;
3237 dma_addr_t dma_addr_in;
3238 dma_addr_t dma_addr_out;
3239 void *addr_in = NULL;
3240 void *addr_out = NULL;
3243 unsigned int reslen = 0;
3244 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
3245 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
3246 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
3249 if (mrioc->reset_in_progress) {
3250 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
3255 if (mrioc->pci_err_recovery) {
3256 ioc_err(mrioc, "%s: pci error recovery in progress!\n", __func__);
3261 rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3262 &dma_addr_out, &dma_len_out, &addr_out);
3267 sg_copy_to_buffer(job->request_payload.sg_list,
3268 job->request_payload.sg_cnt, addr_out,
3269 job->request_payload.payload_len);
3271 rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3272 &dma_addr_in, &dma_len_in, &addr_in);
3276 memset(&mpi_request, 0, request_sz);
3277 memset(&mpi_reply, 0, reply_sz);
3278 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
3279 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
3280 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_rphy(mrioc, rphy);
3281 mpi_request.sas_address = ((rphy) ?
3282 cpu_to_le64(rphy->identify.sas_address) :
3283 cpu_to_le64(mrioc->sas_hba.sas_address));
3284 psge = &mpi_request.request_sge;
3285 mpi3mr_add_sg_single(psge, sgl_flags, dma_len_out - 4, dma_addr_out);
3287 psge = &mpi_request.response_sge;
3288 mpi3mr_add_sg_single(psge, sgl_flags, dma_len_in - 4, dma_addr_in);
3290 dprint_transport_info(mrioc, "sending SMP request\n");
3292 rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
3293 &mpi_reply, reply_sz,
3294 MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
3298 dprint_transport_info(mrioc,
3299 "SMP request completed with ioc_status(0x%04x)\n", ioc_status);
3301 dprint_transport_info(mrioc,
3302 "SMP request - reply data transfer size(%d)\n",
3303 le16_to_cpu(mpi_reply.response_data_length));
3305 memcpy(job->reply, &mpi_reply, reply_sz);
3306 job->reply_len = reply_sz;
3307 reslen = le16_to_cpu(mpi_reply.response_data_length);
3310 sg_copy_from_buffer(job->reply_payload.sg_list,
3311 job->reply_payload.sg_cnt, addr_in,
3312 job->reply_payload.payload_len);
3316 mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3317 dma_addr_in, addr_in);
3319 mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3320 dma_addr_out, addr_out);
3322 bsg_job_done(job, rc, reslen);
3325 struct sas_function_template mpi3mr_transport_functions = {
3326 .get_linkerrors = mpi3mr_transport_get_linkerrors,
3327 .get_enclosure_identifier = mpi3mr_transport_get_enclosure_identifier,
3328 .get_bay_identifier = mpi3mr_transport_get_bay_identifier,
3329 .phy_reset = mpi3mr_transport_phy_reset,
3330 .phy_enable = mpi3mr_transport_phy_enable,
3331 .set_phy_speed = mpi3mr_transport_phy_speed,
3332 .smp_handler = mpi3mr_transport_smp_handler,
3335 struct scsi_transport_template *mpi3mr_transport_template;