]> Pileus Git - ~andy/linux/blob - drivers/scsi/mpt2sas/mpt2sas_transport.c
Merge branch 'for-linus-1' of git://git.infradead.org/mtd-2.6
[~andy/linux] / 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-2010  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 #include <linux/slab.h>
53
54 #include <scsi/scsi.h>
55 #include <scsi/scsi_cmnd.h>
56 #include <scsi/scsi_device.h>
57 #include <scsi/scsi_host.h>
58 #include <scsi/scsi_transport_sas.h>
59 #include <scsi/scsi_dbg.h>
60
61 #include "mpt2sas_base.h"
62 /**
63  * _transport_sas_node_find_by_sas_address - sas node search
64  * @ioc: per adapter object
65  * @sas_address: sas address of expander or sas host
66  * Context: Calling function should acquire ioc->sas_node_lock.
67  *
68  * Search for either hba phys or expander device based on handle, then returns
69  * the sas_node object.
70  */
71 static struct _sas_node *
72 _transport_sas_node_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
73     u64 sas_address)
74 {
75         if (ioc->sas_hba.sas_address == sas_address)
76                 return &ioc->sas_hba;
77         else
78                 return mpt2sas_scsih_expander_find_by_sas_address(ioc,
79                     sas_address);
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 || ioc->pci_error_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  * @msix_index: MSIX table index supplied by the OS
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 1 meaning mf should be freed from _base_interrupt
222  *        0 means the mf is freed from this function.
223  */
224 u8
225 mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
226     u32 reply)
227 {
228         MPI2DefaultReply_t *mpi_reply;
229
230         mpi_reply =  mpt2sas_base_get_reply_virt_addr(ioc, reply);
231         if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED)
232                 return 1;
233         if (ioc->transport_cmds.smid != smid)
234                 return 1;
235         ioc->transport_cmds.status |= MPT2_CMD_COMPLETE;
236         if (mpi_reply) {
237                 memcpy(ioc->transport_cmds.reply, mpi_reply,
238                     mpi_reply->MsgLength*4);
239                 ioc->transport_cmds.status |= MPT2_CMD_REPLY_VALID;
240         }
241         ioc->transport_cmds.status &= ~MPT2_CMD_PENDING;
242         complete(&ioc->transport_cmds.done);
243         return 1;
244 }
245
246 /* report manufacture request structure */
247 struct rep_manu_request{
248         u8 smp_frame_type;
249         u8 function;
250         u8 reserved;
251         u8 request_length;
252 };
253
254 /* report manufacture reply structure */
255 struct rep_manu_reply{
256         u8 smp_frame_type; /* 0x41 */
257         u8 function; /* 0x01 */
258         u8 function_result;
259         u8 response_length;
260         u16 expander_change_count;
261         u8 reserved0[2];
262         u8 sas_format;
263         u8 reserved2[3];
264         u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
265         u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
266         u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
267         u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
268         u16 component_id;
269         u8 component_revision_id;
270         u8 reserved3;
271         u8 vendor_specific[8];
272 };
273
274 /**
275  * _transport_expander_report_manufacture - obtain SMP report_manufacture
276  * @ioc: per adapter object
277  * @sas_address: expander sas address
278  * @edev: the sas_expander_device object
279  *
280  * Fills in the sas_expander_device object when SMP port is created.
281  *
282  * Returns 0 for success, non-zero for failure.
283  */
284 static int
285 _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
286     u64 sas_address, struct sas_expander_device *edev)
287 {
288         Mpi2SmpPassthroughRequest_t *mpi_request;
289         Mpi2SmpPassthroughReply_t *mpi_reply;
290         struct rep_manu_reply *manufacture_reply;
291         struct rep_manu_request *manufacture_request;
292         int rc;
293         u16 smid;
294         u32 ioc_state;
295         unsigned long timeleft;
296         void *psge;
297         u32 sgl_flags;
298         u8 issue_reset = 0;
299         void *data_out = NULL;
300         dma_addr_t data_out_dma;
301         u32 sz;
302         u64 *sas_address_le;
303         u16 wait_state_count;
304
305         if (ioc->shost_recovery || ioc->pci_error_recovery) {
306                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
307                     __func__, ioc->name);
308                 return -EFAULT;
309         }
310
311         mutex_lock(&ioc->transport_cmds.mutex);
312
313         if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
314                 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
315                     ioc->name, __func__);
316                 rc = -EAGAIN;
317                 goto out;
318         }
319         ioc->transport_cmds.status = MPT2_CMD_PENDING;
320
321         wait_state_count = 0;
322         ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
323         while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
324                 if (wait_state_count++ == 10) {
325                         printk(MPT2SAS_ERR_FMT
326                             "%s: failed due to ioc not operational\n",
327                             ioc->name, __func__);
328                         rc = -EFAULT;
329                         goto out;
330                 }
331                 ssleep(1);
332                 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
333                 printk(MPT2SAS_INFO_FMT "%s: waiting for "
334                     "operational state(count=%d)\n", ioc->name,
335                     __func__, wait_state_count);
336         }
337         if (wait_state_count)
338                 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
339                     ioc->name, __func__);
340
341         smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
342         if (!smid) {
343                 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
344                     ioc->name, __func__);
345                 rc = -EAGAIN;
346                 goto out;
347         }
348
349         rc = 0;
350         mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
351         ioc->transport_cmds.smid = smid;
352
353         sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
354         data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
355
356         if (!data_out) {
357                 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
358                     __LINE__, __func__);
359                 rc = -ENOMEM;
360                 mpt2sas_base_free_smid(ioc, smid);
361                 goto out;
362         }
363
364         manufacture_request = data_out;
365         manufacture_request->smp_frame_type = 0x40;
366         manufacture_request->function = 1;
367         manufacture_request->reserved = 0;
368         manufacture_request->request_length = 0;
369
370         memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
371         mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
372         mpi_request->PhysicalPort = 0xFF;
373         mpi_request->VF_ID = 0; /* TODO */
374         mpi_request->VP_ID = 0;
375         sas_address_le = (u64 *)&mpi_request->SASAddress;
376         *sas_address_le = cpu_to_le64(sas_address);
377         mpi_request->RequestDataLength =
378             cpu_to_le16(sizeof(struct rep_manu_request));
379         psge = &mpi_request->SGL;
380
381         /* WRITE sgel first */
382         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
383             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
384         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
385         ioc->base_add_sg_single(psge, sgl_flags |
386             sizeof(struct rep_manu_request), data_out_dma);
387
388         /* incr sgel */
389         psge += ioc->sge_size;
390
391         /* READ sgel last */
392         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
393             MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
394             MPI2_SGE_FLAGS_END_OF_LIST);
395         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
396         ioc->base_add_sg_single(psge, sgl_flags |
397             sizeof(struct rep_manu_reply), data_out_dma +
398             sizeof(struct rep_manu_request));
399
400         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
401             "send to sas_addr(0x%016llx)\n", ioc->name,
402             (unsigned long long)sas_address));
403         mpt2sas_base_put_smid_default(ioc, smid);
404         init_completion(&ioc->transport_cmds.done);
405         timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
406             10*HZ);
407
408         if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
409                 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
410                     ioc->name, __func__);
411                 _debug_dump_mf(mpi_request,
412                     sizeof(Mpi2SmpPassthroughRequest_t)/4);
413                 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
414                         issue_reset = 1;
415                 goto issue_host_reset;
416         }
417
418         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
419             "complete\n", ioc->name));
420
421         if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
422                 u8 *tmp;
423
424                 mpi_reply = ioc->transport_cmds.reply;
425
426                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
427                     "report_manufacture - reply data transfer size(%d)\n",
428                     ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
429
430                 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
431                     sizeof(struct rep_manu_reply))
432                         goto out;
433
434                 manufacture_reply = data_out + sizeof(struct rep_manu_request);
435                 strncpy(edev->vendor_id, manufacture_reply->vendor_id,
436                      SAS_EXPANDER_VENDOR_ID_LEN);
437                 strncpy(edev->product_id, manufacture_reply->product_id,
438                      SAS_EXPANDER_PRODUCT_ID_LEN);
439                 strncpy(edev->product_rev, manufacture_reply->product_rev,
440                      SAS_EXPANDER_PRODUCT_REV_LEN);
441                 edev->level = manufacture_reply->sas_format & 1;
442                 if (edev->level) {
443                         strncpy(edev->component_vendor_id,
444                             manufacture_reply->component_vendor_id,
445                              SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
446                         tmp = (u8 *)&manufacture_reply->component_id;
447                         edev->component_id = tmp[0] << 8 | tmp[1];
448                         edev->component_revision_id =
449                             manufacture_reply->component_revision_id;
450                 }
451         } else
452                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
453                     "report_manufacture - no reply\n", ioc->name));
454
455  issue_host_reset:
456         if (issue_reset)
457                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
458                     FORCE_BIG_HAMMER);
459  out:
460         ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
461         if (data_out)
462                 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
463
464         mutex_unlock(&ioc->transport_cmds.mutex);
465         return rc;
466 }
467
468 /**
469  * _transport_delete_port - helper function to removing a port
470  * @ioc: per adapter object
471  * @mpt2sas_port: mpt2sas per port object
472  *
473  * Returns nothing.
474  */
475 static void
476 _transport_delete_port(struct MPT2SAS_ADAPTER *ioc,
477         struct _sas_port *mpt2sas_port)
478 {
479         u64 sas_address = mpt2sas_port->remote_identify.sas_address;
480         enum sas_device_type device_type =
481             mpt2sas_port->remote_identify.device_type;
482
483         dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
484             "remove: sas_addr(0x%016llx)\n",
485             (unsigned long long) sas_address);
486
487         ioc->logging_level |= MPT_DEBUG_TRANSPORT;
488         if (device_type == SAS_END_DEVICE)
489                 mpt2sas_device_remove(ioc, sas_address);
490         else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
491             device_type == SAS_FANOUT_EXPANDER_DEVICE)
492                 mpt2sas_expander_remove(ioc, sas_address);
493         ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
494 }
495
496 /**
497  * _transport_delete_phy - helper function to removing single phy from port
498  * @ioc: per adapter object
499  * @mpt2sas_port: mpt2sas per port object
500  * @mpt2sas_phy: mpt2sas per phy object
501  *
502  * Returns nothing.
503  */
504 static void
505 _transport_delete_phy(struct MPT2SAS_ADAPTER *ioc,
506         struct _sas_port *mpt2sas_port, struct _sas_phy *mpt2sas_phy)
507 {
508         u64 sas_address = mpt2sas_port->remote_identify.sas_address;
509
510         dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
511             "remove: sas_addr(0x%016llx), phy(%d)\n",
512             (unsigned long long) sas_address, mpt2sas_phy->phy_id);
513
514         list_del(&mpt2sas_phy->port_siblings);
515         mpt2sas_port->num_phys--;
516         sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
517         mpt2sas_phy->phy_belongs_to_port = 0;
518 }
519
520 /**
521  * _transport_add_phy - helper function to adding single phy to port
522  * @ioc: per adapter object
523  * @mpt2sas_port: mpt2sas per port object
524  * @mpt2sas_phy: mpt2sas per phy object
525  *
526  * Returns nothing.
527  */
528 static void
529 _transport_add_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_port *mpt2sas_port,
530         struct _sas_phy *mpt2sas_phy)
531 {
532         u64 sas_address = mpt2sas_port->remote_identify.sas_address;
533
534         dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
535             "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
536             sas_address, mpt2sas_phy->phy_id);
537
538         list_add_tail(&mpt2sas_phy->port_siblings, &mpt2sas_port->phy_list);
539         mpt2sas_port->num_phys++;
540         sas_port_add_phy(mpt2sas_port->port, mpt2sas_phy->phy);
541         mpt2sas_phy->phy_belongs_to_port = 1;
542 }
543
544 /**
545  * _transport_add_phy_to_an_existing_port - adding new phy to existing port
546  * @ioc: per adapter object
547  * @sas_node: sas node object (either expander or sas host)
548  * @mpt2sas_phy: mpt2sas per phy object
549  * @sas_address: sas address of device/expander were phy needs to be added to
550  *
551  * Returns nothing.
552  */
553 static void
554 _transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
555 struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy, u64 sas_address)
556 {
557         struct _sas_port *mpt2sas_port;
558         struct _sas_phy *phy_srch;
559
560         if (mpt2sas_phy->phy_belongs_to_port == 1)
561                 return;
562
563         list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list,
564             port_list) {
565                 if (mpt2sas_port->remote_identify.sas_address !=
566                     sas_address)
567                         continue;
568                 list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
569                     port_siblings) {
570                         if (phy_srch == mpt2sas_phy)
571                                 return;
572                 }
573                 _transport_add_phy(ioc, mpt2sas_port, mpt2sas_phy);
574                         return;
575         }
576
577 }
578
579 /**
580  * _transport_del_phy_from_an_existing_port - delete phy from existing port
581  * @ioc: per adapter object
582  * @sas_node: sas node object (either expander or sas host)
583  * @mpt2sas_phy: mpt2sas per phy object
584  *
585  * Returns nothing.
586  */
587 static void
588 _transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
589         struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy)
590 {
591         struct _sas_port *mpt2sas_port, *next;
592         struct _sas_phy *phy_srch;
593
594         if (mpt2sas_phy->phy_belongs_to_port == 0)
595                 return;
596
597         list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
598             port_list) {
599                 list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
600                     port_siblings) {
601                         if (phy_srch != mpt2sas_phy)
602                                 continue;
603                         if (mpt2sas_port->num_phys == 1)
604                                 _transport_delete_port(ioc, mpt2sas_port);
605                         else
606                                 _transport_delete_phy(ioc, mpt2sas_port,
607                                     mpt2sas_phy);
608                         return;
609                 }
610         }
611 }
612
613 /**
614  * _transport_sanity_check - sanity check when adding a new port
615  * @ioc: per adapter object
616  * @sas_node: sas node object (either expander or sas host)
617  * @sas_address: sas address of device being added
618  *
619  * See the explanation above from _transport_delete_duplicate_port
620  */
621 static void
622 _transport_sanity_check(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node,
623      u64 sas_address)
624 {
625         int i;
626
627         for (i = 0; i < sas_node->num_phys; i++) {
628                 if (sas_node->phy[i].remote_identify.sas_address != sas_address)
629                         continue;
630                 if (sas_node->phy[i].phy_belongs_to_port == 1)
631                         _transport_del_phy_from_an_existing_port(ioc, sas_node,
632                             &sas_node->phy[i]);
633         }
634 }
635
636 /**
637  * mpt2sas_transport_port_add - insert port to the list
638  * @ioc: per adapter object
639  * @handle: handle of attached device
640  * @sas_address: sas address of parent expander or sas host
641  * Context: This function will acquire ioc->sas_node_lock.
642  *
643  * Adding new port object to the sas_node->sas_port_list.
644  *
645  * Returns mpt2sas_port.
646  */
647 struct _sas_port *
648 mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
649     u64 sas_address)
650 {
651         struct _sas_phy *mpt2sas_phy, *next;
652         struct _sas_port *mpt2sas_port;
653         unsigned long flags;
654         struct _sas_node *sas_node;
655         struct sas_rphy *rphy;
656         int i;
657         struct sas_port *port;
658
659         mpt2sas_port = kzalloc(sizeof(struct _sas_port),
660             GFP_KERNEL);
661         if (!mpt2sas_port) {
662                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
663                     ioc->name, __FILE__, __LINE__, __func__);
664                 return NULL;
665         }
666
667         INIT_LIST_HEAD(&mpt2sas_port->port_list);
668         INIT_LIST_HEAD(&mpt2sas_port->phy_list);
669         spin_lock_irqsave(&ioc->sas_node_lock, flags);
670         sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
671         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
672
673         if (!sas_node) {
674                 printk(MPT2SAS_ERR_FMT "%s: Could not find "
675                     "parent sas_address(0x%016llx)!\n", ioc->name,
676                     __func__, (unsigned long long)sas_address);
677                 goto out_fail;
678         }
679
680         if ((_transport_set_identify(ioc, handle,
681             &mpt2sas_port->remote_identify))) {
682                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
683                     ioc->name, __FILE__, __LINE__, __func__);
684                 goto out_fail;
685         }
686
687         if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
688                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
689                     ioc->name, __FILE__, __LINE__, __func__);
690                 goto out_fail;
691         }
692
693         _transport_sanity_check(ioc, sas_node,
694             mpt2sas_port->remote_identify.sas_address);
695
696         for (i = 0; i < sas_node->num_phys; i++) {
697                 if (sas_node->phy[i].remote_identify.sas_address !=
698                     mpt2sas_port->remote_identify.sas_address)
699                         continue;
700                 list_add_tail(&sas_node->phy[i].port_siblings,
701                     &mpt2sas_port->phy_list);
702                 mpt2sas_port->num_phys++;
703         }
704
705         if (!mpt2sas_port->num_phys) {
706                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
707                     ioc->name, __FILE__, __LINE__, __func__);
708                 goto out_fail;
709         }
710
711         port = sas_port_alloc_num(sas_node->parent_dev);
712         if ((sas_port_add(port))) {
713                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
714                     ioc->name, __FILE__, __LINE__, __func__);
715                 goto out_fail;
716         }
717
718         list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
719             port_siblings) {
720                 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
721                         dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
722                             ", sas_addr(0x%016llx), phy(%d)\n", handle,
723                             (unsigned long long)
724                             mpt2sas_port->remote_identify.sas_address,
725                             mpt2sas_phy->phy_id);
726                 sas_port_add_phy(port, mpt2sas_phy->phy);
727                 mpt2sas_phy->phy_belongs_to_port = 1;
728         }
729
730         mpt2sas_port->port = port;
731         if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
732                 rphy = sas_end_device_alloc(port);
733         else
734                 rphy = sas_expander_alloc(port,
735                     mpt2sas_port->remote_identify.device_type);
736
737         rphy->identify = mpt2sas_port->remote_identify;
738         if ((sas_rphy_add(rphy))) {
739                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
740                     ioc->name, __FILE__, __LINE__, __func__);
741         }
742         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
743                 dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
744                     "sas_addr(0x%016llx)\n", handle,
745                     (unsigned long long)
746                     mpt2sas_port->remote_identify.sas_address);
747         mpt2sas_port->rphy = rphy;
748         spin_lock_irqsave(&ioc->sas_node_lock, flags);
749         list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
750         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
751
752         /* fill in report manufacture */
753         if (mpt2sas_port->remote_identify.device_type ==
754             MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
755             mpt2sas_port->remote_identify.device_type ==
756             MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
757                 _transport_expander_report_manufacture(ioc,
758                     mpt2sas_port->remote_identify.sas_address,
759                     rphy_to_expander_device(rphy));
760
761         return mpt2sas_port;
762
763  out_fail:
764         list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
765             port_siblings)
766                 list_del(&mpt2sas_phy->port_siblings);
767         kfree(mpt2sas_port);
768         return NULL;
769 }
770
771 /**
772  * mpt2sas_transport_port_remove - remove port from the list
773  * @ioc: per adapter object
774  * @sas_address: sas address of attached device
775  * @sas_address_parent: sas address of parent expander or sas host
776  * Context: This function will acquire ioc->sas_node_lock.
777  *
778  * Removing object and freeing associated memory from the
779  * ioc->sas_port_list.
780  *
781  * Return nothing.
782  */
783 void
784 mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
785     u64 sas_address_parent)
786 {
787         int i;
788         unsigned long flags;
789         struct _sas_port *mpt2sas_port, *next;
790         struct _sas_node *sas_node;
791         u8 found = 0;
792         struct _sas_phy *mpt2sas_phy, *next_phy;
793
794         spin_lock_irqsave(&ioc->sas_node_lock, flags);
795         sas_node = _transport_sas_node_find_by_sas_address(ioc,
796             sas_address_parent);
797         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
798         if (!sas_node)
799                 return;
800         list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
801             port_list) {
802                 if (mpt2sas_port->remote_identify.sas_address != sas_address)
803                         continue;
804                 found = 1;
805                 list_del(&mpt2sas_port->port_list);
806                 goto out;
807         }
808  out:
809         if (!found)
810                 return;
811
812         for (i = 0; i < sas_node->num_phys; i++) {
813                 if (sas_node->phy[i].remote_identify.sas_address == sas_address)
814                         memset(&sas_node->phy[i].remote_identify, 0 ,
815                             sizeof(struct sas_identify));
816         }
817
818         list_for_each_entry_safe(mpt2sas_phy, next_phy,
819             &mpt2sas_port->phy_list, port_siblings) {
820                 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
821                         dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
822                             "remove: sas_addr(0x%016llx), phy(%d)\n",
823                             (unsigned long long)
824                             mpt2sas_port->remote_identify.sas_address,
825                             mpt2sas_phy->phy_id);
826                 mpt2sas_phy->phy_belongs_to_port = 0;
827                 sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
828                 list_del(&mpt2sas_phy->port_siblings);
829         }
830         sas_port_delete(mpt2sas_port->port);
831         kfree(mpt2sas_port);
832 }
833
834 /**
835  * mpt2sas_transport_add_host_phy - report sas_host phy to transport
836  * @ioc: per adapter object
837  * @mpt2sas_phy: mpt2sas per phy object
838  * @phy_pg0: sas phy page 0
839  * @parent_dev: parent device class object
840  *
841  * Returns 0 for success, non-zero for failure.
842  */
843 int
844 mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
845     *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
846 {
847         struct sas_phy *phy;
848         int phy_index = mpt2sas_phy->phy_id;
849
850
851         INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
852         phy = sas_phy_alloc(parent_dev, phy_index);
853         if (!phy) {
854                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
855                     ioc->name, __FILE__, __LINE__, __func__);
856                 return -1;
857         }
858         if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
859             &mpt2sas_phy->identify))) {
860                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
861                     ioc->name, __FILE__, __LINE__, __func__);
862                 return -1;
863         }
864         phy->identify = mpt2sas_phy->identify;
865         mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
866         if (mpt2sas_phy->attached_handle)
867                 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
868                     &mpt2sas_phy->remote_identify);
869         phy->identify.phy_identifier = mpt2sas_phy->phy_id;
870         phy->negotiated_linkrate = _transport_convert_phy_link_rate(
871             phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
872         phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
873             phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
874         phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
875             phy_pg0.HwLinkRate >> 4);
876         phy->minimum_linkrate = _transport_convert_phy_link_rate(
877             phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
878         phy->maximum_linkrate = _transport_convert_phy_link_rate(
879             phy_pg0.ProgrammedLinkRate >> 4);
880
881         if ((sas_phy_add(phy))) {
882                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
883                     ioc->name, __FILE__, __LINE__, __func__);
884                 sas_phy_free(phy);
885                 return -1;
886         }
887         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
888                 dev_printk(KERN_INFO, &phy->dev,
889                     "add: handle(0x%04x), sas_addr(0x%016llx)\n"
890                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
891                     mpt2sas_phy->handle, (unsigned long long)
892                     mpt2sas_phy->identify.sas_address,
893                     mpt2sas_phy->attached_handle,
894                     (unsigned long long)
895                     mpt2sas_phy->remote_identify.sas_address);
896         mpt2sas_phy->phy = phy;
897         return 0;
898 }
899
900
901 /**
902  * mpt2sas_transport_add_expander_phy - report expander phy to transport
903  * @ioc: per adapter object
904  * @mpt2sas_phy: mpt2sas per phy object
905  * @expander_pg1: expander page 1
906  * @parent_dev: parent device class object
907  *
908  * Returns 0 for success, non-zero for failure.
909  */
910 int
911 mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
912     *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
913 {
914         struct sas_phy *phy;
915         int phy_index = mpt2sas_phy->phy_id;
916
917         INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
918         phy = sas_phy_alloc(parent_dev, phy_index);
919         if (!phy) {
920                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
921                     ioc->name, __FILE__, __LINE__, __func__);
922                 return -1;
923         }
924         if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
925             &mpt2sas_phy->identify))) {
926                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
927                     ioc->name, __FILE__, __LINE__, __func__);
928                 return -1;
929         }
930         phy->identify = mpt2sas_phy->identify;
931         mpt2sas_phy->attached_handle =
932             le16_to_cpu(expander_pg1.AttachedDevHandle);
933         if (mpt2sas_phy->attached_handle)
934                 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
935                     &mpt2sas_phy->remote_identify);
936         phy->identify.phy_identifier = mpt2sas_phy->phy_id;
937         phy->negotiated_linkrate = _transport_convert_phy_link_rate(
938             expander_pg1.NegotiatedLinkRate &
939             MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
940         phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
941             expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
942         phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
943             expander_pg1.HwLinkRate >> 4);
944         phy->minimum_linkrate = _transport_convert_phy_link_rate(
945             expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
946         phy->maximum_linkrate = _transport_convert_phy_link_rate(
947             expander_pg1.ProgrammedLinkRate >> 4);
948
949         if ((sas_phy_add(phy))) {
950                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
951                     ioc->name, __FILE__, __LINE__, __func__);
952                 sas_phy_free(phy);
953                 return -1;
954         }
955         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
956                 dev_printk(KERN_INFO, &phy->dev,
957                     "add: handle(0x%04x), sas_addr(0x%016llx)\n"
958                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
959                     mpt2sas_phy->handle, (unsigned long long)
960                     mpt2sas_phy->identify.sas_address,
961                     mpt2sas_phy->attached_handle,
962                     (unsigned long long)
963                     mpt2sas_phy->remote_identify.sas_address);
964         mpt2sas_phy->phy = phy;
965         return 0;
966 }
967
968 /**
969  * mpt2sas_transport_update_links - refreshing phy link changes
970  * @ioc: per adapter object
971  * @sas_address: sas address of parent expander or sas host
972  * @handle: attached device handle
973  * @phy_numberv: phy number
974  * @link_rate: new link rate
975  *
976  * Returns nothing.
977  */
978 void
979 mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
980      u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
981 {
982         unsigned long flags;
983         struct _sas_node *sas_node;
984         struct _sas_phy *mpt2sas_phy;
985
986         if (ioc->shost_recovery || ioc->pci_error_recovery)
987                 return;
988
989         spin_lock_irqsave(&ioc->sas_node_lock, flags);
990         sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
991         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
992         if (!sas_node)
993                 return;
994
995         mpt2sas_phy = &sas_node->phy[phy_number];
996         mpt2sas_phy->attached_handle = handle;
997         if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
998                 _transport_set_identify(ioc, handle,
999                     &mpt2sas_phy->remote_identify);
1000                 _transport_add_phy_to_an_existing_port(ioc, sas_node,
1001                     mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address);
1002         } else
1003                 memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
1004                     sas_identify));
1005
1006         if (mpt2sas_phy->phy)
1007                 mpt2sas_phy->phy->negotiated_linkrate =
1008                     _transport_convert_phy_link_rate(link_rate);
1009
1010         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
1011                 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
1012                     "refresh: parent sas_addr(0x%016llx),\n"
1013                     "\tlink_rate(0x%02x), phy(%d)\n"
1014                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
1015                     (unsigned long long)sas_address,
1016                     link_rate, phy_number, handle, (unsigned long long)
1017                     mpt2sas_phy->remote_identify.sas_address);
1018 }
1019
1020 static inline void *
1021 phy_to_ioc(struct sas_phy *phy)
1022 {
1023         struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1024         return shost_priv(shost);
1025 }
1026
1027 static inline void *
1028 rphy_to_ioc(struct sas_rphy *rphy)
1029 {
1030         struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
1031         return shost_priv(shost);
1032 }
1033
1034
1035 /* report phy error log structure */
1036 struct phy_error_log_request{
1037         u8 smp_frame_type; /* 0x40 */
1038         u8 function; /* 0x11 */
1039         u8 allocated_response_length;
1040         u8 request_length; /* 02 */
1041         u8 reserved_1[5];
1042         u8 phy_identifier;
1043         u8 reserved_2[2];
1044 };
1045
1046 /* report phy error log reply structure */
1047 struct phy_error_log_reply{
1048         u8 smp_frame_type; /* 0x41 */
1049         u8 function; /* 0x11 */
1050         u8 function_result;
1051         u8 response_length;
1052         u16 expander_change_count;
1053         u8 reserved_1[3];
1054         u8 phy_identifier;
1055         u8 reserved_2[2];
1056         u32 invalid_dword;
1057         u32 running_disparity_error;
1058         u32 loss_of_dword_sync;
1059         u32 phy_reset_problem;
1060 };
1061
1062 /**
1063  * _transport_get_expander_phy_error_log - return expander counters
1064  * @ioc: per adapter object
1065  * @phy: The sas phy object
1066  *
1067  * Returns 0 for success, non-zero for failure.
1068  *
1069  */
1070 static int
1071 _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
1072     struct sas_phy *phy)
1073 {
1074         Mpi2SmpPassthroughRequest_t *mpi_request;
1075         Mpi2SmpPassthroughReply_t *mpi_reply;
1076         struct phy_error_log_request *phy_error_log_request;
1077         struct phy_error_log_reply *phy_error_log_reply;
1078         int rc;
1079         u16 smid;
1080         u32 ioc_state;
1081         unsigned long timeleft;
1082         void *psge;
1083         u32 sgl_flags;
1084         u8 issue_reset = 0;
1085         void *data_out = NULL;
1086         dma_addr_t data_out_dma;
1087         u32 sz;
1088         u64 *sas_address_le;
1089         u16 wait_state_count;
1090
1091         if (ioc->shost_recovery || ioc->pci_error_recovery) {
1092                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1093                     __func__, ioc->name);
1094                 return -EFAULT;
1095         }
1096
1097         mutex_lock(&ioc->transport_cmds.mutex);
1098
1099         if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1100                 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
1101                     ioc->name, __func__);
1102                 rc = -EAGAIN;
1103                 goto out;
1104         }
1105         ioc->transport_cmds.status = MPT2_CMD_PENDING;
1106
1107         wait_state_count = 0;
1108         ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1109         while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1110                 if (wait_state_count++ == 10) {
1111                         printk(MPT2SAS_ERR_FMT
1112                             "%s: failed due to ioc not operational\n",
1113                             ioc->name, __func__);
1114                         rc = -EFAULT;
1115                         goto out;
1116                 }
1117                 ssleep(1);
1118                 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1119                 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1120                     "operational state(count=%d)\n", ioc->name,
1121                     __func__, wait_state_count);
1122         }
1123         if (wait_state_count)
1124                 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1125                     ioc->name, __func__);
1126
1127         smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1128         if (!smid) {
1129                 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1130                     ioc->name, __func__);
1131                 rc = -EAGAIN;
1132                 goto out;
1133         }
1134
1135         mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1136         ioc->transport_cmds.smid = smid;
1137
1138         sz = sizeof(struct phy_error_log_request) +
1139             sizeof(struct phy_error_log_reply);
1140         data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1141         if (!data_out) {
1142                 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
1143                     __LINE__, __func__);
1144                 rc = -ENOMEM;
1145                 mpt2sas_base_free_smid(ioc, smid);
1146                 goto out;
1147         }
1148
1149         rc = -EINVAL;
1150         memset(data_out, 0, sz);
1151         phy_error_log_request = data_out;
1152         phy_error_log_request->smp_frame_type = 0x40;
1153         phy_error_log_request->function = 0x11;
1154         phy_error_log_request->request_length = 2;
1155         phy_error_log_request->allocated_response_length = 0;
1156         phy_error_log_request->phy_identifier = phy->number;
1157
1158         memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1159         mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1160         mpi_request->PhysicalPort = 0xFF;
1161         mpi_request->VF_ID = 0; /* TODO */
1162         mpi_request->VP_ID = 0;
1163         sas_address_le = (u64 *)&mpi_request->SASAddress;
1164         *sas_address_le = cpu_to_le64(phy->identify.sas_address);
1165         mpi_request->RequestDataLength =
1166             cpu_to_le16(sizeof(struct phy_error_log_request));
1167         psge = &mpi_request->SGL;
1168
1169         /* WRITE sgel first */
1170         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1171             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1172         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1173         ioc->base_add_sg_single(psge, sgl_flags |
1174             sizeof(struct phy_error_log_request), data_out_dma);
1175
1176         /* incr sgel */
1177         psge += ioc->sge_size;
1178
1179         /* READ sgel last */
1180         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1181             MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1182             MPI2_SGE_FLAGS_END_OF_LIST);
1183         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1184         ioc->base_add_sg_single(psge, sgl_flags |
1185             sizeof(struct phy_error_log_reply), data_out_dma +
1186             sizeof(struct phy_error_log_request));
1187
1188         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
1189             "send to sas_addr(0x%016llx), phy(%d)\n", ioc->name,
1190             (unsigned long long)phy->identify.sas_address, phy->number));
1191         mpt2sas_base_put_smid_default(ioc, smid);
1192         init_completion(&ioc->transport_cmds.done);
1193         timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1194             10*HZ);
1195
1196         if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1197                 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
1198                     ioc->name, __func__);
1199                 _debug_dump_mf(mpi_request,
1200                     sizeof(Mpi2SmpPassthroughRequest_t)/4);
1201                 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1202                         issue_reset = 1;
1203                 goto issue_host_reset;
1204         }
1205
1206         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
1207             "complete\n", ioc->name));
1208
1209         if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1210
1211                 mpi_reply = ioc->transport_cmds.reply;
1212
1213                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1214                     "phy_error_log - reply data transfer size(%d)\n",
1215                     ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1216
1217                 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1218                     sizeof(struct phy_error_log_reply))
1219                         goto out;
1220
1221                 phy_error_log_reply = data_out +
1222                     sizeof(struct phy_error_log_request);
1223
1224                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1225                     "phy_error_log - function_result(%d)\n",
1226                     ioc->name, phy_error_log_reply->function_result));
1227
1228                 phy->invalid_dword_count =
1229                     be32_to_cpu(phy_error_log_reply->invalid_dword);
1230                 phy->running_disparity_error_count =
1231                     be32_to_cpu(phy_error_log_reply->running_disparity_error);
1232                 phy->loss_of_dword_sync_count =
1233                     be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
1234                 phy->phy_reset_problem_count =
1235                     be32_to_cpu(phy_error_log_reply->phy_reset_problem);
1236                 rc = 0;
1237         } else
1238                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1239                     "phy_error_log - no reply\n", ioc->name));
1240
1241  issue_host_reset:
1242         if (issue_reset)
1243                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1244                     FORCE_BIG_HAMMER);
1245  out:
1246         ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1247         if (data_out)
1248                 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1249
1250         mutex_unlock(&ioc->transport_cmds.mutex);
1251         return rc;
1252 }
1253
1254 /**
1255  * _transport_get_linkerrors - return phy counters for both hba and expanders
1256  * @phy: The sas phy object
1257  *
1258  * Returns 0 for success, non-zero for failure.
1259  *
1260  */
1261 static int
1262 _transport_get_linkerrors(struct sas_phy *phy)
1263 {
1264         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1265         unsigned long flags;
1266         Mpi2ConfigReply_t mpi_reply;
1267         Mpi2SasPhyPage1_t phy_pg1;
1268
1269         spin_lock_irqsave(&ioc->sas_node_lock, flags);
1270         if (_transport_sas_node_find_by_sas_address(ioc,
1271             phy->identify.sas_address) == NULL) {
1272                 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1273                 return -EINVAL;
1274         }
1275         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1276
1277         if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1278                 return _transport_get_expander_phy_error_log(ioc, phy);
1279
1280         /* get hba phy error logs */
1281         if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
1282                     phy->number))) {
1283                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1284                     ioc->name, __FILE__, __LINE__, __func__);
1285                 return -ENXIO;
1286         }
1287
1288         if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1289                 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1290                     "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1291                     phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1292                     le32_to_cpu(mpi_reply.IOCLogInfo));
1293
1294         phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
1295         phy->running_disparity_error_count =
1296             le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
1297         phy->loss_of_dword_sync_count =
1298             le32_to_cpu(phy_pg1.LossDwordSynchCount);
1299         phy->phy_reset_problem_count =
1300             le32_to_cpu(phy_pg1.PhyResetProblemCount);
1301         return 0;
1302 }
1303
1304 /**
1305  * _transport_get_enclosure_identifier -
1306  * @phy: The sas phy object
1307  *
1308  * Obtain the enclosure logical id for an expander.
1309  * Returns 0 for success, non-zero for failure.
1310  */
1311 static int
1312 _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1313 {
1314         struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1315         struct _sas_device *sas_device;
1316         unsigned long flags;
1317
1318         spin_lock_irqsave(&ioc->sas_device_lock, flags);
1319         sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1320             rphy->identify.sas_address);
1321         spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1322
1323         if (!sas_device)
1324                 return -ENXIO;
1325
1326         *identifier = sas_device->enclosure_logical_id;
1327         return 0;
1328 }
1329
1330 /**
1331  * _transport_get_bay_identifier -
1332  * @phy: The sas phy object
1333  *
1334  * Returns the slot id for a device that resides inside an enclosure.
1335  */
1336 static int
1337 _transport_get_bay_identifier(struct sas_rphy *rphy)
1338 {
1339         struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1340         struct _sas_device *sas_device;
1341         unsigned long flags;
1342
1343         spin_lock_irqsave(&ioc->sas_device_lock, flags);
1344         sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1345             rphy->identify.sas_address);
1346         spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1347
1348         if (!sas_device)
1349                 return -ENXIO;
1350
1351         return sas_device->slot;
1352 }
1353
1354 /* phy control request structure */
1355 struct phy_control_request{
1356         u8 smp_frame_type; /* 0x40 */
1357         u8 function; /* 0x91 */
1358         u8 allocated_response_length;
1359         u8 request_length; /* 0x09 */
1360         u16 expander_change_count;
1361         u8 reserved_1[3];
1362         u8 phy_identifier;
1363         u8 phy_operation;
1364         u8 reserved_2[13];
1365         u64 attached_device_name;
1366         u8 programmed_min_physical_link_rate;
1367         u8 programmed_max_physical_link_rate;
1368         u8 reserved_3[6];
1369 };
1370
1371 /* phy control reply structure */
1372 struct phy_control_reply{
1373         u8 smp_frame_type; /* 0x41 */
1374         u8 function; /* 0x11 */
1375         u8 function_result;
1376         u8 response_length;
1377 };
1378
1379 #define SMP_PHY_CONTROL_LINK_RESET      (0x01)
1380 #define SMP_PHY_CONTROL_HARD_RESET      (0x02)
1381 #define SMP_PHY_CONTROL_DISABLE         (0x03)
1382
1383 /**
1384  * _transport_expander_phy_control - expander phy control
1385  * @ioc: per adapter object
1386  * @phy: The sas phy object
1387  *
1388  * Returns 0 for success, non-zero for failure.
1389  *
1390  */
1391 static int
1392 _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
1393     struct sas_phy *phy, u8 phy_operation)
1394 {
1395         Mpi2SmpPassthroughRequest_t *mpi_request;
1396         Mpi2SmpPassthroughReply_t *mpi_reply;
1397         struct phy_control_request *phy_control_request;
1398         struct phy_control_reply *phy_control_reply;
1399         int rc;
1400         u16 smid;
1401         u32 ioc_state;
1402         unsigned long timeleft;
1403         void *psge;
1404         u32 sgl_flags;
1405         u8 issue_reset = 0;
1406         void *data_out = NULL;
1407         dma_addr_t data_out_dma;
1408         u32 sz;
1409         u64 *sas_address_le;
1410         u16 wait_state_count;
1411
1412         if (ioc->shost_recovery) {
1413                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1414                     __func__, ioc->name);
1415                 return -EFAULT;
1416         }
1417
1418         mutex_lock(&ioc->transport_cmds.mutex);
1419
1420         if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1421                 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
1422                     ioc->name, __func__);
1423                 rc = -EAGAIN;
1424                 goto out;
1425         }
1426         ioc->transport_cmds.status = MPT2_CMD_PENDING;
1427
1428         wait_state_count = 0;
1429         ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1430         while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1431                 if (wait_state_count++ == 10) {
1432                         printk(MPT2SAS_ERR_FMT
1433                             "%s: failed due to ioc not operational\n",
1434                             ioc->name, __func__);
1435                         rc = -EFAULT;
1436                         goto out;
1437                 }
1438                 ssleep(1);
1439                 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1440                 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1441                     "operational state(count=%d)\n", ioc->name,
1442                     __func__, wait_state_count);
1443         }
1444         if (wait_state_count)
1445                 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1446                     ioc->name, __func__);
1447
1448         smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1449         if (!smid) {
1450                 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1451                     ioc->name, __func__);
1452                 rc = -EAGAIN;
1453                 goto out;
1454         }
1455
1456         mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1457         ioc->transport_cmds.smid = smid;
1458
1459         sz = sizeof(struct phy_control_request) +
1460             sizeof(struct phy_control_reply);
1461         data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1462         if (!data_out) {
1463                 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
1464                     __LINE__, __func__);
1465                 rc = -ENOMEM;
1466                 mpt2sas_base_free_smid(ioc, smid);
1467                 goto out;
1468         }
1469
1470         rc = -EINVAL;
1471         memset(data_out, 0, sz);
1472         phy_control_request = data_out;
1473         phy_control_request->smp_frame_type = 0x40;
1474         phy_control_request->function = 0x91;
1475         phy_control_request->request_length = 9;
1476         phy_control_request->allocated_response_length = 0;
1477         phy_control_request->phy_identifier = phy->number;
1478         phy_control_request->phy_operation = phy_operation;
1479         phy_control_request->programmed_min_physical_link_rate =
1480             phy->minimum_linkrate << 4;
1481         phy_control_request->programmed_max_physical_link_rate =
1482             phy->maximum_linkrate << 4;
1483
1484         memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1485         mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1486         mpi_request->PhysicalPort = 0xFF;
1487         mpi_request->VF_ID = 0; /* TODO */
1488         mpi_request->VP_ID = 0;
1489         sas_address_le = (u64 *)&mpi_request->SASAddress;
1490         *sas_address_le = cpu_to_le64(phy->identify.sas_address);
1491         mpi_request->RequestDataLength =
1492             cpu_to_le16(sizeof(struct phy_error_log_request));
1493         psge = &mpi_request->SGL;
1494
1495         /* WRITE sgel first */
1496         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1497             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1498         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1499         ioc->base_add_sg_single(psge, sgl_flags |
1500             sizeof(struct phy_control_request), data_out_dma);
1501
1502         /* incr sgel */
1503         psge += ioc->sge_size;
1504
1505         /* READ sgel last */
1506         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1507             MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1508             MPI2_SGE_FLAGS_END_OF_LIST);
1509         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1510         ioc->base_add_sg_single(psge, sgl_flags |
1511             sizeof(struct phy_control_reply), data_out_dma +
1512             sizeof(struct phy_control_request));
1513
1514         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
1515             "send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", ioc->name,
1516             (unsigned long long)phy->identify.sas_address, phy->number,
1517             phy_operation));
1518         mpt2sas_base_put_smid_default(ioc, smid);
1519         init_completion(&ioc->transport_cmds.done);
1520         timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1521             10*HZ);
1522
1523         if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1524                 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
1525                     ioc->name, __func__);
1526                 _debug_dump_mf(mpi_request,
1527                     sizeof(Mpi2SmpPassthroughRequest_t)/4);
1528                 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1529                         issue_reset = 1;
1530                 goto issue_host_reset;
1531         }
1532
1533         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
1534             "complete\n", ioc->name));
1535
1536         if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1537
1538                 mpi_reply = ioc->transport_cmds.reply;
1539
1540                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1541                     "phy_control - reply data transfer size(%d)\n",
1542                     ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1543
1544                 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1545                     sizeof(struct phy_control_reply))
1546                         goto out;
1547
1548                 phy_control_reply = data_out +
1549                     sizeof(struct phy_control_request);
1550
1551                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1552                     "phy_control - function_result(%d)\n",
1553                     ioc->name, phy_control_reply->function_result));
1554
1555                 rc = 0;
1556         } else
1557                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1558                     "phy_control - no reply\n", ioc->name));
1559
1560  issue_host_reset:
1561         if (issue_reset)
1562                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1563                     FORCE_BIG_HAMMER);
1564  out:
1565         ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1566         if (data_out)
1567                 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1568
1569         mutex_unlock(&ioc->transport_cmds.mutex);
1570         return rc;
1571 }
1572
1573 /**
1574  * _transport_phy_reset -
1575  * @phy: The sas phy object
1576  * @hard_reset:
1577  *
1578  * Returns 0 for success, non-zero for failure.
1579  */
1580 static int
1581 _transport_phy_reset(struct sas_phy *phy, int hard_reset)
1582 {
1583         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1584         Mpi2SasIoUnitControlReply_t mpi_reply;
1585         Mpi2SasIoUnitControlRequest_t mpi_request;
1586         unsigned long flags;
1587
1588         spin_lock_irqsave(&ioc->sas_node_lock, flags);
1589         if (_transport_sas_node_find_by_sas_address(ioc,
1590             phy->identify.sas_address) == NULL) {
1591                 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1592                 return -EINVAL;
1593         }
1594         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1595
1596         /* handle expander phys */
1597         if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1598                 return _transport_expander_phy_control(ioc, phy,
1599                     (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
1600                     SMP_PHY_CONTROL_LINK_RESET);
1601
1602         /* handle hba phys */
1603         memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
1604         mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
1605         mpi_request.Operation = hard_reset ?
1606             MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
1607         mpi_request.PhyNum = phy->number;
1608
1609         if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
1610                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1611                     ioc->name, __FILE__, __LINE__, __func__);
1612                 return -ENXIO;
1613         }
1614
1615         if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1616                 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1617                     "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1618                     phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1619                     le32_to_cpu(mpi_reply.IOCLogInfo));
1620
1621         return 0;
1622 }
1623
1624 /**
1625  * _transport_phy_enable - enable/disable phys
1626  * @phy: The sas phy object
1627  * @enable: enable phy when true
1628  *
1629  * Only support sas_host direct attached phys.
1630  * Returns 0 for success, non-zero for failure.
1631  */
1632 static int
1633 _transport_phy_enable(struct sas_phy *phy, int enable)
1634 {
1635         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1636         Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1637         Mpi2ConfigReply_t mpi_reply;
1638         u16 ioc_status;
1639         u16 sz;
1640         int rc = 0;
1641         unsigned long flags;
1642
1643         spin_lock_irqsave(&ioc->sas_node_lock, flags);
1644         if (_transport_sas_node_find_by_sas_address(ioc,
1645             phy->identify.sas_address) == NULL) {
1646                 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1647                 return -EINVAL;
1648         }
1649         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1650
1651         /* handle expander phys */
1652         if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1653                 return _transport_expander_phy_control(ioc, phy,
1654                     (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
1655                     SMP_PHY_CONTROL_DISABLE);
1656
1657         /* handle hba phys */
1658
1659         /* sas_iounit page 1 */
1660         sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1661             sizeof(Mpi2SasIOUnit1PhyData_t));
1662         sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1663         if (!sas_iounit_pg1) {
1664                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1665                     ioc->name, __FILE__, __LINE__, __func__);
1666                 rc = -ENOMEM;
1667                 goto out;
1668         }
1669         if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1670             sas_iounit_pg1, sz))) {
1671                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1672                     ioc->name, __FILE__, __LINE__, __func__);
1673                 rc = -ENXIO;
1674                 goto out;
1675         }
1676         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1677             MPI2_IOCSTATUS_MASK;
1678         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1679                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1680                     ioc->name, __FILE__, __LINE__, __func__);
1681                 rc = -EIO;
1682                 goto out;
1683         }
1684
1685         if (enable)
1686                 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1687                     &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1688         else
1689                 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1690                     |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1691
1692         mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1693
1694         /* link reset */
1695         if (enable)
1696                 _transport_phy_reset(phy, 0);
1697
1698  out:
1699         kfree(sas_iounit_pg1);
1700         return rc;
1701 }
1702
1703 /**
1704  * _transport_phy_speed - set phy min/max link rates
1705  * @phy: The sas phy object
1706  * @rates: rates defined in sas_phy_linkrates
1707  *
1708  * Only support sas_host direct attached phys.
1709  * Returns 0 for success, non-zero for failure.
1710  */
1711 static int
1712 _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1713 {
1714         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1715         Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1716         Mpi2SasPhyPage0_t phy_pg0;
1717         Mpi2ConfigReply_t mpi_reply;
1718         u16 ioc_status;
1719         u16 sz;
1720         int i;
1721         int rc = 0;
1722         unsigned long flags;
1723
1724         spin_lock_irqsave(&ioc->sas_node_lock, flags);
1725         if (_transport_sas_node_find_by_sas_address(ioc,
1726             phy->identify.sas_address) == NULL) {
1727                 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1728                 return -EINVAL;
1729         }
1730         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1731
1732         if (!rates->minimum_linkrate)
1733                 rates->minimum_linkrate = phy->minimum_linkrate;
1734         else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
1735                 rates->minimum_linkrate = phy->minimum_linkrate_hw;
1736
1737         if (!rates->maximum_linkrate)
1738                 rates->maximum_linkrate = phy->maximum_linkrate;
1739         else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
1740                 rates->maximum_linkrate = phy->maximum_linkrate_hw;
1741
1742         /* handle expander phys */
1743         if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
1744                 phy->minimum_linkrate = rates->minimum_linkrate;
1745                 phy->maximum_linkrate = rates->maximum_linkrate;
1746                 return _transport_expander_phy_control(ioc, phy,
1747                     SMP_PHY_CONTROL_LINK_RESET);
1748         }
1749
1750         /* handle hba phys */
1751
1752         /* sas_iounit page 1 */
1753         sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1754             sizeof(Mpi2SasIOUnit1PhyData_t));
1755         sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1756         if (!sas_iounit_pg1) {
1757                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1758                     ioc->name, __FILE__, __LINE__, __func__);
1759                 rc = -ENOMEM;
1760                 goto out;
1761         }
1762         if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1763             sas_iounit_pg1, sz))) {
1764                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1765                     ioc->name, __FILE__, __LINE__, __func__);
1766                 rc = -ENXIO;
1767                 goto out;
1768         }
1769         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1770             MPI2_IOCSTATUS_MASK;
1771         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1772                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1773                     ioc->name, __FILE__, __LINE__, __func__);
1774                 rc = -EIO;
1775                 goto out;
1776         }
1777
1778         for (i = 0; i < ioc->sas_hba.num_phys; i++) {
1779                 if (phy->number != i) {
1780                         sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1781                             (ioc->sas_hba.phy[i].phy->minimum_linkrate +
1782                             (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
1783                 } else {
1784                         sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1785                             (rates->minimum_linkrate +
1786                             (rates->maximum_linkrate << 4));
1787                 }
1788         }
1789
1790         if (mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
1791             sz)) {
1792                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1793                     ioc->name, __FILE__, __LINE__, __func__);
1794                 rc = -ENXIO;
1795                 goto out;
1796         }
1797
1798         /* link reset */
1799         _transport_phy_reset(phy, 0);
1800
1801         /* read phy page 0, then update the rates in the sas transport phy */
1802         if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
1803             phy->number)) {
1804                 phy->minimum_linkrate = _transport_convert_phy_link_rate(
1805                     phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1806                 phy->maximum_linkrate = _transport_convert_phy_link_rate(
1807                     phy_pg0.ProgrammedLinkRate >> 4);
1808                 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1809                     phy_pg0.NegotiatedLinkRate &
1810                     MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1811         }
1812
1813  out:
1814         kfree(sas_iounit_pg1);
1815         return rc;
1816 }
1817
1818
1819 /**
1820  * _transport_smp_handler - transport portal for smp passthru
1821  * @shost: shost object
1822  * @rphy: sas transport rphy object
1823  * @req:
1824  *
1825  * This used primarily for smp_utils.
1826  * Example:
1827  *           smp_rep_general /sys/class/bsg/expander-5:0
1828  */
1829 static int
1830 _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1831     struct request *req)
1832 {
1833         struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1834         Mpi2SmpPassthroughRequest_t *mpi_request;
1835         Mpi2SmpPassthroughReply_t *mpi_reply;
1836         int rc;
1837         u16 smid;
1838         u32 ioc_state;
1839         unsigned long timeleft;
1840         void *psge;
1841         u32 sgl_flags;
1842         u8 issue_reset = 0;
1843         dma_addr_t dma_addr_in = 0;
1844         dma_addr_t dma_addr_out = 0;
1845         u16 wait_state_count;
1846         struct request *rsp = req->next_rq;
1847
1848         if (!rsp) {
1849                 printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
1850                     "missing\n", ioc->name, __func__);
1851                 return -EINVAL;
1852         }
1853
1854         /* do we need to support multiple segments? */
1855         if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
1856                 printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, "
1857                     "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt,
1858                     blk_rq_bytes(req), rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
1859                 return -EINVAL;
1860         }
1861
1862         if (ioc->shost_recovery) {
1863                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1864                     __func__, ioc->name);
1865                 return -EFAULT;
1866         }
1867
1868         rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1869         if (rc)
1870                 return rc;
1871
1872         if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1873                 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
1874                     __func__);
1875                 rc = -EAGAIN;
1876                 goto out;
1877         }
1878         ioc->transport_cmds.status = MPT2_CMD_PENDING;
1879
1880         wait_state_count = 0;
1881         ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1882         while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1883                 if (wait_state_count++ == 10) {
1884                         printk(MPT2SAS_ERR_FMT
1885                             "%s: failed due to ioc not operational\n",
1886                             ioc->name, __func__);
1887                         rc = -EFAULT;
1888                         goto out;
1889                 }
1890                 ssleep(1);
1891                 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1892                 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1893                     "operational state(count=%d)\n", ioc->name,
1894                     __func__, wait_state_count);
1895         }
1896         if (wait_state_count)
1897                 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1898                     ioc->name, __func__);
1899
1900         smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1901         if (!smid) {
1902                 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1903                     ioc->name, __func__);
1904                 rc = -EAGAIN;
1905                 goto out;
1906         }
1907
1908         rc = 0;
1909         mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1910         ioc->transport_cmds.smid = smid;
1911
1912         memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1913         mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1914         mpi_request->PhysicalPort = 0xFF;
1915         mpi_request->VF_ID = 0; /* TODO */
1916         mpi_request->VP_ID = 0;
1917         *((u64 *)&mpi_request->SASAddress) = (rphy) ?
1918             cpu_to_le64(rphy->identify.sas_address) :
1919             cpu_to_le64(ioc->sas_hba.sas_address);
1920         mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
1921         psge = &mpi_request->SGL;
1922
1923         /* WRITE sgel first */
1924         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1925             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1926         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1927         dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
1928                 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
1929         if (!dma_addr_out) {
1930                 mpt2sas_base_free_smid(ioc, smid);
1931                 goto unmap;
1932         }
1933
1934         ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(req) - 4),
1935             dma_addr_out);
1936
1937         /* incr sgel */
1938         psge += ioc->sge_size;
1939
1940         /* READ sgel last */
1941         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1942             MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1943             MPI2_SGE_FLAGS_END_OF_LIST);
1944         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1945         dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
1946                                      blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
1947         if (!dma_addr_in) {
1948                 mpt2sas_base_free_smid(ioc, smid);
1949                 goto unmap;
1950         }
1951
1952         ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4),
1953             dma_addr_in);
1954
1955         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
1956             "sending smp request\n", ioc->name, __func__));
1957
1958         mpt2sas_base_put_smid_default(ioc, smid);
1959         init_completion(&ioc->transport_cmds.done);
1960         timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1961             10*HZ);
1962
1963         if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1964                 printk(MPT2SAS_ERR_FMT "%s : timeout\n",
1965                     __func__, ioc->name);
1966                 _debug_dump_mf(mpi_request,
1967                     sizeof(Mpi2SmpPassthroughRequest_t)/4);
1968                 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1969                         issue_reset = 1;
1970                 goto issue_host_reset;
1971         }
1972
1973         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
1974             "complete\n", ioc->name, __func__));
1975
1976         if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1977
1978                 mpi_reply = ioc->transport_cmds.reply;
1979
1980                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1981                     "%s - reply data transfer size(%d)\n",
1982                     ioc->name, __func__,
1983                     le16_to_cpu(mpi_reply->ResponseDataLength)));
1984
1985                 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
1986                 req->sense_len = sizeof(*mpi_reply);
1987                 req->resid_len = 0;
1988                 rsp->resid_len -=
1989                     le16_to_cpu(mpi_reply->ResponseDataLength);
1990         } else {
1991                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1992                     "%s - no reply\n", ioc->name, __func__));
1993                 rc = -ENXIO;
1994         }
1995
1996  issue_host_reset:
1997         if (issue_reset) {
1998                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1999                     FORCE_BIG_HAMMER);
2000                 rc = -ETIMEDOUT;
2001         }
2002
2003  unmap:
2004         if (dma_addr_out)
2005                 pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
2006                     PCI_DMA_BIDIRECTIONAL);
2007         if (dma_addr_in)
2008                 pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
2009                     PCI_DMA_BIDIRECTIONAL);
2010
2011  out:
2012         ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
2013         mutex_unlock(&ioc->transport_cmds.mutex);
2014         return rc;
2015 }
2016
2017 struct sas_function_template mpt2sas_transport_functions = {
2018         .get_linkerrors         = _transport_get_linkerrors,
2019         .get_enclosure_identifier = _transport_get_enclosure_identifier,
2020         .get_bay_identifier     = _transport_get_bay_identifier,
2021         .phy_reset              = _transport_phy_reset,
2022         .phy_enable             = _transport_phy_enable,
2023         .set_phy_speed          = _transport_phy_speed,
2024         .smp_handler            = _transport_smp_handler,
2025 };
2026
2027 struct scsi_transport_template *mpt2sas_transport_template;