GNU Linux-libre 6.8.9-gnu
[releases.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 = NULL;
1675         int i, j, found, host_port_count = 0, port_idx;
1676         u16 sz, attached_handle, ioc_status;
1677         struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
1678         struct mpi3_device_page0 dev_pg0;
1679         struct mpi3_device0_sas_sata_format *sasinf;
1680         struct mpi3mr_sas_port *mr_sas_port;
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         h_port = kcalloc(64, sizeof(struct host_port), GFP_KERNEL);
1689         if (!h_port)
1690                 goto out;
1691
1692         if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
1693                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1694                     __FILE__, __LINE__, __func__);
1695                 goto out;
1696         }
1697
1698         /* Create a new expander port table */
1699         for (i = 0; i < mrioc->sas_hba.num_phys; i++) {
1700                 attached_handle = le16_to_cpu(
1701                     sas_io_unit_pg0->phy_data[i].attached_dev_handle);
1702                 if (!attached_handle)
1703                         continue;
1704                 found = 0;
1705                 for (j = 0; j < host_port_count; j++) {
1706                         if (h_port[j].handle == attached_handle) {
1707                                 h_port[j].phy_mask |= (1 << i);
1708                                 found = 1;
1709                                 break;
1710                         }
1711                 }
1712                 if (found)
1713                         continue;
1714                 if ((mpi3mr_cfg_get_dev_pg0(mrioc, &ioc_status, &dev_pg0,
1715                     sizeof(dev_pg0), MPI3_DEVICE_PGAD_FORM_HANDLE,
1716                     attached_handle))) {
1717                         dprint_reset(mrioc,
1718                             "failed to read dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1719                             attached_handle, __FILE__, __LINE__, __func__);
1720                         continue;
1721                 }
1722                 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1723                         dprint_reset(mrioc,
1724                             "ioc_status(0x%x) while reading dev_pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1725                             ioc_status, attached_handle,
1726                             __FILE__, __LINE__, __func__);
1727                         continue;
1728                 }
1729                 sasinf = &dev_pg0.device_specific.sas_sata_format;
1730
1731                 port_idx = host_port_count;
1732                 h_port[port_idx].sas_address = le64_to_cpu(sasinf->sas_address);
1733                 h_port[port_idx].handle = attached_handle;
1734                 h_port[port_idx].phy_mask = (1 << i);
1735                 h_port[port_idx].iounit_port_id = sas_io_unit_pg0->phy_data[i].io_unit_port;
1736                 h_port[port_idx].lowest_phy = sasinf->phy_num;
1737                 h_port[port_idx].used = 0;
1738                 host_port_count++;
1739         }
1740
1741         if (!host_port_count)
1742                 goto out;
1743
1744         if (mrioc->logging_level & MPI3_DEBUG_RESET) {
1745                 ioc_info(mrioc, "Host port details before reset\n");
1746                 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1747                     port_list) {
1748                         ioc_info(mrioc,
1749                             "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1750                             mr_sas_port->hba_port->port_id,
1751                             mr_sas_port->remote_identify.sas_address,
1752                             mr_sas_port->phy_mask, mr_sas_port->lowest_phy);
1753                 }
1754                 mr_sas_port = NULL;
1755                 ioc_info(mrioc, "Host port details after reset\n");
1756                 for (i = 0; i < host_port_count; i++) {
1757                         ioc_info(mrioc,
1758                             "port_id:%d, sas_address:(0x%016llx), phy_mask:(0x%llx), lowest phy id:%d\n",
1759                             h_port[i].iounit_port_id, h_port[i].sas_address,
1760                             h_port[i].phy_mask, h_port[i].lowest_phy);
1761                 }
1762         }
1763
1764         /* mark all host sas port entries as dirty */
1765         list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1766             port_list) {
1767                 mr_sas_port->marked_responding = 0;
1768                 mr_sas_port->hba_port->flags |= MPI3MR_HBA_PORT_FLAG_DIRTY;
1769         }
1770
1771         /* First check for matching lowest phy */
1772         for (i = 0; i < host_port_count; i++) {
1773                 mr_sas_port = NULL;
1774                 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1775                     port_list) {
1776                         if (mr_sas_port->marked_responding)
1777                                 continue;
1778                         if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1779                                 continue;
1780                         if (h_port[i].lowest_phy == mr_sas_port->lowest_phy) {
1781                                 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1782                                 break;
1783                         }
1784                 }
1785         }
1786
1787         /* In case if lowest phy is got enabled or disabled during reset */
1788         for (i = 0; i < host_port_count; i++) {
1789                 if (h_port[i].used)
1790                         continue;
1791                 mr_sas_port = NULL;
1792                 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1793                     port_list) {
1794                         if (mr_sas_port->marked_responding)
1795                                 continue;
1796                         if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1797                                 continue;
1798                         if (h_port[i].phy_mask & mr_sas_port->phy_mask) {
1799                                 mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1800                                 break;
1801                         }
1802                 }
1803         }
1804
1805         /* In case if expander cable is removed & connected to another HBA port during reset */
1806         for (i = 0; i < host_port_count; i++) {
1807                 if (h_port[i].used)
1808                         continue;
1809                 mr_sas_port = NULL;
1810                 list_for_each_entry(mr_sas_port, &mrioc->sas_hba.sas_port_list,
1811                     port_list) {
1812                         if (mr_sas_port->marked_responding)
1813                                 continue;
1814                         if (h_port[i].sas_address != mr_sas_port->remote_identify.sas_address)
1815                                 continue;
1816                         mpi3mr_update_mr_sas_port(mrioc, &h_port[i], mr_sas_port);
1817                         break;
1818                 }
1819         }
1820 out:
1821         kfree(h_port);
1822         kfree(sas_io_unit_pg0);
1823 }
1824
1825 /**
1826  * mpi3mr_refresh_expanders - Refresh expander device exposure
1827  * @mrioc: Adapter instance reference
1828  *
1829  * This is executed post controller reset to identify any
1830  * missing expander devices during reset and remove from the upper layers
1831  * or expose any newly detected expander device to the upper layers.
1832  *
1833  * Return: Nothing.
1834  */
1835 void
1836 mpi3mr_refresh_expanders(struct mpi3mr_ioc *mrioc)
1837 {
1838         struct mpi3mr_sas_node *sas_expander, *sas_expander_next;
1839         struct mpi3_sas_expander_page0 expander_pg0;
1840         u16 ioc_status, handle;
1841         u64 sas_address;
1842         int i;
1843         unsigned long flags;
1844         struct mpi3mr_hba_port *hba_port;
1845
1846         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1847         list_for_each_entry(sas_expander, &mrioc->sas_expander_list, list) {
1848                 sas_expander->non_responding = 1;
1849         }
1850         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1851
1852         sas_expander = NULL;
1853
1854         handle = 0xffff;
1855
1856         /* Search for responding expander devices and add them if they are newly got added */
1857         while (true) {
1858                 if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
1859                     sizeof(struct mpi3_sas_expander_page0),
1860                     MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
1861                         dprint_reset(mrioc,
1862                             "failed to read exp pg0 for handle(0x%04x) at %s:%d/%s()!\n",
1863                             handle, __FILE__, __LINE__, __func__);
1864                         break;
1865                 }
1866
1867                 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1868                         dprint_reset(mrioc,
1869                            "ioc_status(0x%x) while reading exp pg0 for handle:(0x%04x), %s:%d/%s()!\n",
1870                            ioc_status, handle, __FILE__, __LINE__, __func__);
1871                         break;
1872                 }
1873
1874                 handle = le16_to_cpu(expander_pg0.dev_handle);
1875                 sas_address = le64_to_cpu(expander_pg0.sas_address);
1876                 hba_port = mpi3mr_get_hba_port_by_id(mrioc, expander_pg0.io_unit_port);
1877
1878                 if (!hba_port) {
1879                         mpi3mr_sas_host_refresh(mrioc);
1880                         mpi3mr_expander_add(mrioc, handle);
1881                         continue;
1882                 }
1883
1884                 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1885                 sas_expander =
1886                     mpi3mr_expander_find_by_sas_address(mrioc,
1887                     sas_address, hba_port);
1888                 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1889
1890                 if (!sas_expander) {
1891                         mpi3mr_sas_host_refresh(mrioc);
1892                         mpi3mr_expander_add(mrioc, handle);
1893                         continue;
1894                 }
1895
1896                 sas_expander->non_responding = 0;
1897                 if (sas_expander->handle == handle)
1898                         continue;
1899
1900                 sas_expander->handle = handle;
1901                 for (i = 0 ; i < sas_expander->num_phys ; i++)
1902                         sas_expander->phy[i].handle = handle;
1903         }
1904
1905         /*
1906          * Delete non responding expander devices and the corresponding
1907          * hba_port if the non responding expander device's parent device
1908          * is a host node.
1909          */
1910         sas_expander = NULL;
1911         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1912         list_for_each_entry_safe_reverse(sas_expander, sas_expander_next,
1913             &mrioc->sas_expander_list, list) {
1914                 if (sas_expander->non_responding) {
1915                         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1916                         mpi3mr_expander_node_remove(mrioc, sas_expander);
1917                         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1918                 }
1919         }
1920         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1921 }
1922
1923 /**
1924  * mpi3mr_expander_node_add - insert an expander to the list.
1925  * @mrioc: Adapter instance reference
1926  * @sas_expander: Expander sas node
1927  * Context: This function will acquire sas_node_lock.
1928  *
1929  * Adding new object to the ioc->sas_expander_list.
1930  *
1931  * Return: None.
1932  */
1933 static void mpi3mr_expander_node_add(struct mpi3mr_ioc *mrioc,
1934         struct mpi3mr_sas_node *sas_expander)
1935 {
1936         unsigned long flags;
1937
1938         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
1939         list_add_tail(&sas_expander->list, &mrioc->sas_expander_list);
1940         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
1941 }
1942
1943 /**
1944  * mpi3mr_expander_add -  Create expander object
1945  * @mrioc: Adapter instance reference
1946  * @handle: Expander firmware device handle
1947  *
1948  * This function creating expander object, stored in
1949  * sas_expander_list and expose it to the SAS transport
1950  * layer.
1951  *
1952  * Return: 0 for success, non-zero for failure.
1953  */
1954 int mpi3mr_expander_add(struct mpi3mr_ioc *mrioc, u16 handle)
1955 {
1956         struct mpi3mr_sas_node *sas_expander;
1957         struct mpi3mr_enclosure_node *enclosure_dev;
1958         struct mpi3_sas_expander_page0 expander_pg0;
1959         struct mpi3_sas_expander_page1 expander_pg1;
1960         u16 ioc_status, parent_handle, temp_handle;
1961         u64 sas_address, sas_address_parent = 0;
1962         int i;
1963         unsigned long flags;
1964         u8 port_id, link_rate;
1965         struct mpi3mr_sas_port *mr_sas_port = NULL;
1966         struct mpi3mr_hba_port *hba_port;
1967         u32 phynum_handle;
1968         int rc = 0;
1969
1970         if (!handle)
1971                 return -1;
1972
1973         if (mrioc->reset_in_progress)
1974                 return -1;
1975
1976         if ((mpi3mr_cfg_get_sas_exp_pg0(mrioc, &ioc_status, &expander_pg0,
1977             sizeof(expander_pg0), MPI3_SAS_EXPAND_PGAD_FORM_HANDLE, handle))) {
1978                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1979                     __FILE__, __LINE__, __func__);
1980                 return -1;
1981         }
1982
1983         if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
1984                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1985                     __FILE__, __LINE__, __func__);
1986                 return -1;
1987         }
1988
1989         parent_handle = le16_to_cpu(expander_pg0.parent_dev_handle);
1990         if (mpi3mr_get_sas_address(mrioc, parent_handle, &sas_address_parent)
1991             != 0) {
1992                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
1993                     __FILE__, __LINE__, __func__);
1994                 return -1;
1995         }
1996
1997         port_id = expander_pg0.io_unit_port;
1998         hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
1999         if (!hba_port) {
2000                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2001                     __FILE__, __LINE__, __func__);
2002                 return -1;
2003         }
2004
2005         if (sas_address_parent != mrioc->sas_hba.sas_address) {
2006                 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2007                 sas_expander =
2008                    mpi3mr_expander_find_by_sas_address(mrioc,
2009                     sas_address_parent, hba_port);
2010                 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2011                 if (!sas_expander) {
2012                         rc = mpi3mr_expander_add(mrioc, parent_handle);
2013                         if (rc != 0)
2014                                 return rc;
2015                 } else {
2016                         /*
2017                          * When there is a parent expander present, update it's
2018                          * phys where child expander is connected with the link
2019                          * speed, attached dev handle and sas address.
2020                          */
2021                         for (i = 0 ; i < sas_expander->num_phys ; i++) {
2022                                 phynum_handle =
2023                                     (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2024                                     parent_handle;
2025                                 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc,
2026                                     &ioc_status, &expander_pg1,
2027                                     sizeof(expander_pg1),
2028                                     MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2029                                     phynum_handle)) {
2030                                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2031                                             __FILE__, __LINE__, __func__);
2032                                         rc = -1;
2033                                         return rc;
2034                                 }
2035                                 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2036                                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2037                                             __FILE__, __LINE__, __func__);
2038                                         rc = -1;
2039                                         return rc;
2040                                 }
2041                                 temp_handle = le16_to_cpu(
2042                                     expander_pg1.attached_dev_handle);
2043                                 if (temp_handle != handle)
2044                                         continue;
2045                                 link_rate = (expander_pg1.negotiated_link_rate &
2046                                     MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2047                                     MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2048                                 mpi3mr_update_links(mrioc, sas_address_parent,
2049                                     handle, i, link_rate, hba_port);
2050                         }
2051                 }
2052         }
2053
2054         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2055         sas_address = le64_to_cpu(expander_pg0.sas_address);
2056         sas_expander = mpi3mr_expander_find_by_sas_address(mrioc,
2057             sas_address, hba_port);
2058         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2059
2060         if (sas_expander)
2061                 return 0;
2062
2063         sas_expander = kzalloc(sizeof(struct mpi3mr_sas_node),
2064             GFP_KERNEL);
2065         if (!sas_expander)
2066                 return -ENOMEM;
2067
2068         sas_expander->handle = handle;
2069         sas_expander->num_phys = expander_pg0.num_phys;
2070         sas_expander->sas_address_parent = sas_address_parent;
2071         sas_expander->sas_address = sas_address;
2072         sas_expander->hba_port = hba_port;
2073
2074         ioc_info(mrioc,
2075             "expander_add: handle(0x%04x), parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
2076             handle, parent_handle, (unsigned long long)
2077             sas_expander->sas_address, sas_expander->num_phys);
2078
2079         if (!sas_expander->num_phys) {
2080                 rc = -1;
2081                 goto out_fail;
2082         }
2083         sas_expander->phy = kcalloc(sas_expander->num_phys,
2084             sizeof(struct mpi3mr_sas_phy), GFP_KERNEL);
2085         if (!sas_expander->phy) {
2086                 rc = -1;
2087                 goto out_fail;
2088         }
2089
2090         INIT_LIST_HEAD(&sas_expander->sas_port_list);
2091         mr_sas_port = mpi3mr_sas_port_add(mrioc, handle, sas_address_parent,
2092             sas_expander->hba_port);
2093         if (!mr_sas_port) {
2094                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2095                     __FILE__, __LINE__, __func__);
2096                 rc = -1;
2097                 goto out_fail;
2098         }
2099         sas_expander->parent_dev = &mr_sas_port->rphy->dev;
2100         sas_expander->rphy = mr_sas_port->rphy;
2101
2102         for (i = 0 ; i < sas_expander->num_phys ; i++) {
2103                 phynum_handle = (i << MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT) |
2104                     handle;
2105                 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2106                     &expander_pg1, sizeof(expander_pg1),
2107                     MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2108                     phynum_handle)) {
2109                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2110                             __FILE__, __LINE__, __func__);
2111                         rc = -1;
2112                         goto out_fail;
2113                 }
2114                 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2115                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2116                             __FILE__, __LINE__, __func__);
2117                         rc = -1;
2118                         goto out_fail;
2119                 }
2120
2121                 sas_expander->phy[i].handle = handle;
2122                 sas_expander->phy[i].phy_id = i;
2123                 sas_expander->phy[i].hba_port = hba_port;
2124
2125                 if ((mpi3mr_add_expander_phy(mrioc, &sas_expander->phy[i],
2126                     expander_pg1, sas_expander->parent_dev))) {
2127                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2128                             __FILE__, __LINE__, __func__);
2129                         rc = -1;
2130                         goto out_fail;
2131                 }
2132         }
2133
2134         if (sas_expander->enclosure_handle) {
2135                 enclosure_dev =
2136                         mpi3mr_enclosure_find_by_handle(mrioc,
2137                                                 sas_expander->enclosure_handle);
2138                 if (enclosure_dev)
2139                         sas_expander->enclosure_logical_id = le64_to_cpu(
2140                             enclosure_dev->pg0.enclosure_logical_id);
2141         }
2142
2143         mpi3mr_expander_node_add(mrioc, sas_expander);
2144         return 0;
2145
2146 out_fail:
2147
2148         if (mr_sas_port)
2149                 mpi3mr_sas_port_remove(mrioc,
2150                     sas_expander->sas_address,
2151                     sas_address_parent, sas_expander->hba_port);
2152         kfree(sas_expander->phy);
2153         kfree(sas_expander);
2154         return rc;
2155 }
2156
2157 /**
2158  * mpi3mr_expander_node_remove - recursive removal of expander.
2159  * @mrioc: Adapter instance reference
2160  * @sas_expander: Expander device object
2161  *
2162  * Removes expander object and freeing associated memory from
2163  * the sas_expander_list and removes the same from SAS TL, if
2164  * one of the attached device is an expander then it recursively
2165  * removes the expander device too.
2166  *
2167  * Return nothing.
2168  */
2169 void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
2170         struct mpi3mr_sas_node *sas_expander)
2171 {
2172         struct mpi3mr_sas_port *mr_sas_port, *next;
2173         unsigned long flags;
2174         u8 port_id;
2175
2176         /* remove sibling ports attached to this expander */
2177         list_for_each_entry_safe(mr_sas_port, next,
2178            &sas_expander->sas_port_list, port_list) {
2179                 if (mrioc->reset_in_progress)
2180                         return;
2181                 if (mr_sas_port->remote_identify.device_type ==
2182                     SAS_END_DEVICE)
2183                         mpi3mr_remove_device_by_sas_address(mrioc,
2184                             mr_sas_port->remote_identify.sas_address,
2185                             mr_sas_port->hba_port);
2186                 else if (mr_sas_port->remote_identify.device_type ==
2187                     SAS_EDGE_EXPANDER_DEVICE ||
2188                     mr_sas_port->remote_identify.device_type ==
2189                     SAS_FANOUT_EXPANDER_DEVICE)
2190                         mpi3mr_expander_remove(mrioc,
2191                             mr_sas_port->remote_identify.sas_address,
2192                             mr_sas_port->hba_port);
2193         }
2194
2195         port_id = sas_expander->hba_port->port_id;
2196         mpi3mr_sas_port_remove(mrioc, sas_expander->sas_address,
2197             sas_expander->sas_address_parent, sas_expander->hba_port);
2198
2199         ioc_info(mrioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n",
2200             sas_expander->handle, (unsigned long long)
2201             sas_expander->sas_address, port_id);
2202
2203         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2204         list_del(&sas_expander->list);
2205         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2206
2207         kfree(sas_expander->phy);
2208         kfree(sas_expander);
2209 }
2210
2211 /**
2212  * mpi3mr_expander_remove - Remove expander object
2213  * @mrioc: Adapter instance reference
2214  * @sas_address: Remove expander sas_address
2215  * @hba_port: HBA port reference
2216  *
2217  * This function remove expander object, stored in
2218  * mrioc->sas_expander_list and removes it from the SAS TL by
2219  * calling mpi3mr_expander_node_remove().
2220  *
2221  * Return: None
2222  */
2223 void mpi3mr_expander_remove(struct mpi3mr_ioc *mrioc, u64 sas_address,
2224         struct mpi3mr_hba_port *hba_port)
2225 {
2226         struct mpi3mr_sas_node *sas_expander;
2227         unsigned long flags;
2228
2229         if (mrioc->reset_in_progress)
2230                 return;
2231
2232         if (!hba_port)
2233                 return;
2234
2235         spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2236         sas_expander = mpi3mr_expander_find_by_sas_address(mrioc, sas_address,
2237             hba_port);
2238         spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2239         if (sas_expander)
2240                 mpi3mr_expander_node_remove(mrioc, sas_expander);
2241
2242 }
2243
2244 /**
2245  * mpi3mr_get_sas_negotiated_logical_linkrate - get linkrate
2246  * @mrioc: Adapter instance reference
2247  * @tgtdev: Target device
2248  *
2249  * This function identifies whether the target device is
2250  * attached directly or through expander and issues sas phy
2251  * page0 or expander phy page1 and gets the link rate, if there
2252  * is any failure in reading the pages then this returns link
2253  * rate of 1.5.
2254  *
2255  * Return: logical link rate.
2256  */
2257 static u8 mpi3mr_get_sas_negotiated_logical_linkrate(struct mpi3mr_ioc *mrioc,
2258         struct mpi3mr_tgt_dev *tgtdev)
2259 {
2260         u8 link_rate = MPI3_SAS_NEG_LINK_RATE_1_5, phy_number;
2261         struct mpi3_sas_expander_page1 expander_pg1;
2262         struct mpi3_sas_phy_page0 phy_pg0;
2263         u32 phynum_handle;
2264         u16 ioc_status;
2265
2266         phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2267         if (!(tgtdev->devpg0_flag & MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED)) {
2268                 phynum_handle = ((phy_number<<MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT)
2269                                  | tgtdev->parent_handle);
2270                 if (mpi3mr_cfg_get_sas_exp_pg1(mrioc, &ioc_status,
2271                     &expander_pg1, sizeof(expander_pg1),
2272                     MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM,
2273                     phynum_handle)) {
2274                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2275                             __FILE__, __LINE__, __func__);
2276                         goto out;
2277                 }
2278                 if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2279                         ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2280                             __FILE__, __LINE__, __func__);
2281                         goto out;
2282                 }
2283                 link_rate = (expander_pg1.negotiated_link_rate &
2284                              MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2285                         MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2286                 goto out;
2287         }
2288         if (mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
2289             sizeof(struct mpi3_sas_phy_page0),
2290             MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy_number)) {
2291                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2292                     __FILE__, __LINE__, __func__);
2293                 goto out;
2294         }
2295         if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2296                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2297                     __FILE__, __LINE__, __func__);
2298                 goto out;
2299         }
2300         link_rate = (phy_pg0.negotiated_link_rate &
2301                      MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK) >>
2302                 MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT;
2303 out:
2304         return link_rate;
2305 }
2306
2307 /**
2308  * mpi3mr_report_tgtdev_to_sas_transport - expose dev to SAS TL
2309  * @mrioc: Adapter instance reference
2310  * @tgtdev: Target device
2311  *
2312  * This function exposes the target device after
2313  * preparing host_phy, setting up link rate etc.
2314  *
2315  * Return: 0 on success, non-zero for failure.
2316  */
2317 int mpi3mr_report_tgtdev_to_sas_transport(struct mpi3mr_ioc *mrioc,
2318         struct mpi3mr_tgt_dev *tgtdev)
2319 {
2320         int retval = 0;
2321         u8 link_rate, parent_phy_number;
2322         u64 sas_address_parent, sas_address;
2323         struct mpi3mr_hba_port *hba_port;
2324         u8 port_id;
2325
2326         if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2327             !mrioc->sas_transport_enabled)
2328                 return -1;
2329
2330         sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2331         if (!mrioc->sas_hba.num_phys)
2332                 mpi3mr_sas_host_add(mrioc);
2333         else
2334                 mpi3mr_sas_host_refresh(mrioc);
2335
2336         if (mpi3mr_get_sas_address(mrioc, tgtdev->parent_handle,
2337             &sas_address_parent) != 0) {
2338                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2339                     __FILE__, __LINE__, __func__);
2340                 return -1;
2341         }
2342         tgtdev->dev_spec.sas_sata_inf.sas_address_parent = sas_address_parent;
2343
2344         parent_phy_number = tgtdev->dev_spec.sas_sata_inf.phy_id;
2345         port_id = tgtdev->io_unit_port;
2346
2347         hba_port = mpi3mr_get_hba_port_by_id(mrioc, port_id);
2348         if (!hba_port) {
2349                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2350                     __FILE__, __LINE__, __func__);
2351                 return -1;
2352         }
2353         tgtdev->dev_spec.sas_sata_inf.hba_port = hba_port;
2354
2355         link_rate = mpi3mr_get_sas_negotiated_logical_linkrate(mrioc, tgtdev);
2356
2357         mpi3mr_update_links(mrioc, sas_address_parent, tgtdev->dev_handle,
2358             parent_phy_number, link_rate, hba_port);
2359
2360         tgtdev->host_exposed = 1;
2361         if (!mpi3mr_sas_port_add(mrioc, tgtdev->dev_handle,
2362             sas_address_parent, hba_port)) {
2363                 retval = -1;
2364                 } else if ((!tgtdev->starget) && (!mrioc->is_driver_loading)) {
2365                         mpi3mr_sas_port_remove(mrioc, sas_address,
2366                             sas_address_parent, hba_port);
2367                 retval = -1;
2368         }
2369         if (retval) {
2370                 tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2371                 tgtdev->host_exposed = 0;
2372         }
2373         return retval;
2374 }
2375
2376 /**
2377  * mpi3mr_remove_tgtdev_from_sas_transport - remove from SAS TL
2378  * @mrioc: Adapter instance reference
2379  * @tgtdev: Target device
2380  *
2381  * This function removes the target device
2382  *
2383  * Return: None.
2384  */
2385 void mpi3mr_remove_tgtdev_from_sas_transport(struct mpi3mr_ioc *mrioc,
2386         struct mpi3mr_tgt_dev *tgtdev)
2387 {
2388         u64 sas_address_parent, sas_address;
2389         struct mpi3mr_hba_port *hba_port;
2390
2391         if ((tgtdev->dev_type != MPI3_DEVICE_DEVFORM_SAS_SATA) ||
2392             !mrioc->sas_transport_enabled)
2393                 return;
2394
2395         hba_port = tgtdev->dev_spec.sas_sata_inf.hba_port;
2396         sas_address = tgtdev->dev_spec.sas_sata_inf.sas_address;
2397         sas_address_parent = tgtdev->dev_spec.sas_sata_inf.sas_address_parent;
2398         mpi3mr_sas_port_remove(mrioc, sas_address, sas_address_parent,
2399             hba_port);
2400         tgtdev->host_exposed = 0;
2401         tgtdev->dev_spec.sas_sata_inf.hba_port = NULL;
2402 }
2403
2404 /**
2405  * mpi3mr_get_port_id_by_sas_phy -  Get port ID of the given phy
2406  * @phy: SAS transport layer phy object
2407  *
2408  * Return: Port number for valid ID else 0xFFFF
2409  */
2410 static inline u8 mpi3mr_get_port_id_by_sas_phy(struct sas_phy *phy)
2411 {
2412         u8 port_id = 0xFF;
2413         struct mpi3mr_hba_port *hba_port = phy->hostdata;
2414
2415         if (hba_port)
2416                 port_id = hba_port->port_id;
2417
2418         return port_id;
2419 }
2420
2421 /**
2422  * mpi3mr_get_port_id_by_rphy - Get Port number from SAS rphy
2423  *
2424  * @mrioc: Adapter instance reference
2425  * @rphy: SAS transport layer remote phy object
2426  *
2427  * Retrieves HBA port number in which the device pointed by the
2428  * rphy object is attached with.
2429  *
2430  * Return: Valid port number on success else OxFFFF.
2431  */
2432 static u8 mpi3mr_get_port_id_by_rphy(struct mpi3mr_ioc *mrioc, struct sas_rphy *rphy)
2433 {
2434         struct mpi3mr_sas_node *sas_expander;
2435         struct mpi3mr_tgt_dev *tgtdev;
2436         unsigned long flags;
2437         u8 port_id = 0xFF;
2438
2439         if (!rphy)
2440                 return port_id;
2441
2442         if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
2443             rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) {
2444                 spin_lock_irqsave(&mrioc->sas_node_lock, flags);
2445                 list_for_each_entry(sas_expander, &mrioc->sas_expander_list,
2446                     list) {
2447                         if (sas_expander->rphy == rphy) {
2448                                 port_id = sas_expander->hba_port->port_id;
2449                                 break;
2450                         }
2451                 }
2452                 spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
2453         } else if (rphy->identify.device_type == SAS_END_DEVICE) {
2454                 spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2455
2456                 tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2457                             rphy->identify.sas_address, rphy);
2458                 if (tgtdev && tgtdev->dev_spec.sas_sata_inf.hba_port) {
2459                         port_id =
2460                                 tgtdev->dev_spec.sas_sata_inf.hba_port->port_id;
2461                         mpi3mr_tgtdev_put(tgtdev);
2462                 }
2463                 spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2464         }
2465         return port_id;
2466 }
2467
2468 static inline struct mpi3mr_ioc *phy_to_mrioc(struct sas_phy *phy)
2469 {
2470         struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
2471
2472         return shost_priv(shost);
2473 }
2474
2475 static inline struct mpi3mr_ioc *rphy_to_mrioc(struct sas_rphy *rphy)
2476 {
2477         struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
2478
2479         return shost_priv(shost);
2480 }
2481
2482 /* report phy error log structure */
2483 struct phy_error_log_request {
2484         u8 smp_frame_type; /* 0x40 */
2485         u8 function; /* 0x11 */
2486         u8 allocated_response_length;
2487         u8 request_length; /* 02 */
2488         u8 reserved_1[5];
2489         u8 phy_identifier;
2490         u8 reserved_2[2];
2491 };
2492
2493 /* report phy error log reply structure */
2494 struct phy_error_log_reply {
2495         u8 smp_frame_type; /* 0x41 */
2496         u8 function; /* 0x11 */
2497         u8 function_result;
2498         u8 response_length;
2499         __be16 expander_change_count;
2500         u8 reserved_1[3];
2501         u8 phy_identifier;
2502         u8 reserved_2[2];
2503         __be32 invalid_dword;
2504         __be32 running_disparity_error;
2505         __be32 loss_of_dword_sync;
2506         __be32 phy_reset_problem;
2507 };
2508
2509
2510 /**
2511  * mpi3mr_get_expander_phy_error_log - return expander counters:
2512  * @mrioc: Adapter instance reference
2513  * @phy: The SAS transport layer phy object
2514  *
2515  * Return: 0 for success, non-zero for failure.
2516  *
2517  */
2518 static int mpi3mr_get_expander_phy_error_log(struct mpi3mr_ioc *mrioc,
2519         struct sas_phy *phy)
2520 {
2521         struct mpi3_smp_passthrough_request mpi_request;
2522         struct mpi3_smp_passthrough_reply mpi_reply;
2523         struct phy_error_log_request *phy_error_log_request;
2524         struct phy_error_log_reply *phy_error_log_reply;
2525         int rc;
2526         void *psge;
2527         void *data_out = NULL;
2528         dma_addr_t data_out_dma, data_in_dma;
2529         u32 data_out_sz, data_in_sz, sz;
2530         u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2531         u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2532         u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2533         u16 ioc_status;
2534
2535         if (mrioc->reset_in_progress) {
2536                 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2537                 return -EFAULT;
2538         }
2539
2540         data_out_sz = sizeof(struct phy_error_log_request);
2541         data_in_sz = sizeof(struct phy_error_log_reply);
2542         sz = data_out_sz + data_in_sz;
2543         data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2544             GFP_KERNEL);
2545         if (!data_out) {
2546                 rc = -ENOMEM;
2547                 goto out;
2548         }
2549
2550         data_in_dma = data_out_dma + data_out_sz;
2551         phy_error_log_reply = data_out + data_out_sz;
2552
2553         rc = -EINVAL;
2554         memset(data_out, 0, sz);
2555         phy_error_log_request = data_out;
2556         phy_error_log_request->smp_frame_type = 0x40;
2557         phy_error_log_request->function = 0x11;
2558         phy_error_log_request->request_length = 2;
2559         phy_error_log_request->allocated_response_length = 0;
2560         phy_error_log_request->phy_identifier = phy->number;
2561
2562         memset(&mpi_request, 0, request_sz);
2563         memset(&mpi_reply, 0, reply_sz);
2564         mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2565         mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2566         mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2567         mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2568
2569         psge = &mpi_request.request_sge;
2570         mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2571
2572         psge = &mpi_request.response_sge;
2573         mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2574
2575         dprint_transport_info(mrioc,
2576             "sending phy error log SMP request to sas_address(0x%016llx), phy_id(%d)\n",
2577             (unsigned long long)phy->identify.sas_address, phy->number);
2578
2579         if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2580             &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2581                 goto out;
2582
2583         dprint_transport_info(mrioc,
2584             "phy error log SMP request completed with ioc_status(0x%04x)\n",
2585             ioc_status);
2586
2587         if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2588                 dprint_transport_info(mrioc,
2589                     "phy error log - reply data transfer size(%d)\n",
2590                     le16_to_cpu(mpi_reply.response_data_length));
2591
2592                 if (le16_to_cpu(mpi_reply.response_data_length) !=
2593                     sizeof(struct phy_error_log_reply))
2594                         goto out;
2595
2596                 dprint_transport_info(mrioc,
2597                     "phy error log - function_result(%d)\n",
2598                     phy_error_log_reply->function_result);
2599
2600                 phy->invalid_dword_count =
2601                     be32_to_cpu(phy_error_log_reply->invalid_dword);
2602                 phy->running_disparity_error_count =
2603                     be32_to_cpu(phy_error_log_reply->running_disparity_error);
2604                 phy->loss_of_dword_sync_count =
2605                     be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
2606                 phy->phy_reset_problem_count =
2607                     be32_to_cpu(phy_error_log_reply->phy_reset_problem);
2608                 rc = 0;
2609         }
2610
2611 out:
2612         if (data_out)
2613                 dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2614                     data_out_dma);
2615
2616         return rc;
2617 }
2618
2619 /**
2620  * mpi3mr_transport_get_linkerrors - return phy error counters
2621  * @phy: The SAS transport layer phy object
2622  *
2623  * This function retrieves the phy error log information of the
2624  * HBA or expander for which the phy belongs to
2625  *
2626  * Return: 0 for success, non-zero for failure.
2627  */
2628 static int mpi3mr_transport_get_linkerrors(struct sas_phy *phy)
2629 {
2630         struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2631         struct mpi3_sas_phy_page1 phy_pg1;
2632         int rc = 0;
2633         u16 ioc_status;
2634
2635         rc = mpi3mr_parent_present(mrioc, phy);
2636         if (rc)
2637                 return rc;
2638
2639         if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2640                 return mpi3mr_get_expander_phy_error_log(mrioc, phy);
2641
2642         memset(&phy_pg1, 0, sizeof(struct mpi3_sas_phy_page1));
2643         /* get hba phy error logs */
2644         if ((mpi3mr_cfg_get_sas_phy_pg1(mrioc, &ioc_status, &phy_pg1,
2645             sizeof(struct mpi3_sas_phy_page1),
2646             MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number))) {
2647                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2648                     __FILE__, __LINE__, __func__);
2649                 return -ENXIO;
2650         }
2651
2652         if (ioc_status != MPI3_IOCSTATUS_SUCCESS) {
2653                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2654                     __FILE__, __LINE__, __func__);
2655                 return -ENXIO;
2656         }
2657         phy->invalid_dword_count = le32_to_cpu(phy_pg1.invalid_dword_count);
2658         phy->running_disparity_error_count =
2659                 le32_to_cpu(phy_pg1.running_disparity_error_count);
2660         phy->loss_of_dword_sync_count =
2661                 le32_to_cpu(phy_pg1.loss_dword_synch_count);
2662         phy->phy_reset_problem_count =
2663                 le32_to_cpu(phy_pg1.phy_reset_problem_count);
2664         return 0;
2665 }
2666
2667 /**
2668  * mpi3mr_transport_get_enclosure_identifier - Get Enclosure ID
2669  * @rphy: The SAS transport layer remote phy object
2670  * @identifier: Enclosure identifier to be returned
2671  *
2672  * Returns the enclosure id for the device pointed by the remote
2673  * phy object.
2674  *
2675  * Return: 0 on success or -ENXIO
2676  */
2677 static int
2678 mpi3mr_transport_get_enclosure_identifier(struct sas_rphy *rphy,
2679         u64 *identifier)
2680 {
2681         struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2682         struct mpi3mr_tgt_dev *tgtdev = NULL;
2683         unsigned long flags;
2684         int rc;
2685
2686         spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2687         tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2688             rphy->identify.sas_address, rphy);
2689         if (tgtdev) {
2690                 *identifier =
2691                         tgtdev->enclosure_logical_id;
2692                 rc = 0;
2693                 mpi3mr_tgtdev_put(tgtdev);
2694         } else {
2695                 *identifier = 0;
2696                 rc = -ENXIO;
2697         }
2698         spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2699
2700         return rc;
2701 }
2702
2703 /**
2704  * mpi3mr_transport_get_bay_identifier - Get bay ID
2705  * @rphy: The SAS transport layer remote phy object
2706  *
2707  * Returns the slot id for the device pointed by the remote phy
2708  * object.
2709  *
2710  * Return: Valid slot ID on success or -ENXIO
2711  */
2712 static int
2713 mpi3mr_transport_get_bay_identifier(struct sas_rphy *rphy)
2714 {
2715         struct mpi3mr_ioc *mrioc = rphy_to_mrioc(rphy);
2716         struct mpi3mr_tgt_dev *tgtdev = NULL;
2717         unsigned long flags;
2718         int rc;
2719
2720         spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
2721         tgtdev = __mpi3mr_get_tgtdev_by_addr_and_rphy(mrioc,
2722             rphy->identify.sas_address, rphy);
2723         if (tgtdev) {
2724                 rc = tgtdev->slot;
2725                 mpi3mr_tgtdev_put(tgtdev);
2726         } else
2727                 rc = -ENXIO;
2728         spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
2729
2730         return rc;
2731 }
2732
2733 /* phy control request structure */
2734 struct phy_control_request {
2735         u8 smp_frame_type; /* 0x40 */
2736         u8 function; /* 0x91 */
2737         u8 allocated_response_length;
2738         u8 request_length; /* 0x09 */
2739         u16 expander_change_count;
2740         u8 reserved_1[3];
2741         u8 phy_identifier;
2742         u8 phy_operation;
2743         u8 reserved_2[13];
2744         u64 attached_device_name;
2745         u8 programmed_min_physical_link_rate;
2746         u8 programmed_max_physical_link_rate;
2747         u8 reserved_3[6];
2748 };
2749
2750 /* phy control reply structure */
2751 struct phy_control_reply {
2752         u8 smp_frame_type; /* 0x41 */
2753         u8 function; /* 0x11 */
2754         u8 function_result;
2755         u8 response_length;
2756 };
2757
2758 #define SMP_PHY_CONTROL_LINK_RESET      (0x01)
2759 #define SMP_PHY_CONTROL_HARD_RESET      (0x02)
2760 #define SMP_PHY_CONTROL_DISABLE         (0x03)
2761
2762 /**
2763  * mpi3mr_expander_phy_control - expander phy control
2764  * @mrioc: Adapter instance reference
2765  * @phy: The SAS transport layer phy object
2766  * @phy_operation: The phy operation to be executed
2767  *
2768  * Issues SMP passthru phy control request to execute a specific
2769  * phy operation for a given expander device.
2770  *
2771  * Return: 0 for success, non-zero for failure.
2772  */
2773 static int
2774 mpi3mr_expander_phy_control(struct mpi3mr_ioc *mrioc,
2775         struct sas_phy *phy, u8 phy_operation)
2776 {
2777         struct mpi3_smp_passthrough_request mpi_request;
2778         struct mpi3_smp_passthrough_reply mpi_reply;
2779         struct phy_control_request *phy_control_request;
2780         struct phy_control_reply *phy_control_reply;
2781         int rc;
2782         void *psge;
2783         void *data_out = NULL;
2784         dma_addr_t data_out_dma;
2785         dma_addr_t data_in_dma;
2786         size_t data_in_sz;
2787         size_t data_out_sz;
2788         u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
2789         u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
2790         u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
2791         u16 ioc_status;
2792         u16 sz;
2793
2794         if (mrioc->reset_in_progress) {
2795                 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
2796                 return -EFAULT;
2797         }
2798
2799         data_out_sz = sizeof(struct phy_control_request);
2800         data_in_sz = sizeof(struct phy_control_reply);
2801         sz = data_out_sz + data_in_sz;
2802         data_out = dma_alloc_coherent(&mrioc->pdev->dev, sz, &data_out_dma,
2803             GFP_KERNEL);
2804         if (!data_out) {
2805                 rc = -ENOMEM;
2806                 goto out;
2807         }
2808
2809         data_in_dma = data_out_dma + data_out_sz;
2810         phy_control_reply = data_out + data_out_sz;
2811
2812         rc = -EINVAL;
2813         memset(data_out, 0, sz);
2814
2815         phy_control_request = data_out;
2816         phy_control_request->smp_frame_type = 0x40;
2817         phy_control_request->function = 0x91;
2818         phy_control_request->request_length = 9;
2819         phy_control_request->allocated_response_length = 0;
2820         phy_control_request->phy_identifier = phy->number;
2821         phy_control_request->phy_operation = phy_operation;
2822         phy_control_request->programmed_min_physical_link_rate =
2823             phy->minimum_linkrate << 4;
2824         phy_control_request->programmed_max_physical_link_rate =
2825             phy->maximum_linkrate << 4;
2826
2827         memset(&mpi_request, 0, request_sz);
2828         memset(&mpi_reply, 0, reply_sz);
2829         mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2830         mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
2831         mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_sas_phy(phy);
2832         mpi_request.sas_address = cpu_to_le64(phy->identify.sas_address);
2833
2834         psge = &mpi_request.request_sge;
2835         mpi3mr_add_sg_single(psge, sgl_flags, data_out_sz, data_out_dma);
2836
2837         psge = &mpi_request.response_sge;
2838         mpi3mr_add_sg_single(psge, sgl_flags, data_in_sz, data_in_dma);
2839
2840         dprint_transport_info(mrioc,
2841             "sending phy control SMP request to sas_address(0x%016llx), phy_id(%d) opcode(%d)\n",
2842             (unsigned long long)phy->identify.sas_address, phy->number,
2843             phy_operation);
2844
2845         if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2846             &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status))
2847                 goto out;
2848
2849         dprint_transport_info(mrioc,
2850             "phy control SMP request completed with ioc_status(0x%04x)\n",
2851             ioc_status);
2852
2853         if (ioc_status == MPI3_IOCSTATUS_SUCCESS) {
2854                 dprint_transport_info(mrioc,
2855                     "phy control - reply data transfer size(%d)\n",
2856                     le16_to_cpu(mpi_reply.response_data_length));
2857
2858                 if (le16_to_cpu(mpi_reply.response_data_length) !=
2859                     sizeof(struct phy_control_reply))
2860                         goto out;
2861                 dprint_transport_info(mrioc,
2862                     "phy control - function_result(%d)\n",
2863                     phy_control_reply->function_result);
2864                 rc = 0;
2865         }
2866  out:
2867         if (data_out)
2868                 dma_free_coherent(&mrioc->pdev->dev, sz, data_out,
2869                     data_out_dma);
2870
2871         return rc;
2872 }
2873
2874 /**
2875  * mpi3mr_transport_phy_reset - Reset a given phy
2876  * @phy: The SAS transport layer phy object
2877  * @hard_reset: Flag to indicate the type of reset
2878  *
2879  * Return: 0 for success, non-zero for failure.
2880  */
2881 static int
2882 mpi3mr_transport_phy_reset(struct sas_phy *phy, int hard_reset)
2883 {
2884         struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2885         struct mpi3_iounit_control_request mpi_request;
2886         struct mpi3_iounit_control_reply mpi_reply;
2887         u16 request_sz = sizeof(struct mpi3_iounit_control_request);
2888         u16 reply_sz = sizeof(struct mpi3_iounit_control_reply);
2889         int rc = 0;
2890         u16 ioc_status;
2891
2892         rc = mpi3mr_parent_present(mrioc, phy);
2893         if (rc)
2894                 return rc;
2895
2896         /* handle expander phys */
2897         if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2898                 return mpi3mr_expander_phy_control(mrioc, phy,
2899                     (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
2900                     SMP_PHY_CONTROL_LINK_RESET);
2901
2902         /* handle hba phys */
2903         memset(&mpi_request, 0, request_sz);
2904         mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
2905         mpi_request.function = MPI3_FUNCTION_IO_UNIT_CONTROL;
2906         mpi_request.operation = MPI3_CTRL_OP_SAS_PHY_CONTROL;
2907         mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_ACTION_INDEX] =
2908                 (hard_reset ? MPI3_CTRL_ACTION_HARD_RESET :
2909                  MPI3_CTRL_ACTION_LINK_RESET);
2910         mpi_request.param8[MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_PHY_INDEX] =
2911                 phy->number;
2912
2913         dprint_transport_info(mrioc,
2914             "sending phy reset request to sas_address(0x%016llx), phy_id(%d) hard_reset(%d)\n",
2915             (unsigned long long)phy->identify.sas_address, phy->number,
2916             hard_reset);
2917
2918         if (mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
2919             &mpi_reply, reply_sz, MPI3MR_INTADMCMD_TIMEOUT, &ioc_status)) {
2920                 rc = -EAGAIN;
2921                 goto out;
2922         }
2923
2924         dprint_transport_info(mrioc,
2925             "phy reset request completed with ioc_status(0x%04x)\n",
2926             ioc_status);
2927 out:
2928         return rc;
2929 }
2930
2931 /**
2932  * mpi3mr_transport_phy_enable - enable/disable phys
2933  * @phy: The SAS transport layer phy object
2934  * @enable: flag to enable/disable, enable phy when true
2935  *
2936  * This function enables/disables a given by executing required
2937  * configuration page changes or expander phy control command
2938  *
2939  * Return: 0 for success, non-zero for failure.
2940  */
2941 static int
2942 mpi3mr_transport_phy_enable(struct sas_phy *phy, int enable)
2943 {
2944         struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
2945         struct mpi3_sas_io_unit_page0 *sas_io_unit_pg0 = NULL;
2946         struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
2947         u16 sz;
2948         int rc = 0;
2949         int i, discovery_active;
2950
2951         rc = mpi3mr_parent_present(mrioc, phy);
2952         if (rc)
2953                 return rc;
2954
2955         /* handle expander phys */
2956         if (phy->identify.sas_address != mrioc->sas_hba.sas_address)
2957                 return mpi3mr_expander_phy_control(mrioc, phy,
2958                     (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
2959                     SMP_PHY_CONTROL_DISABLE);
2960
2961         /* handle hba phys */
2962         sz = offsetof(struct mpi3_sas_io_unit_page0, phy_data) +
2963                 (mrioc->sas_hba.num_phys *
2964                  sizeof(struct mpi3_sas_io_unit0_phy_data));
2965         sas_io_unit_pg0 = kzalloc(sz, GFP_KERNEL);
2966         if (!sas_io_unit_pg0) {
2967                 rc = -ENOMEM;
2968                 goto out;
2969         }
2970         if (mpi3mr_cfg_get_sas_io_unit_pg0(mrioc, sas_io_unit_pg0, sz)) {
2971                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2972                     __FILE__, __LINE__, __func__);
2973                 rc = -ENXIO;
2974                 goto out;
2975         }
2976
2977         /* unable to enable/disable phys when discovery is active */
2978         for (i = 0, discovery_active = 0; i < mrioc->sas_hba.num_phys ; i++) {
2979                 if (sas_io_unit_pg0->phy_data[i].port_flags &
2980                     MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS) {
2981                         ioc_err(mrioc,
2982                             "discovery is active on port = %d, phy = %d\n"
2983                             "\tunable to enable/disable phys, try again later!\n",
2984                             sas_io_unit_pg0->phy_data[i].io_unit_port, i);
2985                         discovery_active = 1;
2986                 }
2987         }
2988
2989         if (discovery_active) {
2990                 rc = -EAGAIN;
2991                 goto out;
2992         }
2993
2994         if ((sas_io_unit_pg0->phy_data[phy->number].phy_flags &
2995              (MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY |
2996               MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY))) {
2997                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
2998                     __FILE__, __LINE__, __func__);
2999                 rc = -ENXIO;
3000                 goto out;
3001         }
3002
3003         /* read sas_iounit page 1 */
3004         sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3005                 (mrioc->sas_hba.num_phys *
3006                  sizeof(struct mpi3_sas_io_unit1_phy_data));
3007         sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3008         if (!sas_io_unit_pg1) {
3009                 rc = -ENOMEM;
3010                 goto out;
3011         }
3012
3013         if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3014                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3015                     __FILE__, __LINE__, __func__);
3016                 rc = -ENXIO;
3017                 goto out;
3018         }
3019
3020         if (enable)
3021                 sas_io_unit_pg1->phy_data[phy->number].phy_flags
3022                     &= ~MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3023         else
3024                 sas_io_unit_pg1->phy_data[phy->number].phy_flags
3025                     |= MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
3026
3027         mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz);
3028
3029         /* link reset */
3030         if (enable)
3031                 mpi3mr_transport_phy_reset(phy, 0);
3032
3033  out:
3034         kfree(sas_io_unit_pg1);
3035         kfree(sas_io_unit_pg0);
3036         return rc;
3037 }
3038
3039 /**
3040  * mpi3mr_transport_phy_speed - set phy min/max speed
3041  * @phy: The SAS transport later phy object
3042  * @rates: Rates defined as in sas_phy_linkrates
3043  *
3044  * This function sets the link rates given in the rates
3045  * argument to the given phy by executing required configuration
3046  * page changes or expander phy control command
3047  *
3048  * Return: 0 for success, non-zero for failure.
3049  */
3050 static int
3051 mpi3mr_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
3052 {
3053         struct mpi3mr_ioc *mrioc = phy_to_mrioc(phy);
3054         struct mpi3_sas_io_unit_page1 *sas_io_unit_pg1 = NULL;
3055         struct mpi3_sas_phy_page0 phy_pg0;
3056         u16 sz, ioc_status;
3057         int rc = 0;
3058
3059         rc = mpi3mr_parent_present(mrioc, phy);
3060         if (rc)
3061                 return rc;
3062
3063         if (!rates->minimum_linkrate)
3064                 rates->minimum_linkrate = phy->minimum_linkrate;
3065         else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
3066                 rates->minimum_linkrate = phy->minimum_linkrate_hw;
3067
3068         if (!rates->maximum_linkrate)
3069                 rates->maximum_linkrate = phy->maximum_linkrate;
3070         else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
3071                 rates->maximum_linkrate = phy->maximum_linkrate_hw;
3072
3073         /* handle expander phys */
3074         if (phy->identify.sas_address != mrioc->sas_hba.sas_address) {
3075                 phy->minimum_linkrate = rates->minimum_linkrate;
3076                 phy->maximum_linkrate = rates->maximum_linkrate;
3077                 return mpi3mr_expander_phy_control(mrioc, phy,
3078                     SMP_PHY_CONTROL_LINK_RESET);
3079         }
3080
3081         /* handle hba phys */
3082         sz = offsetof(struct mpi3_sas_io_unit_page1, phy_data) +
3083                 (mrioc->sas_hba.num_phys *
3084                  sizeof(struct mpi3_sas_io_unit1_phy_data));
3085         sas_io_unit_pg1 = kzalloc(sz, GFP_KERNEL);
3086         if (!sas_io_unit_pg1) {
3087                 rc = -ENOMEM;
3088                 goto out;
3089         }
3090
3091         if (mpi3mr_cfg_get_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3092                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3093                     __FILE__, __LINE__, __func__);
3094                 rc = -ENXIO;
3095                 goto out;
3096         }
3097
3098         sas_io_unit_pg1->phy_data[phy->number].max_min_link_rate =
3099                 (rates->minimum_linkrate + (rates->maximum_linkrate << 4));
3100
3101         if (mpi3mr_cfg_set_sas_io_unit_pg1(mrioc, sas_io_unit_pg1, sz)) {
3102                 ioc_err(mrioc, "failure at %s:%d/%s()!\n",
3103                     __FILE__, __LINE__, __func__);
3104                 rc = -ENXIO;
3105                 goto out;
3106         }
3107
3108         /* link reset */
3109         mpi3mr_transport_phy_reset(phy, 0);
3110
3111         /* read phy page 0, then update the rates in the sas transport phy */
3112         if (!mpi3mr_cfg_get_sas_phy_pg0(mrioc, &ioc_status, &phy_pg0,
3113             sizeof(struct mpi3_sas_phy_page0),
3114             MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER, phy->number) &&
3115             (ioc_status == MPI3_IOCSTATUS_SUCCESS)) {
3116                 phy->minimum_linkrate = mpi3mr_convert_phy_link_rate(
3117                     phy_pg0.programmed_link_rate &
3118                     MPI3_SAS_PRATE_MIN_RATE_MASK);
3119                 phy->maximum_linkrate = mpi3mr_convert_phy_link_rate(
3120                     phy_pg0.programmed_link_rate >> 4);
3121                 phy->negotiated_linkrate =
3122                         mpi3mr_convert_phy_link_rate(
3123                             (phy_pg0.negotiated_link_rate &
3124                             MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK)
3125                             >> MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT);
3126         }
3127
3128 out:
3129         kfree(sas_io_unit_pg1);
3130         return rc;
3131 }
3132
3133 /**
3134  * mpi3mr_map_smp_buffer - map BSG dma buffer
3135  * @dev: Generic device reference
3136  * @buf: BSG buffer pointer
3137  * @dma_addr: Physical address holder
3138  * @dma_len: Mapped DMA buffer length.
3139  * @p: Virtual address holder
3140  *
3141  * This function maps the DMAable buffer
3142  *
3143  * Return: 0 on success, non-zero on failure
3144  */
3145 static int
3146 mpi3mr_map_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3147                 dma_addr_t *dma_addr, size_t *dma_len, void **p)
3148 {
3149         /* Check if the request is split across multiple segments */
3150         if (buf->sg_cnt > 1) {
3151                 *p = dma_alloc_coherent(dev, buf->payload_len, dma_addr,
3152                                 GFP_KERNEL);
3153                 if (!*p)
3154                         return -ENOMEM;
3155                 *dma_len = buf->payload_len;
3156         } else {
3157                 if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
3158                         return -ENOMEM;
3159                 *dma_addr = sg_dma_address(buf->sg_list);
3160                 *dma_len = sg_dma_len(buf->sg_list);
3161                 *p = NULL;
3162         }
3163
3164         return 0;
3165 }
3166
3167 /**
3168  * mpi3mr_unmap_smp_buffer - unmap BSG dma buffer
3169  * @dev: Generic device reference
3170  * @buf: BSG buffer pointer
3171  * @dma_addr: Physical address to be unmapped
3172  * @p: Virtual address
3173  *
3174  * This function unmaps the DMAable buffer
3175  */
3176 static void
3177 mpi3mr_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf,
3178                 dma_addr_t dma_addr, void *p)
3179 {
3180         if (p)
3181                 dma_free_coherent(dev, buf->payload_len, p, dma_addr);
3182         else
3183                 dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL);
3184 }
3185
3186 /**
3187  * mpi3mr_transport_smp_handler - handler for smp passthru
3188  * @job: BSG job reference
3189  * @shost: SCSI host object reference
3190  * @rphy: SAS transport rphy object pointing the expander
3191  *
3192  * This is used primarily by smp utils for sending the SMP
3193  * commands to the expanders attached to the controller
3194  */
3195 static void
3196 mpi3mr_transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
3197         struct sas_rphy *rphy)
3198 {
3199         struct mpi3mr_ioc *mrioc = shost_priv(shost);
3200         struct mpi3_smp_passthrough_request mpi_request;
3201         struct mpi3_smp_passthrough_reply mpi_reply;
3202         int rc;
3203         void *psge;
3204         dma_addr_t dma_addr_in;
3205         dma_addr_t dma_addr_out;
3206         void *addr_in = NULL;
3207         void *addr_out = NULL;
3208         size_t dma_len_in;
3209         size_t dma_len_out;
3210         unsigned int reslen = 0;
3211         u16 request_sz = sizeof(struct mpi3_smp_passthrough_request);
3212         u16 reply_sz = sizeof(struct mpi3_smp_passthrough_reply);
3213         u8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST;
3214         u16 ioc_status;
3215
3216         if (mrioc->reset_in_progress) {
3217                 ioc_err(mrioc, "%s: host reset in progress!\n", __func__);
3218                 rc = -EFAULT;
3219                 goto out;
3220         }
3221
3222         rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3223             &dma_addr_out, &dma_len_out, &addr_out);
3224         if (rc)
3225                 goto out;
3226
3227         if (addr_out)
3228                 sg_copy_to_buffer(job->request_payload.sg_list,
3229                     job->request_payload.sg_cnt, addr_out,
3230                     job->request_payload.payload_len);
3231
3232         rc = mpi3mr_map_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3233                         &dma_addr_in, &dma_len_in, &addr_in);
3234         if (rc)
3235                 goto unmap_out;
3236
3237         memset(&mpi_request, 0, request_sz);
3238         memset(&mpi_reply, 0, reply_sz);
3239         mpi_request.host_tag = cpu_to_le16(MPI3MR_HOSTTAG_TRANSPORT_CMDS);
3240         mpi_request.function = MPI3_FUNCTION_SMP_PASSTHROUGH;
3241         mpi_request.io_unit_port = (u8) mpi3mr_get_port_id_by_rphy(mrioc, rphy);
3242         mpi_request.sas_address = ((rphy) ?
3243             cpu_to_le64(rphy->identify.sas_address) :
3244             cpu_to_le64(mrioc->sas_hba.sas_address));
3245         psge = &mpi_request.request_sge;
3246         mpi3mr_add_sg_single(psge, sgl_flags, dma_len_out - 4, dma_addr_out);
3247
3248         psge = &mpi_request.response_sge;
3249         mpi3mr_add_sg_single(psge, sgl_flags, dma_len_in - 4, dma_addr_in);
3250
3251         dprint_transport_info(mrioc, "sending SMP request\n");
3252
3253         rc = mpi3mr_post_transport_req(mrioc, &mpi_request, request_sz,
3254                                        &mpi_reply, reply_sz,
3255                                        MPI3MR_INTADMCMD_TIMEOUT, &ioc_status);
3256         if (rc)
3257                 goto unmap_in;
3258
3259         dprint_transport_info(mrioc,
3260             "SMP request completed with ioc_status(0x%04x)\n", ioc_status);
3261
3262         dprint_transport_info(mrioc,
3263                     "SMP request - reply data transfer size(%d)\n",
3264                     le16_to_cpu(mpi_reply.response_data_length));
3265
3266         memcpy(job->reply, &mpi_reply, reply_sz);
3267         job->reply_len = reply_sz;
3268         reslen = le16_to_cpu(mpi_reply.response_data_length);
3269
3270         if (addr_in)
3271                 sg_copy_from_buffer(job->reply_payload.sg_list,
3272                                 job->reply_payload.sg_cnt, addr_in,
3273                                 job->reply_payload.payload_len);
3274
3275         rc = 0;
3276 unmap_in:
3277         mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->reply_payload,
3278                         dma_addr_in, addr_in);
3279 unmap_out:
3280         mpi3mr_unmap_smp_buffer(&mrioc->pdev->dev, &job->request_payload,
3281                         dma_addr_out, addr_out);
3282 out:
3283         bsg_job_done(job, rc, reslen);
3284 }
3285
3286 struct sas_function_template mpi3mr_transport_functions = {
3287         .get_linkerrors         = mpi3mr_transport_get_linkerrors,
3288         .get_enclosure_identifier = mpi3mr_transport_get_enclosure_identifier,
3289         .get_bay_identifier     = mpi3mr_transport_get_bay_identifier,
3290         .phy_reset              = mpi3mr_transport_phy_reset,
3291         .phy_enable             = mpi3mr_transport_phy_enable,
3292         .set_phy_speed          = mpi3mr_transport_phy_speed,
3293         .smp_handler            = mpi3mr_transport_smp_handler,
3294 };
3295
3296 struct scsi_transport_template *mpi3mr_transport_template;