Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
[linux-2.6] / drivers / scsi / mpt2sas / mpt2sas_transport.c
1 /*
2  * SAS Transport Layer for MPT (Message Passing Technology) based controllers
3  *
4  * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c
5  * Copyright (C) 2007-2008  LSI Corporation
6  *  (mailto:DL-MPTFusionLinux@lsi.com)
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * NO WARRANTY
19  * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
20  * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
21  * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
22  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
23  * solely responsible for determining the appropriateness of using and
24  * distributing the Program and assumes all risks associated with its
25  * exercise of rights under this Agreement, including but not limited to
26  * the risks and costs of program errors, damage to or loss of data,
27  * programs or equipment, and unavailability or interruption of operations.
28
29  * DISCLAIMER OF LIABILITY
30  * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
31  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
33  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35  * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
36  * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
37
38  * You should have received a copy of the GNU General Public License
39  * along with this program; if not, write to the Free Software
40  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
41  * USA.
42  */
43
44 #include <linux/module.h>
45 #include <linux/kernel.h>
46 #include <linux/init.h>
47 #include <linux/errno.h>
48 #include <linux/sched.h>
49 #include <linux/workqueue.h>
50 #include <linux/delay.h>
51 #include <linux/pci.h>
52
53 #include <scsi/scsi.h>
54 #include <scsi/scsi_cmnd.h>
55 #include <scsi/scsi_device.h>
56 #include <scsi/scsi_host.h>
57 #include <scsi/scsi_transport_sas.h>
58 #include <scsi/scsi_dbg.h>
59
60 #include "mpt2sas_base.h"
61 /**
62  * _transport_sas_node_find_by_handle - sas node search
63  * @ioc: per adapter object
64  * @handle: expander or hba handle (assigned by firmware)
65  * Context: Calling function should acquire ioc->sas_node_lock.
66  *
67  * Search for either hba phys or expander device based on handle, then returns
68  * the sas_node object.
69  */
70 static struct _sas_node *
71 _transport_sas_node_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
72 {
73         int i;
74
75         for (i = 0; i < ioc->sas_hba.num_phys; i++)
76                 if (ioc->sas_hba.phy[i].handle == handle)
77                         return &ioc->sas_hba;
78
79         return mpt2sas_scsih_expander_find_by_handle(ioc, handle);
80 }
81
82 /**
83  * _transport_convert_phy_link_rate -
84  * @link_rate: link rate returned from mpt firmware
85  *
86  * Convert link_rate from mpi fusion into sas_transport form.
87  */
88 static enum sas_linkrate
89 _transport_convert_phy_link_rate(u8 link_rate)
90 {
91         enum sas_linkrate rc;
92
93         switch (link_rate) {
94         case MPI2_SAS_NEG_LINK_RATE_1_5:
95                 rc = SAS_LINK_RATE_1_5_GBPS;
96                 break;
97         case MPI2_SAS_NEG_LINK_RATE_3_0:
98                 rc = SAS_LINK_RATE_3_0_GBPS;
99                 break;
100         case MPI2_SAS_NEG_LINK_RATE_6_0:
101                 rc = SAS_LINK_RATE_6_0_GBPS;
102                 break;
103         case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED:
104                 rc = SAS_PHY_DISABLED;
105                 break;
106         case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
107                 rc = SAS_LINK_RATE_FAILED;
108                 break;
109         case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR:
110                 rc = SAS_SATA_PORT_SELECTOR;
111                 break;
112         case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
113                 rc = SAS_PHY_RESET_IN_PROGRESS;
114                 break;
115         default:
116         case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
117         case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
118                 rc = SAS_LINK_RATE_UNKNOWN;
119                 break;
120         }
121         return rc;
122 }
123
124 /**
125  * _transport_set_identify - set identify for phys and end devices
126  * @ioc: per adapter object
127  * @handle: device handle
128  * @identify: sas identify info
129  *
130  * Populates sas identify info.
131  *
132  * Returns 0 for success, non-zero for failure.
133  */
134 static int
135 _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
136     struct sas_identify *identify)
137 {
138         Mpi2SasDevicePage0_t sas_device_pg0;
139         Mpi2ConfigReply_t mpi_reply;
140         u32 device_info;
141         u32 ioc_status;
142
143         if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
144             MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
145                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
146                     ioc->name, __FILE__, __LINE__, __func__);
147                 return -1;
148         }
149
150         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
151             MPI2_IOCSTATUS_MASK;
152         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
153                 printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
154                     "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
155                      __FILE__, __LINE__, __func__);
156                 return -1;
157         }
158
159         memset(identify, 0, sizeof(identify));
160         device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
161
162         /* sas_address */
163         identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
164
165         /* device_type */
166         switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
167         case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
168                 identify->device_type = SAS_PHY_UNUSED;
169                 break;
170         case MPI2_SAS_DEVICE_INFO_END_DEVICE:
171                 identify->device_type = SAS_END_DEVICE;
172                 break;
173         case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER:
174                 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
175                 break;
176         case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER:
177                 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
178                 break;
179         }
180
181         /* initiator_port_protocols */
182         if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR)
183                 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
184         if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR)
185                 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
186         if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR)
187                 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
188         if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST)
189                 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
190
191         /* target_port_protocols */
192         if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
193                 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
194         if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
195                 identify->target_port_protocols |= SAS_PROTOCOL_STP;
196         if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET)
197                 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
198         if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
199                 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
200
201         return 0;
202 }
203
204 /**
205  * mpt2sas_transport_done -  internal transport layer callback handler.
206  * @ioc: per adapter object
207  * @smid: system request message index
208  * @VF_ID: virtual function id
209  * @reply: reply message frame(lower 32bit addr)
210  *
211  * Callback handler when sending internal generated transport cmds.
212  * The callback index passed is `ioc->transport_cb_idx`
213  *
214  * Return nothing.
215  */
216 void
217 mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
218     u32 reply)
219 {
220         MPI2DefaultReply_t *mpi_reply;
221
222         mpi_reply =  mpt2sas_base_get_reply_virt_addr(ioc, reply);
223         if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED)
224                 return;
225         if (ioc->transport_cmds.smid != smid)
226                 return;
227         ioc->transport_cmds.status |= MPT2_CMD_COMPLETE;
228         if (mpi_reply) {
229                 memcpy(ioc->transport_cmds.reply, mpi_reply,
230                     mpi_reply->MsgLength*4);
231                 ioc->transport_cmds.status |= MPT2_CMD_REPLY_VALID;
232         }
233         ioc->transport_cmds.status &= ~MPT2_CMD_PENDING;
234         complete(&ioc->transport_cmds.done);
235 }
236
237 /* report manufacture request structure */
238 struct rep_manu_request{
239         u8 smp_frame_type;
240         u8 function;
241         u8 reserved;
242         u8 request_length;
243 };
244
245 /* report manufacture reply structure */
246 struct rep_manu_reply{
247         u8 smp_frame_type; /* 0x41 */
248         u8 function; /* 0x01 */
249         u8 function_result;
250         u8 response_length;
251         u16 expander_change_count;
252         u8 reserved0[2];
253         u8 sas_format:1;
254         u8 reserved1:7;
255         u8 reserved2[3];
256         u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
257         u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
258         u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
259         u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
260         u16 component_id;
261         u8 component_revision_id;
262         u8 reserved3;
263         u8 vendor_specific[8];
264 };
265
266 /**
267  * transport_expander_report_manufacture - obtain SMP report_manufacture
268  * @ioc: per adapter object
269  * @sas_address: expander sas address
270  * @edev: the sas_expander_device object
271  *
272  * Fills in the sas_expander_device object when SMP port is created.
273  *
274  * Returns 0 for success, non-zero for failure.
275  */
276 static int
277 transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
278     u64 sas_address, struct sas_expander_device *edev)
279 {
280         Mpi2SmpPassthroughRequest_t *mpi_request;
281         Mpi2SmpPassthroughReply_t *mpi_reply;
282         struct rep_manu_reply *manufacture_reply;
283         struct rep_manu_request *manufacture_request;
284         int rc;
285         u16 smid;
286         u32 ioc_state;
287         unsigned long timeleft;
288         void *psge;
289         u32 sgl_flags;
290         u8 issue_reset = 0;
291         unsigned long flags;
292         void *data_out = NULL;
293         dma_addr_t data_out_dma;
294         u32 sz;
295         u64 *sas_address_le;
296         u16 wait_state_count;
297
298         spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
299         if (ioc->ioc_reset_in_progress) {
300                 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
301                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
302                     __func__, ioc->name);
303                 return -EFAULT;
304         }
305         spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
306
307         mutex_lock(&ioc->transport_cmds.mutex);
308
309         if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
310                 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
311                     ioc->name, __func__);
312                 rc = -EAGAIN;
313                 goto out;
314         }
315         ioc->transport_cmds.status = MPT2_CMD_PENDING;
316
317         wait_state_count = 0;
318         ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
319         while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
320                 if (wait_state_count++ == 10) {
321                         printk(MPT2SAS_ERR_FMT
322                             "%s: failed due to ioc not operational\n",
323                             ioc->name, __func__);
324                         rc = -EFAULT;
325                         goto out;
326                 }
327                 ssleep(1);
328                 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
329                 printk(MPT2SAS_INFO_FMT "%s: waiting for "
330                     "operational state(count=%d)\n", ioc->name,
331                     __func__, wait_state_count);
332         }
333         if (wait_state_count)
334                 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
335                     ioc->name, __func__);
336
337         smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
338         if (!smid) {
339                 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
340                     ioc->name, __func__);
341                 rc = -EAGAIN;
342                 goto out;
343         }
344
345         rc = 0;
346         mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
347         ioc->transport_cmds.smid = smid;
348
349         sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
350         data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
351
352         if (!data_out) {
353                 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
354                     __LINE__, __func__);
355                 rc = -ENOMEM;
356                 mpt2sas_base_free_smid(ioc, smid);
357                 goto out;
358         }
359
360         manufacture_request = data_out;
361         manufacture_request->smp_frame_type = 0x40;
362         manufacture_request->function = 1;
363         manufacture_request->reserved = 0;
364         manufacture_request->request_length = 0;
365
366         memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
367         mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
368         mpi_request->PhysicalPort = 0xFF;
369         sas_address_le = (u64 *)&mpi_request->SASAddress;
370         *sas_address_le = cpu_to_le64(sas_address);
371         mpi_request->RequestDataLength = sizeof(struct rep_manu_request);
372         psge = &mpi_request->SGL;
373
374         /* WRITE sgel first */
375         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
376             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
377         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
378         ioc->base_add_sg_single(psge, sgl_flags |
379             sizeof(struct rep_manu_request), data_out_dma);
380
381         /* incr sgel */
382         psge += ioc->sge_size;
383
384         /* READ sgel last */
385         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
386             MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
387             MPI2_SGE_FLAGS_END_OF_LIST);
388         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
389         ioc->base_add_sg_single(psge, sgl_flags |
390             sizeof(struct rep_manu_reply), data_out_dma +
391             sizeof(struct rep_manu_request));
392
393         dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - "
394             "send to sas_addr(0x%016llx)\n", ioc->name,
395             (unsigned long long)sas_address));
396         mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */);
397         timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
398             10*HZ);
399
400         if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
401                 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
402                     ioc->name, __func__);
403                 _debug_dump_mf(mpi_request,
404                     sizeof(Mpi2SmpPassthroughRequest_t)/4);
405                 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
406                         issue_reset = 1;
407                 goto issue_host_reset;
408         }
409
410         dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - "
411             "complete\n", ioc->name));
412
413         if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
414                 u8 *tmp;
415
416                 mpi_reply = ioc->transport_cmds.reply;
417
418                 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
419                     "report_manufacture - reply data transfer size(%d)\n",
420                     ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
421
422                 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
423                     sizeof(struct rep_manu_reply))
424                         goto out;
425
426                 manufacture_reply = data_out + sizeof(struct rep_manu_request);
427                 strncpy(edev->vendor_id, manufacture_reply->vendor_id,
428                      SAS_EXPANDER_VENDOR_ID_LEN);
429                 strncpy(edev->product_id, manufacture_reply->product_id,
430                      SAS_EXPANDER_PRODUCT_ID_LEN);
431                 strncpy(edev->product_rev, manufacture_reply->product_rev,
432                      SAS_EXPANDER_PRODUCT_REV_LEN);
433                 edev->level = manufacture_reply->sas_format;
434                 if (manufacture_reply->sas_format) {
435                         strncpy(edev->component_vendor_id,
436                             manufacture_reply->component_vendor_id,
437                              SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
438                         tmp = (u8 *)&manufacture_reply->component_id;
439                         edev->component_id = tmp[0] << 8 | tmp[1];
440                         edev->component_revision_id =
441                             manufacture_reply->component_revision_id;
442                 }
443         } else
444                 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
445                     "report_manufacture - no reply\n", ioc->name));
446
447  issue_host_reset:
448         if (issue_reset)
449                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
450                     FORCE_BIG_HAMMER);
451  out:
452         ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
453         if (data_out)
454                 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
455
456         mutex_unlock(&ioc->transport_cmds.mutex);
457         return rc;
458 }
459
460 /**
461  * mpt2sas_transport_port_add - insert port to the list
462  * @ioc: per adapter object
463  * @handle: handle of attached device
464  * @parent_handle: parent handle(either hba or expander)
465  * Context: This function will acquire ioc->sas_node_lock.
466  *
467  * Adding new port object to the sas_node->sas_port_list.
468  *
469  * Returns mpt2sas_port.
470  */
471 struct _sas_port *
472 mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
473     u16 parent_handle)
474 {
475         struct _sas_phy *mpt2sas_phy, *next;
476         struct _sas_port *mpt2sas_port;
477         unsigned long flags;
478         struct _sas_node *sas_node;
479         struct sas_rphy *rphy;
480         int i;
481         struct sas_port *port;
482
483         if (!parent_handle)
484                 return NULL;
485
486         mpt2sas_port = kzalloc(sizeof(struct _sas_port),
487             GFP_KERNEL);
488         if (!mpt2sas_port) {
489                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
490                     ioc->name, __FILE__, __LINE__, __func__);
491                 return NULL;
492         }
493
494         INIT_LIST_HEAD(&mpt2sas_port->port_list);
495         INIT_LIST_HEAD(&mpt2sas_port->phy_list);
496         spin_lock_irqsave(&ioc->sas_node_lock, flags);
497         sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle);
498         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
499
500         if (!sas_node) {
501                 printk(MPT2SAS_ERR_FMT "%s: Could not find parent(0x%04x)!\n",
502                     ioc->name, __func__, parent_handle);
503                 goto out_fail;
504         }
505
506         mpt2sas_port->handle = parent_handle;
507         mpt2sas_port->sas_address = sas_node->sas_address;
508         if ((_transport_set_identify(ioc, handle,
509             &mpt2sas_port->remote_identify))) {
510                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
511                     ioc->name, __FILE__, __LINE__, __func__);
512                 goto out_fail;
513         }
514
515         if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
516                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
517                     ioc->name, __FILE__, __LINE__, __func__);
518                 goto out_fail;
519         }
520
521         for (i = 0; i < sas_node->num_phys; i++) {
522                 if (sas_node->phy[i].remote_identify.sas_address !=
523                     mpt2sas_port->remote_identify.sas_address)
524                         continue;
525                 list_add_tail(&sas_node->phy[i].port_siblings,
526                     &mpt2sas_port->phy_list);
527                 mpt2sas_port->num_phys++;
528         }
529
530         if (!mpt2sas_port->num_phys) {
531                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
532                     ioc->name, __FILE__, __LINE__, __func__);
533                 goto out_fail;
534         }
535
536         port = sas_port_alloc_num(sas_node->parent_dev);
537         if ((sas_port_add(port))) {
538                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
539                     ioc->name, __FILE__, __LINE__, __func__);
540                 goto out_fail;
541         }
542
543         list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
544             port_siblings) {
545                 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
546                         dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
547                             ", sas_addr(0x%016llx), phy(%d)\n", handle,
548                             (unsigned long long)
549                             mpt2sas_port->remote_identify.sas_address,
550                             mpt2sas_phy->phy_id);
551                 sas_port_add_phy(port, mpt2sas_phy->phy);
552         }
553
554         mpt2sas_port->port = port;
555         if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
556                 rphy = sas_end_device_alloc(port);
557         else
558                 rphy = sas_expander_alloc(port,
559                     mpt2sas_port->remote_identify.device_type);
560
561         rphy->identify = mpt2sas_port->remote_identify;
562         if ((sas_rphy_add(rphy))) {
563                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
564                     ioc->name, __FILE__, __LINE__, __func__);
565         }
566         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
567                 dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
568                     "sas_addr(0x%016llx)\n", handle,
569                     (unsigned long long)
570                     mpt2sas_port->remote_identify.sas_address);
571         mpt2sas_port->rphy = rphy;
572         spin_lock_irqsave(&ioc->sas_node_lock, flags);
573         list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
574         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
575
576         /* fill in report manufacture */
577         if (mpt2sas_port->remote_identify.device_type ==
578             MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
579             mpt2sas_port->remote_identify.device_type ==
580             MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
581                 transport_expander_report_manufacture(ioc,
582                     mpt2sas_port->remote_identify.sas_address,
583                     rphy_to_expander_device(rphy));
584
585         return mpt2sas_port;
586
587  out_fail:
588         list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
589             port_siblings)
590                 list_del(&mpt2sas_phy->port_siblings);
591         kfree(mpt2sas_port);
592         return NULL;
593 }
594
595 /**
596  * mpt2sas_transport_port_remove - remove port from the list
597  * @ioc: per adapter object
598  * @sas_address: sas address of attached device
599  * @parent_handle: handle to the upstream parent(either hba or expander)
600  * Context: This function will acquire ioc->sas_node_lock.
601  *
602  * Removing object and freeing associated memory from the
603  * ioc->sas_port_list.
604  *
605  * Return nothing.
606  */
607 void
608 mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
609     u16 parent_handle)
610 {
611         int i;
612         unsigned long flags;
613         struct _sas_port *mpt2sas_port, *next;
614         struct _sas_node *sas_node;
615         u8 found = 0;
616         struct _sas_phy *mpt2sas_phy, *next_phy;
617
618         spin_lock_irqsave(&ioc->sas_node_lock, flags);
619         sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle);
620         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
621         if (!sas_node)
622                 return;
623         list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
624             port_list) {
625                 if (mpt2sas_port->remote_identify.sas_address != sas_address)
626                         continue;
627                 found = 1;
628                 list_del(&mpt2sas_port->port_list);
629                 goto out;
630         }
631  out:
632         if (!found)
633                 return;
634
635         for (i = 0; i < sas_node->num_phys; i++) {
636                 if (sas_node->phy[i].remote_identify.sas_address == sas_address)
637                         memset(&sas_node->phy[i].remote_identify, 0 ,
638                             sizeof(struct sas_identify));
639         }
640
641         list_for_each_entry_safe(mpt2sas_phy, next_phy,
642             &mpt2sas_port->phy_list, port_siblings) {
643                 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
644                         dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
645                             "remove: parent_handle(0x%04x), "
646                             "sas_addr(0x%016llx), phy(%d)\n", parent_handle,
647                             (unsigned long long)
648                             mpt2sas_port->remote_identify.sas_address,
649                             mpt2sas_phy->phy_id);
650                 sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
651                 list_del(&mpt2sas_phy->port_siblings);
652         }
653         sas_port_delete(mpt2sas_port->port);
654         kfree(mpt2sas_port);
655 }
656
657 /**
658  * mpt2sas_transport_add_host_phy - report sas_host phy to transport
659  * @ioc: per adapter object
660  * @mpt2sas_phy: mpt2sas per phy object
661  * @phy_pg0: sas phy page 0
662  * @parent_dev: parent device class object
663  *
664  * Returns 0 for success, non-zero for failure.
665  */
666 int
667 mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
668     *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
669 {
670         struct sas_phy *phy;
671         int phy_index = mpt2sas_phy->phy_id;
672
673
674         INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
675         phy = sas_phy_alloc(parent_dev, phy_index);
676         if (!phy) {
677                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
678                     ioc->name, __FILE__, __LINE__, __func__);
679                 return -1;
680         }
681         if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
682             &mpt2sas_phy->identify))) {
683                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
684                     ioc->name, __FILE__, __LINE__, __func__);
685                 return -1;
686         }
687         phy->identify = mpt2sas_phy->identify;
688         mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
689         if (mpt2sas_phy->attached_handle)
690                 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
691                     &mpt2sas_phy->remote_identify);
692         phy->identify.phy_identifier = mpt2sas_phy->phy_id;
693         phy->negotiated_linkrate = _transport_convert_phy_link_rate(
694             phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
695         phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
696             phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
697         phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
698             phy_pg0.HwLinkRate >> 4);
699         phy->minimum_linkrate = _transport_convert_phy_link_rate(
700             phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
701         phy->maximum_linkrate = _transport_convert_phy_link_rate(
702             phy_pg0.ProgrammedLinkRate >> 4);
703
704         if ((sas_phy_add(phy))) {
705                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
706                     ioc->name, __FILE__, __LINE__, __func__);
707                 sas_phy_free(phy);
708                 return -1;
709         }
710         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
711                 dev_printk(KERN_INFO, &phy->dev,
712                     "add: handle(0x%04x), sas_addr(0x%016llx)\n"
713                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
714                     mpt2sas_phy->handle, (unsigned long long)
715                     mpt2sas_phy->identify.sas_address,
716                     mpt2sas_phy->attached_handle,
717                     (unsigned long long)
718                     mpt2sas_phy->remote_identify.sas_address);
719         mpt2sas_phy->phy = phy;
720         return 0;
721 }
722
723
724 /**
725  * mpt2sas_transport_add_expander_phy - report expander phy to transport
726  * @ioc: per adapter object
727  * @mpt2sas_phy: mpt2sas per phy object
728  * @expander_pg1: expander page 1
729  * @parent_dev: parent device class object
730  *
731  * Returns 0 for success, non-zero for failure.
732  */
733 int
734 mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
735     *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
736 {
737         struct sas_phy *phy;
738         int phy_index = mpt2sas_phy->phy_id;
739
740         INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
741         phy = sas_phy_alloc(parent_dev, phy_index);
742         if (!phy) {
743                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
744                     ioc->name, __FILE__, __LINE__, __func__);
745                 return -1;
746         }
747         if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
748             &mpt2sas_phy->identify))) {
749                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
750                     ioc->name, __FILE__, __LINE__, __func__);
751                 return -1;
752         }
753         phy->identify = mpt2sas_phy->identify;
754         mpt2sas_phy->attached_handle =
755             le16_to_cpu(expander_pg1.AttachedDevHandle);
756         if (mpt2sas_phy->attached_handle)
757                 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
758                     &mpt2sas_phy->remote_identify);
759         phy->identify.phy_identifier = mpt2sas_phy->phy_id;
760         phy->negotiated_linkrate = _transport_convert_phy_link_rate(
761             expander_pg1.NegotiatedLinkRate &
762             MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
763         phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
764             expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
765         phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
766             expander_pg1.HwLinkRate >> 4);
767         phy->minimum_linkrate = _transport_convert_phy_link_rate(
768             expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
769         phy->maximum_linkrate = _transport_convert_phy_link_rate(
770             expander_pg1.ProgrammedLinkRate >> 4);
771
772         if ((sas_phy_add(phy))) {
773                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
774                     ioc->name, __FILE__, __LINE__, __func__);
775                 sas_phy_free(phy);
776                 return -1;
777         }
778         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
779                 dev_printk(KERN_INFO, &phy->dev,
780                     "add: handle(0x%04x), sas_addr(0x%016llx)\n"
781                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
782                     mpt2sas_phy->handle, (unsigned long long)
783                     mpt2sas_phy->identify.sas_address,
784                     mpt2sas_phy->attached_handle,
785                     (unsigned long long)
786                     mpt2sas_phy->remote_identify.sas_address);
787         mpt2sas_phy->phy = phy;
788         return 0;
789 }
790
791 /**
792  * mpt2sas_transport_update_phy_link_change - refreshing phy link changes and attached devices
793  * @ioc: per adapter object
794  * @handle: handle to sas_host or expander
795  * @attached_handle: attached device handle
796  * @phy_numberv: phy number
797  * @link_rate: new link rate
798  *
799  * Returns nothing.
800  */
801 void
802 mpt2sas_transport_update_phy_link_change(struct MPT2SAS_ADAPTER *ioc,
803     u16 handle, u16 attached_handle, u8 phy_number, u8 link_rate)
804 {
805         unsigned long flags;
806         struct _sas_node *sas_node;
807         struct _sas_phy *mpt2sas_phy;
808
809         spin_lock_irqsave(&ioc->sas_node_lock, flags);
810         sas_node = _transport_sas_node_find_by_handle(ioc, handle);
811         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
812         if (!sas_node)
813                 return;
814
815         mpt2sas_phy = &sas_node->phy[phy_number];
816         mpt2sas_phy->attached_handle = attached_handle;
817         if (attached_handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5))
818                 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
819                     &mpt2sas_phy->remote_identify);
820         else
821                 memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
822                     sas_identify));
823
824         if (mpt2sas_phy->phy)
825                 mpt2sas_phy->phy->negotiated_linkrate =
826                     _transport_convert_phy_link_rate(link_rate);
827
828         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
829                 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
830                     "refresh: handle(0x%04x), sas_addr(0x%016llx),\n"
831                     "\tlink_rate(0x%02x), phy(%d)\n"
832                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
833                     handle, (unsigned long long)
834                     mpt2sas_phy->identify.sas_address, link_rate,
835                     phy_number, attached_handle,
836                     (unsigned long long)
837                     mpt2sas_phy->remote_identify.sas_address);
838 }
839
840 static inline void *
841 phy_to_ioc(struct sas_phy *phy)
842 {
843         struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
844         return shost_priv(shost);
845 }
846
847 static inline void *
848 rphy_to_ioc(struct sas_rphy *rphy)
849 {
850         struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
851         return shost_priv(shost);
852 }
853
854 /**
855  * transport_get_linkerrors -
856  * @phy: The sas phy object
857  *
858  * Only support sas_host direct attached phys.
859  * Returns 0 for success, non-zero for failure.
860  *
861  */
862 static int
863 transport_get_linkerrors(struct sas_phy *phy)
864 {
865         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
866         struct _sas_phy *mpt2sas_phy;
867         Mpi2ConfigReply_t mpi_reply;
868         Mpi2SasPhyPage1_t phy_pg1;
869         int i;
870
871         for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys &&
872             !mpt2sas_phy; i++) {
873                 if (ioc->sas_hba.phy[i].phy != phy)
874                         continue;
875                 mpt2sas_phy = &ioc->sas_hba.phy[i];
876         }
877
878         if (!mpt2sas_phy) /* this phy not on sas_host */
879                 return -EINVAL;
880
881         if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
882                     mpt2sas_phy->phy_id))) {
883                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
884                     ioc->name, __FILE__, __LINE__, __func__);
885                 return -ENXIO;
886         }
887
888         if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
889                 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
890                     "(0x%04x), loginfo(0x%08x)\n", ioc->name,
891                     mpt2sas_phy->phy_id,
892                     le16_to_cpu(mpi_reply.IOCStatus),
893                     le32_to_cpu(mpi_reply.IOCLogInfo));
894
895         phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
896         phy->running_disparity_error_count =
897             le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
898         phy->loss_of_dword_sync_count =
899             le32_to_cpu(phy_pg1.LossDwordSynchCount);
900         phy->phy_reset_problem_count =
901             le32_to_cpu(phy_pg1.PhyResetProblemCount);
902         return 0;
903 }
904
905 /**
906  * transport_get_enclosure_identifier -
907  * @phy: The sas phy object
908  *
909  * Obtain the enclosure logical id for an expander.
910  * Returns 0 for success, non-zero for failure.
911  */
912 static int
913 transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
914 {
915         struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
916         struct _sas_node *sas_expander;
917         unsigned long flags;
918
919         spin_lock_irqsave(&ioc->sas_node_lock, flags);
920         sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
921             rphy->identify.sas_address);
922         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
923
924         if (!sas_expander)
925                 return -ENXIO;
926
927         *identifier = sas_expander->enclosure_logical_id;
928         return 0;
929 }
930
931 /**
932  * transport_get_bay_identifier -
933  * @phy: The sas phy object
934  *
935  * Returns the slot id for a device that resides inside an enclosure.
936  */
937 static int
938 transport_get_bay_identifier(struct sas_rphy *rphy)
939 {
940         struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
941         struct _sas_device *sas_device;
942         unsigned long flags;
943
944         spin_lock_irqsave(&ioc->sas_device_lock, flags);
945         sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
946             rphy->identify.sas_address);
947         spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
948
949         if (!sas_device)
950                 return -ENXIO;
951
952         return sas_device->slot;
953 }
954
955 /**
956  * transport_phy_reset -
957  * @phy: The sas phy object
958  * @hard_reset:
959  *
960  * Only support sas_host direct attached phys.
961  * Returns 0 for success, non-zero for failure.
962  */
963 static int
964 transport_phy_reset(struct sas_phy *phy, int hard_reset)
965 {
966         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
967         struct _sas_phy *mpt2sas_phy;
968         Mpi2SasIoUnitControlReply_t mpi_reply;
969         Mpi2SasIoUnitControlRequest_t mpi_request;
970         int i;
971
972         for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys &&
973             !mpt2sas_phy; i++) {
974                 if (ioc->sas_hba.phy[i].phy != phy)
975                         continue;
976                 mpt2sas_phy = &ioc->sas_hba.phy[i];
977         }
978
979         if (!mpt2sas_phy) /* this phy not on sas_host */
980                 return -EINVAL;
981
982         memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
983         mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
984         mpi_request.Operation = hard_reset ?
985             MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
986         mpi_request.PhyNum = mpt2sas_phy->phy_id;
987
988         if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
989                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
990                     ioc->name, __FILE__, __LINE__, __func__);
991                 return -ENXIO;
992         }
993
994         if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
995                 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
996                     "(0x%04x), loginfo(0x%08x)\n", ioc->name,
997                     mpt2sas_phy->phy_id,
998                     le16_to_cpu(mpi_reply.IOCStatus),
999                     le32_to_cpu(mpi_reply.IOCLogInfo));
1000
1001         return 0;
1002 }
1003
1004 /**
1005  * transport_smp_handler - transport portal for smp passthru
1006  * @shost: shost object
1007  * @rphy: sas transport rphy object
1008  * @req:
1009  *
1010  * This used primarily for smp_utils.
1011  * Example:
1012  *           smp_rep_general /sys/class/bsg/expander-5:0
1013  */
1014 static int
1015 transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1016     struct request *req)
1017 {
1018         struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1019         Mpi2SmpPassthroughRequest_t *mpi_request;
1020         Mpi2SmpPassthroughReply_t *mpi_reply;
1021         int rc;
1022         u16 smid;
1023         u32 ioc_state;
1024         unsigned long timeleft;
1025         void *psge;
1026         u32 sgl_flags;
1027         u8 issue_reset = 0;
1028         unsigned long flags;
1029         dma_addr_t dma_addr_in = 0;
1030         dma_addr_t dma_addr_out = 0;
1031         u16 wait_state_count;
1032         struct request *rsp = req->next_rq;
1033
1034         if (!rsp) {
1035                 printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
1036                     "missing\n", ioc->name, __func__);
1037                 return -EINVAL;
1038         }
1039
1040         /* do we need to support multiple segments? */
1041         if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
1042                 printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, "
1043                     "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt,
1044                     req->data_len, rsp->bio->bi_vcnt, rsp->data_len);
1045                 return -EINVAL;
1046         }
1047
1048         spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
1049         if (ioc->ioc_reset_in_progress) {
1050                 spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
1051                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1052                     __func__, ioc->name);
1053                 return -EFAULT;
1054         }
1055         spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
1056
1057         rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1058         if (rc)
1059                 return rc;
1060
1061         if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1062                 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
1063                     __func__);
1064                 rc = -EAGAIN;
1065                 goto out;
1066         }
1067         ioc->transport_cmds.status = MPT2_CMD_PENDING;
1068
1069         wait_state_count = 0;
1070         ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1071         while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1072                 if (wait_state_count++ == 10) {
1073                         printk(MPT2SAS_ERR_FMT
1074                             "%s: failed due to ioc not operational\n",
1075                             ioc->name, __func__);
1076                         rc = -EFAULT;
1077                         goto out;
1078                 }
1079                 ssleep(1);
1080                 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1081                 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1082                     "operational state(count=%d)\n", ioc->name,
1083                     __func__, wait_state_count);
1084         }
1085         if (wait_state_count)
1086                 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1087                     ioc->name, __func__);
1088
1089         smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1090         if (!smid) {
1091                 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1092                     ioc->name, __func__);
1093                 rc = -EAGAIN;
1094                 goto out;
1095         }
1096
1097         rc = 0;
1098         mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1099         ioc->transport_cmds.smid = smid;
1100
1101         memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1102         mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1103         mpi_request->PhysicalPort = 0xFF;
1104         *((u64 *)&mpi_request->SASAddress) = (rphy) ?
1105             cpu_to_le64(rphy->identify.sas_address) :
1106             cpu_to_le64(ioc->sas_hba.sas_address);
1107         mpi_request->RequestDataLength = cpu_to_le16(req->data_len - 4);
1108         psge = &mpi_request->SGL;
1109
1110         /* WRITE sgel first */
1111         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1112             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1113         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1114         dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
1115               req->data_len, PCI_DMA_BIDIRECTIONAL);
1116         if (!dma_addr_out) {
1117                 mpt2sas_base_free_smid(ioc, le16_to_cpu(smid));
1118                 goto unmap;
1119         }
1120
1121         ioc->base_add_sg_single(psge, sgl_flags | (req->data_len - 4),
1122             dma_addr_out);
1123
1124         /* incr sgel */
1125         psge += ioc->sge_size;
1126
1127         /* READ sgel last */
1128         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1129             MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1130             MPI2_SGE_FLAGS_END_OF_LIST);
1131         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1132         dma_addr_in =  pci_map_single(ioc->pdev, bio_data(rsp->bio),
1133               rsp->data_len, PCI_DMA_BIDIRECTIONAL);
1134         if (!dma_addr_in) {
1135                 mpt2sas_base_free_smid(ioc, le16_to_cpu(smid));
1136                 goto unmap;
1137         }
1138
1139         ioc->base_add_sg_single(psge, sgl_flags | (rsp->data_len + 4),
1140             dma_addr_in);
1141
1142         dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
1143             "sending smp request\n", ioc->name, __func__));
1144
1145         mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */);
1146         timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1147             10*HZ);
1148
1149         if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1150                 printk(MPT2SAS_ERR_FMT "%s : timeout\n",
1151                     __func__, ioc->name);
1152                 _debug_dump_mf(mpi_request,
1153                     sizeof(Mpi2SmpPassthroughRequest_t)/4);
1154                 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1155                         issue_reset = 1;
1156                 goto issue_host_reset;
1157         }
1158
1159         dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
1160             "complete\n", ioc->name, __func__));
1161
1162         if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1163
1164                 mpi_reply = ioc->transport_cmds.reply;
1165
1166                 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
1167                     "%s - reply data transfer size(%d)\n",
1168                     ioc->name, __func__,
1169                     le16_to_cpu(mpi_reply->ResponseDataLength)));
1170
1171                 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
1172                 req->sense_len = sizeof(*mpi_reply);
1173                 req->data_len = 0;
1174                 rsp->data_len -= mpi_reply->ResponseDataLength;
1175
1176         } else {
1177                 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
1178                     "%s - no reply\n", ioc->name, __func__));
1179                 rc = -ENXIO;
1180         }
1181
1182  issue_host_reset:
1183         if (issue_reset) {
1184                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1185                     FORCE_BIG_HAMMER);
1186                 rc = -ETIMEDOUT;
1187         }
1188
1189  unmap:
1190         if (dma_addr_out)
1191                 pci_unmap_single(ioc->pdev, dma_addr_out, req->data_len,
1192                     PCI_DMA_BIDIRECTIONAL);
1193         if (dma_addr_in)
1194                 pci_unmap_single(ioc->pdev, dma_addr_in, rsp->data_len,
1195                     PCI_DMA_BIDIRECTIONAL);
1196
1197  out:
1198         ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1199         mutex_unlock(&ioc->transport_cmds.mutex);
1200         return rc;
1201 }
1202
1203 struct sas_function_template mpt2sas_transport_functions = {
1204         .get_linkerrors         = transport_get_linkerrors,
1205         .get_enclosure_identifier = transport_get_enclosure_identifier,
1206         .get_bay_identifier     = transport_get_bay_identifier,
1207         .phy_reset              = transport_phy_reset,
1208         .smp_handler            = transport_smp_handler,
1209 };
1210
1211 struct scsi_transport_template *mpt2sas_transport_template;