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