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