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