1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Driver for Broadcom MPI3 Storage Controllers
5 * Copyright (C) 2017-2023 Broadcom Inc.
6 * (mailto: mpi3mr-linuxdrv.pdl@broadcom.com)
13 * mpi3mr_post_transport_req - Issue transport requests and wait
14 * @mrioc: Adapter instance reference
15 * @request: Properly populated MPI3 request
16 * @request_sz: Size of the MPI3 request
17 * @reply: Pointer to return MPI3 reply
18 * @reply_sz: Size of the MPI3 reply buffer
19 * @timeout: Timeout in seconds
20 * @ioc_status: Pointer to return ioc status
22 * A generic function for posting MPI3 requests from the SAS
23 * transport layer that uses transport command infrastructure.
24 * This blocks for the completion of request for timeout seconds
25 * and if the request times out this function faults the
26 * controller with proper reason code.
28 * On successful completion of the request this function returns
29 * appropriate ioc status from the firmware back to the caller.
31 * Return: 0 on success, non-zero on failure.
33 static int mpi3mr_post_transport_req(struct mpi3mr_ioc *mrioc, void *request,
34 u16 request_sz, void *reply, u16 reply_sz, int timeout,
39 mutex_lock(&mrioc->transport_cmds.mutex);
40 if (mrioc->transport_cmds.state & MPI3MR_CMD_PENDING) {
42 ioc_err(mrioc, "sending transport request failed due to command in use\n");
43 mutex_unlock(&mrioc->transport_cmds.mutex);
46 mrioc->transport_cmds.state = MPI3MR_CMD_PENDING;
47 mrioc->transport_cmds.is_waiting = 1;
48 mrioc->transport_cmds.callback = NULL;
49 mrioc->transport_cmds.ioc_status = 0;
50 mrioc->transport_cmds.ioc_loginfo = 0;
52 init_completion(&mrioc->transport_cmds.done);
53 dprint_cfg_info(mrioc, "posting transport request\n");
54 if (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO)
55 dprint_dump(request, request_sz, "transport_req");
56 retval = mpi3mr_admin_request_post(mrioc, request, request_sz, 1);
58 ioc_err(mrioc, "posting transport request failed\n");
61 wait_for_completion_timeout(&mrioc->transport_cmds.done,
63 if (!(mrioc->transport_cmds.state & MPI3MR_CMD_COMPLETE)) {
64 mpi3mr_check_rh_fault_ioc(mrioc,
65 MPI3MR_RESET_FROM_SAS_TRANSPORT_TIMEOUT);
66 ioc_err(mrioc, "transport request timed out\n");
70 *ioc_status = mrioc->transport_cmds.ioc_status &
71 MPI3_IOCSTATUS_STATUS_MASK;
72 if ((*ioc_status) != MPI3_IOCSTATUS_SUCCESS)
73 dprint_transport_err(mrioc,
74 "transport request returned with ioc_status(0x%04x), log_info(0x%08x)\n",
75 *ioc_status, mrioc->transport_cmds.ioc_loginfo);
77 if ((reply) && (mrioc->transport_cmds.state & MPI3MR_CMD_REPLY_VALID))
78 memcpy((u8 *)reply, mrioc->transport_cmds.reply, reply_sz);
81 mrioc->transport_cmds.state = MPI3MR_CMD_NOTUSED;
82 mutex_unlock(&mrioc->transport_cmds.mutex);
88 /* report manufacture request structure */
89 struct rep_manu_request {
96 /* report manufacture reply structure */
97 struct rep_manu_reply {
98 u8 smp_frame_type; /* 0x41 */
99 u8 function; /* 0x01 */
102 u16 expander_change_count;
106 u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
107 u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
108 u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
109 u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
111 u8 component_revision_id;
113 u8 vendor_specific[8];
117 * mpi3mr_report_manufacture - obtain SMP report_manufacture
118 * @mrioc: Adapter instance reference
119 * @sas_address: SAS address of the expander device
120 * @edev: SAS transport layer sas_expander_device object
121 * @port_id: ID of the HBA port
123 * Fills in the sas_expander_device with manufacturing info.
125 * Return: 0 for success, non-zero for failure.
127 static int mpi3mr_report_manufacture(struct mpi3mr_ioc *mrioc,
128 u64 sas_address, struct sas_expander_device *edev, u8 port_id)
130 struct mpi3_smp_passthrough_request mpi_request;
131 struct mpi3_smp_passthrough_reply mpi_reply;
132 struct rep_manu_reply *manufacture_reply;
133 struct rep_manu_request *manufacture_request;
136 void *data_out = NULL;
137 dma_addr_t data_out_dma;
138 dma_addr_t data_in_dma;
141 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
142 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
143 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
147 if (mrioc->reset_in_progress) {
148 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
152 data_out_sz = sizeof(struct rep_manu_request);
153 data_in_sz = sizeof(struct rep_manu_reply);
154 data_out = dma_alloc_coherent(&mrioc->pdev->dev,
155 data_out_sz + data_in_sz, &data_out_dma, GFP_KERNEL);
161 data_in_dma = data_out_dma + data_out_sz;
162 manufacture_reply = data_out + data_out_sz;
164 manufacture_request = data_out;
165 manufacture_request->smp_frame_type = 0x40;
166 manufacture_request->function = 1;
167 manufacture_request->reserved = 0;
168 manufacture_request->request_length = 0;
170 memset(&mpi_request, 0, request_sz);
171 memset(&mpi_reply, 0, reply_sz);
172 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
173 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
174 mpi_request.io_unit_port = (u8) port_id;
175 mpi_request.sas_address = cpu_to_le64(sas_address);
177 psge = &mpi_request.request_sge;
178 mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
180 psge = &mpi_request.response_sge;
181 mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
183 dprint_transport_info(mrioc,
184 "sending report manufacturer SMP request to sas_address(0x%016llx), port(%d)\n",
185 (unsigned long long)sas_address, port_id);
187 rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
188 &mpi_reply, reply_sz,
189 MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
193 dprint_transport_info(mrioc,
194 "report manufacturer SMP request completed with ioc_status(0x%04x)\n",
197 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
202 dprint_transport_info(mrioc,
203 "report manufacturer - reply data transfer size(%d)\n",
204 le16_to_cpu(mpi_reply.response_data_length));
206 if (le16_to_cpu(mpi_reply.response_data_length) !=
207 sizeof(struct rep_manu_reply)) {
212 strscpy(edev->vendor_id, manufacture_reply->vendor_id,
213 SAS_EXPANDER_VENDOR_ID_LEN);
214 strscpy(edev->product_id, manufacture_reply->product_id,
215 SAS_EXPANDER_PRODUCT_ID_LEN);
216 strscpy(edev->product_rev, manufacture_reply->product_rev,
217 SAS_EXPANDER_PRODUCT_REV_LEN);
218 edev->level = manufacture_reply->sas_format & 1;
220 strscpy(edev->component_vendor_id,
221 manufacture_reply->component_vendor_id,
222 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
223 tmp = (u8 *)&manufacture_reply->component_id;
224 edev->component_id = tmp[0] << 8 | tmp[1];
225 edev->component_revision_id =
226 manufacture_reply->component_revision_id;
231 dma_free_coherent(&mrioc->pdev->dev, data_out_sz + data_in_sz,
232 data_out, data_out_dma);
238 * __mpi3mr_expander_find_by_handle - expander search by handle
239 * @mrioc: Adapter instance reference
240 * @handle: Firmware device handle of the expander
242 * Context: The caller should acquire sas_node_lock
244 * This searches for expander device based on handle, then
245 * returns the sas_node object.
247 * Return: Expander sas_node object reference or NULL
249 struct mpi3mr_sas_node *__mpi3mr_expander_find_by_handle(struct mpi3mr_ioc
252 struct mpi3mr_sas_node *sas_expander, *r;
255 list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
256 if (sas_expander->handle != handle)
266 * mpi3mr_is_expander_device - if device is an expander
267 * @device_info: Bitfield providing information about the device
269 * Return: 1 if the device is expander device, else 0.
271 u8 mpi3mr_is_expander_device(u16 device_info)
273 if ((device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) ==
274 MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER)
281 * mpi3mr_get_sas_address - retrieve sas_address for handle
282 * @mrioc: Adapter instance reference
283 * @handle: Firmware device handle
284 * @sas_address: Address to hold sas address
286 * This function issues device page0 read for a given device
287 * handle and gets the SAS address and return it back
289 * Return: 0 for success, non-zero for failure
291 static int mpi3mr_get_sas_address(struct mpi3mr_ioc *mrioc, u16 handle,
294 struct mpi3_device_page0 dev_pg0;
296 struct mpi3_device0_sas_sata_format *sasinf;
300 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
301 sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
303 ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
307 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
308 ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
309 handle, ioc_status, __FILE__, __LINE__, __func__);
313 if (le16_to_cpu(dev_pg0.flags) &
314 MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE)
315 *sas_address = mrioc->sas_hba.sas_address;
316 else if (dev_pg0.device_form == MPI3_DEVICE_DEVFORM_SAS_SATA) {
317 sasinf = &dev_pg0.device_specific.sas_sata_format;
318 *sas_address = le64_to_cpu(sasinf->sas_address);
320 ioc_err(mrioc, "%s: device_form(%d) is not SAS_SATA\n",
321 __func__, dev_pg0.device_form);
328 * __mpi3mr_get_tgtdev_by_addr - target device search
329 * @mrioc: Adapter instance reference
330 * @sas_address: SAS address of the device
331 * @hba_port: HBA port entry
333 * This searches for target device from sas address and hba port
334 * pointer then return mpi3mr_tgt_dev object.
336 * Return: Valid tget_dev or NULL
338 static struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc,
339 u64 sas_address, struct mpi3mr_hba_port *hba_port)
341 struct mpi3mr_tgt_dev *tgtdev;
343 assert_spin_locked(&mrioc->tgtdev_lock);
345 list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list)
346 if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) &&
347 (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address)
348 && (tgtdev->dev_spec.sas_sata_inf.hba_port == hba_port))
352 mpi3mr_tgtdev_get(tgtdev);
357 * mpi3mr_get_tgtdev_by_addr - target device search
358 * @mrioc: Adapter instance reference
359 * @sas_address: SAS address of the device
360 * @hba_port: HBA port entry
362 * This searches for target device from sas address and hba port
363 * pointer then return mpi3mr_tgt_dev object.
365 * Context: This function will acquire tgtdev_lock and will
366 * release before returning the mpi3mr_tgt_dev object.
368 * Return: Valid tget_dev or NULL
370 static struct mpi3mr_tgt_dev *mpi3mr_get_tgtdev_by_addr(struct mpi3mr_ioc *mrioc,
371 u64 sas_address, struct mpi3mr_hba_port *hba_port)
373 struct mpi3mr_tgt_dev *tgtdev = NULL;
379 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
380 tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc, sas_address, hba_port);
381 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
388 * mpi3mr_remove_device_by_sas_address - remove the device
389 * @mrioc: Adapter instance reference
390 * @sas_address: SAS address of the device
391 * @hba_port: HBA port entry
393 * This searches for target device using sas address and hba
394 * port pointer then removes it from the OS.
398 static void mpi3mr_remove_device_by_sas_address(struct mpi3mr_ioc *mrioc,
399 u64 sas_address, struct mpi3mr_hba_port *hba_port)
401 struct mpi3mr_tgt_dev *tgtdev = NULL;
403 u8 was_on_tgtdev_list = 0;
408 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
409 tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc,
410 sas_address, hba_port);
412 if (!list_empty(&tgtdev->list)) {
413 list_del_init(&tgtdev->list);
414 was_on_tgtdev_list = 1;
415 mpi3mr_tgtdev_put(tgtdev);
418 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
419 if (was_on_tgtdev_list) {
420 if (tgtdev->host_exposed)
421 mpi3mr_remove_tgtdev_from_host(mrioc, tgtdev);
422 mpi3mr_tgtdev_put(tgtdev);
427 * __mpi3mr_get_tgtdev_by_addr_and_rphy - target device search
428 * @mrioc: Adapter instance reference
429 * @sas_address: SAS address of the device
430 * @rphy: SAS transport layer rphy object
432 * This searches for target device from sas address and rphy
433 * pointer then return mpi3mr_tgt_dev object.
435 * Return: Valid tget_dev or NULL
437 struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr_and_rphy(
438 struct mpi3mr_ioc *mrioc, u64 sas_address, struct sas_rphy *rphy)
440 struct mpi3mr_tgt_dev *tgtdev;
442 assert_spin_locked(&mrioc->tgtdev_lock);
444 list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list)
445 if ((tgtdev->dev_type == MPI3_DEVICE_DEVFORM_SAS_SATA) &&
446 (tgtdev->dev_spec.sas_sata_inf.sas_address == sas_address)
447 && (tgtdev->dev_spec.sas_sata_inf.rphy == rphy))
451 mpi3mr_tgtdev_get(tgtdev);
456 * mpi3mr_expander_find_by_sas_address - sas expander search
457 * @mrioc: Adapter instance reference
458 * @sas_address: SAS address of expander
459 * @hba_port: HBA port entry
461 * Return: A valid SAS expander node or NULL.
464 static struct mpi3mr_sas_node *mpi3mr_expander_find_by_sas_address(
465 struct mpi3mr_ioc *mrioc, u64 sas_address,
466 struct mpi3mr_hba_port *hba_port)
468 struct mpi3mr_sas_node *sas_expander, *r = NULL;
473 list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
474 if ((sas_expander->sas_address != sas_address) ||
475 (sas_expander->hba_port != hba_port))
485 * __mpi3mr_sas_node_find_by_sas_address - sas node search
486 * @mrioc: Adapter instance reference
487 * @sas_address: SAS address of expander or sas host
488 * @hba_port: HBA port entry
489 * Context: Caller should acquire mrioc->sas_node_lock.
491 * If the SAS address indicates the device is direct attached to
492 * the controller (controller's SAS address) then the SAS node
493 * associated with the controller is returned back else the SAS
494 * address and hba port are used to identify the exact expander
495 * and the associated sas_node object is returned. If there is
496 * no match NULL is returned.
498 * Return: A valid SAS node or NULL.
501 static struct mpi3mr_sas_node *__mpi3mr_sas_node_find_by_sas_address(
502 struct mpi3mr_ioc *mrioc, u64 sas_address,
503 struct mpi3mr_hba_port *hba_port)
506 if (mrioc->sas_hba.sas_address == sas_address)
507 return &mrioc->sas_hba;
508 return mpi3mr_expander_find_by_sas_address(mrioc, sas_address,
513 * mpi3mr_parent_present - Is parent present for a phy
514 * @mrioc: Adapter instance reference
515 * @phy: SAS transport layer phy object
517 * Return: 0 if parent is present else non-zero
519 static int mpi3mr_parent_present(struct mpi3mr_ioc *mrioc, struct sas_phy *phy)
522 struct mpi3mr_hba_port *hba_port = phy->hostdata;
524 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
525 if (__mpi3mr_sas_node_find_by_sas_address(mrioc,
526 phy->identify.sas_address,
528 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
531 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
536 * mpi3mr_convert_phy_link_rate -
537 * @link_rate: link rate as defined in the MPI header
539 * Convert link_rate from mpi format into sas_transport layer
542 * Return: A valid SAS transport layer defined link rate
544 static enum sas_linkrate mpi3mr_convert_phy_link_rate(u8 link_rate)
546 enum sas_linkrate rc;
549 case MPI3_SAS_NEG_LINK_RATE_1_5:
550 rc = SAS_LINK_RATE_1_5_GBPS;
552 case MPI3_SAS_NEG_LINK_RATE_3_0:
553 rc = SAS_LINK_RATE_3_0_GBPS;
555 case MPI3_SAS_NEG_LINK_RATE_6_0:
556 rc = SAS_LINK_RATE_6_0_GBPS;
558 case MPI3_SAS_NEG_LINK_RATE_12_0:
559 rc = SAS_LINK_RATE_12_0_GBPS;
561 case MPI3_SAS_NEG_LINK_RATE_22_5:
562 rc = SAS_LINK_RATE_22_5_GBPS;
564 case MPI3_SAS_NEG_LINK_RATE_PHY_DISABLED:
565 rc = SAS_PHY_DISABLED;
567 case MPI3_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
568 rc = SAS_LINK_RATE_FAILED;
570 case MPI3_SAS_NEG_LINK_RATE_PORT_SELECTOR:
571 rc = SAS_SATA_PORT_SELECTOR;
573 case MPI3_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
574 rc = SAS_PHY_RESET_IN_PROGRESS;
576 case MPI3_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
577 case MPI3_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
579 rc = SAS_LINK_RATE_UNKNOWN;
586 * mpi3mr_delete_sas_phy - Remove a single phy from port
587 * @mrioc: Adapter instance reference
588 * @mr_sas_port: Internal Port object
589 * @mr_sas_phy: Internal Phy object
593 static void mpi3mr_delete_sas_phy(struct mpi3mr_ioc *mrioc,
594 struct mpi3mr_sas_port *mr_sas_port,
595 struct mpi3mr_sas_phy *mr_sas_phy)
597 u64 sas_address = mr_sas_port->remote_identify.sas_address;
599 dev_info(&mr_sas_phy->phy->dev,
600 "remove: sas_address(0x%016llx), phy(%d)\n",
601 (unsigned long long) sas_address, mr_sas_phy->phy_id);
603 list_del(&mr_sas_phy->port_siblings);
604 mr_sas_port->num_phys--;
605 mr_sas_port->phy_mask &= ~(1 << mr_sas_phy->phy_id);
606 if (mr_sas_port->lowest_phy == mr_sas_phy->phy_id)
607 mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
608 sas_port_delete_phy(mr_sas_port->port, mr_sas_phy->phy);
609 mr_sas_phy->phy_belongs_to_port = 0;
613 * mpi3mr_add_sas_phy - Adding a single phy to a port
614 * @mrioc: Adapter instance reference
615 * @mr_sas_port: Internal Port object
616 * @mr_sas_phy: Internal Phy object
620 static void mpi3mr_add_sas_phy(struct mpi3mr_ioc *mrioc,
621 struct mpi3mr_sas_port *mr_sas_port,
622 struct mpi3mr_sas_phy *mr_sas_phy)
624 u64 sas_address = mr_sas_port->remote_identify.sas_address;
626 dev_info(&mr_sas_phy->phy->dev,
627 "add: sas_address(0x%016llx), phy(%d)\n", (unsigned long long)
628 sas_address, mr_sas_phy->phy_id);
630 list_add_tail(&mr_sas_phy->port_siblings, &mr_sas_port->phy_list);
631 mr_sas_port->num_phys++;
632 mr_sas_port->phy_mask |= (1 << mr_sas_phy->phy_id);
633 if (mr_sas_phy->phy_id < mr_sas_port->lowest_phy)
634 mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
635 sas_port_add_phy(mr_sas_port->port, mr_sas_phy->phy);
636 mr_sas_phy->phy_belongs_to_port = 1;
640 * mpi3mr_add_phy_to_an_existing_port - add phy to existing port
641 * @mrioc: Adapter instance reference
642 * @mr_sas_node: Internal sas node object (expander or host)
643 * @mr_sas_phy: Internal Phy object *
644 * @sas_address: SAS address of device/expander were phy needs
646 * @hba_port: HBA port entry
650 static void mpi3mr_add_phy_to_an_existing_port(struct mpi3mr_ioc *mrioc,
651 struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy,
652 u64 sas_address, struct mpi3mr_hba_port *hba_port)
654 struct mpi3mr_sas_port *mr_sas_port;
655 struct mpi3mr_sas_phy *srch_phy;
657 if (mr_sas_phy->phy_belongs_to_port == 1)
663 list_for_each_entry(mr_sas_port, &mr_sas_node->sas_port_list,
665 if (mr_sas_port->remote_identify.sas_address !=
668 if (mr_sas_port->hba_port != hba_port)
670 list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
672 if (srch_phy == mr_sas_phy)
675 mpi3mr_add_sas_phy(mrioc, mr_sas_port, mr_sas_phy);
681 * mpi3mr_delete_sas_port - helper function to removing a port
682 * @mrioc: Adapter instance reference
683 * @mr_sas_port: Internal Port object
687 static void mpi3mr_delete_sas_port(struct mpi3mr_ioc *mrioc,
688 struct mpi3mr_sas_port *mr_sas_port)
690 u64 sas_address = mr_sas_port->remote_identify.sas_address;
691 struct mpi3mr_hba_port *hba_port = mr_sas_port->hba_port;
692 enum sas_device_type device_type =
693 mr_sas_port->remote_identify.device_type;
695 dev_info(&mr_sas_port->port->dev,
696 "remove: sas_address(0x%016llx)\n",
697 (unsigned long long) sas_address);
699 if (device_type == SAS_END_DEVICE)
700 mpi3mr_remove_device_by_sas_address(mrioc, sas_address,
703 else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
704 device_type == SAS_FANOUT_EXPANDER_DEVICE)
705 mpi3mr_expander_remove(mrioc, sas_address, hba_port);
709 * mpi3mr_del_phy_from_an_existing_port - del phy from a port
710 * @mrioc: Adapter instance reference
711 * @mr_sas_node: Internal sas node object (expander or host)
712 * @mr_sas_phy: Internal Phy object
716 static void mpi3mr_del_phy_from_an_existing_port(struct mpi3mr_ioc *mrioc,
717 struct mpi3mr_sas_node *mr_sas_node, struct mpi3mr_sas_phy *mr_sas_phy)
719 struct mpi3mr_sas_port *mr_sas_port, *next;
720 struct mpi3mr_sas_phy *srch_phy;
722 if (mr_sas_phy->phy_belongs_to_port == 0)
725 list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
727 list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
729 if (srch_phy != mr_sas_phy)
731 if ((mr_sas_port->num_phys == 1) &&
732 !mrioc->reset_in_progress)
733 mpi3mr_delete_sas_port(mrioc, mr_sas_port);
735 mpi3mr_delete_sas_phy(mrioc, mr_sas_port,
743 * mpi3mr_sas_port_sanity_check - sanity check while adding port
744 * @mrioc: Adapter instance reference
745 * @mr_sas_node: Internal sas node object (expander or host)
746 * @sas_address: SAS address of device/expander
747 * @hba_port: HBA port entry
749 * Verifies whether the Phys attached to a device with the given
750 * SAS address already belongs to an existing sas port if so
751 * will remove those phys from the sas port
755 static void mpi3mr_sas_port_sanity_check(struct mpi3mr_ioc *mrioc,
756 struct mpi3mr_sas_node *mr_sas_node, u64 sas_address,
757 struct mpi3mr_hba_port *hba_port)
761 for (i = 0; i < mr_sas_node->num_phys; i++) {
762 if ((mr_sas_node->phy[i].remote_identify.sas_address !=
763 sas_address) || (mr_sas_node->phy[i].hba_port != hba_port))
765 if (mr_sas_node->phy[i].phy_belongs_to_port == 1)
766 mpi3mr_del_phy_from_an_existing_port(mrioc,
767 mr_sas_node, &mr_sas_node->phy[i]);
772 * mpi3mr_set_identify - set identify for phys and end devices
773 * @mrioc: Adapter instance reference
774 * @handle: Firmware device handle
775 * @identify: SAS transport layer's identify info
777 * Populates sas identify info for a specific device.
779 * Return: 0 for success, non-zero for failure.
781 static int mpi3mr_set_identify(struct mpi3mr_ioc *mrioc, u16 handle,
782 struct sas_identify *identify)
785 struct mpi3_device_page0 device_pg0;
786 struct mpi3_device0_sas_sata_format *sasinf;
790 if (mrioc->reset_in_progress) {
791 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
795 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &device_pg0,
796 sizeof(device_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE, handle))) {
797 ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
801 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
802 ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
803 handle, ioc_status, __FILE__, __LINE__, __func__);
807 memset(identify, 0, sizeof(struct sas_identify));
808 sasinf = &device_pg0.device_specific.sas_sata_format;
809 device_info = le16_to_cpu(sasinf->device_info);
812 identify->sas_address = le64_to_cpu(sasinf->sas_address);
814 /* phy number of the parent device this device is linked to */
815 identify->phy_identifier = sasinf->phy_num;
818 switch (device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) {
819 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_NO_DEVICE:
820 identify->device_type = SAS_PHY_UNUSED;
822 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE:
823 identify->device_type = SAS_END_DEVICE;
825 case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER:
826 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
830 /* initiator_port_protocols */
831 if (device_info & MPI3_SAS_DEVICE_INFO_SSP_INITIATOR)
832 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
833 /* MPI3.0 doesn't have define for SATA INIT so setting both here*/
834 if (device_info & MPI3_SAS_DEVICE_INFO_STP_INITIATOR)
835 identify->initiator_port_protocols |= (SAS_PROTOCOL_STP |
837 if (device_info & MPI3_SAS_DEVICE_INFO_SMP_INITIATOR)
838 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
840 /* target_port_protocols */
841 if (device_info & MPI3_SAS_DEVICE_INFO_SSP_TARGET)
842 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
843 /* MPI3.0 doesn't have define for STP Target so setting both here*/
844 if (device_info & MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET)
845 identify->target_port_protocols |= (SAS_PROTOCOL_STP |
847 if (device_info & MPI3_SAS_DEVICE_INFO_SMP_TARGET)
848 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
853 * mpi3mr_add_host_phy - report sas_host phy to SAS transport
854 * @mrioc: Adapter instance reference
855 * @mr_sas_phy: Internal Phy object
856 * @phy_pg0: SAS phy page 0
857 * @parent_dev: Prent device class object
859 * Return: 0 for success, non-zero for failure.
861 static int mpi3mr_add_host_phy(struct mpi3mr_ioc *mrioc,
862 struct mpi3mr_sas_phy *mr_sas_phy, struct mpi3_sas_phy_page0 phy_pg0,
863 struct device *parent_dev)
866 int phy_index = mr_sas_phy->phy_id;
869 INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
870 phy = sas_phy_alloc(parent_dev, phy_index);
872 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
873 __FILE__, __LINE__, __func__);
876 if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle,
877 &mr_sas_phy->identify))) {
878 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
879 __FILE__, __LINE__, __func__);
883 phy->identify = mr_sas_phy->identify;
884 mr_sas_phy->attached_handle = le16_to_cpu(phy_pg0.attached_dev_handle);
885 if (mr_sas_phy->attached_handle)
886 mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle,
887 &mr_sas_phy->remote_identify);
888 phy->identify.phy_identifier = mr_sas_phy->phy_id;
889 phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate(
890 (phy_pg0.negotiated_link_rate &
891 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
892 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
893 phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate(
894 phy_pg0.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK);
895 phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate(
896 phy_pg0.hw_link_rate >> 4);
897 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
898 phy_pg0.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK);
899 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
900 phy_pg0.programmed_link_rate >> 4);
901 phy->hostdata = mr_sas_phy->hba_port;
903 if ((sas_phy_add(phy))) {
904 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
905 __FILE__, __LINE__, __func__);
909 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
911 "add: handle(0x%04x), sas_address(0x%016llx)\n"
912 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
913 mr_sas_phy->handle, (unsigned long long)
914 mr_sas_phy->identify.sas_address,
915 mr_sas_phy->attached_handle,
917 mr_sas_phy->remote_identify.sas_address);
918 mr_sas_phy->phy = phy;
923 * mpi3mr_add_expander_phy - report expander phy to transport
924 * @mrioc: Adapter instance reference
925 * @mr_sas_phy: Internal Phy object
926 * @expander_pg1: SAS Expander page 1
927 * @parent_dev: Parent device class object
929 * Return: 0 for success, non-zero for failure.
931 static int mpi3mr_add_expander_phy(struct mpi3mr_ioc *mrioc,
932 struct mpi3mr_sas_phy *mr_sas_phy,
933 struct mpi3_sas_expander_page1 expander_pg1,
934 struct device *parent_dev)
937 int phy_index = mr_sas_phy->phy_id;
939 INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
940 phy = sas_phy_alloc(parent_dev, phy_index);
942 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
943 __FILE__, __LINE__, __func__);
946 if ((mpi3mr_set_identify(mrioc, mr_sas_phy->handle,
947 &mr_sas_phy->identify))) {
948 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
949 __FILE__, __LINE__, __func__);
953 phy->identify = mr_sas_phy->identify;
954 mr_sas_phy->attached_handle =
955 le16_to_cpu(expander_pg1.attached_dev_handle);
956 if (mr_sas_phy->attached_handle)
957 mpi3mr_set_identify(mrioc, mr_sas_phy->attached_handle,
958 &mr_sas_phy->remote_identify);
959 phy->identify.phy_identifier = mr_sas_phy->phy_id;
960 phy->negotiated_linkrate = mpi3mr_convert_phy_link_rate(
961 (expander_pg1.negotiated_link_rate &
962 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
963 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
964 phy->minimum_linkrate_hw = mpi3mr_convert_phy_link_rate(
965 expander_pg1.hw_link_rate & MPI3_SAS_HWRATE_MIN_RATE_MASK);
966 phy->maximum_linkrate_hw = mpi3mr_convert_phy_link_rate(
967 expander_pg1.hw_link_rate >> 4);
968 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
969 expander_pg1.programmed_link_rate & MPI3_SAS_PRATE_MIN_RATE_MASK);
970 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
971 expander_pg1.programmed_link_rate >> 4);
972 phy->hostdata = mr_sas_phy->hba_port;
974 if ((sas_phy_add(phy))) {
975 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
976 __FILE__, __LINE__, __func__);
980 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
982 "add: handle(0x%04x), sas_address(0x%016llx)\n"
983 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
984 mr_sas_phy->handle, (unsigned long long)
985 mr_sas_phy->identify.sas_address,
986 mr_sas_phy->attached_handle,
988 mr_sas_phy->remote_identify.sas_address);
989 mr_sas_phy->phy = phy;
994 * mpi3mr_alloc_hba_port - alloc hba port object
995 * @mrioc: Adapter instance reference
996 * @port_id: Port number
998 * Alloc memory for hba port object.
1000 static struct mpi3mr_hba_port *
1001 mpi3mr_alloc_hba_port(struct mpi3mr_ioc *mrioc, u16 port_id)
1003 struct mpi3mr_hba_port *hba_port;
1005 hba_port = kzalloc(sizeof(struct mpi3mr_hba_port),
1009 hba_port->port_id = port_id;
1010 ioc_info(mrioc, "hba_port entry: %p, port: %d is added to hba_port list\n",
1011 hba_port, hba_port->port_id);
1012 list_add_tail(&hba_port->list, &mrioc->hba_port_table_list);
1017 * mpi3mr_get_hba_port_by_id - find hba port by id
1018 * @mrioc: Adapter instance reference
1019 * @port_id - Port ID to search
1021 * Return: mpi3mr_hba_port reference for the matched port
1024 struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc,
1027 struct mpi3mr_hba_port *port, *port_next;
1029 list_for_each_entry_safe(port, port_next,
1030 &mrioc->hba_port_table_list, list) {
1031 if (port->port_id != port_id)
1033 if (port->flags & MPI3MR_HBA_PORT_FLAG_DIRTY)
1042 * mpi3mr_update_links - refreshing SAS phy link changes
1043 * @mrioc: Adapter instance reference
1044 * @sas_address_parent: SAS address of parent expander or host
1045 * @handle: Firmware device handle of attached device
1046 * @phy_number: Phy number
1047 * @link_rate: New link rate
1048 * @hba_port: HBA port entry
1052 void mpi3mr_update_links(struct mpi3mr_ioc *mrioc,
1053 u64 sas_address_parent, u16 handle, u8 phy_number, u8 link_rate,
1054 struct mpi3mr_hba_port *hba_port)
1056 unsigned long flags;
1057 struct mpi3mr_sas_node *mr_sas_node;
1058 struct mpi3mr_sas_phy *mr_sas_phy;
1060 if (mrioc->reset_in_progress)
1063 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1064 mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1065 sas_address_parent, hba_port);
1067 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1071 mr_sas_phy = &mr_sas_node->phy[phy_number];
1072 mr_sas_phy->attached_handle = handle;
1073 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1074 if (handle && (link_rate >= MPI3_SAS_NEG_LINK_RATE_1_5)) {
1075 mpi3mr_set_identify(mrioc, handle,
1076 &mr_sas_phy->remote_identify);
1077 mpi3mr_add_phy_to_an_existing_port(mrioc, mr_sas_node,
1078 mr_sas_phy, mr_sas_phy->remote_identify.sas_address,
1081 memset(&mr_sas_phy->remote_identify, 0, sizeof(struct
1084 if (mr_sas_phy->phy)
1085 mr_sas_phy->phy->negotiated_linkrate =
1086 mpi3mr_convert_phy_link_rate(link_rate);
1088 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1089 dev_info(&mr_sas_phy->phy->dev,
1090 "refresh: parent sas_address(0x%016llx),\n"
1091 "\tlink_rate(0x%02x), phy(%d)\n"
1092 "\tattached_handle(0x%04x), sas_address(0x%016llx)\n",
1093 (unsigned long long)sas_address_parent,
1094 link_rate, phy_number, handle, (unsigned long long)
1095 mr_sas_phy->remote_identify.sas_address);
1099 * mpi3mr_sas_host_refresh - refreshing sas host object contents
1100 * @mrioc: Adapter instance reference
1102 * This function refreshes the controllers phy information and
1103 * updates the SAS transport layer with updated information,
1104 * this is executed for each device addition or device info
1109 void mpi3mr_sas_host_refresh(struct mpi3mr_ioc *mrioc)
1113 u16 sz, port_id, attached_handle;
1114 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1116 dprint_transport_info(mrioc,
1117 "updating handles for sas_host(0x%016llx)\n",
1118 (unsigned long long)mrioc->sas_hba.sas_address);
1120 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1121 (mrioc->sas_hba.num_phys *
1122 sizeof(struct mpi3_sas_io_unit0_phy_data));
1123 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1124 if (!sas_io_unit_pg0)
1126 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1127 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1128 __FILE__, __LINE__, __func__);
1132 mrioc->sas_hba.handle = 0;
1133 for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1134 if (sas_io_unit_pg0->phy_data[i].phy_flags &
1135 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
1136 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))
1139 sas_io_unit_pg0->phy_data[i].negotiated_link_rate >> 4;
1140 if (!mrioc->sas_hba.handle)
1141 mrioc->sas_hba.handle = le16_to_cpu(
1142 sas_io_unit_pg0->phy_data[i].controller_dev_handle);
1143 port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1144 if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
1145 if (!mpi3mr_alloc_hba_port(mrioc, port_id))
1148 mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle;
1149 attached_handle = le16_to_cpu(
1150 sas_io_unit_pg0->phy_data[i].attached_dev_handle);
1151 if (attached_handle && link_rate < MPI3_SAS_NEG_LINK_RATE_1_5)
1152 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5;
1153 mrioc->sas_hba.phy[i].hba_port =
1154 mpi3mr_get_hba_port_by_id(mrioc, port_id);
1155 mpi3mr_update_links(mrioc, mrioc->sas_hba.sas_address,
1156 attached_handle, i, link_rate,
1157 mrioc->sas_hba.phy[i].hba_port);
1160 kfree(sas_io_unit_pg0);
1164 * mpi3mr_sas_host_add - create sas host object
1165 * @mrioc: Adapter instance reference
1167 * This function creates the controllers phy information and
1168 * updates the SAS transport layer with updated information,
1169 * this is executed for first device addition or device info
1174 void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc)
1177 u16 sz, num_phys = 1, port_id, ioc_status;
1178 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1179 struct mpi3_sas_phy_page0 phy_pg0;
1180 struct mpi3_device_page0 dev_pg0;
1181 struct mpi3_enclosure_page0 encl_pg0;
1182 struct mpi3_device0_sas_sata_format *sasinf;
1184 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1185 (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data));
1186 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1187 if (!sas_io_unit_pg0)
1190 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1191 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1192 __FILE__, __LINE__, __func__);
1195 num_phys = sas_io_unit_pg0->num_phys;
1196 kfree(sas_io_unit_pg0);
1198 mrioc->sas_hba.host_node = 1;
1199 INIT_LIST_HEAD(&mrioc->sas_hba.sas_port_list);
1200 mrioc->sas_hba.parent_dev = &mrioc->shost->shost_gendev;
1201 mrioc->sas_hba.phy = kcalloc(num_phys,
1202 sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
1203 if (!mrioc->sas_hba.phy)
1206 mrioc->sas_hba.num_phys = num_phys;
1208 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1209 (num_phys * sizeof(struct mpi3_sas_io_unit0_phy_data));
1210 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1211 if (!sas_io_unit_pg0)
1214 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1215 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1216 __FILE__, __LINE__, __func__);
1220 mrioc->sas_hba.handle = 0;
1221 for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1222 if (sas_io_unit_pg0->phy_data[i].phy_flags &
1223 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
1224 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))
1226 if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
1227 sizeof(struct mpi3_sas_phy_page0),
1228 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, i)) {
1229 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1230 __FILE__, __LINE__, __func__);
1233 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1234 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1235 __FILE__, __LINE__, __func__);
1239 if (!mrioc->sas_hba.handle)
1240 mrioc->sas_hba.handle = le16_to_cpu(
1241 sas_io_unit_pg0->phy_data[i].controller_dev_handle);
1242 port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1244 if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
1245 if (!mpi3mr_alloc_hba_port(mrioc, port_id))
1248 mrioc->sas_hba.phy[i].handle = mrioc->sas_hba.handle;
1249 mrioc->sas_hba.phy[i].phy_id = i;
1250 mrioc->sas_hba.phy[i].hba_port =
1251 mpi3mr_get_hba_port_by_id(mrioc, port_id);
1252 mpi3mr_add_host_phy(mrioc, &mrioc->sas_hba.phy[i],
1253 phy_pg0, mrioc->sas_hba.parent_dev);
1255 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
1256 sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
1257 mrioc->sas_hba.handle))) {
1258 ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
1261 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1262 ioc_err(mrioc, "device page read failed for handle(0x%04x), with ioc_status(0x%04x) failure at %s:%d/%s()!\n",
1263 mrioc->sas_hba.handle, ioc_status, __FILE__, __LINE__,
1267 mrioc->sas_hba.enclosure_handle =
1268 le16_to_cpu(dev_pg0.enclosure_handle);
1269 sasinf = &dev_pg0.device_specific.sas_sata_format;
1270 mrioc->sas_hba.sas_address =
1271 le64_to_cpu(sasinf->sas_address);
1273 "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
1274 mrioc->sas_hba.handle,
1275 (unsigned long long) mrioc->sas_hba.sas_address,
1276 mrioc->sas_hba.num_phys);
1278 if (mrioc->sas_hba.enclosure_handle) {
1279 if (!(mpi3mr_cfg_get_enclosure_pg0(mrioc, &ioc_status,
1280 &encl_pg0, sizeof(encl_pg0),
1281 MPI3_ENCLOS_PGAD_FORM_HANDLE,
1282 mrioc->sas_hba.enclosure_handle)) &&
1283 (ioc_status == MPI3_IOCSTATUS_SUCCESS))
1284 mrioc->sas_hba.enclosure_logical_id =
1285 le64_to_cpu(encl_pg0.enclosure_logical_id);
1289 kfree(sas_io_unit_pg0);
1293 * mpi3mr_sas_port_add - Expose the SAS device to the SAS TL
1294 * @mrioc: Adapter instance reference
1295 * @handle: Firmware device handle of the attached device
1296 * @sas_address_parent: sas address of parent expander or host
1297 * @hba_port: HBA port entry
1299 * This function creates a new sas port object for the given end
1300 * device matching sas address and hba_port and adds it to the
1301 * sas_node's sas_port_list and expose the attached sas device
1302 * to the SAS transport layer through sas_rphy_add.
1304 * Returns a valid mpi3mr_sas_port reference or NULL.
1306 static struct mpi3mr_sas_port *mpi3mr_sas_port_add(struct mpi3mr_ioc *mrioc,
1307 u16 handle, u64 sas_address_parent, struct mpi3mr_hba_port *hba_port)
1309 struct mpi3mr_sas_phy *mr_sas_phy, *next;
1310 struct mpi3mr_sas_port *mr_sas_port;
1311 unsigned long flags;
1312 struct mpi3mr_sas_node *mr_sas_node;
1313 struct sas_rphy *rphy;
1314 struct mpi3mr_tgt_dev *tgtdev = NULL;
1316 struct sas_port *port;
1319 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1320 __FILE__, __LINE__, __func__);
1324 mr_sas_port = kzalloc(sizeof(struct mpi3mr_sas_port), GFP_KERNEL);
1328 INIT_LIST_HEAD(&mr_sas_port->port_list);
1329 INIT_LIST_HEAD(&mr_sas_port->phy_list);
1330 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1331 mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1332 sas_address_parent, hba_port);
1333 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1336 ioc_err(mrioc, "%s:could not find parent sas_address(0x%016llx)!\n",
1337 __func__, (unsigned long long)sas_address_parent);
1341 if ((mpi3mr_set_identify(mrioc, handle,
1342 &mr_sas_port->remote_identify))) {
1343 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1344 __FILE__, __LINE__, __func__);
1348 if (mr_sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
1349 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1350 __FILE__, __LINE__, __func__);
1354 mr_sas_port->hba_port = hba_port;
1355 mpi3mr_sas_port_sanity_check(mrioc, mr_sas_node,
1356 mr_sas_port->remote_identify.sas_address, hba_port);
1358 for (i = 0; i < mr_sas_node->num_phys; i++) {
1359 if ((mr_sas_node->phy[i].remote_identify.sas_address !=
1360 mr_sas_port->remote_identify.sas_address) ||
1361 (mr_sas_node->phy[i].hba_port != hba_port))
1363 list_add_tail(&mr_sas_node->phy[i].port_siblings,
1364 &mr_sas_port->phy_list);
1365 mr_sas_port->num_phys++;
1366 mr_sas_port->phy_mask |= (1 << i);
1369 if (!mr_sas_port->num_phys) {
1370 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1371 __FILE__, __LINE__, __func__);
1375 mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
1377 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1378 tgtdev = mpi3mr_get_tgtdev_by_addr(mrioc,
1379 mr_sas_port->remote_identify.sas_address,
1380 mr_sas_port->hba_port);
1383 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1384 __FILE__, __LINE__, __func__);
1387 tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 1;
1390 if (!mr_sas_node->parent_dev) {
1391 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1392 __FILE__, __LINE__, __func__);
1396 port = sas_port_alloc_num(mr_sas_node->parent_dev);
1397 if ((sas_port_add(port))) {
1398 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1399 __FILE__, __LINE__, __func__);
1403 list_for_each_entry(mr_sas_phy, &mr_sas_port->phy_list,
1405 if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1406 dev_info(&port->dev,
1407 "add: handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
1408 handle, (unsigned long long)
1409 mr_sas_port->remote_identify.sas_address,
1410 mr_sas_phy->phy_id);
1411 sas_port_add_phy(port, mr_sas_phy->phy);
1412 mr_sas_phy->phy_belongs_to_port = 1;
1413 mr_sas_phy->hba_port = hba_port;
1416 mr_sas_port->port = port;
1417 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1418 rphy = sas_end_device_alloc(port);
1419 tgtdev->dev_spec.sas_sata_inf.rphy = rphy;
1421 rphy = sas_expander_alloc(port,
1422 mr_sas_port->remote_identify.device_type);
1424 rphy->identify = mr_sas_port->remote_identify;
1426 if (mrioc->current_event)
1427 mrioc->current_event->pending_at_sml = 1;
1429 if ((sas_rphy_add(rphy))) {
1430 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1431 __FILE__, __LINE__, __func__);
1433 if (mr_sas_port->remote_identify.device_type == SAS_END_DEVICE) {
1434 tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 0;
1435 tgtdev->dev_spec.sas_sata_inf.sas_transport_attached = 1;
1436 mpi3mr_tgtdev_put(tgtdev);
1439 dev_info(&rphy->dev,
1440 "%s: added: handle(0x%04x), sas_address(0x%016llx)\n",
1441 __func__, handle, (unsigned long long)
1442 mr_sas_port->remote_identify.sas_address);
1444 mr_sas_port->rphy = rphy;
1445 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1446 list_add_tail(&mr_sas_port->port_list, &mr_sas_node->sas_port_list);
1447 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1449 if (mrioc->current_event) {
1450 mrioc->current_event->pending_at_sml = 0;
1451 if (mrioc->current_event->discard)
1452 mpi3mr_print_device_event_notice(mrioc, true);
1455 /* fill in report manufacture */
1456 if (mr_sas_port->remote_identify.device_type ==
1457 SAS_EDGE_EXPANDER_DEVICE ||
1458 mr_sas_port->remote_identify.device_type ==
1459 SAS_FANOUT_EXPANDER_DEVICE)
1460 mpi3mr_report_manufacture(mrioc,
1461 mr_sas_port->remote_identify.sas_address,
1462 rphy_to_expander_device(rphy), hba_port->port_id);
1467 list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list,
1469 list_del(&mr_sas_phy->port_siblings);
1475 * mpi3mr_sas_port_remove - remove port from the list
1476 * @mrioc: Adapter instance reference
1477 * @sas_address: SAS address of attached device
1478 * @sas_address_parent: SAS address of parent expander or host
1479 * @hba_port: HBA port entry
1481 * Removing object and freeing associated memory from the
1486 static void mpi3mr_sas_port_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
1487 u64 sas_address_parent, struct mpi3mr_hba_port *hba_port)
1490 unsigned long flags;
1491 struct mpi3mr_sas_port *mr_sas_port, *next;
1492 struct mpi3mr_sas_node *mr_sas_node;
1494 struct mpi3mr_sas_phy *mr_sas_phy, *next_phy;
1495 struct mpi3mr_hba_port *srch_port, *hba_port_next = NULL;
1500 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1501 mr_sas_node = __mpi3mr_sas_node_find_by_sas_address(mrioc,
1502 sas_address_parent, hba_port);
1504 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1507 list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
1509 if (mr_sas_port->remote_identify.sas_address != sas_address)
1511 if (mr_sas_port->hba_port != hba_port)
1514 list_del(&mr_sas_port->port_list);
1520 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1524 if (mr_sas_node->host_node) {
1525 list_for_each_entry_safe(srch_port, hba_port_next,
1526 &mrioc->hba_port_table_list, list) {
1527 if (srch_port != hba_port)
1530 "removing hba_port entry: %p port: %d from hba_port list\n",
1531 srch_port, srch_port->port_id);
1532 list_del(&hba_port->list);
1538 for (i = 0; i < mr_sas_node->num_phys; i++) {
1539 if (mr_sas_node->phy[i].remote_identify.sas_address ==
1541 memset(&mr_sas_node->phy[i].remote_identify, 0,
1542 sizeof(struct sas_identify));
1545 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1547 if (mrioc->current_event)
1548 mrioc->current_event->pending_at_sml = 1;
1550 list_for_each_entry_safe(mr_sas_phy, next_phy,
1551 &mr_sas_port->phy_list, port_siblings) {
1552 if ((!mrioc->stop_drv_processing) &&
1553 (mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
1554 dev_info(&mr_sas_port->port->dev,
1555 "remove: sas_address(0x%016llx), phy(%d)\n",
1556 (unsigned long long)
1557 mr_sas_port->remote_identify.sas_address,
1558 mr_sas_phy->phy_id);
1559 mr_sas_phy->phy_belongs_to_port = 0;
1560 if (!mrioc->stop_drv_processing)
1561 sas_port_delete_phy(mr_sas_port->port,
1563 list_del(&mr_sas_phy->port_siblings);
1565 if (!mrioc->stop_drv_processing)
1566 sas_port_delete(mr_sas_port->port);
1567 ioc_info(mrioc, "%s: removed sas_address(0x%016llx)\n",
1568 __func__, (unsigned long long)sas_address);
1570 if (mrioc->current_event) {
1571 mrioc->current_event->pending_at_sml = 0;
1572 if (mrioc->current_event->discard)
1573 mpi3mr_print_device_event_notice(mrioc, false);
1580 * struct host_port - host port details
1581 * @sas_address: SAS Address of the attached device
1582 * @phy_mask: phy mask of host port
1583 * @handle: Device Handle of attached device
1584 * @iounit_port_id: port ID
1585 * @used: host port is already matched with sas port from sas_port_list
1586 * @lowest_phy: lowest phy ID of host port
1598 * mpi3mr_update_mr_sas_port - update sas port objects during reset
1599 * @mrioc: Adapter instance reference
1600 * @h_port: host_port object
1601 * @mr_sas_port: sas_port objects which needs to be updated
1603 * Update the port ID of sas port object. Also add the phys if new phys got
1604 * added to current sas port and remove the phys if some phys are moved
1605 * out of the current sas port.
1610 mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
1611 struct mpi3mr_sas_port *mr_sas_port)
1613 struct mpi3mr_sas_phy *mr_sas_phy;
1615 u64 phys_to_be_added, phys_to_be_removed;
1619 mr_sas_port->marked_responding = 1;
1621 dev_info(&mr_sas_port->port->dev,
1622 "sas_address(0x%016llx), old: port_id %d phy_mask 0x%llx, new: port_id %d phy_mask:0x%llx\n",
1623 mr_sas_port->remote_identify.sas_address,
1624 mr_sas_port->hba_port->port_id, mr_sas_port->phy_mask,
1625 h_port->iounit_port_id, h_port->phy_mask);
1627 mr_sas_port->hba_port->port_id = h_port->iounit_port_id;
1628 mr_sas_port->hba_port->flags &= ~MPI3MR_HBA_PORT_FLAG_DIRTY;
1630 /* Get the newly added phys bit map & removed phys bit map */
1631 phy_mask_xor = mr_sas_port->phy_mask ^ h_port->phy_mask;
1632 phys_to_be_added = h_port->phy_mask & phy_mask_xor;
1633 phys_to_be_removed = mr_sas_port->phy_mask & phy_mask_xor;
1636 * Register these new phys to current mr_sas_port's port.
1637 * if these phys are previously registered with another port
1638 * then delete these phys from that port first.
1640 for_each_set_bit(i, (ulong *) &phys_to_be_added, BITS_PER_TYPE(u64)) {
1641 mr_sas_phy = &mrioc->sas_hba.phy[i];
1642 if (mr_sas_phy->phy_belongs_to_port)
1643 mpi3mr_del_phy_from_an_existing_port(mrioc,
1644 &mrioc->sas_hba, mr_sas_phy);
1645 mpi3mr_add_phy_to_an_existing_port(mrioc,
1646 &mrioc->sas_hba, mr_sas_phy,
1647 mr_sas_port->remote_identify.sas_address,
1648 mr_sas_port->hba_port);
1651 /* Delete the phys which are not part of current mr_sas_port's port. */
1652 for_each_set_bit(i, (ulong *) &phys_to_be_removed, BITS_PER_TYPE(u64)) {
1653 mr_sas_phy = &mrioc->sas_hba.phy[i];
1654 if (mr_sas_phy->phy_belongs_to_port)
1655 mpi3mr_del_phy_from_an_existing_port(mrioc,
1656 &mrioc->sas_hba, mr_sas_phy);
1661 * mpi3mr_refresh_sas_ports - update host's sas ports during reset
1662 * @mrioc: Adapter instance reference
1664 * Update the host's sas ports during reset by checking whether
1665 * sas ports are still intact or not. Add/remove phys if any hba
1666 * phys are (moved in)/(moved out) of sas port. Also update
1667 * io_unit_port if it got changed during reset.
1672 mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
1674 struct host_port *h_port = NULL;
1675 int i, j, found, host_port_count = 0, port_idx;
1676 u16 sz, attached_handle, ioc_status;
1677 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1678 struct mpi3_device_page0 dev_pg0;
1679 struct mpi3_device0_sas_sata_format *sasinf;
1680 struct mpi3mr_sas_port *mr_sas_port;
1682 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
1683 (mrioc->sas_hba.num_phys *
1684 sizeof(struct mpi3_sas_io_unit0_phy_data));
1685 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
1686 if (!sas_io_unit_pg0)
1688 h_port = kcalloc(64, sizeof(struct host_port), GFP_KERNEL);
1692 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1693 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1694 __FILE__, __LINE__, __func__);
1698 /* Create a new expander port table */
1699 for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1700 attached_handle = le16_to_cpu(
1701 sas_io_unit_pg0->phy_data[i].attached_dev_handle);
1702 if (!attached_handle)
1705 for (j = 0; j < host_port_count; j++) {
1706 if (h_port[j].handle == attached_handle) {
1707 h_port[j].phy_mask |= (1 << i);
1714 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
1715 sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
1716 attached_handle))) {
1718 "failed to read dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1719 attached_handle, __FILE__, __LINE__, __func__);
1722 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1724 "ioc_status(0x%x) while reading dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1725 ioc_status, attached_handle,
1726 __FILE__, __LINE__, __func__);
1729 sasinf = &dev_pg0.device_specific.sas_sata_format;
1731 port_idx = host_port_count;
1732 h_port[port_idx].sas_address = le64_to_cpu(sasinf->sas_address);
1733 h_port[port_idx].handle = attached_handle;
1734 h_port[port_idx].phy_mask = (1 << i);
1735 h_port[port_idx].iounit_port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1736 h_port[port_idx].lowest_phy = sasinf->phy_num;
1737 h_port[port_idx].used = 0;
1741 if (!host_port_count)
1744 if (mrioc->logging_level & MPI3_DEBUG_RESET) {
1745 ioc_info(mrioc, "Host port details before reset\n");
1746 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1749 "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1750 mr_sas_port->hba_port->port_id,
1751 mr_sas_port->remote_identify.sas_address,
1752 mr_sas_port->phy_mask, mr_sas_port->lowest_phy);
1755 ioc_info(mrioc, "Host port details after reset\n");
1756 for (i = 0; i < host_port_count; i++) {
1758 "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1759 h_port[i].iounit_port_id, h_port[i].sas_address,
1760 h_port[i].phy_mask, h_port[i].lowest_phy);
1764 /* mark all host sas port entries as dirty */
1765 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1767 mr_sas_port->marked_responding = 0;
1768 mr_sas_port->hba_port->flags |= MPI3MR_HBA_PORT_FLAG_DIRTY;
1771 /* First check for matching lowest phy */
1772 for (i = 0; i < host_port_count; i++) {
1774 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1776 if (mr_sas_port->marked_responding)
1778 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1780 if (h_port[i].lowest_phy == mr_sas_port->lowest_phy) {
1781 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1787 /* In case if lowest phy is got enabled or disabled during reset */
1788 for (i = 0; i < host_port_count; i++) {
1792 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1794 if (mr_sas_port->marked_responding)
1796 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1798 if (h_port[i].phy_mask & mr_sas_port->phy_mask) {
1799 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1805 /* In case if expander cable is removed & connected to another HBA port during reset */
1806 for (i = 0; i < host_port_count; i++) {
1810 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1812 if (mr_sas_port->marked_responding)
1814 if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1816 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1822 kfree(sas_io_unit_pg0);
1826 * mpi3mr_refresh_expanders - Refresh expander device exposure
1827 * @mrioc: Adapter instance reference
1829 * This is executed post controller reset to identify any
1830 * missing expander devices during reset and remove from the upper layers
1831 * or expose any newly detected expander device to the upper layers.
1836 mpi3mr_refresh_expanders(struct mpi3mr_ioc *mrioc)
1838 struct mpi3mr_sas_node *sas_expander, *sas_expander_next;
1839 struct mpi3_sas_expander_page0 expander_pg0;
1840 u16 ioc_status, handle;
1843 unsigned long flags;
1844 struct mpi3mr_hba_port *hba_port;
1846 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1847 list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
1848 sas_expander->non_responding = 1;
1850 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1852 sas_expander = NULL;
1856 /* Search for responding expander devices and add them if they are newly got added */
1858 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
1859 sizeof(struct mpi3_sas_expander_page0),
1860 MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
1862 "failed to read exp pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1863 handle, __FILE__, __LINE__, __func__);
1867 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1869 "ioc_status(0x%x) while reading exp pg0 for handle:(0x%04x), %s:%d/%s()!\n",
1870 ioc_status, handle, __FILE__, __LINE__, __func__);
1874 handle = le16_to_cpu(expander_pg0.dev_handle);
1875 sas_address = le64_to_cpu(expander_pg0.sas_address);
1876 hba_port = mpi3mr_get_hba_port_by_id(mrioc, expander_pg0.io_unit_port);
1879 mpi3mr_sas_host_refresh(mrioc);
1880 mpi3mr_expander_add(mrioc, handle);
1884 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1886 mpi3mr_expander_find_by_sas_address(mrioc,
1887 sas_address, hba_port);
1888 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1890 if (!sas_expander) {
1891 mpi3mr_sas_host_refresh(mrioc);
1892 mpi3mr_expander_add(mrioc, handle);
1896 sas_expander->non_responding = 0;
1897 if (sas_expander->handle == handle)
1900 sas_expander->handle = handle;
1901 for (i = 0 ; i < sas_expander->num_phys ; i++)
1902 sas_expander->phy[i].handle = handle;
1906 * Delete non responding expander devices and the corresponding
1907 * hba_port if the non responding expander device's parent device
1910 sas_expander = NULL;
1911 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1912 list_for_each_entry_safe_reverse(sas_expander, sas_expander_next,
1913 &mrioc->sas_expander_list, list) {
1914 if (sas_expander->non_responding) {
1915 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1916 mpi3mr_expander_node_remove(mrioc, sas_expander);
1917 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1920 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1924 * mpi3mr_expander_node_add - insert an expander to the list.
1925 * @mrioc: Adapter instance reference
1926 * @sas_expander: Expander sas node
1927 * Context: This function will acquire sas_node_lock.
1929 * Adding new object to the ioc->sas_expander_list.
1933 static void mpi3mr_expander_node_add(struct mpi3mr_ioc *mrioc,
1934 struct mpi3mr_sas_node *sas_expander)
1936 unsigned long flags;
1938 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1939 list_add_tail(&sas_expander->list, &mrioc->sas_expander_list);
1940 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1944 * mpi3mr_expander_add - Create expander object
1945 * @mrioc: Adapter instance reference
1946 * @handle: Expander firmware device handle
1948 * This function creating expander object, stored in
1949 * sas_expander_list and expose it to the SAS transport
1952 * Return: 0 for success, non-zero for failure.
1954 int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle)
1956 struct mpi3mr_sas_node *sas_expander;
1957 struct mpi3mr_enclosure_node *enclosure_dev;
1958 struct mpi3_sas_expander_page0 expander_pg0;
1959 struct mpi3_sas_expander_page1 expander_pg1;
1960 u16 ioc_status, parent_handle, temp_handle;
1961 u64 sas_address, sas_address_parent = 0;
1963 unsigned long flags;
1964 u8 port_id, link_rate;
1965 struct mpi3mr_sas_port *mr_sas_port = NULL;
1966 struct mpi3mr_hba_port *hba_port;
1973 if (mrioc->reset_in_progress)
1976 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
1977 sizeof(expander_pg0), MPI3_SAS_EXPAND_PGAD_FORM_HANDLE, handle))) {
1978 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1979 __FILE__, __LINE__, __func__);
1983 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1984 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1985 __FILE__, __LINE__, __func__);
1989 parent_handle = le16_to_cpu(expander_pg0.parent_dev_handle);
1990 if (mpi3mr_get_sas_address(mrioc, parent_handle, &sas_address_parent)
1992 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1993 __FILE__, __LINE__, __func__);
1997 port_id = expander_pg0.io_unit_port;
1998 hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
2000 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2001 __FILE__, __LINE__, __func__);
2005 if (sas_address_parent != mrioc->sas_hba.sas_address) {
2006 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2008 mpi3mr_expander_find_by_sas_address(mrioc,
2009 sas_address_parent, hba_port);
2010 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2011 if (!sas_expander) {
2012 rc = mpi3mr_expander_add(mrioc, parent_handle);
2017 * When there is a parent expander present, update it's
2018 * phys where child expander is connected with the link
2019 * speed, attached dev handle and sas address.
2021 for (i = 0 ; i < sas_expander->num_phys ; i++) {
2023 (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2025 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc,
2026 &ioc_status, &expander_pg1,
2027 sizeof(expander_pg1),
2028 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2030 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2031 __FILE__, __LINE__, __func__);
2035 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2036 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2037 __FILE__, __LINE__, __func__);
2041 temp_handle = le16_to_cpu(
2042 expander_pg1.attached_dev_handle);
2043 if (temp_handle != handle)
2045 link_rate = (expander_pg1.negotiated_link_rate &
2046 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2047 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2048 mpi3mr_update_links(mrioc, sas_address_parent,
2049 handle, i, link_rate, hba_port);
2054 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2055 sas_address = le64_to_cpu(expander_pg0.sas_address);
2056 sas_expander = mpi3mr_expander_find_by_sas_address(mrioc,
2057 sas_address, hba_port);
2058 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2063 sas_expander = kzalloc(sizeof(struct mpi3mr_sas_node),
2068 sas_expander->handle = handle;
2069 sas_expander->num_phys = expander_pg0.num_phys;
2070 sas_expander->sas_address_parent = sas_address_parent;
2071 sas_expander->sas_address = sas_address;
2072 sas_expander->hba_port = hba_port;
2075 "expander_add: handle(0x%04x), parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
2076 handle, parent_handle, (unsigned long long)
2077 sas_expander->sas_address, sas_expander->num_phys);
2079 if (!sas_expander->num_phys) {
2083 sas_expander->phy = kcalloc(sas_expander->num_phys,
2084 sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
2085 if (!sas_expander->phy) {
2090 INIT_LIST_HEAD(&sas_expander->sas_port_list);
2091 mr_sas_port = mpi3mr_sas_port_add(mrioc, handle, sas_address_parent,
2092 sas_expander->hba_port);
2094 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2095 __FILE__, __LINE__, __func__);
2099 sas_expander->parent_dev = &mr_sas_port->rphy->dev;
2100 sas_expander->rphy = mr_sas_port->rphy;
2102 for (i = 0 ; i < sas_expander->num_phys ; i++) {
2103 phynum_handle = (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2105 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2106 &expander_pg1, sizeof(expander_pg1),
2107 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2109 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2110 __FILE__, __LINE__, __func__);
2114 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2115 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2116 __FILE__, __LINE__, __func__);
2121 sas_expander->phy[i].handle = handle;
2122 sas_expander->phy[i].phy_id = i;
2123 sas_expander->phy[i].hba_port = hba_port;
2125 if ((mpi3mr_add_expander_phy(mrioc, &sas_expander->phy[i],
2126 expander_pg1, sas_expander->parent_dev))) {
2127 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2128 __FILE__, __LINE__, __func__);
2134 if (sas_expander->enclosure_handle) {
2136 mpi3mr_enclosure_find_by_handle(mrioc,
2137 sas_expander->enclosure_handle);
2139 sas_expander->enclosure_logical_id = le64_to_cpu(
2140 enclosure_dev->pg0.enclosure_logical_id);
2143 mpi3mr_expander_node_add(mrioc, sas_expander);
2149 mpi3mr_sas_port_remove(mrioc,
2150 sas_expander->sas_address,
2151 sas_address_parent, sas_expander->hba_port);
2152 kfree(sas_expander->phy);
2153 kfree(sas_expander);
2158 * mpi3mr_expander_node_remove - recursive removal of expander.
2159 * @mrioc: Adapter instance reference
2160 * @sas_expander: Expander device object
2162 * Removes expander object and freeing associated memory from
2163 * the sas_expander_list and removes the same from SAS TL, if
2164 * one of the attached device is an expander then it recursively
2165 * removes the expander device too.
2169 void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
2170 struct mpi3mr_sas_node *sas_expander)
2172 struct mpi3mr_sas_port *mr_sas_port, *next;
2173 unsigned long flags;
2176 /* remove sibling ports attached to this expander */
2177 list_for_each_entry_safe(mr_sas_port, next,
2178 &sas_expander->sas_port_list, port_list) {
2179 if (mrioc->reset_in_progress)
2181 if (mr_sas_port->remote_identify.device_type ==
2183 mpi3mr_remove_device_by_sas_address(mrioc,
2184 mr_sas_port->remote_identify.sas_address,
2185 mr_sas_port->hba_port);
2186 else if (mr_sas_port->remote_identify.device_type ==
2187 SAS_EDGE_EXPANDER_DEVICE ||
2188 mr_sas_port->remote_identify.device_type ==
2189 SAS_FANOUT_EXPANDER_DEVICE)
2190 mpi3mr_expander_remove(mrioc,
2191 mr_sas_port->remote_identify.sas_address,
2192 mr_sas_port->hba_port);
2195 port_id = sas_expander->hba_port->port_id;
2196 mpi3mr_sas_port_remove(mrioc, sas_expander->sas_address,
2197 sas_expander->sas_address_parent, sas_expander->hba_port);
2199 ioc_info(mrioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
2200 sas_expander->handle, (unsigned long long)
2201 sas_expander->sas_address, port_id);
2203 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2204 list_del(&sas_expander->list);
2205 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2207 kfree(sas_expander->phy);
2208 kfree(sas_expander);
2212 * mpi3mr_expander_remove - Remove expander object
2213 * @mrioc: Adapter instance reference
2214 * @sas_address: Remove expander sas_address
2215 * @hba_port: HBA port reference
2217 * This function remove expander object, stored in
2218 * mrioc->sas_expander_list and removes it from the SAS TL by
2219 * calling mpi3mr_expander_node_remove().
2223 void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
2224 struct mpi3mr_hba_port *hba_port)
2226 struct mpi3mr_sas_node *sas_expander;
2227 unsigned long flags;
2229 if (mrioc->reset_in_progress)
2235 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2236 sas_expander = mpi3mr_expander_find_by_sas_address(mrioc, sas_address,
2238 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2240 mpi3mr_expander_node_remove(mrioc, sas_expander);
2245 * mpi3mr_get_sas_negotiated_logical_linkrate - get linkrate
2246 * @mrioc: Adapter instance reference
2247 * @tgtdev: Target device
2249 * This function identifies whether the target device is
2250 * attached directly or through expander and issues sas phy
2251 * page0 or expander phy page1 and gets the link rate, if there
2252 * is any failure in reading the pages then this returns link
2255 * Return: logical link rate.
2257 static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc,
2258 struct mpi3mr_tgt_dev *tgtdev)
2260 u8 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5, phy_number;
2261 struct mpi3_sas_expander_page1 expander_pg1;
2262 struct mpi3_sas_phy_page0 phy_pg0;
2266 phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2267 if (!(tgtdev->devpg0_flag & MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED)) {
2268 phynum_handle = ((phy_number<<MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT)
2269 | tgtdev->parent_handle);
2270 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2271 &expander_pg1, sizeof(expander_pg1),
2272 MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2274 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2275 __FILE__, __LINE__, __func__);
2278 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2279 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2280 __FILE__, __LINE__, __func__);
2283 link_rate = (expander_pg1.negotiated_link_rate &
2284 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2285 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2288 if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
2289 sizeof(struct mpi3_sas_phy_page0),
2290 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy_number)) {
2291 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2292 __FILE__, __LINE__, __func__);
2295 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2296 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2297 __FILE__, __LINE__, __func__);
2300 link_rate = (phy_pg0.negotiated_link_rate &
2301 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2302 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2308 * mpi3mr_report_tgtdev_to_sas_transport - expose dev to SAS TL
2309 * @mrioc: Adapter instance reference
2310 * @tgtdev: Target device
2312 * This function exposes the target device after
2313 * preparing host_phy, setting up link rate etc.
2315 * Return: 0 on success, non-zero for failure.
2317 int mpi3mr_report_tgtdev_to_sas_transport(struct mpi3mr_ioc *mrioc,
2318 struct mpi3mr_tgt_dev *tgtdev)
2321 u8 link_rate, parent_phy_number;
2322 u64 sas_address_parent, sas_address;
2323 struct mpi3mr_hba_port *hba_port;
2326 if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2327 !mrioc->sas_transport_enabled)
2330 sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2331 if (!mrioc->sas_hba.num_phys)
2332 mpi3mr_sas_host_add(mrioc);
2334 mpi3mr_sas_host_refresh(mrioc);
2336 if (mpi3mr_get_sas_address(mrioc, tgtdev->parent_handle,
2337 &sas_address_parent) != 0) {
2338 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2339 __FILE__, __LINE__, __func__);
2342 tgtdev->dev_spec.sas_sata_inf.sas_address_parent = sas_address_parent;
2344 parent_phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2345 port_id = tgtdev->io_unit_port;
2347 hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
2349 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2350 __FILE__, __LINE__, __func__);
2353 tgtdev->dev_spec.sas_sata_inf.hba_port = hba_port;
2355 link_rate = mpi3mr_get_sas_negotiated_logical_linkrate(mrioc, tgtdev);
2357 mpi3mr_update_links(mrioc, sas_address_parent, tgtdev->dev_handle,
2358 parent_phy_number, link_rate, hba_port);
2360 tgtdev->host_exposed = 1;
2361 if (!mpi3mr_sas_port_add(mrioc, tgtdev->dev_handle,
2362 sas_address_parent, hba_port)) {
2364 } else if ((!tgtdev->starget) && (!mrioc->is_driver_loading)) {
2365 mpi3mr_sas_port_remove(mrioc, sas_address,
2366 sas_address_parent, hba_port);
2370 tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2371 tgtdev->host_exposed = 0;
2377 * mpi3mr_remove_tgtdev_from_sas_transport - remove from SAS TL
2378 * @mrioc: Adapter instance reference
2379 * @tgtdev: Target device
2381 * This function removes the target device
2385 void mpi3mr_remove_tgtdev_from_sas_transport(struct mpi3mr_ioc *mrioc,
2386 struct mpi3mr_tgt_dev *tgtdev)
2388 u64 sas_address_parent, sas_address;
2389 struct mpi3mr_hba_port *hba_port;
2391 if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2392 !mrioc->sas_transport_enabled)
2395 hba_port = tgtdev->dev_spec.sas_sata_inf.hba_port;
2396 sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2397 sas_address_parent = tgtdev->dev_spec.sas_sata_inf.sas_address_parent;
2398 mpi3mr_sas_port_remove(mrioc, sas_address, sas_address_parent,
2400 tgtdev->host_exposed = 0;
2401 tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2405 * mpi3mr_get_port_id_by_sas_phy - Get port ID of the given phy
2406 * @phy: SAS transport layer phy object
2408 * Return: Port number for valid ID else 0xFFFF
2410 static inline u8 mpi3mr_get_port_id_by_sas_phy(struct sas_phy *phy)
2413 struct mpi3mr_hba_port *hba_port = phy->hostdata;
2416 port_id = hba_port->port_id;
2422 * mpi3mr_get_port_id_by_rphy - Get Port number from SAS rphy
2424 * @mrioc: Adapter instance reference
2425 * @rphy: SAS transport layer remote phy object
2427 * Retrieves HBA port number in which the device pointed by the
2428 * rphy object is attached with.
2430 * Return: Valid port number on success else OxFFFF.
2432 static u8 mpi3mr_get_port_id_by_rphy(struct mpi3mr_ioc *mrioc, struct sas_rphy *rphy)
2434 struct mpi3mr_sas_node *sas_expander;
2435 struct mpi3mr_tgt_dev *tgtdev;
2436 unsigned long flags;
2442 if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
2443 rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) {
2444 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2445 list_for_each_entry(sas_expander, &mrioc->sas_expander_list,
2447 if (sas_expander->rphy == rphy) {
2448 port_id = sas_expander->hba_port->port_id;
2452 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2453 } else if (rphy->identify.device_type == SAS_END_DEVICE) {
2454 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2456 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2457 rphy->identify.sas_address, rphy);
2458 if (tgtdev && tgtdev->dev_spec.sas_sata_inf.hba_port) {
2460 tgtdev->dev_spec.sas_sata_inf.hba_port->port_id;
2461 mpi3mr_tgtdev_put(tgtdev);
2463 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2468 static inline struct mpi3mr_ioc *phy_to_mrioc(struct sas_phy *phy)
2470 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
2472 return shost_priv(shost);
2475 static inline struct mpi3mr_ioc *rphy_to_mrioc(struct sas_rphy *rphy)
2477 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
2479 return shost_priv(shost);
2482 /* report phy error log structure */
2483 struct phy_error_log_request {
2484 u8 smp_frame_type; /* 0x40 */
2485 u8 function; /* 0x11 */
2486 u8 allocated_response_length;
2487 u8 request_length; /* 02 */
2493 /* report phy error log reply structure */
2494 struct phy_error_log_reply {
2495 u8 smp_frame_type; /* 0x41 */
2496 u8 function; /* 0x11 */
2499 __be16 expander_change_count;
2503 __be32 invalid_dword;
2504 __be32 running_disparity_error;
2505 __be32 loss_of_dword_sync;
2506 __be32 phy_reset_problem;
2511 * mpi3mr_get_expander_phy_error_log - return expander counters:
2512 * @mrioc: Adapter instance reference
2513 * @phy: The SAS transport layer phy object
2515 * Return: 0 for success, non-zero for failure.
2518 static int mpi3mr_get_expander_phy_error_log(struct mpi3mr_ioc *mrioc,
2519 struct sas_phy *phy)
2521 struct mpi3_smp_passthrough_request mpi_request;
2522 struct mpi3_smp_passthrough_reply mpi_reply;
2523 struct phy_error_log_request *phy_error_log_request;
2524 struct phy_error_log_reply *phy_error_log_reply;
2527 void *data_out = NULL;
2528 dma_addr_t data_out_dma, data_in_dma;
2529 u32 data_out_sz, data_in_sz, sz;
2530 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2531 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2532 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2535 if (mrioc->reset_in_progress) {
2536 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2540 data_out_sz = sizeof(struct phy_error_log_request);
2541 data_in_sz = sizeof(struct phy_error_log_reply);
2542 sz = data_out_sz + data_in_sz;
2543 data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2550 data_in_dma = data_out_dma + data_out_sz;
2551 phy_error_log_reply = data_out + data_out_sz;
2554 memset(data_out, 0, sz);
2555 phy_error_log_request = data_out;
2556 phy_error_log_request->smp_frame_type = 0x40;
2557 phy_error_log_request->function = 0x11;
2558 phy_error_log_request->request_length = 2;
2559 phy_error_log_request->allocated_response_length = 0;
2560 phy_error_log_request->phy_identifier = phy->number;
2562 memset(&mpi_request, 0, request_sz);
2563 memset(&mpi_reply, 0, reply_sz);
2564 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2565 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2566 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2567 mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2569 psge = &mpi_request.request_sge;
2570 mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2572 psge = &mpi_request.response_sge;
2573 mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2575 dprint_transport_info(mrioc,
2576 "sending phy error log SMP request to sas_address(0x%016llx), phy_id(%d)\n",
2577 (unsigned long long)phy->identify.sas_address, phy->number);
2579 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2580 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2583 dprint_transport_info(mrioc,
2584 "phy error log SMP request completed with ioc_status(0x%04x)\n",
2587 if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2588 dprint_transport_info(mrioc,
2589 "phy error log - reply data transfer size(%d)\n",
2590 le16_to_cpu(mpi_reply.response_data_length));
2592 if (le16_to_cpu(mpi_reply.response_data_length) !=
2593 sizeof(struct phy_error_log_reply))
2596 dprint_transport_info(mrioc,
2597 "phy error log - function_result(%d)\n",
2598 phy_error_log_reply->function_result);
2600 phy->invalid_dword_count =
2601 be32_to_cpu(phy_error_log_reply->invalid_dword);
2602 phy->running_disparity_error_count =
2603 be32_to_cpu(phy_error_log_reply->running_disparity_error);
2604 phy->loss_of_dword_sync_count =
2605 be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
2606 phy->phy_reset_problem_count =
2607 be32_to_cpu(phy_error_log_reply->phy_reset_problem);
2613 dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2620 * mpi3mr_transport_get_linkerrors - return phy error counters
2621 * @phy: The SAS transport layer phy object
2623 * This function retrieves the phy error log information of the
2624 * HBA or expander for which the phy belongs to
2626 * Return: 0 for success, non-zero for failure.
2628 static int mpi3mr_transport_get_linkerrors(struct sas_phy *phy)
2630 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2631 struct mpi3_sas_phy_page1 phy_pg1;
2635 rc = mpi3mr_parent_present(mrioc, phy);
2639 if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2640 return mpi3mr_get_expander_phy_error_log(mrioc, phy);
2642 memset(&phy_pg1, 0, sizeof(struct mpi3_sas_phy_page1));
2643 /* get hba phy error logs */
2644 if ((mpi3mr_cfg_get_sas_phy_pg1(mrioc, &ioc_status, &phy_pg1,
2645 sizeof(struct mpi3_sas_phy_page1),
2646 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number))) {
2647 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2648 __FILE__, __LINE__, __func__);
2652 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2653 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2654 __FILE__, __LINE__, __func__);
2657 phy->invalid_dword_count = le32_to_cpu(phy_pg1.invalid_dword_count);
2658 phy->running_disparity_error_count =
2659 le32_to_cpu(phy_pg1.running_disparity_error_count);
2660 phy->loss_of_dword_sync_count =
2661 le32_to_cpu(phy_pg1.loss_dword_synch_count);
2662 phy->phy_reset_problem_count =
2663 le32_to_cpu(phy_pg1.phy_reset_problem_count);
2668 * mpi3mr_transport_get_enclosure_identifier - Get Enclosure ID
2669 * @rphy: The SAS transport layer remote phy object
2670 * @identifier: Enclosure identifier to be returned
2672 * Returns the enclosure id for the device pointed by the remote
2675 * Return: 0 on success or -ENXIO
2678 mpi3mr_transport_get_enclosure_identifier(struct sas_rphy *rphy,
2681 struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2682 struct mpi3mr_tgt_dev *tgtdev = NULL;
2683 unsigned long flags;
2686 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2687 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2688 rphy->identify.sas_address, rphy);
2691 tgtdev->enclosure_logical_id;
2693 mpi3mr_tgtdev_put(tgtdev);
2698 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2704 * mpi3mr_transport_get_bay_identifier - Get bay ID
2705 * @rphy: The SAS transport layer remote phy object
2707 * Returns the slot id for the device pointed by the remote phy
2710 * Return: Valid slot ID on success or -ENXIO
2713 mpi3mr_transport_get_bay_identifier(struct sas_rphy *rphy)
2715 struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2716 struct mpi3mr_tgt_dev *tgtdev = NULL;
2717 unsigned long flags;
2720 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2721 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2722 rphy->identify.sas_address, rphy);
2725 mpi3mr_tgtdev_put(tgtdev);
2728 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2733 /* phy control request structure */
2734 struct phy_control_request {
2735 u8 smp_frame_type; /* 0x40 */
2736 u8 function; /* 0x91 */
2737 u8 allocated_response_length;
2738 u8 request_length; /* 0x09 */
2739 u16 expander_change_count;
2744 u64 attached_device_name;
2745 u8 programmed_min_physical_link_rate;
2746 u8 programmed_max_physical_link_rate;
2750 /* phy control reply structure */
2751 struct phy_control_reply {
2752 u8 smp_frame_type; /* 0x41 */
2753 u8 function; /* 0x11 */
2758 #define SMP_PHY_CONTROL_LINK_RESET (0x01)
2759 #define SMP_PHY_CONTROL_HARD_RESET (0x02)
2760 #define SMP_PHY_CONTROL_DISABLE (0x03)
2763 * mpi3mr_expander_phy_control - expander phy control
2764 * @mrioc: Adapter instance reference
2765 * @phy: The SAS transport layer phy object
2766 * @phy_operation: The phy operation to be executed
2768 * Issues SMP passthru phy control request to execute a specific
2769 * phy operation for a given expander device.
2771 * Return: 0 for success, non-zero for failure.
2774 mpi3mr_expander_phy_control(struct mpi3mr_ioc *mrioc,
2775 struct sas_phy *phy, u8 phy_operation)
2777 struct mpi3_smp_passthrough_request mpi_request;
2778 struct mpi3_smp_passthrough_reply mpi_reply;
2779 struct phy_control_request *phy_control_request;
2780 struct phy_control_reply *phy_control_reply;
2783 void *data_out = NULL;
2784 dma_addr_t data_out_dma;
2785 dma_addr_t data_in_dma;
2788 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2789 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2790 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2794 if (mrioc->reset_in_progress) {
2795 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2799 data_out_sz = sizeof(struct phy_control_request);
2800 data_in_sz = sizeof(struct phy_control_reply);
2801 sz = data_out_sz + data_in_sz;
2802 data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2809 data_in_dma = data_out_dma + data_out_sz;
2810 phy_control_reply = data_out + data_out_sz;
2813 memset(data_out, 0, sz);
2815 phy_control_request = data_out;
2816 phy_control_request->smp_frame_type = 0x40;
2817 phy_control_request->function = 0x91;
2818 phy_control_request->request_length = 9;
2819 phy_control_request->allocated_response_length = 0;
2820 phy_control_request->phy_identifier = phy->number;
2821 phy_control_request->phy_operation = phy_operation;
2822 phy_control_request->programmed_min_physical_link_rate =
2823 phy->minimum_linkrate << 4;
2824 phy_control_request->programmed_max_physical_link_rate =
2825 phy->maximum_linkrate << 4;
2827 memset(&mpi_request, 0, request_sz);
2828 memset(&mpi_reply, 0, reply_sz);
2829 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2830 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2831 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2832 mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2834 psge = &mpi_request.request_sge;
2835 mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2837 psge = &mpi_request.response_sge;
2838 mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2840 dprint_transport_info(mrioc,
2841 "sending phy control SMP request to sas_address(0x%016llx), phy_id(%d) opcode(%d)\n",
2842 (unsigned long long)phy->identify.sas_address, phy->number,
2845 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2846 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2849 dprint_transport_info(mrioc,
2850 "phy control SMP request completed with ioc_status(0x%04x)\n",
2853 if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2854 dprint_transport_info(mrioc,
2855 "phy control - reply data transfer size(%d)\n",
2856 le16_to_cpu(mpi_reply.response_data_length));
2858 if (le16_to_cpu(mpi_reply.response_data_length) !=
2859 sizeof(struct phy_control_reply))
2861 dprint_transport_info(mrioc,
2862 "phy control - function_result(%d)\n",
2863 phy_control_reply->function_result);
2868 dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2875 * mpi3mr_transport_phy_reset - Reset a given phy
2876 * @phy: The SAS transport layer phy object
2877 * @hard_reset: Flag to indicate the type of reset
2879 * Return: 0 for success, non-zero for failure.
2882 mpi3mr_transport_phy_reset(struct sas_phy *phy, int hard_reset)
2884 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2885 struct mpi3_iounit_control_request mpi_request;
2886 struct mpi3_iounit_control_reply mpi_reply;
2887 u16 request_sz = sizeof(struct mpi3_iounit_control_request);
2888 u16 reply_sz = sizeof(struct mpi3_iounit_control_reply);
2892 rc = mpi3mr_parent_present(mrioc, phy);
2896 /* handle expander phys */
2897 if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2898 return mpi3mr_expander_phy_control(mrioc, phy,
2899 (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
2900 SMP_PHY_CONTROL_LINK_RESET);
2902 /* handle hba phys */
2903 memset(&mpi_request, 0, request_sz);
2904 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2905 mpi_request.function = MPI3_FUNCTION_IO_UNIT_CONTROL;
2906 mpi_request.operation = MPI3_CTRL_OP_SAS_PHY_CONTROL;
2907 mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_ACTION_INDEX] =
2908 (hard_reset ? MPI3_CTRL_ACTION_HARD_RESET :
2909 MPI3_CTRL_ACTION_LINK_RESET);
2910 mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_PHY_INDEX] =
2913 dprint_transport_info(mrioc,
2914 "sending phy reset request to sas_address(0x%016llx), phy_id(%d) hard_reset(%d)\n",
2915 (unsigned long long)phy->identify.sas_address, phy->number,
2918 if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2919 &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) {
2924 dprint_transport_info(mrioc,
2925 "phy reset request completed with ioc_status(0x%04x)\n",
2932 * mpi3mr_transport_phy_enable - enable/disable phys
2933 * @phy: The SAS transport layer phy object
2934 * @enable: flag to enable/disable, enable phy when true
2936 * This function enables/disables a given by executing required
2937 * configuration page changes or expander phy control command
2939 * Return: 0 for success, non-zero for failure.
2942 mpi3mr_transport_phy_enable(struct sas_phy *phy, int enable)
2944 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2945 struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
2946 struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
2949 int i, discovery_active;
2951 rc = mpi3mr_parent_present(mrioc, phy);
2955 /* handle expander phys */
2956 if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2957 return mpi3mr_expander_phy_control(mrioc, phy,
2958 (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
2959 SMP_PHY_CONTROL_DISABLE);
2961 /* handle hba phys */
2962 sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
2963 (mrioc->sas_hba.num_phys *
2964 sizeof(struct mpi3_sas_io_unit0_phy_data));
2965 sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
2966 if (!sas_io_unit_pg0) {
2970 if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
2971 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2972 __FILE__, __LINE__, __func__);
2977 /* unable to enable/disable phys when discovery is active */
2978 for (i = 0, discovery_active = 0; i < mrioc->sas_hba.num_phys ; i++) {
2979 if (sas_io_unit_pg0->phy_data[i].port_flags &
2980 MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS) {
2982 "discovery is active on port = %d, phy = %d\n"
2983 "\tunable to enable/disable phys, try again later!\n",
2984 sas_io_unit_pg0->phy_data[i].io_unit_port, i);
2985 discovery_active = 1;
2989 if (discovery_active) {
2994 if ((sas_io_unit_pg0->phy_data[phy->number].phy_flags &
2995 (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
2996 MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))) {
2997 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2998 __FILE__, __LINE__, __func__);
3003 /* read sas_iounit page 1 */
3004 sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3005 (mrioc->sas_hba.num_phys *
3006 sizeof(struct mpi3_sas_io_unit1_phy_data));
3007 sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3008 if (!sas_io_unit_pg1) {
3013 if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3014 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3015 __FILE__, __LINE__, __func__);
3021 sas_io_unit_pg1->phy_data[phy->number].phy_flags
3022 &= ~MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3024 sas_io_unit_pg1->phy_data[phy->number].phy_flags
3025 |= MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3027 mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz);
3031 mpi3mr_transport_phy_reset(phy, 0);
3034 kfree(sas_io_unit_pg1);
3035 kfree(sas_io_unit_pg0);
3040 * mpi3mr_transport_phy_speed - set phy min/max speed
3041 * @phy: The SAS transport later phy object
3042 * @rates: Rates defined as in sas_phy_linkrates
3044 * This function sets the link rates given in the rates
3045 * argument to the given phy by executing required configuration
3046 * page changes or expander phy control command
3048 * Return: 0 for success, non-zero for failure.
3051 mpi3mr_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
3053 struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
3054 struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
3055 struct mpi3_sas_phy_page0 phy_pg0;
3059 rc = mpi3mr_parent_present(mrioc, phy);
3063 if (!rates->minimum_linkrate)
3064 rates->minimum_linkrate = phy->minimum_linkrate;
3065 else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
3066 rates->minimum_linkrate = phy->minimum_linkrate_hw;
3068 if (!rates->maximum_linkrate)
3069 rates->maximum_linkrate = phy->maximum_linkrate;
3070 else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
3071 rates->maximum_linkrate = phy->maximum_linkrate_hw;
3073 /* handle expander phys */
3074 if (phy->identify.sas_address != mrioc->sas_hba.sas_address) {
3075 phy->minimum_linkrate = rates->minimum_linkrate;
3076 phy->maximum_linkrate = rates->maximum_linkrate;
3077 return mpi3mr_expander_phy_control(mrioc, phy,
3078 SMP_PHY_CONTROL_LINK_RESET);
3081 /* handle hba phys */
3082 sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3083 (mrioc->sas_hba.num_phys *
3084 sizeof(struct mpi3_sas_io_unit1_phy_data));
3085 sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3086 if (!sas_io_unit_pg1) {
3091 if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3092 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3093 __FILE__, __LINE__, __func__);
3098 sas_io_unit_pg1->phy_data[phy->number].max_min_link_rate =
3099 (rates->minimum_linkrate + (rates->maximum_linkrate << 4));
3101 if (mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3102 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3103 __FILE__, __LINE__, __func__);
3109 mpi3mr_transport_phy_reset(phy, 0);
3111 /* read phy page 0, then update the rates in the sas transport phy */
3112 if (!mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
3113 sizeof(struct mpi3_sas_phy_page0),
3114 MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number) &&
3115 (ioc_status == MPI3_IOCSTATUS_SUCCESS)) {
3116 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
3117 phy_pg0.programmed_link_rate &
3118 MPI3_SAS_PRATE_MIN_RATE_MASK);
3119 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
3120 phy_pg0.programmed_link_rate >> 4);
3121 phy->negotiated_linkrate =
3122 mpi3mr_convert_phy_link_rate(
3123 (phy_pg0.negotiated_link_rate &
3124 MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK)
3125 >> MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
3129 kfree(sas_io_unit_pg1);
3134 * mpi3mr_map_smp_buffer - map BSG dma buffer
3135 * @dev: Generic device reference
3136 * @buf: BSG buffer pointer
3137 * @dma_addr: Physical address holder
3138 * @dma_len: Mapped DMA buffer length.
3139 * @p: Virtual address holder
3141 * This function maps the DMAable buffer
3143 * Return: 0 on success, non-zero on failure
3146 mpi3mr_map_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3147 dma_addr_t *dma_addr, size_t *dma_len, void **p)
3149 /* Check if the request is split across multiple segments */
3150 if (buf->sg_cnt > 1) {
3151 *p = dma_alloc_coherent(dev, buf->payload_len, dma_addr,
3155 *dma_len = buf->payload_len;
3157 if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
3159 *dma_addr = sg_dma_address(buf->sg_list);
3160 *dma_len = sg_dma_len(buf->sg_list);
3168 * mpi3mr_unmap_smp_buffer - unmap BSG dma buffer
3169 * @dev: Generic device reference
3170 * @buf: BSG buffer pointer
3171 * @dma_addr: Physical address to be unmapped
3172 * @p: Virtual address
3174 * This function unmaps the DMAable buffer
3177 mpi3mr_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3178 dma_addr_t dma_addr, void *p)
3181 dma_free_coherent(dev, buf->payload_len, p, dma_addr);
3183 dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL);
3187 * mpi3mr_transport_smp_handler - handler for smp passthru
3188 * @job: BSG job reference
3189 * @shost: SCSI host object reference
3190 * @rphy: SAS transport rphy object pointing the expander
3192 * This is used primarily by smp utils for sending the SMP
3193 * commands to the expanders attached to the controller
3196 mpi3mr_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
3197 struct sas_rphy *rphy)
3199 struct mpi3mr_ioc *mrioc = shost_priv(shost);
3200 struct mpi3_smp_passthrough_request mpi_request;
3201 struct mpi3_smp_passthrough_reply mpi_reply;
3204 dma_addr_t dma_addr_in;
3205 dma_addr_t dma_addr_out;
3206 void *addr_in = NULL;
3207 void *addr_out = NULL;
3210 unsigned int reslen = 0;
3211 u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
3212 u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
3213 u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
3216 if (mrioc->reset_in_progress) {
3217 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
3222 rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3223 &dma_addr_out, &dma_len_out, &addr_out);
3228 sg_copy_to_buffer(job->request_payload.sg_list,
3229 job->request_payload.sg_cnt, addr_out,
3230 job->request_payload.payload_len);
3232 rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3233 &dma_addr_in, &dma_len_in, &addr_in);
3237 memset(&mpi_request, 0, request_sz);
3238 memset(&mpi_reply, 0, reply_sz);
3239 mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
3240 mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
3241 mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_rphy(mrioc, rphy);
3242 mpi_request.sas_address = ((rphy) ?
3243 cpu_to_le64(rphy->identify.sas_address) :
3244 cpu_to_le64(mrioc->sas_hba.sas_address));
3245 psge = &mpi_request.request_sge;
3246 mpi3mr_add_sg_single(psge, sgl_flags, dma_len_out - 4, dma_addr_out);
3248 psge = &mpi_request.response_sge;
3249 mpi3mr_add_sg_single(psge, sgl_flags, dma_len_in - 4, dma_addr_in);
3251 dprint_transport_info(mrioc, "sending SMP request\n");
3253 rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
3254 &mpi_reply, reply_sz,
3255 MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
3259 dprint_transport_info(mrioc,
3260 "SMP request completed with ioc_status(0x%04x)\n", ioc_status);
3262 dprint_transport_info(mrioc,
3263 "SMP request - reply data transfer size(%d)\n",
3264 le16_to_cpu(mpi_reply.response_data_length));
3266 memcpy(job->reply, &mpi_reply, reply_sz);
3267 job->reply_len = reply_sz;
3268 reslen = le16_to_cpu(mpi_reply.response_data_length);
3271 sg_copy_from_buffer(job->reply_payload.sg_list,
3272 job->reply_payload.sg_cnt, addr_in,
3273 job->reply_payload.payload_len);
3277 mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3278 dma_addr_in, addr_in);
3280 mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3281 dma_addr_out, addr_out);
3283 bsg_job_done(job, rc, reslen);
3286 struct sas_function_template mpi3mr_transport_functions = {
3287 .get_linkerrors = mpi3mr_transport_get_linkerrors,
3288 .get_enclosure_identifier = mpi3mr_transport_get_enclosure_identifier,
3289 .get_bay_identifier = mpi3mr_transport_get_bay_identifier,
3290 .phy_reset = mpi3mr_transport_phy_reset,
3291 .phy_enable = mpi3mr_transport_phy_enable,
3292 .set_phy_speed = mpi3mr_transport_phy_speed,
3293 .smp_handler = mpi3mr_transport_smp_handler,
3296 struct scsi_transport_template *mpi3mr_transport_template;