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 data_out_sz = sizeof(struct rep_manu_request);
155 data_in_sz = sizeof(struct rep_manu_reply);
156 data_out = dma_alloc_coherent(&mrioc->pdev->dev,
157 data_out_sz + data_in_sz, &data_out_dma, GFP_KERNEL);
163 data_in_dma = data_out_dma + data_out_sz;
164 manufacture_reply = data_out + data_out_sz;
166 manufacture_request = data_out;
167 manufacture_request->smp_frame_type = 0x40;
168 manufacture_request->function = 1;
169 manufacture_request->reserved = 0;
170 manufacture_request->request_length = 0;
172 memset(&mpi_request, 0, request_sz);
173 memset(&mpi_reply, 0, reply_sz);
174 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
175 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
176 mpi_request.io_unit_port = (u8) port_id;
177 mpi_request.sas_address = cpu_to_le64(sas_address);
179 psge = &mpi_request.request_sge;
180 mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
182 psge = &mpi_request.response_sge;
183 mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
185 dprint_transport_info(mrioc,
186 "sending report manufacturer SMP request to sas_address(0x%016llx), port(%d)\n",
187 (unsigned long long)sas_address, port_id);
189 rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
190 &mpi_reply, reply_sz,
191 MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
195 dprint_transport_info(mrioc,
196 "report manufacturer SMP request completed with ioc_status(0x%04x)\n",
199 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
204 dprint_transport_info(mrioc,
205 "report manufacturer - reply data transfer size(%d)\n",
206 le16_to_cpu(mpi_reply.response_data_length));
208 if (le16_to_cpu(mpi_reply.response_data_length) !=
209 sizeof(struct rep_manu_reply)) {
214 memtostr(edev->vendor_id, manufacture_reply->vendor_id);
215 memtostr(edev->product_id, manufacture_reply->product_id);
216 memtostr(edev->product_rev, manufacture_reply->product_rev);
217 edev->level = manufacture_reply->sas_format & 1;
219 memtostr(edev->component_vendor_id,
220 manufacture_reply->component_vendor_id);
221 tmp = (u8 *)&manufacture_reply->component_id;
222 edev->component_id = tmp[0] << 8 | tmp[1];
223 edev->component_revision_id =
224 manufacture_reply->component_revision_id;
229 dma_free_coherent(&mrioc->pdev->dev, data_out_sz + data_in_sz,
230 data_out, data_out_dma);
236 * __mpi3mr_expander_find_by_handle - expander search by handle
237 * @mrioc: Adapter instance reference
238 * @handle: Firmware device handle of the expander
240 * Context: The caller should acquire sas_node_lock
242 * This searches for expander device based on handle, then
243 * returns the sas_node object.
245 * Return: Expander sas_node object reference or NULL
247 struct mpi3mr_sas_node *__mpi3mr_expander_find_by_handle(struct mpi3mr_ioc
250 struct mpi3mr_sas_node *sas_expander, *r;
253 list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
254 if (sas_expander->handle != handle)
264 * mpi3mr_is_expander_device - if device is an expander
265 * @device_info: Bitfield providing information about the device
267 * Return: 1 if the device is expander device, else 0.
269 u8 mpi3mr_is_expander_device(u16 device_info)
271 if ((device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) ==
272 MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER)
279 * mpi3mr_get_sas_address - retrieve sas_address for handle
280 * @mrioc: Adapter instance reference
281 * @handle: Firmware device handle
282 * @sas_address: Address to hold sas address
284 * This function issues device page0 read for a given device
285 * handle and gets the SAS address and return it back
287 * Return: 0 for success, non-zero for failure
289 static int mpi3mr_get_sas_address(struct mpi3mr_ioc *mrioc, u16 handle,
292 struct mpi3_device_page0 dev_pg0;
294 struct mpi3_device0_sas_sata_format *sasinf;
298 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
299 sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
301 ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
305 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
306 ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
307 handle, ioc_status, __FILE__, __LINE__, __func__);
311 if (le16_to_cpu(dev_pg0.flags) &
312 MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE)
313 *sas_address = mrioc->sas_hba.sas_address;
314 else if (dev_pg0.device_form == MPI3_DEVICE_DEVFORM_SAS_SATA) {
315 sasinf = &dev_pg0.device_specific.sas_sata_format;
316 *sas_address = le64_to_cpu(sasinf->sas_address);
318 ioc_err(mrioc, "%s: device_form(%d) is not SAS_SATA\n",
319 __func__, dev_pg0.device_form);
326 * __mpi3mr_get_tgtdev_by_addr - target device search
327 * @mrioc: Adapter instance reference
328 * @sas_address: SAS address of the device
329 * @hba_port: HBA port entry
331 * This searches for target device from sas address and hba port
332 * pointer then return mpi3mr_tgt_dev object.
334 * Return: Valid tget_dev or NULL
336 static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc,
337 u64 sas_address, struct mpi3mr_hba_port *hba_port)
339 struct mpi3mr_tgt_dev *tgtdev;
341 assert_spin_locked(&mrioc->tgtdev_lock);
343 list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list)
344 if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) &&
345 (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address)
346 && (tgtdev->dev_spec.sas_sata_inf.hba_port == hba_port))
350 mpi3mr_tgtdev_get(tgtdev);
355 * mpi3mr_get_tgtdev_by_addr - target device search
356 * @mrioc: Adapter instance reference
357 * @sas_address: SAS address of the device
358 * @hba_port: HBA port entry
360 * This searches for target device from sas address and hba port
361 * pointer then return mpi3mr_tgt_dev object.
363 * Context: This function will acquire tgtdev_lock and will
364 * release before returning the mpi3mr_tgt_dev object.
366 * Return: Valid tget_dev or NULL
368 static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc,
369 u64 sas_address, struct mpi3mr_hba_port *hba_port)
371 struct mpi3mr_tgt_dev *tgtdev = NULL;
377 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
378 tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc, sas_address, hba_port);
379 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
386 * mpi3mr_remove_device_by_sas_address - remove the device
387 * @mrioc: Adapter instance reference
388 * @sas_address: SAS address of the device
389 * @hba_port: HBA port entry
391 * This searches for target device using sas address and hba
392 * port pointer then removes it from the OS.
396 static void mpi3mr_remove_device_by_sas_address(struct mpi3mr_ioc *mrioc,
397 u64 sas_address, struct mpi3mr_hba_port *hba_port)
399 struct mpi3mr_tgt_dev *tgtdev = NULL;
401 u8 was_on_tgtdev_list = 0;
406 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
407 tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc,
408 sas_address, hba_port);
410 if (!list_empty(&tgtdev->list)) {
411 list_del_init(&tgtdev->list);
412 was_on_tgtdev_list = 1;
413 mpi3mr_tgtdev_put(tgtdev);
416 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
417 if (was_on_tgtdev_list) {
418 if (tgtdev->host_exposed)
419 mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev);
420 mpi3mr_tgtdev_put(tgtdev);
425 * __mpi3mr_get_tgtdev_by_addr_and_rphy - target device search
426 * @mrioc: Adapter instance reference
427 * @sas_address: SAS address of the device
428 * @rphy: SAS transport layer rphy object
430 * This searches for target device from sas address and rphy
431 * pointer then return mpi3mr_tgt_dev object.
433 * Return: Valid tget_dev or NULL
435 struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr_and_rphy(
436 struct mpi3mr_ioc *mrioc, u64 sas_address, struct sas_rphy *rphy)
438 struct mpi3mr_tgt_dev *tgtdev;
440 assert_spin_locked(&mrioc->tgtdev_lock);
442 list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list)
443 if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) &&
444 (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address)
445 && (tgtdev->dev_spec.sas_sata_inf.rphy == rphy))
449 mpi3mr_tgtdev_get(tgtdev);
454 * mpi3mr_expander_find_by_sas_address - sas expander search
455 * @mrioc: Adapter instance reference
456 * @sas_address: SAS address of expander
457 * @hba_port: HBA port entry
459 * Return: A valid SAS expander node or NULL.
462 static struct mpi3mr_sas_node *mpi3mr_expander_find_by_sas_address(
463 struct mpi3mr_ioc *mrioc, u64 sas_address,
464 struct mpi3mr_hba_port *hba_port)
466 struct mpi3mr_sas_node *sas_expander, *r = NULL;
471 list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
472 if ((sas_expander->sas_address != sas_address) ||
473 (sas_expander->hba_port != hba_port))
483 * __mpi3mr_sas_node_find_by_sas_address - sas node search
484 * @mrioc: Adapter instance reference
485 * @sas_address: SAS address of expander or sas host
486 * @hba_port: HBA port entry
487 * Context: Caller should acquire mrioc->sas_node_lock.
489 * If the SAS address indicates the device is direct attached to
490 * the controller (controller's SAS address) then the SAS node
491 * associated with the controller is returned back else the SAS
492 * address and hba port are used to identify the exact expander
493 * and the associated sas_node object is returned. If there is
494 * no match NULL is returned.
496 * Return: A valid SAS node or NULL.
499 static struct mpi3mr_sas_node *__mpi3mr_sas_node_find_by_sas_address(
500 struct mpi3mr_ioc *mrioc, u64 sas_address,
501 struct mpi3mr_hba_port *hba_port)
504 if (mrioc->sas_hba.sas_address == sas_address)
505 return &mrioc->sas_hba;
506 return mpi3mr_expander_find_by_sas_address(mrioc, sas_address,
511 * mpi3mr_parent_present - Is parent present for a phy
512 * @mrioc: Adapter instance reference
513 * @phy: SAS transport layer phy object
515 * Return: 0 if parent is present else non-zero
517 static int mpi3mr_parent_present(struct mpi3mr_ioc *mrioc, struct sas_phy *phy)
520 struct mpi3mr_hba_port *hba_port = phy->hostdata;
522 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
523 if (__mpi3mr_sas_node_find_by_sas_address(mrioc,
524 phy->identify.sas_address,
526 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
529 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
534 * mpi3mr_convert_phy_link_rate -
535 * @link_rate: link rate as defined in the MPI header
537 * Convert link_rate from mpi format into sas_transport layer
540 * Return: A valid SAS transport layer defined link rate
542 static enum sas_linkrate mpi3mr_convert_phy_link_rate(u8 link_rate)
544 enum sas_linkrate rc;
547 case MPI3_SAS_NEG_LINK_RATE_1_5:
548 rc = SAS_LINK_RATE_1_5_GBPS;
550 case MPI3_SAS_NEG_LINK_RATE_3_0:
551 rc = SAS_LINK_RATE_3_0_GBPS;
553 case MPI3_SAS_NEG_LINK_RATE_6_0:
554 rc = SAS_LINK_RATE_6_0_GBPS;
556 case MPI3_SAS_NEG_LINK_RATE_12_0:
557 rc = SAS_LINK_RATE_12_0_GBPS;
559 case MPI3_SAS_NEG_LINK_RATE_22_5:
560 rc = SAS_LINK_RATE_22_5_GBPS;
562 case MPI3_SAS_NEG_LINK_RATE_PHY_DISABLED:
563 rc = SAS_PHY_DISABLED;
565 case MPI3_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
566 rc = SAS_LINK_RATE_FAILED;
568 case MPI3_SAS_NEG_LINK_RATE_PORT_SELECTOR:
569 rc = SAS_SATA_PORT_SELECTOR;
571 case MPI3_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
572 rc = SAS_PHY_RESET_IN_PROGRESS;
574 case MPI3_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
575 case MPI3_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
577 rc = SAS_LINK_RATE_UNKNOWN;
584 * mpi3mr_delete_sas_phy - Remove a single phy from port
585 * @mrioc: Adapter instance reference
586 * @mr_sas_port: Internal Port object
587 * @mr_sas_phy: Internal Phy object
591 static void mpi3mr_delete_sas_phy(struct mpi3mr_ioc *mrioc,
592 struct mpi3mr_sas_port *mr_sas_port,
593 struct mpi3mr_sas_phy *mr_sas_phy)
595 u64 sas_address = mr_sas_port->remote_identify.sas_address;
597 dev_info(&mr_sas_phy->phy->dev,
598 "remove: sas_address(0x%016llx), phy(%d)\n",
599 (unsigned long long) sas_address, mr_sas_phy->phy_id);
601 list_del(&mr_sas_phy->port_siblings);
602 mr_sas_port->num_phys--;
603 mr_sas_port->phy_mask &= ~(1 << mr_sas_phy->phy_id);
604 if (mr_sas_port->lowest_phy == mr_sas_phy->phy_id)
605 mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
606 sas_port_delete_phy(mr_sas_port->port, mr_sas_phy->phy);
607 mr_sas_phy->phy_belongs_to_port = 0;
611 * mpi3mr_add_sas_phy - Adding a single phy to a port
612 * @mrioc: Adapter instance reference
613 * @mr_sas_port: Internal Port object
614 * @mr_sas_phy: Internal Phy object
618 static void mpi3mr_add_sas_phy(struct mpi3mr_ioc *mrioc,
619 struct mpi3mr_sas_port *mr_sas_port,
620 struct mpi3mr_sas_phy *mr_sas_phy)
622 u64 sas_address = mr_sas_port->remote_identify.sas_address;
624 dev_info(&mr_sas_phy->phy->dev,
625 "add: sas_address(0x%016llx), phy(%d)\n", (unsigned long long)
626 sas_address, mr_sas_phy->phy_id);
628 list_add_tail(&mr_sas_phy->port_siblings, &mr_sas_port->phy_list);
629 mr_sas_port->num_phys++;
630 mr_sas_port->phy_mask |= (1 << mr_sas_phy->phy_id);
631 if (mr_sas_phy->phy_id < mr_sas_port->lowest_phy)
632 mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
633 sas_port_add_phy(mr_sas_port->port, mr_sas_phy->phy);
634 mr_sas_phy->phy_belongs_to_port = 1;
638 * mpi3mr_add_phy_to_an_existing_port - add phy to existing port
639 * @mrioc: Adapter instance reference
640 * @mr_sas_node: Internal sas node object (expander or host)
641 * @mr_sas_phy: Internal Phy object *
642 * @sas_address: SAS address of device/expander were phy needs
644 * @hba_port: HBA port entry
648 static void mpi3mr_add_phy_to_an_existing_port(struct mpi3mr_ioc *mrioc,
649 struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy,
650 u64 sas_address, struct mpi3mr_hba_port *hba_port)
652 struct mpi3mr_sas_port *mr_sas_port;
653 struct mpi3mr_sas_phy *srch_phy;
655 if (mr_sas_phy->phy_belongs_to_port == 1)
661 list_for_each_entry(mr_sas_port, &mr_sas_node->sas_port_list,
663 if (mr_sas_port->remote_identify.sas_address !=
666 if (mr_sas_port->hba_port != hba_port)
668 list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
670 if (srch_phy == mr_sas_phy)
673 mpi3mr_add_sas_phy(mrioc, mr_sas_port, mr_sas_phy);
679 * mpi3mr_delete_sas_port - helper function to removing a port
680 * @mrioc: Adapter instance reference
681 * @mr_sas_port: Internal Port object
685 static void mpi3mr_delete_sas_port(struct mpi3mr_ioc *mrioc,
686 struct mpi3mr_sas_port *mr_sas_port)
688 u64 sas_address = mr_sas_port->remote_identify.sas_address;
689 struct mpi3mr_hba_port *hba_port = mr_sas_port->hba_port;
690 enum sas_device_type device_type =
691 mr_sas_port->remote_identify.device_type;
693 dev_info(&mr_sas_port->port->dev,
694 "remove: sas_address(0x%016llx)\n",
695 (unsigned long long) sas_address);
697 if (device_type == SAS_END_DEVICE)
698 mpi3mr_remove_device_by_sas_address(mrioc, sas_address,
701 else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
702 device_type == SAS_FANOUT_EXPANDER_DEVICE)
703 mpi3mr_expander_remove(mrioc, sas_address, hba_port);
707 * mpi3mr_del_phy_from_an_existing_port - del phy from a port
708 * @mrioc: Adapter instance reference
709 * @mr_sas_node: Internal sas node object (expander or host)
710 * @mr_sas_phy: Internal Phy object
714 static void mpi3mr_del_phy_from_an_existing_port(struct mpi3mr_ioc *mrioc,
715 struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy)
717 struct mpi3mr_sas_port *mr_sas_port, *next;
718 struct mpi3mr_sas_phy *srch_phy;
720 if (mr_sas_phy->phy_belongs_to_port == 0)
723 list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
725 list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
727 if (srch_phy != mr_sas_phy)
729 if ((mr_sas_port->num_phys == 1) &&
730 !mrioc->reset_in_progress)
731 mpi3mr_delete_sas_port(mrioc, mr_sas_port);
733 mpi3mr_delete_sas_phy(mrioc, mr_sas_port,
741 * mpi3mr_sas_port_sanity_check - sanity check while adding port
742 * @mrioc: Adapter instance reference
743 * @mr_sas_node: Internal sas node object (expander or host)
744 * @sas_address: SAS address of device/expander
745 * @hba_port: HBA port entry
747 * Verifies whether the Phys attached to a device with the given
748 * SAS address already belongs to an existing sas port if so
749 * will remove those phys from the sas port
753 static void mpi3mr_sas_port_sanity_check(struct mpi3mr_ioc *mrioc,
754 struct mpi3mr_sas_node *mr_sas_node, u64 sas_address,
755 struct mpi3mr_hba_port *hba_port)
759 for (i = 0; i < mr_sas_node->num_phys; i++) {
760 if ((mr_sas_node->phy[i].remote_identify.sas_address !=
761 sas_address) || (mr_sas_node->phy[i].hba_port != hba_port))
763 if (mr_sas_node->phy[i].phy_belongs_to_port == 1)
764 mpi3mr_del_phy_from_an_existing_port(mrioc,
765 mr_sas_node, &mr_sas_node->phy[i]);
770 * mpi3mr_set_identify - set identify for phys and end devices
771 * @mrioc: Adapter instance reference
772 * @handle: Firmware device handle
773 * @identify: SAS transport layer's identify info
775 * Populates sas identify info for a specific device.
777 * Return: 0 for success, non-zero for failure.
779 static int mpi3mr_set_identify(struct mpi3mr_ioc *mrioc, u16 handle,
780 struct sas_identify *identify)
783 struct mpi3_device_page0 device_pg0;
784 struct mpi3_device0_sas_sata_format *sasinf;
788 if (mrioc->reset_in_progress) {
789 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
793 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &device_pg0,
794 sizeof(device_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, handle))) {
795 ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
799 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
800 ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
801 handle, ioc_status, __FILE__, __LINE__, __func__);
805 memset(identify, 0, sizeof(struct sas_identify));
806 sasinf = &device_pg0.device_specific.sas_sata_format;
807 device_info = le16_to_cpu(sasinf->device_info);
810 identify->sas_address = le64_to_cpu(sasinf->sas_address);
812 /* phy number of the parent device this device is linked to */
813 identify->phy_identifier = sasinf->phy_num;
816 switch (device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) {
817 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_NO_DEVICE:
818 identify->device_type = SAS_PHY_UNUSED;
820 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE:
821 identify->device_type = SAS_END_DEVICE;
823 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER:
824 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
828 /* initiator_port_protocols */
829 if (device_info & MPI3_SAS_DEVICE_INFO_SSP_INITIATOR)
830 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
831 /* MPI3.0 doesn't have define for SATA INIT so setting both here*/
832 if (device_info & MPI3_SAS_DEVICE_INFO_STP_INITIATOR)
833 identify->initiator_port_protocols |= (SAS_PROTOCOL_STP |
835 if (device_info & MPI3_SAS_DEVICE_INFO_SMP_INITIATOR)
836 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
838 /* target_port_protocols */
839 if (device_info & MPI3_SAS_DEVICE_INFO_SSP_TARGET)
840 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
841 /* MPI3.0 doesn't have define for STP Target so setting both here*/
842 if (device_info & MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET)
843 identify->target_port_protocols |= (SAS_PROTOCOL_STP |
845 if (device_info & MPI3_SAS_DEVICE_INFO_SMP_TARGET)
846 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
851 * mpi3mr_add_host_phy - report sas_host phy to SAS transport
852 * @mrioc: Adapter instance reference
853 * @mr_sas_phy: Internal Phy object
854 * @phy_pg0: SAS phy page 0
855 * @parent_dev: Prent device class object
857 * Return: 0 for success, non-zero for failure.
859 static int mpi3mr_add_host_phy(struct mpi3mr_ioc *mrioc,
860 struct mpi3mr_sas_phy *mr_sas_phy, struct mpi3_sas_phy_page0 phy_pg0,
861 struct device *parent_dev)
864 int phy_index = mr_sas_phy->phy_id;
867 INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
868 phy = sas_phy_alloc(parent_dev, phy_index);
870 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
871 __FILE__, __LINE__, __func__);
874 if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle,
875 &mr_sas_phy->identify))) {
876 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
877 __FILE__, __LINE__, __func__);
881 phy->identify = mr_sas_phy->identify;
882 mr_sas_phy->attached_handle = le16_to_cpu(phy_pg0.attached_dev_handle);
883 if (mr_sas_phy->attached_handle)
884 mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle,
885 &mr_sas_phy->remote_identify);
886 phy->identify.phy_identifier = mr_sas_phy->phy_id;
887 phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate(
888 (phy_pg0.negotiated_link_rate &
889 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
890 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
891 phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate(
892 phy_pg0.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK);
893 phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate(
894 phy_pg0.hw_link_rate >> 4);
895 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
896 phy_pg0.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK);
897 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
898 phy_pg0.programmed_link_rate >> 4);
899 phy->hostdata = mr_sas_phy->hba_port;
901 if ((sas_phy_add(phy))) {
902 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
903 __FILE__, __LINE__, __func__);
907 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
909 "add: handle(0x%04x), sas_address(0x%016llx)\n"
910 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
911 mr_sas_phy->handle, (unsigned long long)
912 mr_sas_phy->identify.sas_address,
913 mr_sas_phy->attached_handle,
915 mr_sas_phy->remote_identify.sas_address);
916 mr_sas_phy->phy = phy;
921 * mpi3mr_add_expander_phy - report expander phy to transport
922 * @mrioc: Adapter instance reference
923 * @mr_sas_phy: Internal Phy object
924 * @expander_pg1: SAS Expander page 1
925 * @parent_dev: Parent device class object
927 * Return: 0 for success, non-zero for failure.
929 static int mpi3mr_add_expander_phy(struct mpi3mr_ioc *mrioc,
930 struct mpi3mr_sas_phy *mr_sas_phy,
931 struct mpi3_sas_expander_page1 expander_pg1,
932 struct device *parent_dev)
935 int phy_index = mr_sas_phy->phy_id;
937 INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
938 phy = sas_phy_alloc(parent_dev, phy_index);
940 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
941 __FILE__, __LINE__, __func__);
944 if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle,
945 &mr_sas_phy->identify))) {
946 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
947 __FILE__, __LINE__, __func__);
951 phy->identify = mr_sas_phy->identify;
952 mr_sas_phy->attached_handle =
953 le16_to_cpu(expander_pg1.attached_dev_handle);
954 if (mr_sas_phy->attached_handle)
955 mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle,
956 &mr_sas_phy->remote_identify);
957 phy->identify.phy_identifier = mr_sas_phy->phy_id;
958 phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate(
959 (expander_pg1.negotiated_link_rate &
960 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
961 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
962 phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate(
963 expander_pg1.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK);
964 phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate(
965 expander_pg1.hw_link_rate >> 4);
966 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
967 expander_pg1.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK);
968 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
969 expander_pg1.programmed_link_rate >> 4);
970 phy->hostdata = mr_sas_phy->hba_port;
972 if ((sas_phy_add(phy))) {
973 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
974 __FILE__, __LINE__, __func__);
978 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
980 "add: handle(0x%04x), sas_address(0x%016llx)\n"
981 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
982 mr_sas_phy->handle, (unsigned long long)
983 mr_sas_phy->identify.sas_address,
984 mr_sas_phy->attached_handle,
986 mr_sas_phy->remote_identify.sas_address);
987 mr_sas_phy->phy = phy;
992 * mpi3mr_alloc_hba_port - alloc hba port object
993 * @mrioc: Adapter instance reference
994 * @port_id: Port number
996 * Alloc memory for hba port object.
998 static struct mpi3mr_hba_port *
999 mpi3mr_alloc_hba_port(struct mpi3mr_ioc *mrioc, u16 port_id)
1001 struct mpi3mr_hba_port *hba_port;
1003 hba_port = kzalloc(sizeof(struct mpi3mr_hba_port),
1007 hba_port->port_id = port_id;
1008 ioc_info(mrioc, "hba_port entry: %p, port: %d is added to hba_port list\n",
1009 hba_port, hba_port->port_id);
1010 list_add_tail(&hba_port->list, &mrioc->hba_port_table_list);
1015 * mpi3mr_get_hba_port_by_id - find hba port by id
1016 * @mrioc: Adapter instance reference
1017 * @port_id - Port ID to search
1019 * Return: mpi3mr_hba_port reference for the matched port
1022 struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc,
1025 struct mpi3mr_hba_port *port, *port_next;
1027 list_for_each_entry_safe(port, port_next,
1028 &mrioc->hba_port_table_list, list) {
1029 if (port->port_id != port_id)
1031 if (port->flags & MPI3MR_HBA_PORT_FLAG_DIRTY)
1040 * mpi3mr_update_links - refreshing SAS phy link changes
1041 * @mrioc: Adapter instance reference
1042 * @sas_address_parent: SAS address of parent expander or host
1043 * @handle: Firmware device handle of attached device
1044 * @phy_number: Phy number
1045 * @link_rate: New link rate
1046 * @hba_port: HBA port entry
1050 void mpi3mr_update_links(struct mpi3mr_ioc *mrioc,
1051 u64 sas_address_parent, u16 handle, u8 phy_number, u8 link_rate,
1052 struct mpi3mr_hba_port *hba_port)
1054 unsigned long flags;
1055 struct mpi3mr_sas_node *mr_sas_node;
1056 struct mpi3mr_sas_phy *mr_sas_phy;
1058 if (mrioc->reset_in_progress)
1061 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1062 mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1063 sas_address_parent, hba_port);
1065 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1069 mr_sas_phy = &mr_sas_node->phy[phy_number];
1070 mr_sas_phy->attached_handle = handle;
1071 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1072 if (handle && (link_rate >= MPI3_SAS_NEG_LINK_RATE_1_5)) {
1073 mpi3mr_set_identify(mrioc, handle,
1074 &mr_sas_phy->remote_identify);
1075 mpi3mr_add_phy_to_an_existing_port(mrioc, mr_sas_node,
1076 mr_sas_phy, mr_sas_phy->remote_identify.sas_address,
1079 memset(&mr_sas_phy->remote_identify, 0, sizeof(struct
1082 if (mr_sas_phy->phy)
1083 mr_sas_phy->phy->negotiated_linkrate =
1084 mpi3mr_convert_phy_link_rate(link_rate);
1086 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1087 dev_info(&mr_sas_phy->phy->dev,
1088 "refresh: parent sas_address(0x%016llx),\n"
1089 "\tlink_rate(0x%02x), phy(%d)\n"
1090 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
1091 (unsigned long long)sas_address_parent,
1092 link_rate, phy_number, handle, (unsigned long long)
1093 mr_sas_phy->remote_identify.sas_address);
1097 * mpi3mr_sas_host_refresh - refreshing sas host object contents
1098 * @mrioc: Adapter instance reference
1100 * This function refreshes the controllers phy information and
1101 * updates the SAS transport layer with updated information,
1102 * this is executed for each device addition or device info
1107 void mpi3mr_sas_host_refresh(struct mpi3mr_ioc *mrioc)
1111 u16 sz, port_id, attached_handle;
1112 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1114 dprint_transport_info(mrioc,
1115 "updating handles for sas_host(0x%016llx)\n",
1116 (unsigned long long)mrioc->sas_hba.sas_address);
1118 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1119 (mrioc->sas_hba.num_phys *
1120 sizeof(struct mpi3_sas_io_unit0_phy_data));
1121 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1122 if (!sas_io_unit_pg0)
1124 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1125 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1126 __FILE__, __LINE__, __func__);
1130 mrioc->sas_hba.handle = 0;
1131 for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1132 if (sas_io_unit_pg0->phy_data[i].phy_flags &
1133 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
1134 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))
1137 sas_io_unit_pg0->phy_data[i].negotiated_link_rate >> 4;
1138 if (!mrioc->sas_hba.handle)
1139 mrioc->sas_hba.handle = le16_to_cpu(
1140 sas_io_unit_pg0->phy_data[i].controller_dev_handle);
1141 port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1142 if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
1143 if (!mpi3mr_alloc_hba_port(mrioc, port_id))
1146 mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle;
1147 attached_handle = le16_to_cpu(
1148 sas_io_unit_pg0->phy_data[i].attached_dev_handle);
1149 if (attached_handle && link_rate < MPI3_SAS_NEG_LINK_RATE_1_5)
1150 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5;
1151 mrioc->sas_hba.phy[i].hba_port =
1152 mpi3mr_get_hba_port_by_id(mrioc, port_id);
1153 mpi3mr_update_links(mrioc, mrioc->sas_hba.sas_address,
1154 attached_handle, i, link_rate,
1155 mrioc->sas_hba.phy[i].hba_port);
1158 kfree(sas_io_unit_pg0);
1162 * mpi3mr_sas_host_add - create sas host object
1163 * @mrioc: Adapter instance reference
1165 * This function creates the controllers phy information and
1166 * updates the SAS transport layer with updated information,
1167 * this is executed for first device addition or device info
1172 void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc)
1175 u16 sz, num_phys = 1, port_id, ioc_status;
1176 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1177 struct mpi3_sas_phy_page0 phy_pg0;
1178 struct mpi3_device_page0 dev_pg0;
1179 struct mpi3_enclosure_page0 encl_pg0;
1180 struct mpi3_device0_sas_sata_format *sasinf;
1182 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1183 (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data));
1184 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1185 if (!sas_io_unit_pg0)
1188 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1189 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1190 __FILE__, __LINE__, __func__);
1193 num_phys = sas_io_unit_pg0->num_phys;
1194 kfree(sas_io_unit_pg0);
1196 mrioc->sas_hba.host_node = 1;
1197 INIT_LIST_HEAD(&mrioc->sas_hba.sas_port_list);
1198 mrioc->sas_hba.parent_dev = &mrioc->shost->shost_gendev;
1199 mrioc->sas_hba.phy = kcalloc(num_phys,
1200 sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
1201 if (!mrioc->sas_hba.phy)
1204 mrioc->sas_hba.num_phys = num_phys;
1206 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1207 (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data));
1208 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1209 if (!sas_io_unit_pg0)
1212 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1213 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1214 __FILE__, __LINE__, __func__);
1218 mrioc->sas_hba.handle = 0;
1219 for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1220 if (sas_io_unit_pg0->phy_data[i].phy_flags &
1221 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
1222 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))
1224 if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
1225 sizeof(struct mpi3_sas_phy_page0),
1226 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, i)) {
1227 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1228 __FILE__, __LINE__, __func__);
1231 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1232 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1233 __FILE__, __LINE__, __func__);
1237 if (!mrioc->sas_hba.handle)
1238 mrioc->sas_hba.handle = le16_to_cpu(
1239 sas_io_unit_pg0->phy_data[i].controller_dev_handle);
1240 port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1242 if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
1243 if (!mpi3mr_alloc_hba_port(mrioc, port_id))
1246 mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle;
1247 mrioc->sas_hba.phy[i].phy_id = i;
1248 mrioc->sas_hba.phy[i].hba_port =
1249 mpi3mr_get_hba_port_by_id(mrioc, port_id);
1250 mpi3mr_add_host_phy(mrioc, &mrioc->sas_hba.phy[i],
1251 phy_pg0, mrioc->sas_hba.parent_dev);
1253 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
1254 sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
1255 mrioc->sas_hba.handle))) {
1256 ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
1259 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1260 ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
1261 mrioc->sas_hba.handle, ioc_status, __FILE__, __LINE__,
1265 mrioc->sas_hba.enclosure_handle =
1266 le16_to_cpu(dev_pg0.enclosure_handle);
1267 sasinf = &dev_pg0.device_specific.sas_sata_format;
1268 mrioc->sas_hba.sas_address =
1269 le64_to_cpu(sasinf->sas_address);
1271 "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
1272 mrioc->sas_hba.handle,
1273 (unsigned long long) mrioc->sas_hba.sas_address,
1274 mrioc->sas_hba.num_phys);
1276 if (mrioc->sas_hba.enclosure_handle) {
1277 if (!(mpi3mr_cfg_get_enclosure_pg0(mrioc, &ioc_status,
1278 &encl_pg0, sizeof(encl_pg0),
1279 MPI3_ENCLOS_PGAD_FORM_HANDLE,
1280 mrioc->sas_hba.enclosure_handle)) &&
1281 (ioc_status == MPI3_IOCSTATUS_SUCCESS))
1282 mrioc->sas_hba.enclosure_logical_id =
1283 le64_to_cpu(encl_pg0.enclosure_logical_id);
1287 kfree(sas_io_unit_pg0);
1291 * mpi3mr_sas_port_add - Expose the SAS device to the SAS TL
1292 * @mrioc: Adapter instance reference
1293 * @handle: Firmware device handle of the attached device
1294 * @sas_address_parent: sas address of parent expander or host
1295 * @hba_port: HBA port entry
1297 * This function creates a new sas port object for the given end
1298 * device matching sas address and hba_port and adds it to the
1299 * sas_node's sas_port_list and expose the attached sas device
1300 * to the SAS transport layer through sas_rphy_add.
1302 * Returns a valid mpi3mr_sas_port reference or NULL.
1304 static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
1305 u16 handle, u64 sas_address_parent, struct mpi3mr_hba_port *hba_port)
1307 struct mpi3mr_sas_phy *mr_sas_phy, *next;
1308 struct mpi3mr_sas_port *mr_sas_port;
1309 unsigned long flags;
1310 struct mpi3mr_sas_node *mr_sas_node;
1311 struct sas_rphy *rphy;
1312 struct mpi3mr_tgt_dev *tgtdev = NULL;
1314 struct sas_port *port;
1317 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1318 __FILE__, __LINE__, __func__);
1322 mr_sas_port = kzalloc(sizeof(struct mpi3mr_sas_port), GFP_KERNEL);
1326 INIT_LIST_HEAD(&mr_sas_port->port_list);
1327 INIT_LIST_HEAD(&mr_sas_port->phy_list);
1328 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1329 mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1330 sas_address_parent, hba_port);
1331 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1334 ioc_err(mrioc, "%s:could not find parent sas_address(0x%016llx)!\n",
1335 __func__, (unsigned long long)sas_address_parent);
1339 if ((mpi3mr_set_identify(mrioc, handle,
1340 &mr_sas_port->remote_identify))) {
1341 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1342 __FILE__, __LINE__, __func__);
1346 if (mr_sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
1347 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1348 __FILE__, __LINE__, __func__);
1352 mr_sas_port->hba_port = hba_port;
1353 mpi3mr_sas_port_sanity_check(mrioc, mr_sas_node,
1354 mr_sas_port->remote_identify.sas_address, hba_port);
1356 if (mr_sas_node->num_phys > sizeof(mr_sas_port->phy_mask) * 8)
1357 ioc_info(mrioc, "max port count %u could be too high\n",
1358 mr_sas_node->num_phys);
1360 for (i = 0; i < mr_sas_node->num_phys; i++) {
1361 if ((mr_sas_node->phy[i].remote_identify.sas_address !=
1362 mr_sas_port->remote_identify.sas_address) ||
1363 (mr_sas_node->phy[i].hba_port != hba_port))
1366 if (i > sizeof(mr_sas_port->phy_mask) * 8) {
1367 ioc_warn(mrioc, "skipping port %u, max allowed value is %lu\n",
1368 i, sizeof(mr_sas_port->phy_mask) * 8);
1371 list_add_tail(&mr_sas_node->phy[i].port_siblings,
1372 &mr_sas_port->phy_list);
1373 mr_sas_port->num_phys++;
1374 mr_sas_port->phy_mask |= (1 << i);
1377 if (!mr_sas_port->num_phys) {
1378 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1379 __FILE__, __LINE__, __func__);
1383 mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
1385 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1386 tgtdev = mpi3mr_get_tgtdev_by_addr(mrioc,
1387 mr_sas_port->remote_identify.sas_address,
1388 mr_sas_port->hba_port);
1391 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1392 __FILE__, __LINE__, __func__);
1395 tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 1;
1398 if (!mr_sas_node->parent_dev) {
1399 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1400 __FILE__, __LINE__, __func__);
1404 port = sas_port_alloc_num(mr_sas_node->parent_dev);
1405 if ((sas_port_add(port))) {
1406 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1407 __FILE__, __LINE__, __func__);
1411 list_for_each_entry(mr_sas_phy, &mr_sas_port->phy_list,
1413 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1414 dev_info(&port->dev,
1415 "add: handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
1416 handle, (unsigned long long)
1417 mr_sas_port->remote_identify.sas_address,
1418 mr_sas_phy->phy_id);
1419 sas_port_add_phy(port, mr_sas_phy->phy);
1420 mr_sas_phy->phy_belongs_to_port = 1;
1421 mr_sas_phy->hba_port = hba_port;
1424 mr_sas_port->port = port;
1425 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1426 rphy = sas_end_device_alloc(port);
1427 tgtdev->dev_spec.sas_sata_inf.rphy = rphy;
1429 rphy = sas_expander_alloc(port,
1430 mr_sas_port->remote_identify.device_type);
1432 rphy->identify = mr_sas_port->remote_identify;
1434 if (mrioc->current_event)
1435 mrioc->current_event->pending_at_sml = 1;
1437 if ((sas_rphy_add(rphy))) {
1438 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1439 __FILE__, __LINE__, __func__);
1441 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1442 tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 0;
1443 tgtdev->dev_spec.sas_sata_inf.sas_transport_attached = 1;
1444 mpi3mr_tgtdev_put(tgtdev);
1447 dev_info(&rphy->dev,
1448 "%s: added: handle(0x%04x), sas_address(0x%016llx)\n",
1449 __func__, handle, (unsigned long long)
1450 mr_sas_port->remote_identify.sas_address);
1452 mr_sas_port->rphy = rphy;
1453 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1454 list_add_tail(&mr_sas_port->port_list, &mr_sas_node->sas_port_list);
1455 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1457 if (mrioc->current_event) {
1458 mrioc->current_event->pending_at_sml = 0;
1459 if (mrioc->current_event->discard)
1460 mpi3mr_print_device_event_notice(mrioc, true);
1463 /* fill in report manufacture */
1464 if (mr_sas_port->remote_identify.device_type ==
1465 SAS_EDGE_EXPANDER_DEVICE ||
1466 mr_sas_port->remote_identify.device_type ==
1467 SAS_FANOUT_EXPANDER_DEVICE)
1468 mpi3mr_report_manufacture(mrioc,
1469 mr_sas_port->remote_identify.sas_address,
1470 rphy_to_expander_device(rphy), hba_port->port_id);
1475 list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list,
1477 list_del(&mr_sas_phy->port_siblings);
1483 * mpi3mr_sas_port_remove - remove port from the list
1484 * @mrioc: Adapter instance reference
1485 * @sas_address: SAS address of attached device
1486 * @sas_address_parent: SAS address of parent expander or host
1487 * @hba_port: HBA port entry
1489 * Removing object and freeing associated memory from the
1494 static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
1495 u64 sas_address_parent, struct mpi3mr_hba_port *hba_port)
1498 unsigned long flags;
1499 struct mpi3mr_sas_port *mr_sas_port, *next;
1500 struct mpi3mr_sas_node *mr_sas_node;
1502 struct mpi3mr_sas_phy *mr_sas_phy, *next_phy;
1503 struct mpi3mr_hba_port *srch_port, *hba_port_next = NULL;
1508 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1509 mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1510 sas_address_parent, hba_port);
1512 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1515 list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
1517 if (mr_sas_port->remote_identify.sas_address != sas_address)
1519 if (mr_sas_port->hba_port != hba_port)
1522 list_del(&mr_sas_port->port_list);
1528 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1532 if (mr_sas_node->host_node) {
1533 list_for_each_entry_safe(srch_port, hba_port_next,
1534 &mrioc->hba_port_table_list, list) {
1535 if (srch_port != hba_port)
1538 "removing hba_port entry: %p port: %d from hba_port list\n",
1539 srch_port, srch_port->port_id);
1540 list_del(&hba_port->list);
1546 for (i = 0; i < mr_sas_node->num_phys; i++) {
1547 if (mr_sas_node->phy[i].remote_identify.sas_address ==
1549 memset(&mr_sas_node->phy[i].remote_identify, 0,
1550 sizeof(struct sas_identify));
1553 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1555 if (mrioc->current_event)
1556 mrioc->current_event->pending_at_sml = 1;
1558 list_for_each_entry_safe(mr_sas_phy, next_phy,
1559 &mr_sas_port->phy_list, port_siblings) {
1560 if ((!mrioc->stop_drv_processing) &&
1561 (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1562 dev_info(&mr_sas_port->port->dev,
1563 "remove: sas_address(0x%016llx), phy(%d)\n",
1564 (unsigned long long)
1565 mr_sas_port->remote_identify.sas_address,
1566 mr_sas_phy->phy_id);
1567 mr_sas_phy->phy_belongs_to_port = 0;
1568 if (!mrioc->stop_drv_processing)
1569 sas_port_delete_phy(mr_sas_port->port,
1571 list_del(&mr_sas_phy->port_siblings);
1573 if (!mrioc->stop_drv_processing)
1574 sas_port_delete(mr_sas_port->port);
1575 ioc_info(mrioc, "%s: removed sas_address(0x%016llx)\n",
1576 __func__, (unsigned long long)sas_address);
1578 if (mrioc->current_event) {
1579 mrioc->current_event->pending_at_sml = 0;
1580 if (mrioc->current_event->discard)
1581 mpi3mr_print_device_event_notice(mrioc, false);
1588 * struct host_port - host port details
1589 * @sas_address: SAS Address of the attached device
1590 * @phy_mask: phy mask of host port
1591 * @handle: Device Handle of attached device
1592 * @iounit_port_id: port ID
1593 * @used: host port is already matched with sas port from sas_port_list
1594 * @lowest_phy: lowest phy ID of host port
1606 * mpi3mr_update_mr_sas_port - update sas port objects during reset
1607 * @mrioc: Adapter instance reference
1608 * @h_port: host_port object
1609 * @mr_sas_port: sas_port objects which needs to be updated
1611 * Update the port ID of sas port object. Also add the phys if new phys got
1612 * added to current sas port and remove the phys if some phys are moved
1613 * out of the current sas port.
1618 mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
1619 struct mpi3mr_sas_port *mr_sas_port)
1621 struct mpi3mr_sas_phy *mr_sas_phy;
1623 u64 phys_to_be_added, phys_to_be_removed;
1627 mr_sas_port->marked_responding = 1;
1629 dev_info(&mr_sas_port->port->dev,
1630 "sas_address(0x%016llx), old: port_id %d phy_mask 0x%llx, new: port_id %d phy_mask:0x%llx\n",
1631 mr_sas_port->remote_identify.sas_address,
1632 mr_sas_port->hba_port->port_id, mr_sas_port->phy_mask,
1633 h_port->iounit_port_id, h_port->phy_mask);
1635 mr_sas_port->hba_port->port_id = h_port->iounit_port_id;
1636 mr_sas_port->hba_port->flags &= ~MPI3MR_HBA_PORT_FLAG_DIRTY;
1638 /* Get the newly added phys bit map & removed phys bit map */
1639 phy_mask_xor = mr_sas_port->phy_mask ^ h_port->phy_mask;
1640 phys_to_be_added = h_port->phy_mask & phy_mask_xor;
1641 phys_to_be_removed = mr_sas_port->phy_mask & phy_mask_xor;
1644 * Register these new phys to current mr_sas_port's port.
1645 * if these phys are previously registered with another port
1646 * then delete these phys from that port first.
1648 for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u64)) {
1649 mr_sas_phy = &mrioc->sas_hba.phy[i];
1650 if (mr_sas_phy->phy_belongs_to_port)
1651 mpi3mr_del_phy_from_an_existing_port(mrioc,
1652 &mrioc->sas_hba, mr_sas_phy);
1653 mpi3mr_add_phy_to_an_existing_port(mrioc,
1654 &mrioc->sas_hba, mr_sas_phy,
1655 mr_sas_port->remote_identify.sas_address,
1656 mr_sas_port->hba_port);
1659 /* Delete the phys which are not part of current mr_sas_port's port. */
1660 for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u64)) {
1661 mr_sas_phy = &mrioc->sas_hba.phy[i];
1662 if (mr_sas_phy->phy_belongs_to_port)
1663 mpi3mr_del_phy_from_an_existing_port(mrioc,
1664 &mrioc->sas_hba, mr_sas_phy);
1669 * mpi3mr_refresh_sas_ports - update host's sas ports during reset
1670 * @mrioc: Adapter instance reference
1672 * Update the host's sas ports during reset by checking whether
1673 * sas ports are still intact or not. Add/remove phys if any hba
1674 * phys are (moved in)/(moved out) of sas port. Also update
1675 * io_unit_port if it got changed during reset.
1680 mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
1682 struct host_port *h_port = NULL;
1683 int i, j, found, host_port_count = 0, port_idx;
1684 u16 sz, attached_handle, ioc_status;
1685 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1686 struct mpi3_device_page0 dev_pg0;
1687 struct mpi3_device0_sas_sata_format *sasinf;
1688 struct mpi3mr_sas_port *mr_sas_port;
1690 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1691 (mrioc->sas_hba.num_phys *
1692 sizeof(struct mpi3_sas_io_unit0_phy_data));
1693 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1694 if (!sas_io_unit_pg0)
1696 h_port = kcalloc(64, sizeof(struct host_port), GFP_KERNEL);
1700 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1701 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1702 __FILE__, __LINE__, __func__);
1706 /* Create a new expander port table */
1707 for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1708 attached_handle = le16_to_cpu(
1709 sas_io_unit_pg0->phy_data[i].attached_dev_handle);
1710 if (!attached_handle)
1713 for (j = 0; j < host_port_count; j++) {
1714 if (h_port[j].handle == attached_handle) {
1715 h_port[j].phy_mask |= (1 << i);
1722 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
1723 sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
1724 attached_handle))) {
1726 "failed to read dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1727 attached_handle, __FILE__, __LINE__, __func__);
1730 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1732 "ioc_status(0x%x) while reading dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1733 ioc_status, attached_handle,
1734 __FILE__, __LINE__, __func__);
1737 sasinf = &dev_pg0.device_specific.sas_sata_format;
1739 port_idx = host_port_count;
1740 h_port[port_idx].sas_address = le64_to_cpu(sasinf->sas_address);
1741 h_port[port_idx].handle = attached_handle;
1742 h_port[port_idx].phy_mask = (1 << i);
1743 h_port[port_idx].iounit_port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1744 h_port[port_idx].lowest_phy = sasinf->phy_num;
1745 h_port[port_idx].used = 0;
1749 if (!host_port_count)
1752 if (mrioc->logging_level & MPI3_DEBUG_RESET) {
1753 ioc_info(mrioc, "Host port details before reset\n");
1754 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1757 "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1758 mr_sas_port->hba_port->port_id,
1759 mr_sas_port->remote_identify.sas_address,
1760 mr_sas_port->phy_mask, mr_sas_port->lowest_phy);
1763 ioc_info(mrioc, "Host port details after reset\n");
1764 for (i = 0; i < host_port_count; i++) {
1766 "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1767 h_port[i].iounit_port_id, h_port[i].sas_address,
1768 h_port[i].phy_mask, h_port[i].lowest_phy);
1772 /* mark all host sas port entries as dirty */
1773 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1775 mr_sas_port->marked_responding = 0;
1776 mr_sas_port->hba_port->flags |= MPI3MR_HBA_PORT_FLAG_DIRTY;
1779 /* First check for matching lowest phy */
1780 for (i = 0; i < host_port_count; i++) {
1782 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1784 if (mr_sas_port->marked_responding)
1786 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1788 if (h_port[i].lowest_phy == mr_sas_port->lowest_phy) {
1789 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1795 /* In case if lowest phy is got enabled or disabled during reset */
1796 for (i = 0; i < host_port_count; i++) {
1800 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1802 if (mr_sas_port->marked_responding)
1804 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1806 if (h_port[i].phy_mask & mr_sas_port->phy_mask) {
1807 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1813 /* In case if expander cable is removed & connected to another HBA port during reset */
1814 for (i = 0; i < host_port_count; i++) {
1818 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1820 if (mr_sas_port->marked_responding)
1822 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1824 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1830 kfree(sas_io_unit_pg0);
1834 * mpi3mr_refresh_expanders - Refresh expander device exposure
1835 * @mrioc: Adapter instance reference
1837 * This is executed post controller reset to identify any
1838 * missing expander devices during reset and remove from the upper layers
1839 * or expose any newly detected expander device to the upper layers.
1844 mpi3mr_refresh_expanders(struct mpi3mr_ioc *mrioc)
1846 struct mpi3mr_sas_node *sas_expander, *sas_expander_next;
1847 struct mpi3_sas_expander_page0 expander_pg0;
1848 u16 ioc_status, handle;
1851 unsigned long flags;
1852 struct mpi3mr_hba_port *hba_port;
1854 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1855 list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
1856 sas_expander->non_responding = 1;
1858 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1860 sas_expander = NULL;
1864 /* Search for responding expander devices and add them if they are newly got added */
1866 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
1867 sizeof(struct mpi3_sas_expander_page0),
1868 MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
1870 "failed to read exp pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1871 handle, __FILE__, __LINE__, __func__);
1875 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1877 "ioc_status(0x%x) while reading exp pg0 for handle:(0x%04x), %s:%d/%s()!\n",
1878 ioc_status, handle, __FILE__, __LINE__, __func__);
1882 handle = le16_to_cpu(expander_pg0.dev_handle);
1883 sas_address = le64_to_cpu(expander_pg0.sas_address);
1884 hba_port = mpi3mr_get_hba_port_by_id(mrioc, expander_pg0.io_unit_port);
1887 mpi3mr_sas_host_refresh(mrioc);
1888 mpi3mr_expander_add(mrioc, handle);
1892 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1894 mpi3mr_expander_find_by_sas_address(mrioc,
1895 sas_address, hba_port);
1896 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1898 if (!sas_expander) {
1899 mpi3mr_sas_host_refresh(mrioc);
1900 mpi3mr_expander_add(mrioc, handle);
1904 sas_expander->non_responding = 0;
1905 if (sas_expander->handle == handle)
1908 sas_expander->handle = handle;
1909 for (i = 0 ; i < sas_expander->num_phys ; i++)
1910 sas_expander->phy[i].handle = handle;
1914 * Delete non responding expander devices and the corresponding
1915 * hba_port if the non responding expander device's parent device
1918 sas_expander = NULL;
1919 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1920 list_for_each_entry_safe_reverse(sas_expander, sas_expander_next,
1921 &mrioc->sas_expander_list, list) {
1922 if (sas_expander->non_responding) {
1923 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1924 mpi3mr_expander_node_remove(mrioc, sas_expander);
1925 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1928 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1932 * mpi3mr_expander_node_add - insert an expander to the list.
1933 * @mrioc: Adapter instance reference
1934 * @sas_expander: Expander sas node
1935 * Context: This function will acquire sas_node_lock.
1937 * Adding new object to the ioc->sas_expander_list.
1941 static void mpi3mr_expander_node_add(struct mpi3mr_ioc *mrioc,
1942 struct mpi3mr_sas_node *sas_expander)
1944 unsigned long flags;
1946 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1947 list_add_tail(&sas_expander->list, &mrioc->sas_expander_list);
1948 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1952 * mpi3mr_expander_add - Create expander object
1953 * @mrioc: Adapter instance reference
1954 * @handle: Expander firmware device handle
1956 * This function creating expander object, stored in
1957 * sas_expander_list and expose it to the SAS transport
1960 * Return: 0 for success, non-zero for failure.
1962 int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle)
1964 struct mpi3mr_sas_node *sas_expander;
1965 struct mpi3mr_enclosure_node *enclosure_dev;
1966 struct mpi3_sas_expander_page0 expander_pg0;
1967 struct mpi3_sas_expander_page1 expander_pg1;
1968 u16 ioc_status, parent_handle, temp_handle;
1969 u64 sas_address, sas_address_parent = 0;
1971 unsigned long flags;
1972 u8 port_id, link_rate;
1973 struct mpi3mr_sas_port *mr_sas_port = NULL;
1974 struct mpi3mr_hba_port *hba_port;
1981 if (mrioc->reset_in_progress)
1984 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
1985 sizeof(expander_pg0), MPI3_SAS_EXPAND_PGAD_FORM_HANDLE, handle))) {
1986 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1987 __FILE__, __LINE__, __func__);
1991 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1992 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1993 __FILE__, __LINE__, __func__);
1997 parent_handle = le16_to_cpu(expander_pg0.parent_dev_handle);
1998 if (mpi3mr_get_sas_address(mrioc, parent_handle, &sas_address_parent)
2000 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2001 __FILE__, __LINE__, __func__);
2005 port_id = expander_pg0.io_unit_port;
2006 hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
2008 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2009 __FILE__, __LINE__, __func__);
2013 if (sas_address_parent != mrioc->sas_hba.sas_address) {
2014 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2016 mpi3mr_expander_find_by_sas_address(mrioc,
2017 sas_address_parent, hba_port);
2018 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2019 if (!sas_expander) {
2020 rc = mpi3mr_expander_add(mrioc, parent_handle);
2025 * When there is a parent expander present, update it's
2026 * phys where child expander is connected with the link
2027 * speed, attached dev handle and sas address.
2029 for (i = 0 ; i < sas_expander->num_phys ; i++) {
2031 (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2033 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc,
2034 &ioc_status, &expander_pg1,
2035 sizeof(expander_pg1),
2036 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2038 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2039 __FILE__, __LINE__, __func__);
2043 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2044 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2045 __FILE__, __LINE__, __func__);
2049 temp_handle = le16_to_cpu(
2050 expander_pg1.attached_dev_handle);
2051 if (temp_handle != handle)
2053 link_rate = (expander_pg1.negotiated_link_rate &
2054 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2055 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2056 mpi3mr_update_links(mrioc, sas_address_parent,
2057 handle, i, link_rate, hba_port);
2062 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2063 sas_address = le64_to_cpu(expander_pg0.sas_address);
2064 sas_expander = mpi3mr_expander_find_by_sas_address(mrioc,
2065 sas_address, hba_port);
2066 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2071 sas_expander = kzalloc(sizeof(struct mpi3mr_sas_node),
2076 sas_expander->handle = handle;
2077 sas_expander->num_phys = expander_pg0.num_phys;
2078 sas_expander->sas_address_parent = sas_address_parent;
2079 sas_expander->sas_address = sas_address;
2080 sas_expander->hba_port = hba_port;
2083 "expander_add: handle(0x%04x), parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
2084 handle, parent_handle, (unsigned long long)
2085 sas_expander->sas_address, sas_expander->num_phys);
2087 if (!sas_expander->num_phys) {
2091 sas_expander->phy = kcalloc(sas_expander->num_phys,
2092 sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
2093 if (!sas_expander->phy) {
2098 INIT_LIST_HEAD(&sas_expander->sas_port_list);
2099 mr_sas_port = mpi3mr_sas_port_add(mrioc, handle, sas_address_parent,
2100 sas_expander->hba_port);
2102 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2103 __FILE__, __LINE__, __func__);
2107 sas_expander->parent_dev = &mr_sas_port->rphy->dev;
2108 sas_expander->rphy = mr_sas_port->rphy;
2110 for (i = 0 ; i < sas_expander->num_phys ; i++) {
2111 phynum_handle = (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2113 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2114 &expander_pg1, sizeof(expander_pg1),
2115 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2117 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2118 __FILE__, __LINE__, __func__);
2122 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2123 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2124 __FILE__, __LINE__, __func__);
2129 sas_expander->phy[i].handle = handle;
2130 sas_expander->phy[i].phy_id = i;
2131 sas_expander->phy[i].hba_port = hba_port;
2133 if ((mpi3mr_add_expander_phy(mrioc, &sas_expander->phy[i],
2134 expander_pg1, sas_expander->parent_dev))) {
2135 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2136 __FILE__, __LINE__, __func__);
2142 if (sas_expander->enclosure_handle) {
2144 mpi3mr_enclosure_find_by_handle(mrioc,
2145 sas_expander->enclosure_handle);
2147 sas_expander->enclosure_logical_id = le64_to_cpu(
2148 enclosure_dev->pg0.enclosure_logical_id);
2151 mpi3mr_expander_node_add(mrioc, sas_expander);
2157 mpi3mr_sas_port_remove(mrioc,
2158 sas_expander->sas_address,
2159 sas_address_parent, sas_expander->hba_port);
2160 kfree(sas_expander->phy);
2161 kfree(sas_expander);
2166 * mpi3mr_expander_node_remove - recursive removal of expander.
2167 * @mrioc: Adapter instance reference
2168 * @sas_expander: Expander device object
2170 * Removes expander object and freeing associated memory from
2171 * the sas_expander_list and removes the same from SAS TL, if
2172 * one of the attached device is an expander then it recursively
2173 * removes the expander device too.
2177 void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
2178 struct mpi3mr_sas_node *sas_expander)
2180 struct mpi3mr_sas_port *mr_sas_port, *next;
2181 unsigned long flags;
2184 /* remove sibling ports attached to this expander */
2185 list_for_each_entry_safe(mr_sas_port, next,
2186 &sas_expander->sas_port_list, port_list) {
2187 if (mrioc->reset_in_progress)
2189 if (mr_sas_port->remote_identify.device_type ==
2191 mpi3mr_remove_device_by_sas_address(mrioc,
2192 mr_sas_port->remote_identify.sas_address,
2193 mr_sas_port->hba_port);
2194 else if (mr_sas_port->remote_identify.device_type ==
2195 SAS_EDGE_EXPANDER_DEVICE ||
2196 mr_sas_port->remote_identify.device_type ==
2197 SAS_FANOUT_EXPANDER_DEVICE)
2198 mpi3mr_expander_remove(mrioc,
2199 mr_sas_port->remote_identify.sas_address,
2200 mr_sas_port->hba_port);
2203 port_id = sas_expander->hba_port->port_id;
2204 mpi3mr_sas_port_remove(mrioc, sas_expander->sas_address,
2205 sas_expander->sas_address_parent, sas_expander->hba_port);
2207 ioc_info(mrioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
2208 sas_expander->handle, (unsigned long long)
2209 sas_expander->sas_address, port_id);
2211 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2212 list_del(&sas_expander->list);
2213 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2215 kfree(sas_expander->phy);
2216 kfree(sas_expander);
2220 * mpi3mr_expander_remove - Remove expander object
2221 * @mrioc: Adapter instance reference
2222 * @sas_address: Remove expander sas_address
2223 * @hba_port: HBA port reference
2225 * This function remove expander object, stored in
2226 * mrioc->sas_expander_list and removes it from the SAS TL by
2227 * calling mpi3mr_expander_node_remove().
2231 void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
2232 struct mpi3mr_hba_port *hba_port)
2234 struct mpi3mr_sas_node *sas_expander;
2235 unsigned long flags;
2237 if (mrioc->reset_in_progress)
2243 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2244 sas_expander = mpi3mr_expander_find_by_sas_address(mrioc, sas_address,
2246 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2248 mpi3mr_expander_node_remove(mrioc, sas_expander);
2253 * mpi3mr_get_sas_negotiated_logical_linkrate - get linkrate
2254 * @mrioc: Adapter instance reference
2255 * @tgtdev: Target device
2257 * This function identifies whether the target device is
2258 * attached directly or through expander and issues sas phy
2259 * page0 or expander phy page1 and gets the link rate, if there
2260 * is any failure in reading the pages then this returns link
2263 * Return: logical link rate.
2265 static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc,
2266 struct mpi3mr_tgt_dev *tgtdev)
2268 u8 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5, phy_number;
2269 struct mpi3_sas_expander_page1 expander_pg1;
2270 struct mpi3_sas_phy_page0 phy_pg0;
2274 phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2275 if (!(tgtdev->devpg0_flag & MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED)) {
2276 phynum_handle = ((phy_number<<MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT)
2277 | tgtdev->parent_handle);
2278 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2279 &expander_pg1, sizeof(expander_pg1),
2280 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2282 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2283 __FILE__, __LINE__, __func__);
2286 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2287 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2288 __FILE__, __LINE__, __func__);
2291 link_rate = (expander_pg1.negotiated_link_rate &
2292 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2293 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2296 if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
2297 sizeof(struct mpi3_sas_phy_page0),
2298 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy_number)) {
2299 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2300 __FILE__, __LINE__, __func__);
2303 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2304 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2305 __FILE__, __LINE__, __func__);
2308 link_rate = (phy_pg0.negotiated_link_rate &
2309 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2310 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2316 * mpi3mr_report_tgtdev_to_sas_transport - expose dev to SAS TL
2317 * @mrioc: Adapter instance reference
2318 * @tgtdev: Target device
2320 * This function exposes the target device after
2321 * preparing host_phy, setting up link rate etc.
2323 * Return: 0 on success, non-zero for failure.
2325 int mpi3mr_report_tgtdev_to_sas_transport(struct mpi3mr_ioc *mrioc,
2326 struct mpi3mr_tgt_dev *tgtdev)
2329 u8 link_rate, parent_phy_number;
2330 u64 sas_address_parent, sas_address;
2331 struct mpi3mr_hba_port *hba_port;
2334 if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2335 !mrioc->sas_transport_enabled)
2338 sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2339 if (!mrioc->sas_hba.num_phys)
2340 mpi3mr_sas_host_add(mrioc);
2342 mpi3mr_sas_host_refresh(mrioc);
2344 if (mpi3mr_get_sas_address(mrioc, tgtdev->parent_handle,
2345 &sas_address_parent) != 0) {
2346 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2347 __FILE__, __LINE__, __func__);
2350 tgtdev->dev_spec.sas_sata_inf.sas_address_parent = sas_address_parent;
2352 parent_phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2353 port_id = tgtdev->io_unit_port;
2355 hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
2357 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2358 __FILE__, __LINE__, __func__);
2361 tgtdev->dev_spec.sas_sata_inf.hba_port = hba_port;
2363 link_rate = mpi3mr_get_sas_negotiated_logical_linkrate(mrioc, tgtdev);
2365 mpi3mr_update_links(mrioc, sas_address_parent, tgtdev->dev_handle,
2366 parent_phy_number, link_rate, hba_port);
2368 tgtdev->host_exposed = 1;
2369 if (!mpi3mr_sas_port_add(mrioc, tgtdev->dev_handle,
2370 sas_address_parent, hba_port)) {
2372 } else if ((!tgtdev->starget) && (!mrioc->is_driver_loading)) {
2373 mpi3mr_sas_port_remove(mrioc, sas_address,
2374 sas_address_parent, hba_port);
2378 tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2379 tgtdev->host_exposed = 0;
2385 * mpi3mr_remove_tgtdev_from_sas_transport - remove from SAS TL
2386 * @mrioc: Adapter instance reference
2387 * @tgtdev: Target device
2389 * This function removes the target device
2393 void mpi3mr_remove_tgtdev_from_sas_transport(struct mpi3mr_ioc *mrioc,
2394 struct mpi3mr_tgt_dev *tgtdev)
2396 u64 sas_address_parent, sas_address;
2397 struct mpi3mr_hba_port *hba_port;
2399 if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2400 !mrioc->sas_transport_enabled)
2403 hba_port = tgtdev->dev_spec.sas_sata_inf.hba_port;
2404 sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2405 sas_address_parent = tgtdev->dev_spec.sas_sata_inf.sas_address_parent;
2406 mpi3mr_sas_port_remove(mrioc, sas_address, sas_address_parent,
2408 tgtdev->host_exposed = 0;
2409 tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2413 * mpi3mr_get_port_id_by_sas_phy - Get port ID of the given phy
2414 * @phy: SAS transport layer phy object
2416 * Return: Port number for valid ID else 0xFFFF
2418 static inline u8 mpi3mr_get_port_id_by_sas_phy(struct sas_phy *phy)
2421 struct mpi3mr_hba_port *hba_port = phy->hostdata;
2424 port_id = hba_port->port_id;
2430 * mpi3mr_get_port_id_by_rphy - Get Port number from SAS rphy
2432 * @mrioc: Adapter instance reference
2433 * @rphy: SAS transport layer remote phy object
2435 * Retrieves HBA port number in which the device pointed by the
2436 * rphy object is attached with.
2438 * Return: Valid port number on success else OxFFFF.
2440 static u8 mpi3mr_get_port_id_by_rphy(struct mpi3mr_ioc *mrioc, struct sas_rphy *rphy)
2442 struct mpi3mr_sas_node *sas_expander;
2443 struct mpi3mr_tgt_dev *tgtdev;
2444 unsigned long flags;
2450 if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
2451 rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) {
2452 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2453 list_for_each_entry(sas_expander, &mrioc->sas_expander_list,
2455 if (sas_expander->rphy == rphy) {
2456 port_id = sas_expander->hba_port->port_id;
2460 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2461 } else if (rphy->identify.device_type == SAS_END_DEVICE) {
2462 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2464 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2465 rphy->identify.sas_address, rphy);
2466 if (tgtdev && tgtdev->dev_spec.sas_sata_inf.hba_port) {
2468 tgtdev->dev_spec.sas_sata_inf.hba_port->port_id;
2469 mpi3mr_tgtdev_put(tgtdev);
2471 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2476 static inline struct mpi3mr_ioc *phy_to_mrioc(struct sas_phy *phy)
2478 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
2480 return shost_priv(shost);
2483 static inline struct mpi3mr_ioc *rphy_to_mrioc(struct sas_rphy *rphy)
2485 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
2487 return shost_priv(shost);
2490 /* report phy error log structure */
2491 struct phy_error_log_request {
2492 u8 smp_frame_type; /* 0x40 */
2493 u8 function; /* 0x11 */
2494 u8 allocated_response_length;
2495 u8 request_length; /* 02 */
2501 /* report phy error log reply structure */
2502 struct phy_error_log_reply {
2503 u8 smp_frame_type; /* 0x41 */
2504 u8 function; /* 0x11 */
2507 __be16 expander_change_count;
2511 __be32 invalid_dword;
2512 __be32 running_disparity_error;
2513 __be32 loss_of_dword_sync;
2514 __be32 phy_reset_problem;
2519 * mpi3mr_get_expander_phy_error_log - return expander counters:
2520 * @mrioc: Adapter instance reference
2521 * @phy: The SAS transport layer phy object
2523 * Return: 0 for success, non-zero for failure.
2526 static int mpi3mr_get_expander_phy_error_log(struct mpi3mr_ioc *mrioc,
2527 struct sas_phy *phy)
2529 struct mpi3_smp_passthrough_request mpi_request;
2530 struct mpi3_smp_passthrough_reply mpi_reply;
2531 struct phy_error_log_request *phy_error_log_request;
2532 struct phy_error_log_reply *phy_error_log_reply;
2535 void *data_out = NULL;
2536 dma_addr_t data_out_dma, data_in_dma;
2537 u32 data_out_sz, data_in_sz, sz;
2538 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2539 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2540 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2543 if (mrioc->reset_in_progress) {
2544 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2548 data_out_sz = sizeof(struct phy_error_log_request);
2549 data_in_sz = sizeof(struct phy_error_log_reply);
2550 sz = data_out_sz + data_in_sz;
2551 data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2558 data_in_dma = data_out_dma + data_out_sz;
2559 phy_error_log_reply = data_out + data_out_sz;
2562 memset(data_out, 0, sz);
2563 phy_error_log_request = data_out;
2564 phy_error_log_request->smp_frame_type = 0x40;
2565 phy_error_log_request->function = 0x11;
2566 phy_error_log_request->request_length = 2;
2567 phy_error_log_request->allocated_response_length = 0;
2568 phy_error_log_request->phy_identifier = phy->number;
2570 memset(&mpi_request, 0, request_sz);
2571 memset(&mpi_reply, 0, reply_sz);
2572 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2573 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2574 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2575 mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2577 psge = &mpi_request.request_sge;
2578 mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2580 psge = &mpi_request.response_sge;
2581 mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2583 dprint_transport_info(mrioc,
2584 "sending phy error log SMP request to sas_address(0x%016llx), phy_id(%d)\n",
2585 (unsigned long long)phy->identify.sas_address, phy->number);
2587 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2588 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2591 dprint_transport_info(mrioc,
2592 "phy error log SMP request completed with ioc_status(0x%04x)\n",
2595 if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2596 dprint_transport_info(mrioc,
2597 "phy error log - reply data transfer size(%d)\n",
2598 le16_to_cpu(mpi_reply.response_data_length));
2600 if (le16_to_cpu(mpi_reply.response_data_length) !=
2601 sizeof(struct phy_error_log_reply))
2604 dprint_transport_info(mrioc,
2605 "phy error log - function_result(%d)\n",
2606 phy_error_log_reply->function_result);
2608 phy->invalid_dword_count =
2609 be32_to_cpu(phy_error_log_reply->invalid_dword);
2610 phy->running_disparity_error_count =
2611 be32_to_cpu(phy_error_log_reply->running_disparity_error);
2612 phy->loss_of_dword_sync_count =
2613 be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
2614 phy->phy_reset_problem_count =
2615 be32_to_cpu(phy_error_log_reply->phy_reset_problem);
2621 dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2628 * mpi3mr_transport_get_linkerrors - return phy error counters
2629 * @phy: The SAS transport layer phy object
2631 * This function retrieves the phy error log information of the
2632 * HBA or expander for which the phy belongs to
2634 * Return: 0 for success, non-zero for failure.
2636 static int mpi3mr_transport_get_linkerrors(struct sas_phy *phy)
2638 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2639 struct mpi3_sas_phy_page1 phy_pg1;
2643 rc = mpi3mr_parent_present(mrioc, phy);
2647 if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2648 return mpi3mr_get_expander_phy_error_log(mrioc, phy);
2650 memset(&phy_pg1, 0, sizeof(struct mpi3_sas_phy_page1));
2651 /* get hba phy error logs */
2652 if ((mpi3mr_cfg_get_sas_phy_pg1(mrioc, &ioc_status, &phy_pg1,
2653 sizeof(struct mpi3_sas_phy_page1),
2654 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number))) {
2655 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2656 __FILE__, __LINE__, __func__);
2660 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2661 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2662 __FILE__, __LINE__, __func__);
2665 phy->invalid_dword_count = le32_to_cpu(phy_pg1.invalid_dword_count);
2666 phy->running_disparity_error_count =
2667 le32_to_cpu(phy_pg1.running_disparity_error_count);
2668 phy->loss_of_dword_sync_count =
2669 le32_to_cpu(phy_pg1.loss_dword_synch_count);
2670 phy->phy_reset_problem_count =
2671 le32_to_cpu(phy_pg1.phy_reset_problem_count);
2676 * mpi3mr_transport_get_enclosure_identifier - Get Enclosure ID
2677 * @rphy: The SAS transport layer remote phy object
2678 * @identifier: Enclosure identifier to be returned
2680 * Returns the enclosure id for the device pointed by the remote
2683 * Return: 0 on success or -ENXIO
2686 mpi3mr_transport_get_enclosure_identifier(struct sas_rphy *rphy,
2689 struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2690 struct mpi3mr_tgt_dev *tgtdev = NULL;
2691 unsigned long flags;
2694 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2695 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2696 rphy->identify.sas_address, rphy);
2699 tgtdev->enclosure_logical_id;
2701 mpi3mr_tgtdev_put(tgtdev);
2706 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2712 * mpi3mr_transport_get_bay_identifier - Get bay ID
2713 * @rphy: The SAS transport layer remote phy object
2715 * Returns the slot id for the device pointed by the remote phy
2718 * Return: Valid slot ID on success or -ENXIO
2721 mpi3mr_transport_get_bay_identifier(struct sas_rphy *rphy)
2723 struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2724 struct mpi3mr_tgt_dev *tgtdev = NULL;
2725 unsigned long flags;
2728 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2729 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2730 rphy->identify.sas_address, rphy);
2733 mpi3mr_tgtdev_put(tgtdev);
2736 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2741 /* phy control request structure */
2742 struct phy_control_request {
2743 u8 smp_frame_type; /* 0x40 */
2744 u8 function; /* 0x91 */
2745 u8 allocated_response_length;
2746 u8 request_length; /* 0x09 */
2747 u16 expander_change_count;
2752 u64 attached_device_name;
2753 u8 programmed_min_physical_link_rate;
2754 u8 programmed_max_physical_link_rate;
2758 /* phy control reply structure */
2759 struct phy_control_reply {
2760 u8 smp_frame_type; /* 0x41 */
2761 u8 function; /* 0x11 */
2766 #define SMP_PHY_CONTROL_LINK_RESET (0x01)
2767 #define SMP_PHY_CONTROL_HARD_RESET (0x02)
2768 #define SMP_PHY_CONTROL_DISABLE (0x03)
2771 * mpi3mr_expander_phy_control - expander phy control
2772 * @mrioc: Adapter instance reference
2773 * @phy: The SAS transport layer phy object
2774 * @phy_operation: The phy operation to be executed
2776 * Issues SMP passthru phy control request to execute a specific
2777 * phy operation for a given expander device.
2779 * Return: 0 for success, non-zero for failure.
2782 mpi3mr_expander_phy_control(struct mpi3mr_ioc *mrioc,
2783 struct sas_phy *phy, u8 phy_operation)
2785 struct mpi3_smp_passthrough_request mpi_request;
2786 struct mpi3_smp_passthrough_reply mpi_reply;
2787 struct phy_control_request *phy_control_request;
2788 struct phy_control_reply *phy_control_reply;
2791 void *data_out = NULL;
2792 dma_addr_t data_out_dma;
2793 dma_addr_t data_in_dma;
2796 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2797 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2798 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2802 if (mrioc->reset_in_progress) {
2803 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2807 data_out_sz = sizeof(struct phy_control_request);
2808 data_in_sz = sizeof(struct phy_control_reply);
2809 sz = data_out_sz + data_in_sz;
2810 data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2817 data_in_dma = data_out_dma + data_out_sz;
2818 phy_control_reply = data_out + data_out_sz;
2821 memset(data_out, 0, sz);
2823 phy_control_request = data_out;
2824 phy_control_request->smp_frame_type = 0x40;
2825 phy_control_request->function = 0x91;
2826 phy_control_request->request_length = 9;
2827 phy_control_request->allocated_response_length = 0;
2828 phy_control_request->phy_identifier = phy->number;
2829 phy_control_request->phy_operation = phy_operation;
2830 phy_control_request->programmed_min_physical_link_rate =
2831 phy->minimum_linkrate << 4;
2832 phy_control_request->programmed_max_physical_link_rate =
2833 phy->maximum_linkrate << 4;
2835 memset(&mpi_request, 0, request_sz);
2836 memset(&mpi_reply, 0, reply_sz);
2837 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2838 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2839 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2840 mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2842 psge = &mpi_request.request_sge;
2843 mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2845 psge = &mpi_request.response_sge;
2846 mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2848 dprint_transport_info(mrioc,
2849 "sending phy control SMP request to sas_address(0x%016llx), phy_id(%d) opcode(%d)\n",
2850 (unsigned long long)phy->identify.sas_address, phy->number,
2853 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2854 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2857 dprint_transport_info(mrioc,
2858 "phy control SMP request completed with ioc_status(0x%04x)\n",
2861 if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2862 dprint_transport_info(mrioc,
2863 "phy control - reply data transfer size(%d)\n",
2864 le16_to_cpu(mpi_reply.response_data_length));
2866 if (le16_to_cpu(mpi_reply.response_data_length) !=
2867 sizeof(struct phy_control_reply))
2869 dprint_transport_info(mrioc,
2870 "phy control - function_result(%d)\n",
2871 phy_control_reply->function_result);
2876 dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2883 * mpi3mr_transport_phy_reset - Reset a given phy
2884 * @phy: The SAS transport layer phy object
2885 * @hard_reset: Flag to indicate the type of reset
2887 * Return: 0 for success, non-zero for failure.
2890 mpi3mr_transport_phy_reset(struct sas_phy *phy, int hard_reset)
2892 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2893 struct mpi3_iounit_control_request mpi_request;
2894 struct mpi3_iounit_control_reply mpi_reply;
2895 u16 request_sz = sizeof(struct mpi3_iounit_control_request);
2896 u16 reply_sz = sizeof(struct mpi3_iounit_control_reply);
2900 rc = mpi3mr_parent_present(mrioc, phy);
2904 /* handle expander phys */
2905 if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2906 return mpi3mr_expander_phy_control(mrioc, phy,
2907 (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
2908 SMP_PHY_CONTROL_LINK_RESET);
2910 /* handle hba phys */
2911 memset(&mpi_request, 0, request_sz);
2912 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2913 mpi_request.function = MPI3_FUNCTION_IO_UNIT_CONTROL;
2914 mpi_request.operation = MPI3_CTRL_OP_SAS_PHY_CONTROL;
2915 mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_ACTION_INDEX] =
2916 (hard_reset ? MPI3_CTRL_ACTION_HARD_RESET :
2917 MPI3_CTRL_ACTION_LINK_RESET);
2918 mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_PHY_INDEX] =
2921 dprint_transport_info(mrioc,
2922 "sending phy reset request to sas_address(0x%016llx), phy_id(%d) hard_reset(%d)\n",
2923 (unsigned long long)phy->identify.sas_address, phy->number,
2926 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2927 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) {
2932 dprint_transport_info(mrioc,
2933 "phy reset request completed with ioc_status(0x%04x)\n",
2940 * mpi3mr_transport_phy_enable - enable/disable phys
2941 * @phy: The SAS transport layer phy object
2942 * @enable: flag to enable/disable, enable phy when true
2944 * This function enables/disables a given by executing required
2945 * configuration page changes or expander phy control command
2947 * Return: 0 for success, non-zero for failure.
2950 mpi3mr_transport_phy_enable(struct sas_phy *phy, int enable)
2952 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2953 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
2954 struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
2957 int i, discovery_active;
2959 rc = mpi3mr_parent_present(mrioc, phy);
2963 /* handle expander phys */
2964 if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2965 return mpi3mr_expander_phy_control(mrioc, phy,
2966 (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
2967 SMP_PHY_CONTROL_DISABLE);
2969 /* handle hba phys */
2970 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
2971 (mrioc->sas_hba.num_phys *
2972 sizeof(struct mpi3_sas_io_unit0_phy_data));
2973 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
2974 if (!sas_io_unit_pg0) {
2978 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
2979 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2980 __FILE__, __LINE__, __func__);
2985 /* unable to enable/disable phys when discovery is active */
2986 for (i = 0, discovery_active = 0; i < mrioc->sas_hba.num_phys ; i++) {
2987 if (sas_io_unit_pg0->phy_data[i].port_flags &
2988 MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS) {
2990 "discovery is active on port = %d, phy = %d\n"
2991 "\tunable to enable/disable phys, try again later!\n",
2992 sas_io_unit_pg0->phy_data[i].io_unit_port, i);
2993 discovery_active = 1;
2997 if (discovery_active) {
3002 if ((sas_io_unit_pg0->phy_data[phy->number].phy_flags &
3003 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
3004 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))) {
3005 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3006 __FILE__, __LINE__, __func__);
3011 /* read sas_iounit page 1 */
3012 sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3013 (mrioc->sas_hba.num_phys *
3014 sizeof(struct mpi3_sas_io_unit1_phy_data));
3015 sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3016 if (!sas_io_unit_pg1) {
3021 if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3022 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3023 __FILE__, __LINE__, __func__);
3029 sas_io_unit_pg1->phy_data[phy->number].phy_flags
3030 &= ~MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3032 sas_io_unit_pg1->phy_data[phy->number].phy_flags
3033 |= MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3035 mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz);
3039 mpi3mr_transport_phy_reset(phy, 0);
3042 kfree(sas_io_unit_pg1);
3043 kfree(sas_io_unit_pg0);
3048 * mpi3mr_transport_phy_speed - set phy min/max speed
3049 * @phy: The SAS transport later phy object
3050 * @rates: Rates defined as in sas_phy_linkrates
3052 * This function sets the link rates given in the rates
3053 * argument to the given phy by executing required configuration
3054 * page changes or expander phy control command
3056 * Return: 0 for success, non-zero for failure.
3059 mpi3mr_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
3061 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
3062 struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
3063 struct mpi3_sas_phy_page0 phy_pg0;
3067 rc = mpi3mr_parent_present(mrioc, phy);
3071 if (!rates->minimum_linkrate)
3072 rates->minimum_linkrate = phy->minimum_linkrate;
3073 else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
3074 rates->minimum_linkrate = phy->minimum_linkrate_hw;
3076 if (!rates->maximum_linkrate)
3077 rates->maximum_linkrate = phy->maximum_linkrate;
3078 else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
3079 rates->maximum_linkrate = phy->maximum_linkrate_hw;
3081 /* handle expander phys */
3082 if (phy->identify.sas_address != mrioc->sas_hba.sas_address) {
3083 phy->minimum_linkrate = rates->minimum_linkrate;
3084 phy->maximum_linkrate = rates->maximum_linkrate;
3085 return mpi3mr_expander_phy_control(mrioc, phy,
3086 SMP_PHY_CONTROL_LINK_RESET);
3089 /* handle hba phys */
3090 sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3091 (mrioc->sas_hba.num_phys *
3092 sizeof(struct mpi3_sas_io_unit1_phy_data));
3093 sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3094 if (!sas_io_unit_pg1) {
3099 if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3100 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3101 __FILE__, __LINE__, __func__);
3106 sas_io_unit_pg1->phy_data[phy->number].max_min_link_rate =
3107 (rates->minimum_linkrate + (rates->maximum_linkrate << 4));
3109 if (mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3110 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3111 __FILE__, __LINE__, __func__);
3117 mpi3mr_transport_phy_reset(phy, 0);
3119 /* read phy page 0, then update the rates in the sas transport phy */
3120 if (!mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
3121 sizeof(struct mpi3_sas_phy_page0),
3122 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number) &&
3123 (ioc_status == MPI3_IOCSTATUS_SUCCESS)) {
3124 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
3125 phy_pg0.programmed_link_rate &
3126 MPI3_SAS_PRATE_MIN_RATE_MASK);
3127 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
3128 phy_pg0.programmed_link_rate >> 4);
3129 phy->negotiated_linkrate =
3130 mpi3mr_convert_phy_link_rate(
3131 (phy_pg0.negotiated_link_rate &
3132 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK)
3133 >> MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
3137 kfree(sas_io_unit_pg1);
3142 * mpi3mr_map_smp_buffer - map BSG dma buffer
3143 * @dev: Generic device reference
3144 * @buf: BSG buffer pointer
3145 * @dma_addr: Physical address holder
3146 * @dma_len: Mapped DMA buffer length.
3147 * @p: Virtual address holder
3149 * This function maps the DMAable buffer
3151 * Return: 0 on success, non-zero on failure
3154 mpi3mr_map_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3155 dma_addr_t *dma_addr, size_t *dma_len, void **p)
3157 /* Check if the request is split across multiple segments */
3158 if (buf->sg_cnt > 1) {
3159 *p = dma_alloc_coherent(dev, buf->payload_len, dma_addr,
3163 *dma_len = buf->payload_len;
3165 if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
3167 *dma_addr = sg_dma_address(buf->sg_list);
3168 *dma_len = sg_dma_len(buf->sg_list);
3176 * mpi3mr_unmap_smp_buffer - unmap BSG dma buffer
3177 * @dev: Generic device reference
3178 * @buf: BSG buffer pointer
3179 * @dma_addr: Physical address to be unmapped
3180 * @p: Virtual address
3182 * This function unmaps the DMAable buffer
3185 mpi3mr_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3186 dma_addr_t dma_addr, void *p)
3189 dma_free_coherent(dev, buf->payload_len, p, dma_addr);
3191 dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL);
3195 * mpi3mr_transport_smp_handler - handler for smp passthru
3196 * @job: BSG job reference
3197 * @shost: SCSI host object reference
3198 * @rphy: SAS transport rphy object pointing the expander
3200 * This is used primarily by smp utils for sending the SMP
3201 * commands to the expanders attached to the controller
3204 mpi3mr_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
3205 struct sas_rphy *rphy)
3207 struct mpi3mr_ioc *mrioc = shost_priv(shost);
3208 struct mpi3_smp_passthrough_request mpi_request;
3209 struct mpi3_smp_passthrough_reply mpi_reply;
3212 dma_addr_t dma_addr_in;
3213 dma_addr_t dma_addr_out;
3214 void *addr_in = NULL;
3215 void *addr_out = NULL;
3218 unsigned int reslen = 0;
3219 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
3220 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
3221 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
3224 if (mrioc->reset_in_progress) {
3225 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
3230 rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3231 &dma_addr_out, &dma_len_out, &addr_out);
3236 sg_copy_to_buffer(job->request_payload.sg_list,
3237 job->request_payload.sg_cnt, addr_out,
3238 job->request_payload.payload_len);
3240 rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3241 &dma_addr_in, &dma_len_in, &addr_in);
3245 memset(&mpi_request, 0, request_sz);
3246 memset(&mpi_reply, 0, reply_sz);
3247 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
3248 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
3249 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_rphy(mrioc, rphy);
3250 mpi_request.sas_address = ((rphy) ?
3251 cpu_to_le64(rphy->identify.sas_address) :
3252 cpu_to_le64(mrioc->sas_hba.sas_address));
3253 psge = &mpi_request.request_sge;
3254 mpi3mr_add_sg_single(psge, sgl_flags, dma_len_out - 4, dma_addr_out);
3256 psge = &mpi_request.response_sge;
3257 mpi3mr_add_sg_single(psge, sgl_flags, dma_len_in - 4, dma_addr_in);
3259 dprint_transport_info(mrioc, "sending SMP request\n");
3261 rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
3262 &mpi_reply, reply_sz,
3263 MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
3267 dprint_transport_info(mrioc,
3268 "SMP request completed with ioc_status(0x%04x)\n", ioc_status);
3270 dprint_transport_info(mrioc,
3271 "SMP request - reply data transfer size(%d)\n",
3272 le16_to_cpu(mpi_reply.response_data_length));
3274 memcpy(job->reply, &mpi_reply, reply_sz);
3275 job->reply_len = reply_sz;
3276 reslen = le16_to_cpu(mpi_reply.response_data_length);
3279 sg_copy_from_buffer(job->reply_payload.sg_list,
3280 job->reply_payload.sg_cnt, addr_in,
3281 job->reply_payload.payload_len);
3285 mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3286 dma_addr_in, addr_in);
3288 mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3289 dma_addr_out, addr_out);
3291 bsg_job_done(job, rc, reslen);
3294 struct sas_function_template mpi3mr_transport_functions = {
3295 .get_linkerrors = mpi3mr_transport_get_linkerrors,
3296 .get_enclosure_identifier = mpi3mr_transport_get_enclosure_identifier,
3297 .get_bay_identifier = mpi3mr_transport_get_bay_identifier,
3298 .phy_reset = mpi3mr_transport_phy_reset,
3299 .phy_enable = mpi3mr_transport_phy_enable,
3300 .set_phy_speed = mpi3mr_transport_phy_speed,
3301 .smp_handler = mpi3mr_transport_smp_handler,
3304 struct scsi_transport_template *mpi3mr_transport_template;