]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/scsi/mpt2sas/mpt2sas_transport.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[mv-sheeva.git] / 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 (ioc->shost_recovery) {
144                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
145                     __func__, ioc->name);
146                 return -EFAULT;
147         }
148
149         if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
150             MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
151                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
152
153                     ioc->name, __FILE__, __LINE__, __func__);
154                 return -ENXIO;
155         }
156
157         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
158             MPI2_IOCSTATUS_MASK;
159         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
160                 printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
161                     "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
162                      __FILE__, __LINE__, __func__);
163                 return -EIO;
164         }
165
166         memset(identify, 0, sizeof(identify));
167         device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
168
169         /* sas_address */
170         identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
171
172         /* device_type */
173         switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
174         case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
175                 identify->device_type = SAS_PHY_UNUSED;
176                 break;
177         case MPI2_SAS_DEVICE_INFO_END_DEVICE:
178                 identify->device_type = SAS_END_DEVICE;
179                 break;
180         case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER:
181                 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
182                 break;
183         case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER:
184                 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
185                 break;
186         }
187
188         /* initiator_port_protocols */
189         if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR)
190                 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
191         if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR)
192                 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
193         if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR)
194                 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
195         if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST)
196                 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
197
198         /* target_port_protocols */
199         if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
200                 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
201         if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
202                 identify->target_port_protocols |= SAS_PROTOCOL_STP;
203         if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET)
204                 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
205         if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
206                 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
207
208         return 0;
209 }
210
211 /**
212  * mpt2sas_transport_done -  internal transport layer callback handler.
213  * @ioc: per adapter object
214  * @smid: system request message index
215  * @VF_ID: virtual function id
216  * @reply: reply message frame(lower 32bit addr)
217  *
218  * Callback handler when sending internal generated transport cmds.
219  * The callback index passed is `ioc->transport_cb_idx`
220  *
221  * Return nothing.
222  */
223 void
224 mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
225     u32 reply)
226 {
227         MPI2DefaultReply_t *mpi_reply;
228
229         mpi_reply =  mpt2sas_base_get_reply_virt_addr(ioc, reply);
230         if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED)
231                 return;
232         if (ioc->transport_cmds.smid != smid)
233                 return;
234         ioc->transport_cmds.status |= MPT2_CMD_COMPLETE;
235         if (mpi_reply) {
236                 memcpy(ioc->transport_cmds.reply, mpi_reply,
237                     mpi_reply->MsgLength*4);
238                 ioc->transport_cmds.status |= MPT2_CMD_REPLY_VALID;
239         }
240         ioc->transport_cmds.status &= ~MPT2_CMD_PENDING;
241         complete(&ioc->transport_cmds.done);
242 }
243
244 /* report manufacture request structure */
245 struct rep_manu_request{
246         u8 smp_frame_type;
247         u8 function;
248         u8 reserved;
249         u8 request_length;
250 };
251
252 /* report manufacture reply structure */
253 struct rep_manu_reply{
254         u8 smp_frame_type; /* 0x41 */
255         u8 function; /* 0x01 */
256         u8 function_result;
257         u8 response_length;
258         u16 expander_change_count;
259         u8 reserved0[2];
260         u8 sas_format:1;
261         u8 reserved1:7;
262         u8 reserved2[3];
263         u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
264         u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
265         u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
266         u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
267         u16 component_id;
268         u8 component_revision_id;
269         u8 reserved3;
270         u8 vendor_specific[8];
271 };
272
273 /**
274  * _transport_expander_report_manufacture - obtain SMP report_manufacture
275  * @ioc: per adapter object
276  * @sas_address: expander sas address
277  * @edev: the sas_expander_device object
278  *
279  * Fills in the sas_expander_device object when SMP port is created.
280  *
281  * Returns 0 for success, non-zero for failure.
282  */
283 static int
284 _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
285     u64 sas_address, struct sas_expander_device *edev)
286 {
287         Mpi2SmpPassthroughRequest_t *mpi_request;
288         Mpi2SmpPassthroughReply_t *mpi_reply;
289         struct rep_manu_reply *manufacture_reply;
290         struct rep_manu_request *manufacture_request;
291         int rc;
292         u16 smid;
293         u32 ioc_state;
294         unsigned long timeleft;
295         void *psge;
296         u32 sgl_flags;
297         u8 issue_reset = 0;
298         void *data_out = NULL;
299         dma_addr_t data_out_dma;
300         u32 sz;
301         u64 *sas_address_le;
302         u16 wait_state_count;
303
304         if (ioc->shost_recovery) {
305                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
306                     __func__, ioc->name);
307                 return -EFAULT;
308         }
309
310         mutex_lock(&ioc->transport_cmds.mutex);
311
312         if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
313                 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
314                     ioc->name, __func__);
315                 rc = -EAGAIN;
316                 goto out;
317         }
318         ioc->transport_cmds.status = MPT2_CMD_PENDING;
319
320         wait_state_count = 0;
321         ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
322         while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
323                 if (wait_state_count++ == 10) {
324                         printk(MPT2SAS_ERR_FMT
325                             "%s: failed due to ioc not operational\n",
326                             ioc->name, __func__);
327                         rc = -EFAULT;
328                         goto out;
329                 }
330                 ssleep(1);
331                 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
332                 printk(MPT2SAS_INFO_FMT "%s: waiting for "
333                     "operational state(count=%d)\n", ioc->name,
334                     __func__, wait_state_count);
335         }
336         if (wait_state_count)
337                 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
338                     ioc->name, __func__);
339
340         smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
341         if (!smid) {
342                 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
343                     ioc->name, __func__);
344                 rc = -EAGAIN;
345                 goto out;
346         }
347
348         rc = 0;
349         mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
350         ioc->transport_cmds.smid = smid;
351
352         sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
353         data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
354
355         if (!data_out) {
356                 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
357                     __LINE__, __func__);
358                 rc = -ENOMEM;
359                 mpt2sas_base_free_smid(ioc, smid);
360                 goto out;
361         }
362
363         manufacture_request = data_out;
364         manufacture_request->smp_frame_type = 0x40;
365         manufacture_request->function = 1;
366         manufacture_request->reserved = 0;
367         manufacture_request->request_length = 0;
368
369         memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
370         mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
371         mpi_request->PhysicalPort = 0xFF;
372         sas_address_le = (u64 *)&mpi_request->SASAddress;
373         *sas_address_le = cpu_to_le64(sas_address);
374         mpi_request->RequestDataLength = sizeof(struct rep_manu_request);
375         psge = &mpi_request->SGL;
376
377         /* WRITE sgel first */
378         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
379             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
380         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
381         ioc->base_add_sg_single(psge, sgl_flags |
382             sizeof(struct rep_manu_request), data_out_dma);
383
384         /* incr sgel */
385         psge += ioc->sge_size;
386
387         /* READ sgel last */
388         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
389             MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
390             MPI2_SGE_FLAGS_END_OF_LIST);
391         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
392         ioc->base_add_sg_single(psge, sgl_flags |
393             sizeof(struct rep_manu_reply), data_out_dma +
394             sizeof(struct rep_manu_request));
395
396         dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - "
397             "send to sas_addr(0x%016llx)\n", ioc->name,
398             (unsigned long long)sas_address));
399         mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */);
400         timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
401             10*HZ);
402
403         if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
404                 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
405                     ioc->name, __func__);
406                 _debug_dump_mf(mpi_request,
407                     sizeof(Mpi2SmpPassthroughRequest_t)/4);
408                 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
409                         issue_reset = 1;
410                 goto issue_host_reset;
411         }
412
413         dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - "
414             "complete\n", ioc->name));
415
416         if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
417                 u8 *tmp;
418
419                 mpi_reply = ioc->transport_cmds.reply;
420
421                 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
422                     "report_manufacture - reply data transfer size(%d)\n",
423                     ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
424
425                 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
426                     sizeof(struct rep_manu_reply))
427                         goto out;
428
429                 manufacture_reply = data_out + sizeof(struct rep_manu_request);
430                 strncpy(edev->vendor_id, manufacture_reply->vendor_id,
431                      SAS_EXPANDER_VENDOR_ID_LEN);
432                 strncpy(edev->product_id, manufacture_reply->product_id,
433                      SAS_EXPANDER_PRODUCT_ID_LEN);
434                 strncpy(edev->product_rev, manufacture_reply->product_rev,
435                      SAS_EXPANDER_PRODUCT_REV_LEN);
436                 edev->level = manufacture_reply->sas_format;
437                 if (manufacture_reply->sas_format) {
438                         strncpy(edev->component_vendor_id,
439                             manufacture_reply->component_vendor_id,
440                              SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
441                         tmp = (u8 *)&manufacture_reply->component_id;
442                         edev->component_id = tmp[0] << 8 | tmp[1];
443                         edev->component_revision_id =
444                             manufacture_reply->component_revision_id;
445                 }
446         } else
447                 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
448                     "report_manufacture - no reply\n", ioc->name));
449
450  issue_host_reset:
451         if (issue_reset)
452                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
453                     FORCE_BIG_HAMMER);
454  out:
455         ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
456         if (data_out)
457                 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
458
459         mutex_unlock(&ioc->transport_cmds.mutex);
460         return rc;
461 }
462
463 /**
464  * mpt2sas_transport_port_add - insert port to the list
465  * @ioc: per adapter object
466  * @handle: handle of attached device
467  * @parent_handle: parent handle(either hba or expander)
468  * Context: This function will acquire ioc->sas_node_lock.
469  *
470  * Adding new port object to the sas_node->sas_port_list.
471  *
472  * Returns mpt2sas_port.
473  */
474 struct _sas_port *
475 mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
476     u16 parent_handle)
477 {
478         struct _sas_phy *mpt2sas_phy, *next;
479         struct _sas_port *mpt2sas_port;
480         unsigned long flags;
481         struct _sas_node *sas_node;
482         struct sas_rphy *rphy;
483         int i;
484         struct sas_port *port;
485
486         if (!parent_handle)
487                 return NULL;
488
489         mpt2sas_port = kzalloc(sizeof(struct _sas_port),
490             GFP_KERNEL);
491         if (!mpt2sas_port) {
492                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
493                     ioc->name, __FILE__, __LINE__, __func__);
494                 return NULL;
495         }
496
497         INIT_LIST_HEAD(&mpt2sas_port->port_list);
498         INIT_LIST_HEAD(&mpt2sas_port->phy_list);
499         spin_lock_irqsave(&ioc->sas_node_lock, flags);
500         sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle);
501         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
502
503         if (!sas_node) {
504                 printk(MPT2SAS_ERR_FMT "%s: Could not find parent(0x%04x)!\n",
505                     ioc->name, __func__, parent_handle);
506                 goto out_fail;
507         }
508
509         mpt2sas_port->handle = parent_handle;
510         mpt2sas_port->sas_address = sas_node->sas_address;
511         if ((_transport_set_identify(ioc, handle,
512             &mpt2sas_port->remote_identify))) {
513                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
514                     ioc->name, __FILE__, __LINE__, __func__);
515                 goto out_fail;
516         }
517
518         if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
519                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
520                     ioc->name, __FILE__, __LINE__, __func__);
521                 goto out_fail;
522         }
523
524         for (i = 0; i < sas_node->num_phys; i++) {
525                 if (sas_node->phy[i].remote_identify.sas_address !=
526                     mpt2sas_port->remote_identify.sas_address)
527                         continue;
528                 list_add_tail(&sas_node->phy[i].port_siblings,
529                     &mpt2sas_port->phy_list);
530                 mpt2sas_port->num_phys++;
531         }
532
533         if (!mpt2sas_port->num_phys) {
534                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
535                     ioc->name, __FILE__, __LINE__, __func__);
536                 goto out_fail;
537         }
538
539         port = sas_port_alloc_num(sas_node->parent_dev);
540         if ((sas_port_add(port))) {
541                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
542                     ioc->name, __FILE__, __LINE__, __func__);
543                 goto out_fail;
544         }
545
546         list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
547             port_siblings) {
548                 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
549                         dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
550                             ", sas_addr(0x%016llx), phy(%d)\n", handle,
551                             (unsigned long long)
552                             mpt2sas_port->remote_identify.sas_address,
553                             mpt2sas_phy->phy_id);
554                 sas_port_add_phy(port, mpt2sas_phy->phy);
555         }
556
557         mpt2sas_port->port = port;
558         if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
559                 rphy = sas_end_device_alloc(port);
560         else
561                 rphy = sas_expander_alloc(port,
562                     mpt2sas_port->remote_identify.device_type);
563
564         rphy->identify = mpt2sas_port->remote_identify;
565         if ((sas_rphy_add(rphy))) {
566                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
567                     ioc->name, __FILE__, __LINE__, __func__);
568         }
569         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
570                 dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
571                     "sas_addr(0x%016llx)\n", handle,
572                     (unsigned long long)
573                     mpt2sas_port->remote_identify.sas_address);
574         mpt2sas_port->rphy = rphy;
575         spin_lock_irqsave(&ioc->sas_node_lock, flags);
576         list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
577         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
578
579         /* fill in report manufacture */
580         if (mpt2sas_port->remote_identify.device_type ==
581             MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
582             mpt2sas_port->remote_identify.device_type ==
583             MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
584                 _transport_expander_report_manufacture(ioc,
585                     mpt2sas_port->remote_identify.sas_address,
586                     rphy_to_expander_device(rphy));
587
588         return mpt2sas_port;
589
590  out_fail:
591         list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
592             port_siblings)
593                 list_del(&mpt2sas_phy->port_siblings);
594         kfree(mpt2sas_port);
595         return NULL;
596 }
597
598 /**
599  * mpt2sas_transport_port_remove - remove port from the list
600  * @ioc: per adapter object
601  * @sas_address: sas address of attached device
602  * @parent_handle: handle to the upstream parent(either hba or expander)
603  * Context: This function will acquire ioc->sas_node_lock.
604  *
605  * Removing object and freeing associated memory from the
606  * ioc->sas_port_list.
607  *
608  * Return nothing.
609  */
610 void
611 mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
612     u16 parent_handle)
613 {
614         int i;
615         unsigned long flags;
616         struct _sas_port *mpt2sas_port, *next;
617         struct _sas_node *sas_node;
618         u8 found = 0;
619         struct _sas_phy *mpt2sas_phy, *next_phy;
620
621         spin_lock_irqsave(&ioc->sas_node_lock, flags);
622         sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle);
623         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
624         if (!sas_node)
625                 return;
626         list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
627             port_list) {
628                 if (mpt2sas_port->remote_identify.sas_address != sas_address)
629                         continue;
630                 found = 1;
631                 list_del(&mpt2sas_port->port_list);
632                 goto out;
633         }
634  out:
635         if (!found)
636                 return;
637
638         for (i = 0; i < sas_node->num_phys; i++) {
639                 if (sas_node->phy[i].remote_identify.sas_address == sas_address)
640                         memset(&sas_node->phy[i].remote_identify, 0 ,
641                             sizeof(struct sas_identify));
642         }
643
644         list_for_each_entry_safe(mpt2sas_phy, next_phy,
645             &mpt2sas_port->phy_list, port_siblings) {
646                 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
647                         dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
648                             "remove: parent_handle(0x%04x), "
649                             "sas_addr(0x%016llx), phy(%d)\n", parent_handle,
650                             (unsigned long long)
651                             mpt2sas_port->remote_identify.sas_address,
652                             mpt2sas_phy->phy_id);
653                 sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
654                 list_del(&mpt2sas_phy->port_siblings);
655         }
656         sas_port_delete(mpt2sas_port->port);
657         kfree(mpt2sas_port);
658 }
659
660 /**
661  * mpt2sas_transport_add_host_phy - report sas_host phy to transport
662  * @ioc: per adapter object
663  * @mpt2sas_phy: mpt2sas per phy object
664  * @phy_pg0: sas phy page 0
665  * @parent_dev: parent device class object
666  *
667  * Returns 0 for success, non-zero for failure.
668  */
669 int
670 mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
671     *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
672 {
673         struct sas_phy *phy;
674         int phy_index = mpt2sas_phy->phy_id;
675
676
677         INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
678         phy = sas_phy_alloc(parent_dev, phy_index);
679         if (!phy) {
680                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
681                     ioc->name, __FILE__, __LINE__, __func__);
682                 return -1;
683         }
684         if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
685             &mpt2sas_phy->identify))) {
686                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
687                     ioc->name, __FILE__, __LINE__, __func__);
688                 return -1;
689         }
690         phy->identify = mpt2sas_phy->identify;
691         mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
692         if (mpt2sas_phy->attached_handle)
693                 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
694                     &mpt2sas_phy->remote_identify);
695         phy->identify.phy_identifier = mpt2sas_phy->phy_id;
696         phy->negotiated_linkrate = _transport_convert_phy_link_rate(
697             phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
698         phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
699             phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
700         phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
701             phy_pg0.HwLinkRate >> 4);
702         phy->minimum_linkrate = _transport_convert_phy_link_rate(
703             phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
704         phy->maximum_linkrate = _transport_convert_phy_link_rate(
705             phy_pg0.ProgrammedLinkRate >> 4);
706
707         if ((sas_phy_add(phy))) {
708                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
709                     ioc->name, __FILE__, __LINE__, __func__);
710                 sas_phy_free(phy);
711                 return -1;
712         }
713         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
714                 dev_printk(KERN_INFO, &phy->dev,
715                     "add: handle(0x%04x), sas_addr(0x%016llx)\n"
716                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
717                     mpt2sas_phy->handle, (unsigned long long)
718                     mpt2sas_phy->identify.sas_address,
719                     mpt2sas_phy->attached_handle,
720                     (unsigned long long)
721                     mpt2sas_phy->remote_identify.sas_address);
722         mpt2sas_phy->phy = phy;
723         return 0;
724 }
725
726
727 /**
728  * mpt2sas_transport_add_expander_phy - report expander phy to transport
729  * @ioc: per adapter object
730  * @mpt2sas_phy: mpt2sas per phy object
731  * @expander_pg1: expander page 1
732  * @parent_dev: parent device class object
733  *
734  * Returns 0 for success, non-zero for failure.
735  */
736 int
737 mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
738     *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
739 {
740         struct sas_phy *phy;
741         int phy_index = mpt2sas_phy->phy_id;
742
743         INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
744         phy = sas_phy_alloc(parent_dev, phy_index);
745         if (!phy) {
746                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
747                     ioc->name, __FILE__, __LINE__, __func__);
748                 return -1;
749         }
750         if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
751             &mpt2sas_phy->identify))) {
752                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
753                     ioc->name, __FILE__, __LINE__, __func__);
754                 return -1;
755         }
756         phy->identify = mpt2sas_phy->identify;
757         mpt2sas_phy->attached_handle =
758             le16_to_cpu(expander_pg1.AttachedDevHandle);
759         if (mpt2sas_phy->attached_handle)
760                 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
761                     &mpt2sas_phy->remote_identify);
762         phy->identify.phy_identifier = mpt2sas_phy->phy_id;
763         phy->negotiated_linkrate = _transport_convert_phy_link_rate(
764             expander_pg1.NegotiatedLinkRate &
765             MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
766         phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
767             expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
768         phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
769             expander_pg1.HwLinkRate >> 4);
770         phy->minimum_linkrate = _transport_convert_phy_link_rate(
771             expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
772         phy->maximum_linkrate = _transport_convert_phy_link_rate(
773             expander_pg1.ProgrammedLinkRate >> 4);
774
775         if ((sas_phy_add(phy))) {
776                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
777                     ioc->name, __FILE__, __LINE__, __func__);
778                 sas_phy_free(phy);
779                 return -1;
780         }
781         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
782                 dev_printk(KERN_INFO, &phy->dev,
783                     "add: handle(0x%04x), sas_addr(0x%016llx)\n"
784                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
785                     mpt2sas_phy->handle, (unsigned long long)
786                     mpt2sas_phy->identify.sas_address,
787                     mpt2sas_phy->attached_handle,
788                     (unsigned long long)
789                     mpt2sas_phy->remote_identify.sas_address);
790         mpt2sas_phy->phy = phy;
791         return 0;
792 }
793
794 /**
795  * mpt2sas_transport_update_links - refreshing phy link changes
796  * @ioc: per adapter object
797  * @handle: handle to sas_host or expander
798  * @attached_handle: attached device handle
799  * @phy_numberv: phy number
800  * @link_rate: new link rate
801  *
802  * Returns nothing.
803  */
804 void
805 mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
806     u16 handle, u16 attached_handle, u8 phy_number, u8 link_rate)
807 {
808         unsigned long flags;
809         struct _sas_node *sas_node;
810         struct _sas_phy *mpt2sas_phy;
811
812         if (ioc->shost_recovery) {
813                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
814                         __func__, ioc->name);
815                 return;
816         }
817
818         spin_lock_irqsave(&ioc->sas_node_lock, flags);
819         sas_node = _transport_sas_node_find_by_handle(ioc, handle);
820         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
821         if (!sas_node)
822                 return;
823
824         mpt2sas_phy = &sas_node->phy[phy_number];
825         mpt2sas_phy->attached_handle = attached_handle;
826         if (attached_handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5))
827                 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
828                     &mpt2sas_phy->remote_identify);
829         else
830                 memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
831                     sas_identify));
832
833         if (mpt2sas_phy->phy)
834                 mpt2sas_phy->phy->negotiated_linkrate =
835                     _transport_convert_phy_link_rate(link_rate);
836
837         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
838                 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
839                     "refresh: handle(0x%04x), sas_addr(0x%016llx),\n"
840                     "\tlink_rate(0x%02x), phy(%d)\n"
841                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
842                     handle, (unsigned long long)
843                     mpt2sas_phy->identify.sas_address, link_rate,
844                     phy_number, attached_handle,
845                     (unsigned long long)
846                     mpt2sas_phy->remote_identify.sas_address);
847 }
848
849 static inline void *
850 phy_to_ioc(struct sas_phy *phy)
851 {
852         struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
853         return shost_priv(shost);
854 }
855
856 static inline void *
857 rphy_to_ioc(struct sas_rphy *rphy)
858 {
859         struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
860         return shost_priv(shost);
861 }
862
863 /**
864  * _transport_get_linkerrors -
865  * @phy: The sas phy object
866  *
867  * Only support sas_host direct attached phys.
868  * Returns 0 for success, non-zero for failure.
869  *
870  */
871 static int
872 _transport_get_linkerrors(struct sas_phy *phy)
873 {
874         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
875         struct _sas_phy *mpt2sas_phy;
876         Mpi2ConfigReply_t mpi_reply;
877         Mpi2SasPhyPage1_t phy_pg1;
878         int i;
879
880         for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys &&
881             !mpt2sas_phy; i++) {
882                 if (ioc->sas_hba.phy[i].phy != phy)
883                         continue;
884                 mpt2sas_phy = &ioc->sas_hba.phy[i];
885         }
886
887         if (!mpt2sas_phy) /* this phy not on sas_host */
888                 return -EINVAL;
889
890         if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
891                     mpt2sas_phy->phy_id))) {
892                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
893                     ioc->name, __FILE__, __LINE__, __func__);
894                 return -ENXIO;
895         }
896
897         if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
898                 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
899                     "(0x%04x), loginfo(0x%08x)\n", ioc->name,
900                     mpt2sas_phy->phy_id,
901                     le16_to_cpu(mpi_reply.IOCStatus),
902                     le32_to_cpu(mpi_reply.IOCLogInfo));
903
904         phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
905         phy->running_disparity_error_count =
906             le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
907         phy->loss_of_dword_sync_count =
908             le32_to_cpu(phy_pg1.LossDwordSynchCount);
909         phy->phy_reset_problem_count =
910             le32_to_cpu(phy_pg1.PhyResetProblemCount);
911         return 0;
912 }
913
914 /**
915  * _transport_get_enclosure_identifier -
916  * @phy: The sas phy object
917  *
918  * Obtain the enclosure logical id for an expander.
919  * Returns 0 for success, non-zero for failure.
920  */
921 static int
922 _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
923 {
924         struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
925         struct _sas_node *sas_expander;
926         unsigned long flags;
927
928         spin_lock_irqsave(&ioc->sas_node_lock, flags);
929         sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
930             rphy->identify.sas_address);
931         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
932
933         if (!sas_expander)
934                 return -ENXIO;
935
936         *identifier = sas_expander->enclosure_logical_id;
937         return 0;
938 }
939
940 /**
941  * _transport_get_bay_identifier -
942  * @phy: The sas phy object
943  *
944  * Returns the slot id for a device that resides inside an enclosure.
945  */
946 static int
947 _transport_get_bay_identifier(struct sas_rphy *rphy)
948 {
949         struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
950         struct _sas_device *sas_device;
951         unsigned long flags;
952
953         spin_lock_irqsave(&ioc->sas_device_lock, flags);
954         sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
955             rphy->identify.sas_address);
956         spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
957
958         if (!sas_device)
959                 return -ENXIO;
960
961         return sas_device->slot;
962 }
963
964 /**
965  * _transport_phy_reset -
966  * @phy: The sas phy object
967  * @hard_reset:
968  *
969  * Only support sas_host direct attached phys.
970  * Returns 0 for success, non-zero for failure.
971  */
972 static int
973 _transport_phy_reset(struct sas_phy *phy, int hard_reset)
974 {
975         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
976         struct _sas_phy *mpt2sas_phy;
977         Mpi2SasIoUnitControlReply_t mpi_reply;
978         Mpi2SasIoUnitControlRequest_t mpi_request;
979         int i;
980
981         for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys &&
982             !mpt2sas_phy; i++) {
983                 if (ioc->sas_hba.phy[i].phy != phy)
984                         continue;
985                 mpt2sas_phy = &ioc->sas_hba.phy[i];
986         }
987
988         if (!mpt2sas_phy) /* this phy not on sas_host */
989                 return -EINVAL;
990
991         memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
992         mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
993         mpi_request.Operation = hard_reset ?
994             MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
995         mpi_request.PhyNum = mpt2sas_phy->phy_id;
996
997         if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
998                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
999                     ioc->name, __FILE__, __LINE__, __func__);
1000                 return -ENXIO;
1001         }
1002
1003         if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1004                 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1005                     "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1006                     mpt2sas_phy->phy_id,
1007                     le16_to_cpu(mpi_reply.IOCStatus),
1008                     le32_to_cpu(mpi_reply.IOCLogInfo));
1009
1010         return 0;
1011 }
1012
1013 /**
1014  * _transport_smp_handler - transport portal for smp passthru
1015  * @shost: shost object
1016  * @rphy: sas transport rphy object
1017  * @req:
1018  *
1019  * This used primarily for smp_utils.
1020  * Example:
1021  *           smp_rep_general /sys/class/bsg/expander-5:0
1022  */
1023 static int
1024 _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1025     struct request *req)
1026 {
1027         struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1028         Mpi2SmpPassthroughRequest_t *mpi_request;
1029         Mpi2SmpPassthroughReply_t *mpi_reply;
1030         int rc;
1031         u16 smid;
1032         u32 ioc_state;
1033         unsigned long timeleft;
1034         void *psge;
1035         u32 sgl_flags;
1036         u8 issue_reset = 0;
1037         dma_addr_t dma_addr_in = 0;
1038         dma_addr_t dma_addr_out = 0;
1039         u16 wait_state_count;
1040         struct request *rsp = req->next_rq;
1041
1042         if (!rsp) {
1043                 printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
1044                     "missing\n", ioc->name, __func__);
1045                 return -EINVAL;
1046         }
1047
1048         /* do we need to support multiple segments? */
1049         if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
1050                 printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, "
1051                     "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt,
1052                     blk_rq_bytes(req), rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
1053                 return -EINVAL;
1054         }
1055
1056         if (ioc->shost_recovery) {
1057                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1058                     __func__, ioc->name);
1059                 return -EFAULT;
1060         }
1061
1062         rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1063         if (rc)
1064                 return rc;
1065
1066         if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1067                 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
1068                     __func__);
1069                 rc = -EAGAIN;
1070                 goto out;
1071         }
1072         ioc->transport_cmds.status = MPT2_CMD_PENDING;
1073
1074         wait_state_count = 0;
1075         ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1076         while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1077                 if (wait_state_count++ == 10) {
1078                         printk(MPT2SAS_ERR_FMT
1079                             "%s: failed due to ioc not operational\n",
1080                             ioc->name, __func__);
1081                         rc = -EFAULT;
1082                         goto out;
1083                 }
1084                 ssleep(1);
1085                 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1086                 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1087                     "operational state(count=%d)\n", ioc->name,
1088                     __func__, wait_state_count);
1089         }
1090         if (wait_state_count)
1091                 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1092                     ioc->name, __func__);
1093
1094         smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1095         if (!smid) {
1096                 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1097                     ioc->name, __func__);
1098                 rc = -EAGAIN;
1099                 goto out;
1100         }
1101
1102         rc = 0;
1103         mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1104         ioc->transport_cmds.smid = smid;
1105
1106         memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1107         mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1108         mpi_request->PhysicalPort = 0xFF;
1109         *((u64 *)&mpi_request->SASAddress) = (rphy) ?
1110             cpu_to_le64(rphy->identify.sas_address) :
1111             cpu_to_le64(ioc->sas_hba.sas_address);
1112         mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
1113         psge = &mpi_request->SGL;
1114
1115         /* WRITE sgel first */
1116         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1117             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1118         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1119         dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
1120                 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
1121         if (!dma_addr_out) {
1122                 mpt2sas_base_free_smid(ioc, le16_to_cpu(smid));
1123                 goto unmap;
1124         }
1125
1126         ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(req) - 4),
1127             dma_addr_out);
1128
1129         /* incr sgel */
1130         psge += ioc->sge_size;
1131
1132         /* READ sgel last */
1133         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1134             MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1135             MPI2_SGE_FLAGS_END_OF_LIST);
1136         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1137         dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
1138                                      blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
1139         if (!dma_addr_in) {
1140                 mpt2sas_base_free_smid(ioc, le16_to_cpu(smid));
1141                 goto unmap;
1142         }
1143
1144         ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4),
1145             dma_addr_in);
1146
1147         dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
1148             "sending smp request\n", ioc->name, __func__));
1149
1150         mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */);
1151         timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1152             10*HZ);
1153
1154         if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1155                 printk(MPT2SAS_ERR_FMT "%s : timeout\n",
1156                     __func__, ioc->name);
1157                 _debug_dump_mf(mpi_request,
1158                     sizeof(Mpi2SmpPassthroughRequest_t)/4);
1159                 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1160                         issue_reset = 1;
1161                 goto issue_host_reset;
1162         }
1163
1164         dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
1165             "complete\n", ioc->name, __func__));
1166
1167         if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1168
1169                 mpi_reply = ioc->transport_cmds.reply;
1170
1171                 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
1172                     "%s - reply data transfer size(%d)\n",
1173                     ioc->name, __func__,
1174                     le16_to_cpu(mpi_reply->ResponseDataLength)));
1175
1176                 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
1177                 req->sense_len = sizeof(*mpi_reply);
1178                 req->resid_len = 0;
1179                 rsp->resid_len -= mpi_reply->ResponseDataLength;
1180         } else {
1181                 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
1182                     "%s - no reply\n", ioc->name, __func__));
1183                 rc = -ENXIO;
1184         }
1185
1186  issue_host_reset:
1187         if (issue_reset) {
1188                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1189                     FORCE_BIG_HAMMER);
1190                 rc = -ETIMEDOUT;
1191         }
1192
1193  unmap:
1194         if (dma_addr_out)
1195                 pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
1196                     PCI_DMA_BIDIRECTIONAL);
1197         if (dma_addr_in)
1198                 pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
1199                     PCI_DMA_BIDIRECTIONAL);
1200
1201  out:
1202         ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1203         mutex_unlock(&ioc->transport_cmds.mutex);
1204         return rc;
1205 }
1206
1207 struct sas_function_template mpt2sas_transport_functions = {
1208         .get_linkerrors         = _transport_get_linkerrors,
1209         .get_enclosure_identifier = _transport_get_enclosure_identifier,
1210         .get_bay_identifier     = _transport_get_bay_identifier,
1211         .phy_reset              = _transport_phy_reset,
1212         .smp_handler            = _transport_smp_handler,
1213 };
1214
1215 struct scsi_transport_template *mpt2sas_transport_template;