Merge tag 'qcom-drivers-for-6.9-2' of https://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / drivers / scsi / mpi3mr / mpi3mr_transport.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Driver for Broadcom MPI3 Storage Controllers
4  *
5  * Copyright (C) 2017-2023 Broadcom Inc.
6  *  (mailto: mpi3mr-linuxdrv.pdl@broadcom.com)
7  *
8  */
9
10 #include "mpi3mr.h"
11
12 /**
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
21  *
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.
27  *
28  * On successful completion of the request this function returns
29  * appropriate ioc status from the firmware back to the caller.
30  *
31  * Return: 0 on success, non-zero on failure.
32  */
33 static int mpi3mr_post_transport_req(struct mpi3mr_ioc *mrioc, void *request,
34         u16 request_sz, void *reply, u16 reply_sz, int timeout,
35         u16 *ioc_status)
36 {
37         int retval = 0;
38
39         mutex_lock(&mrioc->transport_cmds.mutex);
40         if (mrioc->transport_cmds.state & MPI3MR_CMD_PENDING) {
41                 retval = -1;
42                 ioc_err(mrioc, "sending transport request failed due to command in use\n");
43                 mutex_unlock(&mrioc->transport_cmds.mutex);
44                 goto out;
45         }
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;
51
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);
57         if (retval) {
58                 ioc_err(mrioc, "posting transport request failed\n");
59                 goto out_unlock;
60         }
61         wait_for_completion_timeout(&mrioc->transport_cmds.done,
62             (timeout * HZ));
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");
67                 retval = -1;
68                 goto out_unlock;
69         }
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);
76
77         if ((reply) && (mrioc->transport_cmds.state & MPI3MR_CMD_REPLY_VALID))
78                 memcpy((u8 *)reply, mrioc->transport_cmds.reply, reply_sz);
79
80 out_unlock:
81         mrioc->transport_cmds.state = MPI3MR_CMD_NOTUSED;
82         mutex_unlock(&mrioc->transport_cmds.mutex);
83
84 out:
85         return retval;
86 }
87
88 /* report manufacture request structure */
89 struct rep_manu_request {
90         u8 smp_frame_type;
91         u8 function;
92         u8 reserved;
93         u8 request_length;
94 };
95
96 /* report manufacture reply structure */
97 struct rep_manu_reply {
98         u8 smp_frame_type; /* 0x41 */
99         u8 function; /* 0x01 */
100         u8 function_result;
101         u8 response_length;
102         u16 expander_change_count;
103         u8 reserved0[2];
104         u8 sas_format;
105         u8 reserved2[3];
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];
110         u16 component_id;
111         u8 component_revision_id;
112         u8 reserved3;
113         u8 vendor_specific[8];
114 };
115
116 /**
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
122  *
123  * Fills in the sas_expander_device with manufacturing info.
124  *
125  * Return: 0 for success, non-zero for failure.
126  */
127 static int mpi3mr_report_manufacture(struct mpi3mr_ioc *mrioc,
128         u64 sas_address, struct sas_expander_device *edev, u8 port_id)
129 {
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;
134         int rc = 0;
135         void *psge;
136         void *data_out = NULL;
137         dma_addr_t data_out_dma;
138         dma_addr_t data_in_dma;
139         size_t data_in_sz;
140         size_t data_out_sz;
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);
144         u16 ioc_status;
145         u8 *tmp;
146
147         if (mrioc->reset_in_progress) {
148                 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
149                 return -EFAULT;
150         }
151
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);
156         if (!data_out) {
157                 rc = -ENOMEM;
158                 goto out;
159         }
160
161         data_in_dma = data_out_dma + data_out_sz;
162         manufacture_reply = data_out + data_out_sz;
163
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;
169
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);
176
177         psge = &mpi_request.request_sge;
178         mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
179
180         psge = &mpi_request.response_sge;
181         mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
182
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);
186
187         rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
188                                        &mpi_reply, reply_sz,
189                                        MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
190         if (rc)
191                 goto out;
192
193         dprint_transport_info(mrioc,
194             "report manufacturer SMP request completed with ioc_status(0x%04x)\n",
195             ioc_status);
196
197         if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
198                 rc = -EINVAL;
199                 goto out;
200         }
201
202         dprint_transport_info(mrioc,
203             "report manufacturer - reply data transfer size(%d)\n",
204             le16_to_cpu(mpi_reply.response_data_length));
205
206         if (le16_to_cpu(mpi_reply.response_data_length) !=
207             sizeof(struct rep_manu_reply)) {
208                 rc = -EINVAL;
209                 goto out;
210         }
211
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;
219         if (edev->level) {
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;
227         }
228
229 out:
230         if (data_out)
231                 dma_free_coherent(&mrioc->pdev->dev, data_out_sz + data_in_sz,
232                     data_out, data_out_dma);
233
234         return rc;
235 }
236
237 /**
238  * __mpi3mr_expander_find_by_handle - expander search by handle
239  * @mrioc: Adapter instance reference
240  * @handle: Firmware device handle of the expander
241  *
242  * Context: The caller should acquire sas_node_lock
243  *
244  * This searches for expander device based on handle, then
245  * returns the sas_node object.
246  *
247  * Return: Expander sas_node object reference or NULL
248  */
249 struct mpi3mr_sas_node *__mpi3mr_expander_find_by_handle(struct mpi3mr_ioc
250         *mrioc, u16 handle)
251 {
252         struct mpi3mr_sas_node *sas_expander, *r;
253
254         r = NULL;
255         list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
256                 if (sas_expander->handle != handle)
257                         continue;
258                 r = sas_expander;
259                 goto out;
260         }
261  out:
262         return r;
263 }
264
265 /**
266  * mpi3mr_is_expander_device - if device is an expander
267  * @device_info: Bitfield providing information about the device
268  *
269  * Return: 1 if the device is expander device, else 0.
270  */
271 u8 mpi3mr_is_expander_device(u16 device_info)
272 {
273         if ((device_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) ==
274              MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER)
275                 return 1;
276         else
277                 return 0;
278 }
279
280 /**
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
285  *
286  * This function issues device page0 read for a given device
287  * handle and gets the SAS address and return it back
288  *
289  * Return: 0 for success, non-zero for failure
290  */
291 static int mpi3mr_get_sas_address(struct mpi3mr_ioc *mrioc, u16 handle,
292         u64 *sas_address)
293 {
294         struct mpi3_device_page0 dev_pg0;
295         u16 ioc_status;
296         struct mpi3_device0_sas_sata_format *sasinf;
297
298         *sas_address = 0;
299
300         if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
301             sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
302             handle))) {
303                 ioc_err(mrioc, "%s: device page0 read failed\n", __func__);
304                 return -ENXIO;
305         }
306
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__);
310                 return -ENXIO;
311         }
312
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);
319         } else {
320                 ioc_err(mrioc, "%s: device_form(%d) is not SAS_SATA\n",
321                     __func__, dev_pg0.device_form);
322                 return -ENXIO;
323         }
324         return 0;
325 }
326
327 /**
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
332  *
333  * This searches for target device from sas address and hba port
334  * pointer then return mpi3mr_tgt_dev object.
335  *
336  * Return: Valid tget_dev or NULL
337  */
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)
340 {
341         struct mpi3mr_tgt_dev *tgtdev;
342
343         assert_spin_locked(&mrioc->tgtdev_lock);
344
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))
349                         goto found_device;
350         return NULL;
351 found_device:
352         mpi3mr_tgtdev_get(tgtdev);
353         return tgtdev;
354 }
355
356 /**
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
361  *
362  * This searches for target device from sas address and hba port
363  * pointer then return mpi3mr_tgt_dev object.
364  *
365  * Context: This function will acquire tgtdev_lock and will
366  * release before returning the mpi3mr_tgt_dev object.
367  *
368  * Return: Valid tget_dev or NULL
369  */
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)
372 {
373         struct mpi3mr_tgt_dev *tgtdev = NULL;
374         unsigned long flags;
375
376         if (!hba_port)
377                 goto out;
378
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);
382
383 out:
384         return tgtdev;
385 }
386
387 /**
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
392  *
393  * This searches for target device using sas address and hba
394  * port pointer then removes it from the OS.
395  *
396  * Return: None
397  */
398 static void mpi3mr_remove_device_by_sas_address(struct mpi3mr_ioc *mrioc,
399         u64 sas_address, struct mpi3mr_hba_port *hba_port)
400 {
401         struct mpi3mr_tgt_dev *tgtdev = NULL;
402         unsigned long flags;
403         u8 was_on_tgtdev_list = 0;
404
405         if (!hba_port)
406                 return;
407
408         spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
409         tgtdev = __mpi3mr_get_tgtdev_by_addr(mrioc,
410                          sas_address, hba_port);
411         if (tgtdev) {
412                 if (!list_empty(&tgtdev->list)) {
413                         list_del_init(&tgtdev->list);
414                         was_on_tgtdev_list = 1;
415                         mpi3mr_tgtdev_put(tgtdev);
416                 }
417         }
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);
423         }
424 }
425
426 /**
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
431  *
432  * This searches for target device from sas address and rphy
433  * pointer then return mpi3mr_tgt_dev object.
434  *
435  * Return: Valid tget_dev or NULL
436  */
437 struct mpi3mr_tgt_dev *__mpi3mr_get_tgtdev_by_addr_and_rphy(
438         struct mpi3mr_ioc *mrioc, u64 sas_address, struct sas_rphy *rphy)
439 {
440         struct mpi3mr_tgt_dev *tgtdev;
441
442         assert_spin_locked(&mrioc->tgtdev_lock);
443
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))
448                         goto found_device;
449         return NULL;
450 found_device:
451         mpi3mr_tgtdev_get(tgtdev);
452         return tgtdev;
453 }
454
455 /**
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
460  *
461  * Return: A valid SAS expander node or NULL.
462  *
463  */
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)
467 {
468         struct mpi3mr_sas_node *sas_expander, *r = NULL;
469
470         if (!hba_port)
471                 goto out;
472
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))
476                         continue;
477                 r = sas_expander;
478                 goto out;
479         }
480 out:
481         return r;
482 }
483
484 /**
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.
490  *
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.
497  *
498  * Return: A valid SAS node or NULL.
499  *
500  */
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)
504 {
505
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,
509             hba_port);
510 }
511
512 /**
513  * mpi3mr_parent_present - Is parent present for a phy
514  * @mrioc: Adapter instance reference
515  * @phy: SAS transport layer phy object
516  *
517  * Return: 0 if parent is present else non-zero
518  */
519 static int mpi3mr_parent_present(struct mpi3mr_ioc *mrioc, struct sas_phy *phy)
520 {
521         unsigned long flags;
522         struct mpi3mr_hba_port *hba_port = phy->hostdata;
523
524         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
525         if (__mpi3mr_sas_node_find_by_sas_address(mrioc,
526             phy->identify.sas_address,
527             hba_port) == NULL) {
528                 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
529                 return -1;
530         }
531         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
532         return 0;
533 }
534
535 /**
536  * mpi3mr_convert_phy_link_rate -
537  * @link_rate: link rate as defined in the MPI header
538  *
539  * Convert link_rate from mpi format into sas_transport layer
540  * form.
541  *
542  * Return: A valid SAS transport layer defined link rate
543  */
544 static enum sas_linkrate mpi3mr_convert_phy_link_rate(u8 link_rate)
545 {
546         enum sas_linkrate rc;
547
548         switch (link_rate) {
549         case MPI3_SAS_NEG_LINK_RATE_1_5:
550                 rc = SAS_LINK_RATE_1_5_GBPS;
551                 break;
552         case MPI3_SAS_NEG_LINK_RATE_3_0:
553                 rc = SAS_LINK_RATE_3_0_GBPS;
554                 break;
555         case MPI3_SAS_NEG_LINK_RATE_6_0:
556                 rc = SAS_LINK_RATE_6_0_GBPS;
557                 break;
558         case MPI3_SAS_NEG_LINK_RATE_12_0:
559                 rc = SAS_LINK_RATE_12_0_GBPS;
560                 break;
561         case MPI3_SAS_NEG_LINK_RATE_22_5:
562                 rc = SAS_LINK_RATE_22_5_GBPS;
563                 break;
564         case MPI3_SAS_NEG_LINK_RATE_PHY_DISABLED:
565                 rc = SAS_PHY_DISABLED;
566                 break;
567         case MPI3_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
568                 rc = SAS_LINK_RATE_FAILED;
569                 break;
570         case MPI3_SAS_NEG_LINK_RATE_PORT_SELECTOR:
571                 rc = SAS_SATA_PORT_SELECTOR;
572                 break;
573         case MPI3_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
574                 rc = SAS_PHY_RESET_IN_PROGRESS;
575                 break;
576         case MPI3_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
577         case MPI3_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
578         default:
579                 rc = SAS_LINK_RATE_UNKNOWN;
580                 break;
581         }
582         return rc;
583 }
584
585 /**
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
590  *
591  * Return: None.
592  */
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)
596 {
597         u64 sas_address = mr_sas_port->remote_identify.sas_address;
598
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);
602
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;
610 }
611
612 /**
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
617  *
618  * Return: None.
619  */
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)
623 {
624         u64 sas_address = mr_sas_port->remote_identify.sas_address;
625
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);
629
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;
637 }
638
639 /**
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
645  *             to be added to
646  * @hba_port: HBA port entry
647  *
648  * Return: None.
649  */
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)
653 {
654         struct mpi3mr_sas_port *mr_sas_port;
655         struct mpi3mr_sas_phy *srch_phy;
656
657         if (mr_sas_phy->phy_belongs_to_port == 1)
658                 return;
659
660         if (!hba_port)
661                 return;
662
663         list_for_each_entry(mr_sas_port, &mr_sas_node->sas_port_list,
664             port_list) {
665                 if (mr_sas_port->remote_identify.sas_address !=
666                     sas_address)
667                         continue;
668                 if (mr_sas_port->hba_port != hba_port)
669                         continue;
670                 list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
671                     port_siblings) {
672                         if (srch_phy == mr_sas_phy)
673                                 return;
674                 }
675                 mpi3mr_add_sas_phy(mrioc, mr_sas_port, mr_sas_phy);
676                 return;
677         }
678 }
679
680 /**
681  * mpi3mr_delete_sas_port - helper function to removing a port
682  * @mrioc: Adapter instance reference
683  * @mr_sas_port: Internal Port object
684  *
685  * Return: None.
686  */
687 static void  mpi3mr_delete_sas_port(struct mpi3mr_ioc *mrioc,
688         struct mpi3mr_sas_port *mr_sas_port)
689 {
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;
694
695         dev_info(&mr_sas_port->port->dev,
696             "remove: sas_address(0x%016llx)\n",
697             (unsigned long long) sas_address);
698
699         if (device_type == SAS_END_DEVICE)
700                 mpi3mr_remove_device_by_sas_address(mrioc, sas_address,
701                     hba_port);
702
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);
706 }
707
708 /**
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
713  *
714  * Return: None.
715  */
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)
718 {
719         struct mpi3mr_sas_port *mr_sas_port, *next;
720         struct mpi3mr_sas_phy *srch_phy;
721
722         if (mr_sas_phy->phy_belongs_to_port == 0)
723                 return;
724
725         list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
726             port_list) {
727                 list_for_each_entry(srch_phy, &mr_sas_port->phy_list,
728                     port_siblings) {
729                         if (srch_phy != mr_sas_phy)
730                                 continue;
731                         if ((mr_sas_port->num_phys == 1) &&
732                             !mrioc->reset_in_progress)
733                                 mpi3mr_delete_sas_port(mrioc, mr_sas_port);
734                         else
735                                 mpi3mr_delete_sas_phy(mrioc, mr_sas_port,
736                                     mr_sas_phy);
737                         return;
738                 }
739         }
740 }
741
742 /**
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
748  *
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
752  *
753  * Return: None.
754  */
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)
758 {
759         int i;
760
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))
764                         continue;
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]);
768         }
769 }
770
771 /**
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
776  *
777  * Populates sas identify info for a specific device.
778  *
779  * Return: 0 for success, non-zero for failure.
780  */
781 static int mpi3mr_set_identify(struct mpi3mr_ioc *mrioc, u16 handle,
782         struct sas_identify *identify)
783 {
784
785         struct mpi3_device_page0 device_pg0;
786         struct mpi3_device0_sas_sata_format *sasinf;
787         u16 device_info;
788         u16 ioc_status;
789
790         if (mrioc->reset_in_progress) {
791                 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
792                 return -EFAULT;
793         }
794
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__);
798                 return -ENXIO;
799         }
800
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__);
804                 return -EIO;
805         }
806
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);
810
811         /* sas_address */
812         identify->sas_address = le64_to_cpu(sasinf->sas_address);
813
814         /* phy number of the parent device this device is linked to */
815         identify->phy_identifier = sasinf->phy_num;
816
817         /* device_type */
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;
821                 break;
822         case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE:
823                 identify->device_type = SAS_END_DEVICE;
824                 break;
825         case MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER:
826                 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
827                 break;
828         }
829
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 |
836                     SAS_PROTOCOL_SATA);
837         if (device_info & MPI3_SAS_DEVICE_INFO_SMP_INITIATOR)
838                 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
839
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 |
846                     SAS_PROTOCOL_SATA);
847         if (device_info & MPI3_SAS_DEVICE_INFO_SMP_TARGET)
848                 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
849         return 0;
850 }
851
852 /**
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
858  *
859  * Return: 0 for success, non-zero for failure.
860  */
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)
864 {
865         struct sas_phy *phy;
866         int phy_index = mr_sas_phy->phy_id;
867
868
869         INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
870         phy = sas_phy_alloc(parent_dev, phy_index);
871         if (!phy) {
872                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
873                     __FILE__, __LINE__, __func__);
874                 return -1;
875         }
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__);
880                 sas_phy_free(phy);
881                 return -1;
882         }
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;
902
903         if ((sas_phy_add(phy))) {
904                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
905                     __FILE__, __LINE__, __func__);
906                 sas_phy_free(phy);
907                 return -1;
908         }
909         if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
910                 dev_info(&phy->dev,
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,
916                     (unsigned long long)
917                     mr_sas_phy->remote_identify.sas_address);
918         mr_sas_phy->phy = phy;
919         return 0;
920 }
921
922 /**
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
928  *
929  * Return: 0 for success, non-zero for failure.
930  */
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)
935 {
936         struct sas_phy *phy;
937         int phy_index = mr_sas_phy->phy_id;
938
939         INIT_LIST_HEAD(&mr_sas_phy->port_siblings);
940         phy = sas_phy_alloc(parent_dev, phy_index);
941         if (!phy) {
942                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
943                     __FILE__, __LINE__, __func__);
944                 return -1;
945         }
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__);
950                 sas_phy_free(phy);
951                 return -1;
952         }
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;
973
974         if ((sas_phy_add(phy))) {
975                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
976                     __FILE__, __LINE__, __func__);
977                 sas_phy_free(phy);
978                 return -1;
979         }
980         if ((mrioc->logging_level & MPI3_DEBUG_TRANSPORT_INFO))
981                 dev_info(&phy->dev,
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,
987                     (unsigned long long)
988                     mr_sas_phy->remote_identify.sas_address);
989         mr_sas_phy->phy = phy;
990         return 0;
991 }
992
993 /**
994  * mpi3mr_alloc_hba_port - alloc hba port object
995  * @mrioc: Adapter instance reference
996  * @port_id: Port number
997  *
998  * Alloc memory for hba port object.
999  */
1000 static struct mpi3mr_hba_port *
1001 mpi3mr_alloc_hba_port(struct mpi3mr_ioc *mrioc, u16 port_id)
1002 {
1003         struct mpi3mr_hba_port *hba_port;
1004
1005         hba_port = kzalloc(sizeof(struct mpi3mr_hba_port),
1006             GFP_KERNEL);
1007         if (!hba_port)
1008                 return NULL;
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);
1013         return hba_port;
1014 }
1015
1016 /**
1017  * mpi3mr_get_hba_port_by_id - find hba port by id
1018  * @mrioc: Adapter instance reference
1019  * @port_id - Port ID to search
1020  *
1021  * Return: mpi3mr_hba_port reference for the matched port
1022  */
1023
1024 struct mpi3mr_hba_port *mpi3mr_get_hba_port_by_id(struct mpi3mr_ioc *mrioc,
1025         u8 port_id)
1026 {
1027         struct mpi3mr_hba_port *port, *port_next;
1028
1029         list_for_each_entry_safe(port, port_next,
1030             &mrioc->hba_port_table_list, list) {
1031                 if (port->port_id != port_id)
1032                         continue;
1033                 if (port->flags & MPI3MR_HBA_PORT_FLAG_DIRTY)
1034                         continue;
1035                 return port;
1036         }
1037
1038         return NULL;
1039 }
1040
1041 /**
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
1049  *
1050  * Return: None.
1051  */
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)
1055 {
1056         unsigned long flags;
1057         struct mpi3mr_sas_node *mr_sas_node;
1058         struct mpi3mr_sas_phy *mr_sas_phy;
1059
1060         if (mrioc->reset_in_progress)
1061                 return;
1062
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);
1066         if (!mr_sas_node) {
1067                 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1068                 return;
1069         }
1070
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,
1079                     hba_port);
1080         } else
1081                 memset(&mr_sas_phy->remote_identify, 0, sizeof(struct
1082                     sas_identify));
1083
1084         if (mr_sas_phy->phy)
1085                 mr_sas_phy->phy->negotiated_linkrate =
1086                     mpi3mr_convert_phy_link_rate(link_rate);
1087
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);
1096 }
1097
1098 /**
1099  * mpi3mr_sas_host_refresh - refreshing sas host object contents
1100  * @mrioc: Adapter instance reference
1101  *
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
1105  * change events
1106  *
1107  * Return: None.
1108  */
1109 void mpi3mr_sas_host_refresh(struct mpi3mr_ioc *mrioc)
1110 {
1111         int i;
1112         u8 link_rate;
1113         u16 sz, port_id, attached_handle;
1114         struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1115
1116         dprint_transport_info(mrioc,
1117             "updating handles for sas_host(0x%016llx)\n",
1118             (unsigned long long)mrioc->sas_hba.sas_address);
1119
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)
1125                 return;
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__);
1129                 goto out;
1130         }
1131
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))
1137                         continue;
1138                 link_rate =
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))
1146                                 goto out;
1147
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);
1158         }
1159  out:
1160         kfree(sas_io_unit_pg0);
1161 }
1162
1163 /**
1164  * mpi3mr_sas_host_add - create sas host object
1165  * @mrioc: Adapter instance reference
1166  *
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
1170  * change event.
1171  *
1172  * Return: None.
1173  */
1174 void mpi3mr_sas_host_add(struct mpi3mr_ioc *mrioc)
1175 {
1176         int i;
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;
1183
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)
1188                 return;
1189
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__);
1193                 goto out;
1194         }
1195         num_phys = sas_io_unit_pg0->num_phys;
1196         kfree(sas_io_unit_pg0);
1197
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)
1204                 return;
1205
1206         mrioc->sas_hba.num_phys = num_phys;
1207
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)
1212                 return;
1213
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__);
1217                 goto out;
1218         }
1219
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))
1225                         continue;
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__);
1231                         goto out;
1232                 }
1233                 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1234                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1235                             __FILE__, __LINE__, __func__);
1236                         goto out;
1237                 }
1238
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;
1243
1244                 if (!(mpi3mr_get_hba_port_by_id(mrioc, port_id)))
1245                         if (!mpi3mr_alloc_hba_port(mrioc, port_id))
1246                                 goto out;
1247
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);
1254         }
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__);
1259                 goto out;
1260         }
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__,
1264                     __func__);
1265                 goto out;
1266         }
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);
1272         ioc_info(mrioc,
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);
1277
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);
1286         }
1287
1288 out:
1289         kfree(sas_io_unit_pg0);
1290 }
1291
1292 /**
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
1298  *
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.
1303  *
1304  * Returns a valid mpi3mr_sas_port reference or NULL.
1305  */
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)
1308 {
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;
1315         int i;
1316         struct sas_port *port;
1317
1318         if (!hba_port) {
1319                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1320                     __FILE__, __LINE__, __func__);
1321                 return NULL;
1322         }
1323
1324         mr_sas_port = kzalloc(sizeof(struct mpi3mr_sas_port), GFP_KERNEL);
1325         if (!mr_sas_port)
1326                 return NULL;
1327
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);
1334
1335         if (!mr_sas_node) {
1336                 ioc_err(mrioc, "%s:could not find parent sas_address(0x%016llx)!\n",
1337                     __func__, (unsigned long long)sas_address_parent);
1338                 goto out_fail;
1339         }
1340
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__);
1345                 goto out_fail;
1346         }
1347
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__);
1351                 goto out_fail;
1352         }
1353
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);
1357
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))
1362                         continue;
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);
1367         }
1368
1369         if (!mr_sas_port->num_phys) {
1370                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1371                     __FILE__, __LINE__, __func__);
1372                 goto out_fail;
1373         }
1374
1375         mr_sas_port->lowest_phy = ffs(mr_sas_port->phy_mask) - 1;
1376
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);
1381
1382                 if (!tgtdev) {
1383                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1384                             __FILE__, __LINE__, __func__);
1385                         goto out_fail;
1386                 }
1387                 tgtdev->dev_spec.sas_sata_inf.pend_sas_rphy_add = 1;
1388         }
1389
1390         if (!mr_sas_node->parent_dev) {
1391                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1392                     __FILE__, __LINE__, __func__);
1393                 goto out_fail;
1394         }
1395
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__);
1400                 goto out_fail;
1401         }
1402
1403         list_for_each_entry(mr_sas_phy, &mr_sas_port->phy_list,
1404             port_siblings) {
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;
1414         }
1415
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;
1420         } else {
1421                 rphy = sas_expander_alloc(port,
1422                     mr_sas_port->remote_identify.device_type);
1423         }
1424         rphy->identify = mr_sas_port->remote_identify;
1425
1426         if (mrioc->current_event)
1427                 mrioc->current_event->pending_at_sml = 1;
1428
1429         if ((sas_rphy_add(rphy))) {
1430                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1431                     __FILE__, __LINE__, __func__);
1432         }
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);
1437         }
1438
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);
1443
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);
1448
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);
1453         }
1454
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);
1463
1464         return mr_sas_port;
1465
1466  out_fail:
1467         list_for_each_entry_safe(mr_sas_phy, next, &mr_sas_port->phy_list,
1468             port_siblings)
1469                 list_del(&mr_sas_phy->port_siblings);
1470         kfree(mr_sas_port);
1471         return NULL;
1472 }
1473
1474 /**
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
1480  *
1481  * Removing object and freeing associated memory from the
1482  * sas_port_list.
1483  *
1484  * Return: None
1485  */
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)
1488 {
1489         int i;
1490         unsigned long flags;
1491         struct mpi3mr_sas_port *mr_sas_port, *next;
1492         struct mpi3mr_sas_node *mr_sas_node;
1493         u8 found = 0;
1494         struct mpi3mr_sas_phy *mr_sas_phy, *next_phy;
1495         struct mpi3mr_hba_port *srch_port, *hba_port_next = NULL;
1496
1497         if (!hba_port)
1498                 return;
1499
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);
1503         if (!mr_sas_node) {
1504                 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1505                 return;
1506         }
1507         list_for_each_entry_safe(mr_sas_port, next, &mr_sas_node->sas_port_list,
1508             port_list) {
1509                 if (mr_sas_port->remote_identify.sas_address != sas_address)
1510                         continue;
1511                 if (mr_sas_port->hba_port != hba_port)
1512                         continue;
1513                 found = 1;
1514                 list_del(&mr_sas_port->port_list);
1515                 goto out;
1516         }
1517
1518  out:
1519         if (!found) {
1520                 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1521                 return;
1522         }
1523
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)
1528                                 continue;
1529                         ioc_info(mrioc,
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);
1533                         kfree(hba_port);
1534                         break;
1535                 }
1536         }
1537
1538         for (i = 0; i < mr_sas_node->num_phys; i++) {
1539                 if (mr_sas_node->phy[i].remote_identify.sas_address ==
1540                     sas_address)
1541                         memset(&mr_sas_node->phy[i].remote_identify, 0,
1542                             sizeof(struct sas_identify));
1543         }
1544
1545         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1546
1547         if (mrioc->current_event)
1548                 mrioc->current_event->pending_at_sml = 1;
1549
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,
1562                             mr_sas_phy->phy);
1563                 list_del(&mr_sas_phy->port_siblings);
1564         }
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);
1569
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);
1574         }
1575
1576         kfree(mr_sas_port);
1577 }
1578
1579 /**
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
1587  */
1588 struct host_port {
1589         u64     sas_address;
1590         u64     phy_mask;
1591         u16     handle;
1592         u8      iounit_port_id;
1593         u8      used;
1594         u8      lowest_phy;
1595 };
1596
1597 /**
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
1602  *
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.
1606  *
1607  * Return: Nothing.
1608  */
1609 static void
1610 mpi3mr_update_mr_sas_port(struct mpi3mr_ioc *mrioc, struct host_port *h_port,
1611         struct mpi3mr_sas_port *mr_sas_port)
1612 {
1613         struct mpi3mr_sas_phy *mr_sas_phy;
1614         u64 phy_mask_xor;
1615         u64 phys_to_be_added, phys_to_be_removed;
1616         int i;
1617
1618         h_port->used = 1;
1619         mr_sas_port->marked_responding = 1;
1620
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);
1626
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;
1629
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;
1634
1635         /*
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.
1639          */
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);
1649         }
1650
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);
1657         }
1658 }
1659
1660 /**
1661  * mpi3mr_refresh_sas_ports - update host's sas ports during reset
1662  * @mrioc: Adapter instance reference
1663  *
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.
1668  *
1669  * Return: Nothing.
1670  */
1671 void
1672 mpi3mr_refresh_sas_ports(struct mpi3mr_ioc *mrioc)
1673 {
1674         struct host_port h_port[64];
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;
1681
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)
1687                 return;
1688         if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1689                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1690                     __FILE__, __LINE__, __func__);
1691                 goto out;
1692         }
1693
1694         /* Create a new expander port table */
1695         for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1696                 attached_handle = le16_to_cpu(
1697                     sas_io_unit_pg0->phy_data[i].attached_dev_handle);
1698                 if (!attached_handle)
1699                         continue;
1700                 found = 0;
1701                 for (j = 0; j < host_port_count; j++) {
1702                         if (h_port[j].handle == attached_handle) {
1703                                 h_port[j].phy_mask |= (1 << i);
1704                                 found = 1;
1705                                 break;
1706                         }
1707                 }
1708                 if (found)
1709                         continue;
1710                 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
1711                     sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
1712                     attached_handle))) {
1713                         dprint_reset(mrioc,
1714                             "failed to read dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1715                             attached_handle, __FILE__, __LINE__, __func__);
1716                         continue;
1717                 }
1718                 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1719                         dprint_reset(mrioc,
1720                             "ioc_status(0x%x) while reading dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1721                             ioc_status, attached_handle,
1722                             __FILE__, __LINE__, __func__);
1723                         continue;
1724                 }
1725                 sasinf = &dev_pg0.device_specific.sas_sata_format;
1726
1727                 port_idx = host_port_count;
1728                 h_port[port_idx].sas_address = le64_to_cpu(sasinf->sas_address);
1729                 h_port[port_idx].handle = attached_handle;
1730                 h_port[port_idx].phy_mask = (1 << i);
1731                 h_port[port_idx].iounit_port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1732                 h_port[port_idx].lowest_phy = sasinf->phy_num;
1733                 h_port[port_idx].used = 0;
1734                 host_port_count++;
1735         }
1736
1737         if (!host_port_count)
1738                 goto out;
1739
1740         if (mrioc->logging_level & MPI3_DEBUG_RESET) {
1741                 ioc_info(mrioc, "Host port details before reset\n");
1742                 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1743                     port_list) {
1744                         ioc_info(mrioc,
1745                             "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1746                             mr_sas_port->hba_port->port_id,
1747                             mr_sas_port->remote_identify.sas_address,
1748                             mr_sas_port->phy_mask, mr_sas_port->lowest_phy);
1749                 }
1750                 mr_sas_port = NULL;
1751                 ioc_info(mrioc, "Host port details after reset\n");
1752                 for (i = 0; i < host_port_count; i++) {
1753                         ioc_info(mrioc,
1754                             "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1755                             h_port[i].iounit_port_id, h_port[i].sas_address,
1756                             h_port[i].phy_mask, h_port[i].lowest_phy);
1757                 }
1758         }
1759
1760         /* mark all host sas port entries as dirty */
1761         list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1762             port_list) {
1763                 mr_sas_port->marked_responding = 0;
1764                 mr_sas_port->hba_port->flags |= MPI3MR_HBA_PORT_FLAG_DIRTY;
1765         }
1766
1767         /* First check for matching lowest phy */
1768         for (i = 0; i < host_port_count; i++) {
1769                 mr_sas_port = NULL;
1770                 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1771                     port_list) {
1772                         if (mr_sas_port->marked_responding)
1773                                 continue;
1774                         if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1775                                 continue;
1776                         if (h_port[i].lowest_phy == mr_sas_port->lowest_phy) {
1777                                 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1778                                 break;
1779                         }
1780                 }
1781         }
1782
1783         /* In case if lowest phy is got enabled or disabled during reset */
1784         for (i = 0; i < host_port_count; i++) {
1785                 if (h_port[i].used)
1786                         continue;
1787                 mr_sas_port = NULL;
1788                 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1789                     port_list) {
1790                         if (mr_sas_port->marked_responding)
1791                                 continue;
1792                         if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1793                                 continue;
1794                         if (h_port[i].phy_mask & mr_sas_port->phy_mask) {
1795                                 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1796                                 break;
1797                         }
1798                 }
1799         }
1800
1801         /* In case if expander cable is removed & connected to another HBA port during reset */
1802         for (i = 0; i < host_port_count; i++) {
1803                 if (h_port[i].used)
1804                         continue;
1805                 mr_sas_port = NULL;
1806                 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1807                     port_list) {
1808                         if (mr_sas_port->marked_responding)
1809                                 continue;
1810                         if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1811                                 continue;
1812                         mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1813                         break;
1814                 }
1815         }
1816 out:
1817         kfree(sas_io_unit_pg0);
1818 }
1819
1820 /**
1821  * mpi3mr_refresh_expanders - Refresh expander device exposure
1822  * @mrioc: Adapter instance reference
1823  *
1824  * This is executed post controller reset to identify any
1825  * missing expander devices during reset and remove from the upper layers
1826  * or expose any newly detected expander device to the upper layers.
1827  *
1828  * Return: Nothing.
1829  */
1830 void
1831 mpi3mr_refresh_expanders(struct mpi3mr_ioc *mrioc)
1832 {
1833         struct mpi3mr_sas_node *sas_expander, *sas_expander_next;
1834         struct mpi3_sas_expander_page0 expander_pg0;
1835         u16 ioc_status, handle;
1836         u64 sas_address;
1837         int i;
1838         unsigned long flags;
1839         struct mpi3mr_hba_port *hba_port;
1840
1841         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1842         list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
1843                 sas_expander->non_responding = 1;
1844         }
1845         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1846
1847         sas_expander = NULL;
1848
1849         handle = 0xffff;
1850
1851         /* Search for responding expander devices and add them if they are newly got added */
1852         while (true) {
1853                 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
1854                     sizeof(struct mpi3_sas_expander_page0),
1855                     MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
1856                         dprint_reset(mrioc,
1857                             "failed to read exp pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1858                             handle, __FILE__, __LINE__, __func__);
1859                         break;
1860                 }
1861
1862                 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1863                         dprint_reset(mrioc,
1864                            "ioc_status(0x%x) while reading exp pg0 for handle:(0x%04x), %s:%d/%s()!\n",
1865                            ioc_status, handle, __FILE__, __LINE__, __func__);
1866                         break;
1867                 }
1868
1869                 handle = le16_to_cpu(expander_pg0.dev_handle);
1870                 sas_address = le64_to_cpu(expander_pg0.sas_address);
1871                 hba_port = mpi3mr_get_hba_port_by_id(mrioc, expander_pg0.io_unit_port);
1872
1873                 if (!hba_port) {
1874                         mpi3mr_sas_host_refresh(mrioc);
1875                         mpi3mr_expander_add(mrioc, handle);
1876                         continue;
1877                 }
1878
1879                 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1880                 sas_expander =
1881                     mpi3mr_expander_find_by_sas_address(mrioc,
1882                     sas_address, hba_port);
1883                 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1884
1885                 if (!sas_expander) {
1886                         mpi3mr_sas_host_refresh(mrioc);
1887                         mpi3mr_expander_add(mrioc, handle);
1888                         continue;
1889                 }
1890
1891                 sas_expander->non_responding = 0;
1892                 if (sas_expander->handle == handle)
1893                         continue;
1894
1895                 sas_expander->handle = handle;
1896                 for (i = 0 ; i < sas_expander->num_phys ; i++)
1897                         sas_expander->phy[i].handle = handle;
1898         }
1899
1900         /*
1901          * Delete non responding expander devices and the corresponding
1902          * hba_port if the non responding expander device's parent device
1903          * is a host node.
1904          */
1905         sas_expander = NULL;
1906         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1907         list_for_each_entry_safe_reverse(sas_expander, sas_expander_next,
1908             &mrioc->sas_expander_list, list) {
1909                 if (sas_expander->non_responding) {
1910                         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1911                         mpi3mr_expander_node_remove(mrioc, sas_expander);
1912                         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1913                 }
1914         }
1915         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1916 }
1917
1918 /**
1919  * mpi3mr_expander_node_add - insert an expander to the list.
1920  * @mrioc: Adapter instance reference
1921  * @sas_expander: Expander sas node
1922  * Context: This function will acquire sas_node_lock.
1923  *
1924  * Adding new object to the ioc->sas_expander_list.
1925  *
1926  * Return: None.
1927  */
1928 static void mpi3mr_expander_node_add(struct mpi3mr_ioc *mrioc,
1929         struct mpi3mr_sas_node *sas_expander)
1930 {
1931         unsigned long flags;
1932
1933         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1934         list_add_tail(&sas_expander->list, &mrioc->sas_expander_list);
1935         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1936 }
1937
1938 /**
1939  * mpi3mr_expander_add -  Create expander object
1940  * @mrioc: Adapter instance reference
1941  * @handle: Expander firmware device handle
1942  *
1943  * This function creating expander object, stored in
1944  * sas_expander_list and expose it to the SAS transport
1945  * layer.
1946  *
1947  * Return: 0 for success, non-zero for failure.
1948  */
1949 int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle)
1950 {
1951         struct mpi3mr_sas_node *sas_expander;
1952         struct mpi3mr_enclosure_node *enclosure_dev;
1953         struct mpi3_sas_expander_page0 expander_pg0;
1954         struct mpi3_sas_expander_page1 expander_pg1;
1955         u16 ioc_status, parent_handle, temp_handle;
1956         u64 sas_address, sas_address_parent = 0;
1957         int i;
1958         unsigned long flags;
1959         u8 port_id, link_rate;
1960         struct mpi3mr_sas_port *mr_sas_port = NULL;
1961         struct mpi3mr_hba_port *hba_port;
1962         u32 phynum_handle;
1963         int rc = 0;
1964
1965         if (!handle)
1966                 return -1;
1967
1968         if (mrioc->reset_in_progress)
1969                 return -1;
1970
1971         if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
1972             sizeof(expander_pg0), MPI3_SAS_EXPAND_PGAD_FORM_HANDLE, handle))) {
1973                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1974                     __FILE__, __LINE__, __func__);
1975                 return -1;
1976         }
1977
1978         if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1979                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1980                     __FILE__, __LINE__, __func__);
1981                 return -1;
1982         }
1983
1984         parent_handle = le16_to_cpu(expander_pg0.parent_dev_handle);
1985         if (mpi3mr_get_sas_address(mrioc, parent_handle, &sas_address_parent)
1986             != 0) {
1987                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1988                     __FILE__, __LINE__, __func__);
1989                 return -1;
1990         }
1991
1992         port_id = expander_pg0.io_unit_port;
1993         hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
1994         if (!hba_port) {
1995                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1996                     __FILE__, __LINE__, __func__);
1997                 return -1;
1998         }
1999
2000         if (sas_address_parent != mrioc->sas_hba.sas_address) {
2001                 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2002                 sas_expander =
2003                    mpi3mr_expander_find_by_sas_address(mrioc,
2004                     sas_address_parent, hba_port);
2005                 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2006                 if (!sas_expander) {
2007                         rc = mpi3mr_expander_add(mrioc, parent_handle);
2008                         if (rc != 0)
2009                                 return rc;
2010                 } else {
2011                         /*
2012                          * When there is a parent expander present, update it's
2013                          * phys where child expander is connected with the link
2014                          * speed, attached dev handle and sas address.
2015                          */
2016                         for (i = 0 ; i < sas_expander->num_phys ; i++) {
2017                                 phynum_handle =
2018                                     (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2019                                     parent_handle;
2020                                 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc,
2021                                     &ioc_status, &expander_pg1,
2022                                     sizeof(expander_pg1),
2023                                     MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2024                                     phynum_handle)) {
2025                                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2026                                             __FILE__, __LINE__, __func__);
2027                                         rc = -1;
2028                                         return rc;
2029                                 }
2030                                 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2031                                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2032                                             __FILE__, __LINE__, __func__);
2033                                         rc = -1;
2034                                         return rc;
2035                                 }
2036                                 temp_handle = le16_to_cpu(
2037                                     expander_pg1.attached_dev_handle);
2038                                 if (temp_handle != handle)
2039                                         continue;
2040                                 link_rate = (expander_pg1.negotiated_link_rate &
2041                                     MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2042                                     MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2043                                 mpi3mr_update_links(mrioc, sas_address_parent,
2044                                     handle, i, link_rate, hba_port);
2045                         }
2046                 }
2047         }
2048
2049         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2050         sas_address = le64_to_cpu(expander_pg0.sas_address);
2051         sas_expander = mpi3mr_expander_find_by_sas_address(mrioc,
2052             sas_address, hba_port);
2053         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2054
2055         if (sas_expander)
2056                 return 0;
2057
2058         sas_expander = kzalloc(sizeof(struct mpi3mr_sas_node),
2059             GFP_KERNEL);
2060         if (!sas_expander)
2061                 return -ENOMEM;
2062
2063         sas_expander->handle = handle;
2064         sas_expander->num_phys = expander_pg0.num_phys;
2065         sas_expander->sas_address_parent = sas_address_parent;
2066         sas_expander->sas_address = sas_address;
2067         sas_expander->hba_port = hba_port;
2068
2069         ioc_info(mrioc,
2070             "expander_add: handle(0x%04x), parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
2071             handle, parent_handle, (unsigned long long)
2072             sas_expander->sas_address, sas_expander->num_phys);
2073
2074         if (!sas_expander->num_phys) {
2075                 rc = -1;
2076                 goto out_fail;
2077         }
2078         sas_expander->phy = kcalloc(sas_expander->num_phys,
2079             sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
2080         if (!sas_expander->phy) {
2081                 rc = -1;
2082                 goto out_fail;
2083         }
2084
2085         INIT_LIST_HEAD(&sas_expander->sas_port_list);
2086         mr_sas_port = mpi3mr_sas_port_add(mrioc, handle, sas_address_parent,
2087             sas_expander->hba_port);
2088         if (!mr_sas_port) {
2089                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2090                     __FILE__, __LINE__, __func__);
2091                 rc = -1;
2092                 goto out_fail;
2093         }
2094         sas_expander->parent_dev = &mr_sas_port->rphy->dev;
2095         sas_expander->rphy = mr_sas_port->rphy;
2096
2097         for (i = 0 ; i < sas_expander->num_phys ; i++) {
2098                 phynum_handle = (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2099                     handle;
2100                 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2101                     &expander_pg1, sizeof(expander_pg1),
2102                     MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2103                     phynum_handle)) {
2104                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2105                             __FILE__, __LINE__, __func__);
2106                         rc = -1;
2107                         goto out_fail;
2108                 }
2109                 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2110                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2111                             __FILE__, __LINE__, __func__);
2112                         rc = -1;
2113                         goto out_fail;
2114                 }
2115
2116                 sas_expander->phy[i].handle = handle;
2117                 sas_expander->phy[i].phy_id = i;
2118                 sas_expander->phy[i].hba_port = hba_port;
2119
2120                 if ((mpi3mr_add_expander_phy(mrioc, &sas_expander->phy[i],
2121                     expander_pg1, sas_expander->parent_dev))) {
2122                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2123                             __FILE__, __LINE__, __func__);
2124                         rc = -1;
2125                         goto out_fail;
2126                 }
2127         }
2128
2129         if (sas_expander->enclosure_handle) {
2130                 enclosure_dev =
2131                         mpi3mr_enclosure_find_by_handle(mrioc,
2132                                                 sas_expander->enclosure_handle);
2133                 if (enclosure_dev)
2134                         sas_expander->enclosure_logical_id = le64_to_cpu(
2135                             enclosure_dev->pg0.enclosure_logical_id);
2136         }
2137
2138         mpi3mr_expander_node_add(mrioc, sas_expander);
2139         return 0;
2140
2141 out_fail:
2142
2143         if (mr_sas_port)
2144                 mpi3mr_sas_port_remove(mrioc,
2145                     sas_expander->sas_address,
2146                     sas_address_parent, sas_expander->hba_port);
2147         kfree(sas_expander->phy);
2148         kfree(sas_expander);
2149         return rc;
2150 }
2151
2152 /**
2153  * mpi3mr_expander_node_remove - recursive removal of expander.
2154  * @mrioc: Adapter instance reference
2155  * @sas_expander: Expander device object
2156  *
2157  * Removes expander object and freeing associated memory from
2158  * the sas_expander_list and removes the same from SAS TL, if
2159  * one of the attached device is an expander then it recursively
2160  * removes the expander device too.
2161  *
2162  * Return nothing.
2163  */
2164 void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
2165         struct mpi3mr_sas_node *sas_expander)
2166 {
2167         struct mpi3mr_sas_port *mr_sas_port, *next;
2168         unsigned long flags;
2169         u8 port_id;
2170
2171         /* remove sibling ports attached to this expander */
2172         list_for_each_entry_safe(mr_sas_port, next,
2173            &sas_expander->sas_port_list, port_list) {
2174                 if (mrioc->reset_in_progress)
2175                         return;
2176                 if (mr_sas_port->remote_identify.device_type ==
2177                     SAS_END_DEVICE)
2178                         mpi3mr_remove_device_by_sas_address(mrioc,
2179                             mr_sas_port->remote_identify.sas_address,
2180                             mr_sas_port->hba_port);
2181                 else if (mr_sas_port->remote_identify.device_type ==
2182                     SAS_EDGE_EXPANDER_DEVICE ||
2183                     mr_sas_port->remote_identify.device_type ==
2184                     SAS_FANOUT_EXPANDER_DEVICE)
2185                         mpi3mr_expander_remove(mrioc,
2186                             mr_sas_port->remote_identify.sas_address,
2187                             mr_sas_port->hba_port);
2188         }
2189
2190         port_id = sas_expander->hba_port->port_id;
2191         mpi3mr_sas_port_remove(mrioc, sas_expander->sas_address,
2192             sas_expander->sas_address_parent, sas_expander->hba_port);
2193
2194         ioc_info(mrioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
2195             sas_expander->handle, (unsigned long long)
2196             sas_expander->sas_address, port_id);
2197
2198         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2199         list_del(&sas_expander->list);
2200         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2201
2202         kfree(sas_expander->phy);
2203         kfree(sas_expander);
2204 }
2205
2206 /**
2207  * mpi3mr_expander_remove - Remove expander object
2208  * @mrioc: Adapter instance reference
2209  * @sas_address: Remove expander sas_address
2210  * @hba_port: HBA port reference
2211  *
2212  * This function remove expander object, stored in
2213  * mrioc->sas_expander_list and removes it from the SAS TL by
2214  * calling mpi3mr_expander_node_remove().
2215  *
2216  * Return: None
2217  */
2218 void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
2219         struct mpi3mr_hba_port *hba_port)
2220 {
2221         struct mpi3mr_sas_node *sas_expander;
2222         unsigned long flags;
2223
2224         if (mrioc->reset_in_progress)
2225                 return;
2226
2227         if (!hba_port)
2228                 return;
2229
2230         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2231         sas_expander = mpi3mr_expander_find_by_sas_address(mrioc, sas_address,
2232             hba_port);
2233         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2234         if (sas_expander)
2235                 mpi3mr_expander_node_remove(mrioc, sas_expander);
2236
2237 }
2238
2239 /**
2240  * mpi3mr_get_sas_negotiated_logical_linkrate - get linkrate
2241  * @mrioc: Adapter instance reference
2242  * @tgtdev: Target device
2243  *
2244  * This function identifies whether the target device is
2245  * attached directly or through expander and issues sas phy
2246  * page0 or expander phy page1 and gets the link rate, if there
2247  * is any failure in reading the pages then this returns link
2248  * rate of 1.5.
2249  *
2250  * Return: logical link rate.
2251  */
2252 static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc,
2253         struct mpi3mr_tgt_dev *tgtdev)
2254 {
2255         u8 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5, phy_number;
2256         struct mpi3_sas_expander_page1 expander_pg1;
2257         struct mpi3_sas_phy_page0 phy_pg0;
2258         u32 phynum_handle;
2259         u16 ioc_status;
2260
2261         phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2262         if (!(tgtdev->devpg0_flag & MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED)) {
2263                 phynum_handle = ((phy_number<<MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT)
2264                                  | tgtdev->parent_handle);
2265                 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2266                     &expander_pg1, sizeof(expander_pg1),
2267                     MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2268                     phynum_handle)) {
2269                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2270                             __FILE__, __LINE__, __func__);
2271                         goto out;
2272                 }
2273                 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2274                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2275                             __FILE__, __LINE__, __func__);
2276                         goto out;
2277                 }
2278                 link_rate = (expander_pg1.negotiated_link_rate &
2279                              MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2280                         MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2281                 goto out;
2282         }
2283         if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
2284             sizeof(struct mpi3_sas_phy_page0),
2285             MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy_number)) {
2286                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2287                     __FILE__, __LINE__, __func__);
2288                 goto out;
2289         }
2290         if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2291                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2292                     __FILE__, __LINE__, __func__);
2293                 goto out;
2294         }
2295         link_rate = (phy_pg0.negotiated_link_rate &
2296                      MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2297                 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2298 out:
2299         return link_rate;
2300 }
2301
2302 /**
2303  * mpi3mr_report_tgtdev_to_sas_transport - expose dev to SAS TL
2304  * @mrioc: Adapter instance reference
2305  * @tgtdev: Target device
2306  *
2307  * This function exposes the target device after
2308  * preparing host_phy, setting up link rate etc.
2309  *
2310  * Return: 0 on success, non-zero for failure.
2311  */
2312 int mpi3mr_report_tgtdev_to_sas_transport(struct mpi3mr_ioc *mrioc,
2313         struct mpi3mr_tgt_dev *tgtdev)
2314 {
2315         int retval = 0;
2316         u8 link_rate, parent_phy_number;
2317         u64 sas_address_parent, sas_address;
2318         struct mpi3mr_hba_port *hba_port;
2319         u8 port_id;
2320
2321         if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2322             !mrioc->sas_transport_enabled)
2323                 return -1;
2324
2325         sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2326         if (!mrioc->sas_hba.num_phys)
2327                 mpi3mr_sas_host_add(mrioc);
2328         else
2329                 mpi3mr_sas_host_refresh(mrioc);
2330
2331         if (mpi3mr_get_sas_address(mrioc, tgtdev->parent_handle,
2332             &sas_address_parent) != 0) {
2333                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2334                     __FILE__, __LINE__, __func__);
2335                 return -1;
2336         }
2337         tgtdev->dev_spec.sas_sata_inf.sas_address_parent = sas_address_parent;
2338
2339         parent_phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2340         port_id = tgtdev->io_unit_port;
2341
2342         hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
2343         if (!hba_port) {
2344                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2345                     __FILE__, __LINE__, __func__);
2346                 return -1;
2347         }
2348         tgtdev->dev_spec.sas_sata_inf.hba_port = hba_port;
2349
2350         link_rate = mpi3mr_get_sas_negotiated_logical_linkrate(mrioc, tgtdev);
2351
2352         mpi3mr_update_links(mrioc, sas_address_parent, tgtdev->dev_handle,
2353             parent_phy_number, link_rate, hba_port);
2354
2355         tgtdev->host_exposed = 1;
2356         if (!mpi3mr_sas_port_add(mrioc, tgtdev->dev_handle,
2357             sas_address_parent, hba_port)) {
2358                 retval = -1;
2359                 } else if ((!tgtdev->starget) && (!mrioc->is_driver_loading)) {
2360                         mpi3mr_sas_port_remove(mrioc, sas_address,
2361                             sas_address_parent, hba_port);
2362                 retval = -1;
2363         }
2364         if (retval) {
2365                 tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2366                 tgtdev->host_exposed = 0;
2367         }
2368         return retval;
2369 }
2370
2371 /**
2372  * mpi3mr_remove_tgtdev_from_sas_transport - remove from SAS TL
2373  * @mrioc: Adapter instance reference
2374  * @tgtdev: Target device
2375  *
2376  * This function removes the target device
2377  *
2378  * Return: None.
2379  */
2380 void mpi3mr_remove_tgtdev_from_sas_transport(struct mpi3mr_ioc *mrioc,
2381         struct mpi3mr_tgt_dev *tgtdev)
2382 {
2383         u64 sas_address_parent, sas_address;
2384         struct mpi3mr_hba_port *hba_port;
2385
2386         if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2387             !mrioc->sas_transport_enabled)
2388                 return;
2389
2390         hba_port = tgtdev->dev_spec.sas_sata_inf.hba_port;
2391         sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2392         sas_address_parent = tgtdev->dev_spec.sas_sata_inf.sas_address_parent;
2393         mpi3mr_sas_port_remove(mrioc, sas_address, sas_address_parent,
2394             hba_port);
2395         tgtdev->host_exposed = 0;
2396         tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2397 }
2398
2399 /**
2400  * mpi3mr_get_port_id_by_sas_phy -  Get port ID of the given phy
2401  * @phy: SAS transport layer phy object
2402  *
2403  * Return: Port number for valid ID else 0xFFFF
2404  */
2405 static inline u8 mpi3mr_get_port_id_by_sas_phy(struct sas_phy *phy)
2406 {
2407         u8 port_id = 0xFF;
2408         struct mpi3mr_hba_port *hba_port = phy->hostdata;
2409
2410         if (hba_port)
2411                 port_id = hba_port->port_id;
2412
2413         return port_id;
2414 }
2415
2416 /**
2417  * mpi3mr_get_port_id_by_rphy - Get Port number from SAS rphy
2418  *
2419  * @mrioc: Adapter instance reference
2420  * @rphy: SAS transport layer remote phy object
2421  *
2422  * Retrieves HBA port number in which the device pointed by the
2423  * rphy object is attached with.
2424  *
2425  * Return: Valid port number on success else OxFFFF.
2426  */
2427 static u8 mpi3mr_get_port_id_by_rphy(struct mpi3mr_ioc *mrioc, struct sas_rphy *rphy)
2428 {
2429         struct mpi3mr_sas_node *sas_expander;
2430         struct mpi3mr_tgt_dev *tgtdev;
2431         unsigned long flags;
2432         u8 port_id = 0xFF;
2433
2434         if (!rphy)
2435                 return port_id;
2436
2437         if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
2438             rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) {
2439                 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2440                 list_for_each_entry(sas_expander, &mrioc->sas_expander_list,
2441                     list) {
2442                         if (sas_expander->rphy == rphy) {
2443                                 port_id = sas_expander->hba_port->port_id;
2444                                 break;
2445                         }
2446                 }
2447                 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2448         } else if (rphy->identify.device_type == SAS_END_DEVICE) {
2449                 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2450
2451                 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2452                             rphy->identify.sas_address, rphy);
2453                 if (tgtdev && tgtdev->dev_spec.sas_sata_inf.hba_port) {
2454                         port_id =
2455                                 tgtdev->dev_spec.sas_sata_inf.hba_port->port_id;
2456                         mpi3mr_tgtdev_put(tgtdev);
2457                 }
2458                 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2459         }
2460         return port_id;
2461 }
2462
2463 static inline struct mpi3mr_ioc *phy_to_mrioc(struct sas_phy *phy)
2464 {
2465         struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
2466
2467         return shost_priv(shost);
2468 }
2469
2470 static inline struct mpi3mr_ioc *rphy_to_mrioc(struct sas_rphy *rphy)
2471 {
2472         struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
2473
2474         return shost_priv(shost);
2475 }
2476
2477 /* report phy error log structure */
2478 struct phy_error_log_request {
2479         u8 smp_frame_type; /* 0x40 */
2480         u8 function; /* 0x11 */
2481         u8 allocated_response_length;
2482         u8 request_length; /* 02 */
2483         u8 reserved_1[5];
2484         u8 phy_identifier;
2485         u8 reserved_2[2];
2486 };
2487
2488 /* report phy error log reply structure */
2489 struct phy_error_log_reply {
2490         u8 smp_frame_type; /* 0x41 */
2491         u8 function; /* 0x11 */
2492         u8 function_result;
2493         u8 response_length;
2494         __be16 expander_change_count;
2495         u8 reserved_1[3];
2496         u8 phy_identifier;
2497         u8 reserved_2[2];
2498         __be32 invalid_dword;
2499         __be32 running_disparity_error;
2500         __be32 loss_of_dword_sync;
2501         __be32 phy_reset_problem;
2502 };
2503
2504
2505 /**
2506  * mpi3mr_get_expander_phy_error_log - return expander counters:
2507  * @mrioc: Adapter instance reference
2508  * @phy: The SAS transport layer phy object
2509  *
2510  * Return: 0 for success, non-zero for failure.
2511  *
2512  */
2513 static int mpi3mr_get_expander_phy_error_log(struct mpi3mr_ioc *mrioc,
2514         struct sas_phy *phy)
2515 {
2516         struct mpi3_smp_passthrough_request mpi_request;
2517         struct mpi3_smp_passthrough_reply mpi_reply;
2518         struct phy_error_log_request *phy_error_log_request;
2519         struct phy_error_log_reply *phy_error_log_reply;
2520         int rc;
2521         void *psge;
2522         void *data_out = NULL;
2523         dma_addr_t data_out_dma, data_in_dma;
2524         u32 data_out_sz, data_in_sz, sz;
2525         u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2526         u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2527         u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2528         u16 ioc_status;
2529
2530         if (mrioc->reset_in_progress) {
2531                 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2532                 return -EFAULT;
2533         }
2534
2535         data_out_sz = sizeof(struct phy_error_log_request);
2536         data_in_sz = sizeof(struct phy_error_log_reply);
2537         sz = data_out_sz + data_in_sz;
2538         data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2539             GFP_KERNEL);
2540         if (!data_out) {
2541                 rc = -ENOMEM;
2542                 goto out;
2543         }
2544
2545         data_in_dma = data_out_dma + data_out_sz;
2546         phy_error_log_reply = data_out + data_out_sz;
2547
2548         rc = -EINVAL;
2549         memset(data_out, 0, sz);
2550         phy_error_log_request = data_out;
2551         phy_error_log_request->smp_frame_type = 0x40;
2552         phy_error_log_request->function = 0x11;
2553         phy_error_log_request->request_length = 2;
2554         phy_error_log_request->allocated_response_length = 0;
2555         phy_error_log_request->phy_identifier = phy->number;
2556
2557         memset(&mpi_request, 0, request_sz);
2558         memset(&mpi_reply, 0, reply_sz);
2559         mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2560         mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2561         mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2562         mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2563
2564         psge = &mpi_request.request_sge;
2565         mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2566
2567         psge = &mpi_request.response_sge;
2568         mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2569
2570         dprint_transport_info(mrioc,
2571             "sending phy error log SMP request to sas_address(0x%016llx), phy_id(%d)\n",
2572             (unsigned long long)phy->identify.sas_address, phy->number);
2573
2574         if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2575             &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2576                 goto out;
2577
2578         dprint_transport_info(mrioc,
2579             "phy error log SMP request completed with ioc_status(0x%04x)\n",
2580             ioc_status);
2581
2582         if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2583                 dprint_transport_info(mrioc,
2584                     "phy error log - reply data transfer size(%d)\n",
2585                     le16_to_cpu(mpi_reply.response_data_length));
2586
2587                 if (le16_to_cpu(mpi_reply.response_data_length) !=
2588                     sizeof(struct phy_error_log_reply))
2589                         goto out;
2590
2591                 dprint_transport_info(mrioc,
2592                     "phy error log - function_result(%d)\n",
2593                     phy_error_log_reply->function_result);
2594
2595                 phy->invalid_dword_count =
2596                     be32_to_cpu(phy_error_log_reply->invalid_dword);
2597                 phy->running_disparity_error_count =
2598                     be32_to_cpu(phy_error_log_reply->running_disparity_error);
2599                 phy->loss_of_dword_sync_count =
2600                     be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
2601                 phy->phy_reset_problem_count =
2602                     be32_to_cpu(phy_error_log_reply->phy_reset_problem);
2603                 rc = 0;
2604         }
2605
2606 out:
2607         if (data_out)
2608                 dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2609                     data_out_dma);
2610
2611         return rc;
2612 }
2613
2614 /**
2615  * mpi3mr_transport_get_linkerrors - return phy error counters
2616  * @phy: The SAS transport layer phy object
2617  *
2618  * This function retrieves the phy error log information of the
2619  * HBA or expander for which the phy belongs to
2620  *
2621  * Return: 0 for success, non-zero for failure.
2622  */
2623 static int mpi3mr_transport_get_linkerrors(struct sas_phy *phy)
2624 {
2625         struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2626         struct mpi3_sas_phy_page1 phy_pg1;
2627         int rc = 0;
2628         u16 ioc_status;
2629
2630         rc = mpi3mr_parent_present(mrioc, phy);
2631         if (rc)
2632                 return rc;
2633
2634         if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2635                 return mpi3mr_get_expander_phy_error_log(mrioc, phy);
2636
2637         memset(&phy_pg1, 0, sizeof(struct mpi3_sas_phy_page1));
2638         /* get hba phy error logs */
2639         if ((mpi3mr_cfg_get_sas_phy_pg1(mrioc, &ioc_status, &phy_pg1,
2640             sizeof(struct mpi3_sas_phy_page1),
2641             MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number))) {
2642                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2643                     __FILE__, __LINE__, __func__);
2644                 return -ENXIO;
2645         }
2646
2647         if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2648                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2649                     __FILE__, __LINE__, __func__);
2650                 return -ENXIO;
2651         }
2652         phy->invalid_dword_count = le32_to_cpu(phy_pg1.invalid_dword_count);
2653         phy->running_disparity_error_count =
2654                 le32_to_cpu(phy_pg1.running_disparity_error_count);
2655         phy->loss_of_dword_sync_count =
2656                 le32_to_cpu(phy_pg1.loss_dword_synch_count);
2657         phy->phy_reset_problem_count =
2658                 le32_to_cpu(phy_pg1.phy_reset_problem_count);
2659         return 0;
2660 }
2661
2662 /**
2663  * mpi3mr_transport_get_enclosure_identifier - Get Enclosure ID
2664  * @rphy: The SAS transport layer remote phy object
2665  * @identifier: Enclosure identifier to be returned
2666  *
2667  * Returns the enclosure id for the device pointed by the remote
2668  * phy object.
2669  *
2670  * Return: 0 on success or -ENXIO
2671  */
2672 static int
2673 mpi3mr_transport_get_enclosure_identifier(struct sas_rphy *rphy,
2674         u64 *identifier)
2675 {
2676         struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2677         struct mpi3mr_tgt_dev *tgtdev = NULL;
2678         unsigned long flags;
2679         int rc;
2680
2681         spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2682         tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2683             rphy->identify.sas_address, rphy);
2684         if (tgtdev) {
2685                 *identifier =
2686                         tgtdev->enclosure_logical_id;
2687                 rc = 0;
2688                 mpi3mr_tgtdev_put(tgtdev);
2689         } else {
2690                 *identifier = 0;
2691                 rc = -ENXIO;
2692         }
2693         spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2694
2695         return rc;
2696 }
2697
2698 /**
2699  * mpi3mr_transport_get_bay_identifier - Get bay ID
2700  * @rphy: The SAS transport layer remote phy object
2701  *
2702  * Returns the slot id for the device pointed by the remote phy
2703  * object.
2704  *
2705  * Return: Valid slot ID on success or -ENXIO
2706  */
2707 static int
2708 mpi3mr_transport_get_bay_identifier(struct sas_rphy *rphy)
2709 {
2710         struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2711         struct mpi3mr_tgt_dev *tgtdev = NULL;
2712         unsigned long flags;
2713         int rc;
2714
2715         spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2716         tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2717             rphy->identify.sas_address, rphy);
2718         if (tgtdev) {
2719                 rc = tgtdev->slot;
2720                 mpi3mr_tgtdev_put(tgtdev);
2721         } else
2722                 rc = -ENXIO;
2723         spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2724
2725         return rc;
2726 }
2727
2728 /* phy control request structure */
2729 struct phy_control_request {
2730         u8 smp_frame_type; /* 0x40 */
2731         u8 function; /* 0x91 */
2732         u8 allocated_response_length;
2733         u8 request_length; /* 0x09 */
2734         u16 expander_change_count;
2735         u8 reserved_1[3];
2736         u8 phy_identifier;
2737         u8 phy_operation;
2738         u8 reserved_2[13];
2739         u64 attached_device_name;
2740         u8 programmed_min_physical_link_rate;
2741         u8 programmed_max_physical_link_rate;
2742         u8 reserved_3[6];
2743 };
2744
2745 /* phy control reply structure */
2746 struct phy_control_reply {
2747         u8 smp_frame_type; /* 0x41 */
2748         u8 function; /* 0x11 */
2749         u8 function_result;
2750         u8 response_length;
2751 };
2752
2753 #define SMP_PHY_CONTROL_LINK_RESET      (0x01)
2754 #define SMP_PHY_CONTROL_HARD_RESET      (0x02)
2755 #define SMP_PHY_CONTROL_DISABLE         (0x03)
2756
2757 /**
2758  * mpi3mr_expander_phy_control - expander phy control
2759  * @mrioc: Adapter instance reference
2760  * @phy: The SAS transport layer phy object
2761  * @phy_operation: The phy operation to be executed
2762  *
2763  * Issues SMP passthru phy control request to execute a specific
2764  * phy operation for a given expander device.
2765  *
2766  * Return: 0 for success, non-zero for failure.
2767  */
2768 static int
2769 mpi3mr_expander_phy_control(struct mpi3mr_ioc *mrioc,
2770         struct sas_phy *phy, u8 phy_operation)
2771 {
2772         struct mpi3_smp_passthrough_request mpi_request;
2773         struct mpi3_smp_passthrough_reply mpi_reply;
2774         struct phy_control_request *phy_control_request;
2775         struct phy_control_reply *phy_control_reply;
2776         int rc;
2777         void *psge;
2778         void *data_out = NULL;
2779         dma_addr_t data_out_dma;
2780         dma_addr_t data_in_dma;
2781         size_t data_in_sz;
2782         size_t data_out_sz;
2783         u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2784         u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2785         u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2786         u16 ioc_status;
2787         u16 sz;
2788
2789         if (mrioc->reset_in_progress) {
2790                 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2791                 return -EFAULT;
2792         }
2793
2794         data_out_sz = sizeof(struct phy_control_request);
2795         data_in_sz = sizeof(struct phy_control_reply);
2796         sz = data_out_sz + data_in_sz;
2797         data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2798             GFP_KERNEL);
2799         if (!data_out) {
2800                 rc = -ENOMEM;
2801                 goto out;
2802         }
2803
2804         data_in_dma = data_out_dma + data_out_sz;
2805         phy_control_reply = data_out + data_out_sz;
2806
2807         rc = -EINVAL;
2808         memset(data_out, 0, sz);
2809
2810         phy_control_request = data_out;
2811         phy_control_request->smp_frame_type = 0x40;
2812         phy_control_request->function = 0x91;
2813         phy_control_request->request_length = 9;
2814         phy_control_request->allocated_response_length = 0;
2815         phy_control_request->phy_identifier = phy->number;
2816         phy_control_request->phy_operation = phy_operation;
2817         phy_control_request->programmed_min_physical_link_rate =
2818             phy->minimum_linkrate << 4;
2819         phy_control_request->programmed_max_physical_link_rate =
2820             phy->maximum_linkrate << 4;
2821
2822         memset(&mpi_request, 0, request_sz);
2823         memset(&mpi_reply, 0, reply_sz);
2824         mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2825         mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2826         mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2827         mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2828
2829         psge = &mpi_request.request_sge;
2830         mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2831
2832         psge = &mpi_request.response_sge;
2833         mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2834
2835         dprint_transport_info(mrioc,
2836             "sending phy control SMP request to sas_address(0x%016llx), phy_id(%d) opcode(%d)\n",
2837             (unsigned long long)phy->identify.sas_address, phy->number,
2838             phy_operation);
2839
2840         if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2841             &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2842                 goto out;
2843
2844         dprint_transport_info(mrioc,
2845             "phy control SMP request completed with ioc_status(0x%04x)\n",
2846             ioc_status);
2847
2848         if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2849                 dprint_transport_info(mrioc,
2850                     "phy control - reply data transfer size(%d)\n",
2851                     le16_to_cpu(mpi_reply.response_data_length));
2852
2853                 if (le16_to_cpu(mpi_reply.response_data_length) !=
2854                     sizeof(struct phy_control_reply))
2855                         goto out;
2856                 dprint_transport_info(mrioc,
2857                     "phy control - function_result(%d)\n",
2858                     phy_control_reply->function_result);
2859                 rc = 0;
2860         }
2861  out:
2862         if (data_out)
2863                 dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2864                     data_out_dma);
2865
2866         return rc;
2867 }
2868
2869 /**
2870  * mpi3mr_transport_phy_reset - Reset a given phy
2871  * @phy: The SAS transport layer phy object
2872  * @hard_reset: Flag to indicate the type of reset
2873  *
2874  * Return: 0 for success, non-zero for failure.
2875  */
2876 static int
2877 mpi3mr_transport_phy_reset(struct sas_phy *phy, int hard_reset)
2878 {
2879         struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2880         struct mpi3_iounit_control_request mpi_request;
2881         struct mpi3_iounit_control_reply mpi_reply;
2882         u16 request_sz = sizeof(struct mpi3_iounit_control_request);
2883         u16 reply_sz = sizeof(struct mpi3_iounit_control_reply);
2884         int rc = 0;
2885         u16 ioc_status;
2886
2887         rc = mpi3mr_parent_present(mrioc, phy);
2888         if (rc)
2889                 return rc;
2890
2891         /* handle expander phys */
2892         if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2893                 return mpi3mr_expander_phy_control(mrioc, phy,
2894                     (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
2895                     SMP_PHY_CONTROL_LINK_RESET);
2896
2897         /* handle hba phys */
2898         memset(&mpi_request, 0, request_sz);
2899         mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2900         mpi_request.function = MPI3_FUNCTION_IO_UNIT_CONTROL;
2901         mpi_request.operation = MPI3_CTRL_OP_SAS_PHY_CONTROL;
2902         mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_ACTION_INDEX] =
2903                 (hard_reset ? MPI3_CTRL_ACTION_HARD_RESET :
2904                  MPI3_CTRL_ACTION_LINK_RESET);
2905         mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_PHY_INDEX] =
2906                 phy->number;
2907
2908         dprint_transport_info(mrioc,
2909             "sending phy reset request to sas_address(0x%016llx), phy_id(%d) hard_reset(%d)\n",
2910             (unsigned long long)phy->identify.sas_address, phy->number,
2911             hard_reset);
2912
2913         if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2914             &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) {
2915                 rc = -EAGAIN;
2916                 goto out;
2917         }
2918
2919         dprint_transport_info(mrioc,
2920             "phy reset request completed with ioc_status(0x%04x)\n",
2921             ioc_status);
2922 out:
2923         return rc;
2924 }
2925
2926 /**
2927  * mpi3mr_transport_phy_enable - enable/disable phys
2928  * @phy: The SAS transport layer phy object
2929  * @enable: flag to enable/disable, enable phy when true
2930  *
2931  * This function enables/disables a given by executing required
2932  * configuration page changes or expander phy control command
2933  *
2934  * Return: 0 for success, non-zero for failure.
2935  */
2936 static int
2937 mpi3mr_transport_phy_enable(struct sas_phy *phy, int enable)
2938 {
2939         struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2940         struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
2941         struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
2942         u16 sz;
2943         int rc = 0;
2944         int i, discovery_active;
2945
2946         rc = mpi3mr_parent_present(mrioc, phy);
2947         if (rc)
2948                 return rc;
2949
2950         /* handle expander phys */
2951         if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2952                 return mpi3mr_expander_phy_control(mrioc, phy,
2953                     (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
2954                     SMP_PHY_CONTROL_DISABLE);
2955
2956         /* handle hba phys */
2957         sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
2958                 (mrioc->sas_hba.num_phys *
2959                  sizeof(struct mpi3_sas_io_unit0_phy_data));
2960         sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
2961         if (!sas_io_unit_pg0) {
2962                 rc = -ENOMEM;
2963                 goto out;
2964         }
2965         if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
2966                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2967                     __FILE__, __LINE__, __func__);
2968                 rc = -ENXIO;
2969                 goto out;
2970         }
2971
2972         /* unable to enable/disable phys when discovery is active */
2973         for (i = 0, discovery_active = 0; i < mrioc->sas_hba.num_phys ; i++) {
2974                 if (sas_io_unit_pg0->phy_data[i].port_flags &
2975                     MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS) {
2976                         ioc_err(mrioc,
2977                             "discovery is active on port = %d, phy = %d\n"
2978                             "\tunable to enable/disable phys, try again later!\n",
2979                             sas_io_unit_pg0->phy_data[i].io_unit_port, i);
2980                         discovery_active = 1;
2981                 }
2982         }
2983
2984         if (discovery_active) {
2985                 rc = -EAGAIN;
2986                 goto out;
2987         }
2988
2989         if ((sas_io_unit_pg0->phy_data[phy->number].phy_flags &
2990              (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
2991               MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))) {
2992                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2993                     __FILE__, __LINE__, __func__);
2994                 rc = -ENXIO;
2995                 goto out;
2996         }
2997
2998         /* read sas_iounit page 1 */
2999         sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3000                 (mrioc->sas_hba.num_phys *
3001                  sizeof(struct mpi3_sas_io_unit1_phy_data));
3002         sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3003         if (!sas_io_unit_pg1) {
3004                 rc = -ENOMEM;
3005                 goto out;
3006         }
3007
3008         if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3009                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3010                     __FILE__, __LINE__, __func__);
3011                 rc = -ENXIO;
3012                 goto out;
3013         }
3014
3015         if (enable)
3016                 sas_io_unit_pg1->phy_data[phy->number].phy_flags
3017                     &= ~MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3018         else
3019                 sas_io_unit_pg1->phy_data[phy->number].phy_flags
3020                     |= MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3021
3022         mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz);
3023
3024         /* link reset */
3025         if (enable)
3026                 mpi3mr_transport_phy_reset(phy, 0);
3027
3028  out:
3029         kfree(sas_io_unit_pg1);
3030         kfree(sas_io_unit_pg0);
3031         return rc;
3032 }
3033
3034 /**
3035  * mpi3mr_transport_phy_speed - set phy min/max speed
3036  * @phy: The SAS transport later phy object
3037  * @rates: Rates defined as in sas_phy_linkrates
3038  *
3039  * This function sets the link rates given in the rates
3040  * argument to the given phy by executing required configuration
3041  * page changes or expander phy control command
3042  *
3043  * Return: 0 for success, non-zero for failure.
3044  */
3045 static int
3046 mpi3mr_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
3047 {
3048         struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
3049         struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
3050         struct mpi3_sas_phy_page0 phy_pg0;
3051         u16 sz, ioc_status;
3052         int rc = 0;
3053
3054         rc = mpi3mr_parent_present(mrioc, phy);
3055         if (rc)
3056                 return rc;
3057
3058         if (!rates->minimum_linkrate)
3059                 rates->minimum_linkrate = phy->minimum_linkrate;
3060         else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
3061                 rates->minimum_linkrate = phy->minimum_linkrate_hw;
3062
3063         if (!rates->maximum_linkrate)
3064                 rates->maximum_linkrate = phy->maximum_linkrate;
3065         else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
3066                 rates->maximum_linkrate = phy->maximum_linkrate_hw;
3067
3068         /* handle expander phys */
3069         if (phy->identify.sas_address != mrioc->sas_hba.sas_address) {
3070                 phy->minimum_linkrate = rates->minimum_linkrate;
3071                 phy->maximum_linkrate = rates->maximum_linkrate;
3072                 return mpi3mr_expander_phy_control(mrioc, phy,
3073                     SMP_PHY_CONTROL_LINK_RESET);
3074         }
3075
3076         /* handle hba phys */
3077         sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3078                 (mrioc->sas_hba.num_phys *
3079                  sizeof(struct mpi3_sas_io_unit1_phy_data));
3080         sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3081         if (!sas_io_unit_pg1) {
3082                 rc = -ENOMEM;
3083                 goto out;
3084         }
3085
3086         if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3087                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3088                     __FILE__, __LINE__, __func__);
3089                 rc = -ENXIO;
3090                 goto out;
3091         }
3092
3093         sas_io_unit_pg1->phy_data[phy->number].max_min_link_rate =
3094                 (rates->minimum_linkrate + (rates->maximum_linkrate << 4));
3095
3096         if (mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3097                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3098                     __FILE__, __LINE__, __func__);
3099                 rc = -ENXIO;
3100                 goto out;
3101         }
3102
3103         /* link reset */
3104         mpi3mr_transport_phy_reset(phy, 0);
3105
3106         /* read phy page 0, then update the rates in the sas transport phy */
3107         if (!mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
3108             sizeof(struct mpi3_sas_phy_page0),
3109             MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number) &&
3110             (ioc_status == MPI3_IOCSTATUS_SUCCESS)) {
3111                 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
3112                     phy_pg0.programmed_link_rate &
3113                     MPI3_SAS_PRATE_MIN_RATE_MASK);
3114                 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
3115                     phy_pg0.programmed_link_rate >> 4);
3116                 phy->negotiated_linkrate =
3117                         mpi3mr_convert_phy_link_rate(
3118                             (phy_pg0.negotiated_link_rate &
3119                             MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK)
3120                             >> MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
3121         }
3122
3123 out:
3124         kfree(sas_io_unit_pg1);
3125         return rc;
3126 }
3127
3128 /**
3129  * mpi3mr_map_smp_buffer - map BSG dma buffer
3130  * @dev: Generic device reference
3131  * @buf: BSG buffer pointer
3132  * @dma_addr: Physical address holder
3133  * @dma_len: Mapped DMA buffer length.
3134  * @p: Virtual address holder
3135  *
3136  * This function maps the DMAable buffer
3137  *
3138  * Return: 0 on success, non-zero on failure
3139  */
3140 static int
3141 mpi3mr_map_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3142                 dma_addr_t *dma_addr, size_t *dma_len, void **p)
3143 {
3144         /* Check if the request is split across multiple segments */
3145         if (buf->sg_cnt > 1) {
3146                 *p = dma_alloc_coherent(dev, buf->payload_len, dma_addr,
3147                                 GFP_KERNEL);
3148                 if (!*p)
3149                         return -ENOMEM;
3150                 *dma_len = buf->payload_len;
3151         } else {
3152                 if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
3153                         return -ENOMEM;
3154                 *dma_addr = sg_dma_address(buf->sg_list);
3155                 *dma_len = sg_dma_len(buf->sg_list);
3156                 *p = NULL;
3157         }
3158
3159         return 0;
3160 }
3161
3162 /**
3163  * mpi3mr_unmap_smp_buffer - unmap BSG dma buffer
3164  * @dev: Generic device reference
3165  * @buf: BSG buffer pointer
3166  * @dma_addr: Physical address to be unmapped
3167  * @p: Virtual address
3168  *
3169  * This function unmaps the DMAable buffer
3170  */
3171 static void
3172 mpi3mr_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3173                 dma_addr_t dma_addr, void *p)
3174 {
3175         if (p)
3176                 dma_free_coherent(dev, buf->payload_len, p, dma_addr);
3177         else
3178                 dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL);
3179 }
3180
3181 /**
3182  * mpi3mr_transport_smp_handler - handler for smp passthru
3183  * @job: BSG job reference
3184  * @shost: SCSI host object reference
3185  * @rphy: SAS transport rphy object pointing the expander
3186  *
3187  * This is used primarily by smp utils for sending the SMP
3188  * commands to the expanders attached to the controller
3189  */
3190 static void
3191 mpi3mr_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
3192         struct sas_rphy *rphy)
3193 {
3194         struct mpi3mr_ioc *mrioc = shost_priv(shost);
3195         struct mpi3_smp_passthrough_request mpi_request;
3196         struct mpi3_smp_passthrough_reply mpi_reply;
3197         int rc;
3198         void *psge;
3199         dma_addr_t dma_addr_in;
3200         dma_addr_t dma_addr_out;
3201         void *addr_in = NULL;
3202         void *addr_out = NULL;
3203         size_t dma_len_in;
3204         size_t dma_len_out;
3205         unsigned int reslen = 0;
3206         u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
3207         u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
3208         u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
3209         u16 ioc_status;
3210
3211         if (mrioc->reset_in_progress) {
3212                 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
3213                 rc = -EFAULT;
3214                 goto out;
3215         }
3216
3217         rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3218             &dma_addr_out, &dma_len_out, &addr_out);
3219         if (rc)
3220                 goto out;
3221
3222         if (addr_out)
3223                 sg_copy_to_buffer(job->request_payload.sg_list,
3224                     job->request_payload.sg_cnt, addr_out,
3225                     job->request_payload.payload_len);
3226
3227         rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3228                         &dma_addr_in, &dma_len_in, &addr_in);
3229         if (rc)
3230                 goto unmap_out;
3231
3232         memset(&mpi_request, 0, request_sz);
3233         memset(&mpi_reply, 0, reply_sz);
3234         mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
3235         mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
3236         mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_rphy(mrioc, rphy);
3237         mpi_request.sas_address = ((rphy) ?
3238             cpu_to_le64(rphy->identify.sas_address) :
3239             cpu_to_le64(mrioc->sas_hba.sas_address));
3240         psge = &mpi_request.request_sge;
3241         mpi3mr_add_sg_single(psge, sgl_flags, dma_len_out - 4, dma_addr_out);
3242
3243         psge = &mpi_request.response_sge;
3244         mpi3mr_add_sg_single(psge, sgl_flags, dma_len_in - 4, dma_addr_in);
3245
3246         dprint_transport_info(mrioc, "sending SMP request\n");
3247
3248         rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
3249                                        &mpi_reply, reply_sz,
3250                                        MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
3251         if (rc)
3252                 goto unmap_in;
3253
3254         dprint_transport_info(mrioc,
3255             "SMP request completed with ioc_status(0x%04x)\n", ioc_status);
3256
3257         dprint_transport_info(mrioc,
3258                     "SMP request - reply data transfer size(%d)\n",
3259                     le16_to_cpu(mpi_reply.response_data_length));
3260
3261         memcpy(job->reply, &mpi_reply, reply_sz);
3262         job->reply_len = reply_sz;
3263         reslen = le16_to_cpu(mpi_reply.response_data_length);
3264
3265         if (addr_in)
3266                 sg_copy_from_buffer(job->reply_payload.sg_list,
3267                                 job->reply_payload.sg_cnt, addr_in,
3268                                 job->reply_payload.payload_len);
3269
3270         rc = 0;
3271 unmap_in:
3272         mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3273                         dma_addr_in, addr_in);
3274 unmap_out:
3275         mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3276                         dma_addr_out, addr_out);
3277 out:
3278         bsg_job_done(job, rc, reslen);
3279 }
3280
3281 struct sas_function_template mpi3mr_transport_functions = {
3282         .get_linkerrors         = mpi3mr_transport_get_linkerrors,
3283         .get_enclosure_identifier = mpi3mr_transport_get_enclosure_identifier,
3284         .get_bay_identifier     = mpi3mr_transport_get_bay_identifier,
3285         .phy_reset              = mpi3mr_transport_phy_reset,
3286         .phy_enable             = mpi3mr_transport_phy_enable,
3287         .set_phy_speed          = mpi3mr_transport_phy_speed,
3288         .smp_handler            = mpi3mr_transport_smp_handler,
3289 };
3290
3291 struct scsi_transport_template *mpi3mr_transport_template;