Merge branch 'fbdev/udlfb'
[pandora-kernel.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-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 /**
470  * _transport_delete_duplicate_port - (see below description)
471  * @ioc: per adapter object
472  * @sas_node: sas node object (either expander or sas host)
473  * @sas_address: sas address of device being added
474  * @phy_num: phy number
475  *
476  * This function is called when attempting to add a new port that is claiming
477  * the same phy resources already in use by another port.  If we don't release
478  * the claimed phy resources, the sas transport layer will hang from the BUG
479  * in sas_port_add_phy.
480  *
481  * The reason we would hit this issue is becuase someone is changing the
482  * sas address of a device on the fly, meanwhile controller firmware sends
483  * EVENTs out of order when removing the previous instance of the device.
484  */
485 static void
486 _transport_delete_duplicate_port(struct MPT2SAS_ADAPTER *ioc,
487     struct _sas_node *sas_node, u64 sas_address, int phy_num)
488 {
489         struct _sas_port *mpt2sas_port, *mpt2sas_port_duplicate;
490         struct _sas_phy *mpt2sas_phy;
491
492         printk(MPT2SAS_ERR_FMT "new device located at sas_addr(0x%016llx), "
493             "phy_id(%d)\n", ioc->name, (unsigned long long)sas_address,
494             phy_num);
495
496         mpt2sas_port_duplicate = NULL;
497         list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list, port_list) {
498                 dev_printk(KERN_ERR, &mpt2sas_port->port->dev,
499                     "existing device at sas_addr(0x%016llx), num_phys(%d)\n",
500                     (unsigned long long)
501                     mpt2sas_port->remote_identify.sas_address,
502                     mpt2sas_port->num_phys);
503                 list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
504                     port_siblings) {
505                         dev_printk(KERN_ERR, &mpt2sas_phy->phy->dev,
506                             "phy_number(%d)\n", mpt2sas_phy->phy_id);
507                         if (mpt2sas_phy->phy_id == phy_num)
508                                 mpt2sas_port_duplicate = mpt2sas_port;
509                 }
510         }
511
512         if (!mpt2sas_port_duplicate)
513                 return;
514
515         dev_printk(KERN_ERR, &mpt2sas_port_duplicate->port->dev,
516             "deleting duplicate device at sas_addr(0x%016llx), phy(%d)!!!!\n",
517             (unsigned long long)
518             mpt2sas_port_duplicate->remote_identify.sas_address, phy_num);
519         ioc->logging_level |= MPT_DEBUG_TRANSPORT;
520         mpt2sas_transport_port_remove(ioc,
521             mpt2sas_port_duplicate->remote_identify.sas_address,
522             sas_node->sas_address);
523         ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
524 }
525
526 /**
527  * _transport_sanity_check - sanity check when adding a new port
528  * @ioc: per adapter object
529  * @sas_node: sas node object (either expander or sas host)
530  * @sas_address: sas address of device being added
531  *
532  * See the explanation above from _transport_delete_duplicate_port
533  */
534 static void
535 _transport_sanity_check(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node,
536      u64 sas_address)
537 {
538         int i;
539
540         for (i = 0; i < sas_node->num_phys; i++)
541                 if (sas_node->phy[i].remote_identify.sas_address == sas_address)
542                         if (sas_node->phy[i].phy_belongs_to_port)
543                                 _transport_delete_duplicate_port(ioc, sas_node,
544                                         sas_address, i);
545 }
546
547 /**
548  * mpt2sas_transport_port_add - insert port to the list
549  * @ioc: per adapter object
550  * @handle: handle of attached device
551  * @sas_address: sas address of parent expander or sas host
552  * Context: This function will acquire ioc->sas_node_lock.
553  *
554  * Adding new port object to the sas_node->sas_port_list.
555  *
556  * Returns mpt2sas_port.
557  */
558 struct _sas_port *
559 mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
560     u64 sas_address)
561 {
562         struct _sas_phy *mpt2sas_phy, *next;
563         struct _sas_port *mpt2sas_port;
564         unsigned long flags;
565         struct _sas_node *sas_node;
566         struct sas_rphy *rphy;
567         int i;
568         struct sas_port *port;
569
570         mpt2sas_port = kzalloc(sizeof(struct _sas_port),
571             GFP_KERNEL);
572         if (!mpt2sas_port) {
573                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
574                     ioc->name, __FILE__, __LINE__, __func__);
575                 return NULL;
576         }
577
578         INIT_LIST_HEAD(&mpt2sas_port->port_list);
579         INIT_LIST_HEAD(&mpt2sas_port->phy_list);
580         spin_lock_irqsave(&ioc->sas_node_lock, flags);
581         sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
582         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
583
584         if (!sas_node) {
585                 printk(MPT2SAS_ERR_FMT "%s: Could not find "
586                     "parent sas_address(0x%016llx)!\n", ioc->name,
587                     __func__, (unsigned long long)sas_address);
588                 goto out_fail;
589         }
590
591         if ((_transport_set_identify(ioc, handle,
592             &mpt2sas_port->remote_identify))) {
593                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
594                     ioc->name, __FILE__, __LINE__, __func__);
595                 goto out_fail;
596         }
597
598         if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
599                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
600                     ioc->name, __FILE__, __LINE__, __func__);
601                 goto out_fail;
602         }
603
604         _transport_sanity_check(ioc, sas_node,
605             mpt2sas_port->remote_identify.sas_address);
606
607         for (i = 0; i < sas_node->num_phys; i++) {
608                 if (sas_node->phy[i].remote_identify.sas_address !=
609                     mpt2sas_port->remote_identify.sas_address)
610                         continue;
611                 list_add_tail(&sas_node->phy[i].port_siblings,
612                     &mpt2sas_port->phy_list);
613                 mpt2sas_port->num_phys++;
614         }
615
616         if (!mpt2sas_port->num_phys) {
617                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
618                     ioc->name, __FILE__, __LINE__, __func__);
619                 goto out_fail;
620         }
621
622         port = sas_port_alloc_num(sas_node->parent_dev);
623         if ((sas_port_add(port))) {
624                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
625                     ioc->name, __FILE__, __LINE__, __func__);
626                 goto out_fail;
627         }
628
629         list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
630             port_siblings) {
631                 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
632                         dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
633                             ", sas_addr(0x%016llx), phy(%d)\n", handle,
634                             (unsigned long long)
635                             mpt2sas_port->remote_identify.sas_address,
636                             mpt2sas_phy->phy_id);
637                 sas_port_add_phy(port, mpt2sas_phy->phy);
638                 mpt2sas_phy->phy_belongs_to_port = 1;
639         }
640
641         mpt2sas_port->port = port;
642         if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
643                 rphy = sas_end_device_alloc(port);
644         else
645                 rphy = sas_expander_alloc(port,
646                     mpt2sas_port->remote_identify.device_type);
647
648         rphy->identify = mpt2sas_port->remote_identify;
649         if ((sas_rphy_add(rphy))) {
650                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
651                     ioc->name, __FILE__, __LINE__, __func__);
652         }
653         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
654                 dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
655                     "sas_addr(0x%016llx)\n", handle,
656                     (unsigned long long)
657                     mpt2sas_port->remote_identify.sas_address);
658         mpt2sas_port->rphy = rphy;
659         spin_lock_irqsave(&ioc->sas_node_lock, flags);
660         list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
661         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
662
663         /* fill in report manufacture */
664         if (mpt2sas_port->remote_identify.device_type ==
665             MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
666             mpt2sas_port->remote_identify.device_type ==
667             MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
668                 _transport_expander_report_manufacture(ioc,
669                     mpt2sas_port->remote_identify.sas_address,
670                     rphy_to_expander_device(rphy));
671
672         return mpt2sas_port;
673
674  out_fail:
675         list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
676             port_siblings)
677                 list_del(&mpt2sas_phy->port_siblings);
678         kfree(mpt2sas_port);
679         return NULL;
680 }
681
682 /**
683  * mpt2sas_transport_port_remove - remove port from the list
684  * @ioc: per adapter object
685  * @sas_address: sas address of attached device
686  * @sas_address_parent: sas address of parent expander or sas host
687  * Context: This function will acquire ioc->sas_node_lock.
688  *
689  * Removing object and freeing associated memory from the
690  * ioc->sas_port_list.
691  *
692  * Return nothing.
693  */
694 void
695 mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
696     u64 sas_address_parent)
697 {
698         int i;
699         unsigned long flags;
700         struct _sas_port *mpt2sas_port, *next;
701         struct _sas_node *sas_node;
702         u8 found = 0;
703         struct _sas_phy *mpt2sas_phy, *next_phy;
704
705         spin_lock_irqsave(&ioc->sas_node_lock, flags);
706         sas_node = _transport_sas_node_find_by_sas_address(ioc,
707             sas_address_parent);
708         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
709         if (!sas_node)
710                 return;
711         list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
712             port_list) {
713                 if (mpt2sas_port->remote_identify.sas_address != sas_address)
714                         continue;
715                 found = 1;
716                 list_del(&mpt2sas_port->port_list);
717                 goto out;
718         }
719  out:
720         if (!found)
721                 return;
722
723         for (i = 0; i < sas_node->num_phys; i++) {
724                 if (sas_node->phy[i].remote_identify.sas_address == sas_address)
725                         memset(&sas_node->phy[i].remote_identify, 0 ,
726                             sizeof(struct sas_identify));
727         }
728
729         list_for_each_entry_safe(mpt2sas_phy, next_phy,
730             &mpt2sas_port->phy_list, port_siblings) {
731                 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
732                         dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
733                             "remove: sas_addr(0x%016llx), phy(%d)\n",
734                             (unsigned long long)
735                             mpt2sas_port->remote_identify.sas_address,
736                             mpt2sas_phy->phy_id);
737                 mpt2sas_phy->phy_belongs_to_port = 0;
738                 sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
739                 list_del(&mpt2sas_phy->port_siblings);
740         }
741         sas_port_delete(mpt2sas_port->port);
742         kfree(mpt2sas_port);
743 }
744
745 /**
746  * mpt2sas_transport_add_host_phy - report sas_host phy to transport
747  * @ioc: per adapter object
748  * @mpt2sas_phy: mpt2sas per phy object
749  * @phy_pg0: sas phy page 0
750  * @parent_dev: parent device class object
751  *
752  * Returns 0 for success, non-zero for failure.
753  */
754 int
755 mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
756     *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
757 {
758         struct sas_phy *phy;
759         int phy_index = mpt2sas_phy->phy_id;
760
761
762         INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
763         phy = sas_phy_alloc(parent_dev, phy_index);
764         if (!phy) {
765                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
766                     ioc->name, __FILE__, __LINE__, __func__);
767                 return -1;
768         }
769         if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
770             &mpt2sas_phy->identify))) {
771                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
772                     ioc->name, __FILE__, __LINE__, __func__);
773                 return -1;
774         }
775         phy->identify = mpt2sas_phy->identify;
776         mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
777         if (mpt2sas_phy->attached_handle)
778                 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
779                     &mpt2sas_phy->remote_identify);
780         phy->identify.phy_identifier = mpt2sas_phy->phy_id;
781         phy->negotiated_linkrate = _transport_convert_phy_link_rate(
782             phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
783         phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
784             phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
785         phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
786             phy_pg0.HwLinkRate >> 4);
787         phy->minimum_linkrate = _transport_convert_phy_link_rate(
788             phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
789         phy->maximum_linkrate = _transport_convert_phy_link_rate(
790             phy_pg0.ProgrammedLinkRate >> 4);
791
792         if ((sas_phy_add(phy))) {
793                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
794                     ioc->name, __FILE__, __LINE__, __func__);
795                 sas_phy_free(phy);
796                 return -1;
797         }
798         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
799                 dev_printk(KERN_INFO, &phy->dev,
800                     "add: handle(0x%04x), sas_addr(0x%016llx)\n"
801                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
802                     mpt2sas_phy->handle, (unsigned long long)
803                     mpt2sas_phy->identify.sas_address,
804                     mpt2sas_phy->attached_handle,
805                     (unsigned long long)
806                     mpt2sas_phy->remote_identify.sas_address);
807         mpt2sas_phy->phy = phy;
808         return 0;
809 }
810
811
812 /**
813  * mpt2sas_transport_add_expander_phy - report expander phy to transport
814  * @ioc: per adapter object
815  * @mpt2sas_phy: mpt2sas per phy object
816  * @expander_pg1: expander page 1
817  * @parent_dev: parent device class object
818  *
819  * Returns 0 for success, non-zero for failure.
820  */
821 int
822 mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
823     *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
824 {
825         struct sas_phy *phy;
826         int phy_index = mpt2sas_phy->phy_id;
827
828         INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
829         phy = sas_phy_alloc(parent_dev, phy_index);
830         if (!phy) {
831                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
832                     ioc->name, __FILE__, __LINE__, __func__);
833                 return -1;
834         }
835         if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
836             &mpt2sas_phy->identify))) {
837                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
838                     ioc->name, __FILE__, __LINE__, __func__);
839                 return -1;
840         }
841         phy->identify = mpt2sas_phy->identify;
842         mpt2sas_phy->attached_handle =
843             le16_to_cpu(expander_pg1.AttachedDevHandle);
844         if (mpt2sas_phy->attached_handle)
845                 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
846                     &mpt2sas_phy->remote_identify);
847         phy->identify.phy_identifier = mpt2sas_phy->phy_id;
848         phy->negotiated_linkrate = _transport_convert_phy_link_rate(
849             expander_pg1.NegotiatedLinkRate &
850             MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
851         phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
852             expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
853         phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
854             expander_pg1.HwLinkRate >> 4);
855         phy->minimum_linkrate = _transport_convert_phy_link_rate(
856             expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
857         phy->maximum_linkrate = _transport_convert_phy_link_rate(
858             expander_pg1.ProgrammedLinkRate >> 4);
859
860         if ((sas_phy_add(phy))) {
861                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
862                     ioc->name, __FILE__, __LINE__, __func__);
863                 sas_phy_free(phy);
864                 return -1;
865         }
866         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
867                 dev_printk(KERN_INFO, &phy->dev,
868                     "add: handle(0x%04x), sas_addr(0x%016llx)\n"
869                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
870                     mpt2sas_phy->handle, (unsigned long long)
871                     mpt2sas_phy->identify.sas_address,
872                     mpt2sas_phy->attached_handle,
873                     (unsigned long long)
874                     mpt2sas_phy->remote_identify.sas_address);
875         mpt2sas_phy->phy = phy;
876         return 0;
877 }
878
879 /**
880  * mpt2sas_transport_update_links - refreshing phy link changes
881  * @ioc: per adapter object
882  * @sas_address: sas address of parent expander or sas host
883  * @handle: attached device handle
884  * @phy_numberv: phy number
885  * @link_rate: new link rate
886  *
887  * Returns nothing.
888  */
889 void
890 mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
891      u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
892 {
893         unsigned long flags;
894         struct _sas_node *sas_node;
895         struct _sas_phy *mpt2sas_phy;
896
897         if (ioc->shost_recovery || ioc->pci_error_recovery)
898                 return;
899
900         spin_lock_irqsave(&ioc->sas_node_lock, flags);
901         sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
902         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
903         if (!sas_node)
904                 return;
905
906         mpt2sas_phy = &sas_node->phy[phy_number];
907         mpt2sas_phy->attached_handle = handle;
908         if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5))
909                 _transport_set_identify(ioc, handle,
910                     &mpt2sas_phy->remote_identify);
911         else
912                 memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
913                     sas_identify));
914
915         if (mpt2sas_phy->phy)
916                 mpt2sas_phy->phy->negotiated_linkrate =
917                     _transport_convert_phy_link_rate(link_rate);
918
919         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
920                 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
921                     "refresh: parent sas_addr(0x%016llx),\n"
922                     "\tlink_rate(0x%02x), phy(%d)\n"
923                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
924                     (unsigned long long)sas_address,
925                     link_rate, phy_number, handle, (unsigned long long)
926                     mpt2sas_phy->remote_identify.sas_address);
927 }
928
929 static inline void *
930 phy_to_ioc(struct sas_phy *phy)
931 {
932         struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
933         return shost_priv(shost);
934 }
935
936 static inline void *
937 rphy_to_ioc(struct sas_rphy *rphy)
938 {
939         struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
940         return shost_priv(shost);
941 }
942
943
944 /* report phy error log structure */
945 struct phy_error_log_request{
946         u8 smp_frame_type; /* 0x40 */
947         u8 function; /* 0x11 */
948         u8 allocated_response_length;
949         u8 request_length; /* 02 */
950         u8 reserved_1[5];
951         u8 phy_identifier;
952         u8 reserved_2[2];
953 };
954
955 /* report phy error log reply structure */
956 struct phy_error_log_reply{
957         u8 smp_frame_type; /* 0x41 */
958         u8 function; /* 0x11 */
959         u8 function_result;
960         u8 response_length;
961         u16 expander_change_count;
962         u8 reserved_1[3];
963         u8 phy_identifier;
964         u8 reserved_2[2];
965         u32 invalid_dword;
966         u32 running_disparity_error;
967         u32 loss_of_dword_sync;
968         u32 phy_reset_problem;
969 };
970
971 /**
972  * _transport_get_expander_phy_error_log - return expander counters
973  * @ioc: per adapter object
974  * @phy: The sas phy object
975  *
976  * Returns 0 for success, non-zero for failure.
977  *
978  */
979 static int
980 _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
981     struct sas_phy *phy)
982 {
983         Mpi2SmpPassthroughRequest_t *mpi_request;
984         Mpi2SmpPassthroughReply_t *mpi_reply;
985         struct phy_error_log_request *phy_error_log_request;
986         struct phy_error_log_reply *phy_error_log_reply;
987         int rc;
988         u16 smid;
989         u32 ioc_state;
990         unsigned long timeleft;
991         void *psge;
992         u32 sgl_flags;
993         u8 issue_reset = 0;
994         void *data_out = NULL;
995         dma_addr_t data_out_dma;
996         u32 sz;
997         u64 *sas_address_le;
998         u16 wait_state_count;
999
1000         if (ioc->shost_recovery || ioc->pci_error_recovery) {
1001                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1002                     __func__, ioc->name);
1003                 return -EFAULT;
1004         }
1005
1006         mutex_lock(&ioc->transport_cmds.mutex);
1007
1008         if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1009                 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
1010                     ioc->name, __func__);
1011                 rc = -EAGAIN;
1012                 goto out;
1013         }
1014         ioc->transport_cmds.status = MPT2_CMD_PENDING;
1015
1016         wait_state_count = 0;
1017         ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1018         while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1019                 if (wait_state_count++ == 10) {
1020                         printk(MPT2SAS_ERR_FMT
1021                             "%s: failed due to ioc not operational\n",
1022                             ioc->name, __func__);
1023                         rc = -EFAULT;
1024                         goto out;
1025                 }
1026                 ssleep(1);
1027                 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1028                 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1029                     "operational state(count=%d)\n", ioc->name,
1030                     __func__, wait_state_count);
1031         }
1032         if (wait_state_count)
1033                 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1034                     ioc->name, __func__);
1035
1036         smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1037         if (!smid) {
1038                 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1039                     ioc->name, __func__);
1040                 rc = -EAGAIN;
1041                 goto out;
1042         }
1043
1044         mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1045         ioc->transport_cmds.smid = smid;
1046
1047         sz = sizeof(struct phy_error_log_request) +
1048             sizeof(struct phy_error_log_reply);
1049         data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1050         if (!data_out) {
1051                 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
1052                     __LINE__, __func__);
1053                 rc = -ENOMEM;
1054                 mpt2sas_base_free_smid(ioc, smid);
1055                 goto out;
1056         }
1057
1058         rc = -EINVAL;
1059         memset(data_out, 0, sz);
1060         phy_error_log_request = data_out;
1061         phy_error_log_request->smp_frame_type = 0x40;
1062         phy_error_log_request->function = 0x11;
1063         phy_error_log_request->request_length = 2;
1064         phy_error_log_request->allocated_response_length = 0;
1065         phy_error_log_request->phy_identifier = phy->number;
1066
1067         memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1068         mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1069         mpi_request->PhysicalPort = 0xFF;
1070         mpi_request->VF_ID = 0; /* TODO */
1071         mpi_request->VP_ID = 0;
1072         sas_address_le = (u64 *)&mpi_request->SASAddress;
1073         *sas_address_le = cpu_to_le64(phy->identify.sas_address);
1074         mpi_request->RequestDataLength =
1075             cpu_to_le16(sizeof(struct phy_error_log_request));
1076         psge = &mpi_request->SGL;
1077
1078         /* WRITE sgel first */
1079         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1080             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1081         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1082         ioc->base_add_sg_single(psge, sgl_flags |
1083             sizeof(struct phy_error_log_request), data_out_dma);
1084
1085         /* incr sgel */
1086         psge += ioc->sge_size;
1087
1088         /* READ sgel last */
1089         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1090             MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1091             MPI2_SGE_FLAGS_END_OF_LIST);
1092         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1093         ioc->base_add_sg_single(psge, sgl_flags |
1094             sizeof(struct phy_error_log_reply), data_out_dma +
1095             sizeof(struct phy_error_log_request));
1096
1097         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
1098             "send to sas_addr(0x%016llx), phy(%d)\n", ioc->name,
1099             (unsigned long long)phy->identify.sas_address, phy->number));
1100         mpt2sas_base_put_smid_default(ioc, smid);
1101         init_completion(&ioc->transport_cmds.done);
1102         timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1103             10*HZ);
1104
1105         if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1106                 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
1107                     ioc->name, __func__);
1108                 _debug_dump_mf(mpi_request,
1109                     sizeof(Mpi2SmpPassthroughRequest_t)/4);
1110                 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1111                         issue_reset = 1;
1112                 goto issue_host_reset;
1113         }
1114
1115         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
1116             "complete\n", ioc->name));
1117
1118         if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1119
1120                 mpi_reply = ioc->transport_cmds.reply;
1121
1122                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1123                     "phy_error_log - reply data transfer size(%d)\n",
1124                     ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1125
1126                 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1127                     sizeof(struct phy_error_log_reply))
1128                         goto out;
1129
1130                 phy_error_log_reply = data_out +
1131                     sizeof(struct phy_error_log_request);
1132
1133                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1134                     "phy_error_log - function_result(%d)\n",
1135                     ioc->name, phy_error_log_reply->function_result));
1136
1137                 phy->invalid_dword_count =
1138                     be32_to_cpu(phy_error_log_reply->invalid_dword);
1139                 phy->running_disparity_error_count =
1140                     be32_to_cpu(phy_error_log_reply->running_disparity_error);
1141                 phy->loss_of_dword_sync_count =
1142                     be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
1143                 phy->phy_reset_problem_count =
1144                     be32_to_cpu(phy_error_log_reply->phy_reset_problem);
1145                 rc = 0;
1146         } else
1147                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1148                     "phy_error_log - no reply\n", ioc->name));
1149
1150  issue_host_reset:
1151         if (issue_reset)
1152                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1153                     FORCE_BIG_HAMMER);
1154  out:
1155         ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1156         if (data_out)
1157                 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1158
1159         mutex_unlock(&ioc->transport_cmds.mutex);
1160         return rc;
1161 }
1162
1163 /**
1164  * _transport_get_linkerrors - return phy counters for both hba and expanders
1165  * @phy: The sas phy object
1166  *
1167  * Returns 0 for success, non-zero for failure.
1168  *
1169  */
1170 static int
1171 _transport_get_linkerrors(struct sas_phy *phy)
1172 {
1173         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1174         unsigned long flags;
1175         Mpi2ConfigReply_t mpi_reply;
1176         Mpi2SasPhyPage1_t phy_pg1;
1177
1178         spin_lock_irqsave(&ioc->sas_node_lock, flags);
1179         if (_transport_sas_node_find_by_sas_address(ioc,
1180             phy->identify.sas_address) == NULL) {
1181                 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1182                 return -EINVAL;
1183         }
1184         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1185
1186         if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1187                 return _transport_get_expander_phy_error_log(ioc, phy);
1188
1189         /* get hba phy error logs */
1190         if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
1191                     phy->number))) {
1192                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1193                     ioc->name, __FILE__, __LINE__, __func__);
1194                 return -ENXIO;
1195         }
1196
1197         if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1198                 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1199                     "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1200                     phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1201                     le32_to_cpu(mpi_reply.IOCLogInfo));
1202
1203         phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
1204         phy->running_disparity_error_count =
1205             le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
1206         phy->loss_of_dword_sync_count =
1207             le32_to_cpu(phy_pg1.LossDwordSynchCount);
1208         phy->phy_reset_problem_count =
1209             le32_to_cpu(phy_pg1.PhyResetProblemCount);
1210         return 0;
1211 }
1212
1213 /**
1214  * _transport_get_enclosure_identifier -
1215  * @phy: The sas phy object
1216  *
1217  * Obtain the enclosure logical id for an expander.
1218  * Returns 0 for success, non-zero for failure.
1219  */
1220 static int
1221 _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1222 {
1223         struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1224         struct _sas_device *sas_device;
1225         unsigned long flags;
1226
1227         spin_lock_irqsave(&ioc->sas_device_lock, flags);
1228         sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1229             rphy->identify.sas_address);
1230         spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1231
1232         if (!sas_device)
1233                 return -ENXIO;
1234
1235         *identifier = sas_device->enclosure_logical_id;
1236         return 0;
1237 }
1238
1239 /**
1240  * _transport_get_bay_identifier -
1241  * @phy: The sas phy object
1242  *
1243  * Returns the slot id for a device that resides inside an enclosure.
1244  */
1245 static int
1246 _transport_get_bay_identifier(struct sas_rphy *rphy)
1247 {
1248         struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1249         struct _sas_device *sas_device;
1250         unsigned long flags;
1251
1252         spin_lock_irqsave(&ioc->sas_device_lock, flags);
1253         sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1254             rphy->identify.sas_address);
1255         spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1256
1257         if (!sas_device)
1258                 return -ENXIO;
1259
1260         return sas_device->slot;
1261 }
1262
1263 /* phy control request structure */
1264 struct phy_control_request{
1265         u8 smp_frame_type; /* 0x40 */
1266         u8 function; /* 0x91 */
1267         u8 allocated_response_length;
1268         u8 request_length; /* 0x09 */
1269         u16 expander_change_count;
1270         u8 reserved_1[3];
1271         u8 phy_identifier;
1272         u8 phy_operation;
1273         u8 reserved_2[13];
1274         u64 attached_device_name;
1275         u8 programmed_min_physical_link_rate;
1276         u8 programmed_max_physical_link_rate;
1277         u8 reserved_3[6];
1278 };
1279
1280 /* phy control reply structure */
1281 struct phy_control_reply{
1282         u8 smp_frame_type; /* 0x41 */
1283         u8 function; /* 0x11 */
1284         u8 function_result;
1285         u8 response_length;
1286 };
1287
1288 #define SMP_PHY_CONTROL_LINK_RESET      (0x01)
1289 #define SMP_PHY_CONTROL_HARD_RESET      (0x02)
1290 #define SMP_PHY_CONTROL_DISABLE         (0x03)
1291
1292 /**
1293  * _transport_expander_phy_control - expander phy control
1294  * @ioc: per adapter object
1295  * @phy: The sas phy object
1296  *
1297  * Returns 0 for success, non-zero for failure.
1298  *
1299  */
1300 static int
1301 _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
1302     struct sas_phy *phy, u8 phy_operation)
1303 {
1304         Mpi2SmpPassthroughRequest_t *mpi_request;
1305         Mpi2SmpPassthroughReply_t *mpi_reply;
1306         struct phy_control_request *phy_control_request;
1307         struct phy_control_reply *phy_control_reply;
1308         int rc;
1309         u16 smid;
1310         u32 ioc_state;
1311         unsigned long timeleft;
1312         void *psge;
1313         u32 sgl_flags;
1314         u8 issue_reset = 0;
1315         void *data_out = NULL;
1316         dma_addr_t data_out_dma;
1317         u32 sz;
1318         u64 *sas_address_le;
1319         u16 wait_state_count;
1320
1321         if (ioc->shost_recovery) {
1322                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1323                     __func__, ioc->name);
1324                 return -EFAULT;
1325         }
1326
1327         mutex_lock(&ioc->transport_cmds.mutex);
1328
1329         if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1330                 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
1331                     ioc->name, __func__);
1332                 rc = -EAGAIN;
1333                 goto out;
1334         }
1335         ioc->transport_cmds.status = MPT2_CMD_PENDING;
1336
1337         wait_state_count = 0;
1338         ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1339         while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1340                 if (wait_state_count++ == 10) {
1341                         printk(MPT2SAS_ERR_FMT
1342                             "%s: failed due to ioc not operational\n",
1343                             ioc->name, __func__);
1344                         rc = -EFAULT;
1345                         goto out;
1346                 }
1347                 ssleep(1);
1348                 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1349                 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1350                     "operational state(count=%d)\n", ioc->name,
1351                     __func__, wait_state_count);
1352         }
1353         if (wait_state_count)
1354                 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1355                     ioc->name, __func__);
1356
1357         smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1358         if (!smid) {
1359                 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1360                     ioc->name, __func__);
1361                 rc = -EAGAIN;
1362                 goto out;
1363         }
1364
1365         mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1366         ioc->transport_cmds.smid = smid;
1367
1368         sz = sizeof(struct phy_control_request) +
1369             sizeof(struct phy_control_reply);
1370         data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1371         if (!data_out) {
1372                 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
1373                     __LINE__, __func__);
1374                 rc = -ENOMEM;
1375                 mpt2sas_base_free_smid(ioc, smid);
1376                 goto out;
1377         }
1378
1379         rc = -EINVAL;
1380         memset(data_out, 0, sz);
1381         phy_control_request = data_out;
1382         phy_control_request->smp_frame_type = 0x40;
1383         phy_control_request->function = 0x91;
1384         phy_control_request->request_length = 9;
1385         phy_control_request->allocated_response_length = 0;
1386         phy_control_request->phy_identifier = phy->number;
1387         phy_control_request->phy_operation = phy_operation;
1388         phy_control_request->programmed_min_physical_link_rate =
1389             phy->minimum_linkrate << 4;
1390         phy_control_request->programmed_max_physical_link_rate =
1391             phy->maximum_linkrate << 4;
1392
1393         memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1394         mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1395         mpi_request->PhysicalPort = 0xFF;
1396         mpi_request->VF_ID = 0; /* TODO */
1397         mpi_request->VP_ID = 0;
1398         sas_address_le = (u64 *)&mpi_request->SASAddress;
1399         *sas_address_le = cpu_to_le64(phy->identify.sas_address);
1400         mpi_request->RequestDataLength =
1401             cpu_to_le16(sizeof(struct phy_error_log_request));
1402         psge = &mpi_request->SGL;
1403
1404         /* WRITE sgel first */
1405         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1406             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1407         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1408         ioc->base_add_sg_single(psge, sgl_flags |
1409             sizeof(struct phy_control_request), data_out_dma);
1410
1411         /* incr sgel */
1412         psge += ioc->sge_size;
1413
1414         /* READ sgel last */
1415         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1416             MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1417             MPI2_SGE_FLAGS_END_OF_LIST);
1418         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1419         ioc->base_add_sg_single(psge, sgl_flags |
1420             sizeof(struct phy_control_reply), data_out_dma +
1421             sizeof(struct phy_control_request));
1422
1423         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
1424             "send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", ioc->name,
1425             (unsigned long long)phy->identify.sas_address, phy->number,
1426             phy_operation));
1427         mpt2sas_base_put_smid_default(ioc, smid);
1428         init_completion(&ioc->transport_cmds.done);
1429         timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1430             10*HZ);
1431
1432         if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1433                 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
1434                     ioc->name, __func__);
1435                 _debug_dump_mf(mpi_request,
1436                     sizeof(Mpi2SmpPassthroughRequest_t)/4);
1437                 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1438                         issue_reset = 1;
1439                 goto issue_host_reset;
1440         }
1441
1442         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
1443             "complete\n", ioc->name));
1444
1445         if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1446
1447                 mpi_reply = ioc->transport_cmds.reply;
1448
1449                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1450                     "phy_control - reply data transfer size(%d)\n",
1451                     ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1452
1453                 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1454                     sizeof(struct phy_control_reply))
1455                         goto out;
1456
1457                 phy_control_reply = data_out +
1458                     sizeof(struct phy_control_request);
1459
1460                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1461                     "phy_control - function_result(%d)\n",
1462                     ioc->name, phy_control_reply->function_result));
1463
1464                 rc = 0;
1465         } else
1466                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1467                     "phy_control - no reply\n", ioc->name));
1468
1469  issue_host_reset:
1470         if (issue_reset)
1471                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1472                     FORCE_BIG_HAMMER);
1473  out:
1474         ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1475         if (data_out)
1476                 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1477
1478         mutex_unlock(&ioc->transport_cmds.mutex);
1479         return rc;
1480 }
1481
1482 /**
1483  * _transport_phy_reset -
1484  * @phy: The sas phy object
1485  * @hard_reset:
1486  *
1487  * Returns 0 for success, non-zero for failure.
1488  */
1489 static int
1490 _transport_phy_reset(struct sas_phy *phy, int hard_reset)
1491 {
1492         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1493         Mpi2SasIoUnitControlReply_t mpi_reply;
1494         Mpi2SasIoUnitControlRequest_t mpi_request;
1495         unsigned long flags;
1496
1497         spin_lock_irqsave(&ioc->sas_node_lock, flags);
1498         if (_transport_sas_node_find_by_sas_address(ioc,
1499             phy->identify.sas_address) == NULL) {
1500                 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1501                 return -EINVAL;
1502         }
1503         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1504
1505         /* handle expander phys */
1506         if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1507                 return _transport_expander_phy_control(ioc, phy,
1508                     (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
1509                     SMP_PHY_CONTROL_LINK_RESET);
1510
1511         /* handle hba phys */
1512         memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
1513         mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
1514         mpi_request.Operation = hard_reset ?
1515             MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
1516         mpi_request.PhyNum = phy->number;
1517
1518         if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
1519                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1520                     ioc->name, __FILE__, __LINE__, __func__);
1521                 return -ENXIO;
1522         }
1523
1524         if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1525                 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1526                     "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1527                     phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1528                     le32_to_cpu(mpi_reply.IOCLogInfo));
1529
1530         return 0;
1531 }
1532
1533 /**
1534  * _transport_phy_enable - enable/disable phys
1535  * @phy: The sas phy object
1536  * @enable: enable phy when true
1537  *
1538  * Only support sas_host direct attached phys.
1539  * Returns 0 for success, non-zero for failure.
1540  */
1541 static int
1542 _transport_phy_enable(struct sas_phy *phy, int enable)
1543 {
1544         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1545         Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1546         Mpi2ConfigReply_t mpi_reply;
1547         u16 ioc_status;
1548         u16 sz;
1549         int rc = 0;
1550         unsigned long flags;
1551
1552         spin_lock_irqsave(&ioc->sas_node_lock, flags);
1553         if (_transport_sas_node_find_by_sas_address(ioc,
1554             phy->identify.sas_address) == NULL) {
1555                 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1556                 return -EINVAL;
1557         }
1558         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1559
1560         /* handle expander phys */
1561         if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1562                 return _transport_expander_phy_control(ioc, phy,
1563                     (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
1564                     SMP_PHY_CONTROL_DISABLE);
1565
1566         /* handle hba phys */
1567
1568         /* sas_iounit page 1 */
1569         sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1570             sizeof(Mpi2SasIOUnit1PhyData_t));
1571         sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1572         if (!sas_iounit_pg1) {
1573                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1574                     ioc->name, __FILE__, __LINE__, __func__);
1575                 rc = -ENOMEM;
1576                 goto out;
1577         }
1578         if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1579             sas_iounit_pg1, sz))) {
1580                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1581                     ioc->name, __FILE__, __LINE__, __func__);
1582                 rc = -ENXIO;
1583                 goto out;
1584         }
1585         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1586             MPI2_IOCSTATUS_MASK;
1587         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1588                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1589                     ioc->name, __FILE__, __LINE__, __func__);
1590                 rc = -EIO;
1591                 goto out;
1592         }
1593
1594         if (enable)
1595                 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1596                     &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1597         else
1598                 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1599                     |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1600
1601         mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1602
1603         /* link reset */
1604         if (enable)
1605                 _transport_phy_reset(phy, 0);
1606
1607  out:
1608         kfree(sas_iounit_pg1);
1609         return rc;
1610 }
1611
1612 /**
1613  * _transport_phy_speed - set phy min/max link rates
1614  * @phy: The sas phy object
1615  * @rates: rates defined in sas_phy_linkrates
1616  *
1617  * Only support sas_host direct attached phys.
1618  * Returns 0 for success, non-zero for failure.
1619  */
1620 static int
1621 _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1622 {
1623         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1624         Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1625         Mpi2SasPhyPage0_t phy_pg0;
1626         Mpi2ConfigReply_t mpi_reply;
1627         u16 ioc_status;
1628         u16 sz;
1629         int i;
1630         int rc = 0;
1631         unsigned long flags;
1632
1633         spin_lock_irqsave(&ioc->sas_node_lock, flags);
1634         if (_transport_sas_node_find_by_sas_address(ioc,
1635             phy->identify.sas_address) == NULL) {
1636                 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1637                 return -EINVAL;
1638         }
1639         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1640
1641         if (!rates->minimum_linkrate)
1642                 rates->minimum_linkrate = phy->minimum_linkrate;
1643         else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
1644                 rates->minimum_linkrate = phy->minimum_linkrate_hw;
1645
1646         if (!rates->maximum_linkrate)
1647                 rates->maximum_linkrate = phy->maximum_linkrate;
1648         else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
1649                 rates->maximum_linkrate = phy->maximum_linkrate_hw;
1650
1651         /* handle expander phys */
1652         if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
1653                 phy->minimum_linkrate = rates->minimum_linkrate;
1654                 phy->maximum_linkrate = rates->maximum_linkrate;
1655                 return _transport_expander_phy_control(ioc, phy,
1656                     SMP_PHY_CONTROL_LINK_RESET);
1657         }
1658
1659         /* handle hba phys */
1660
1661         /* sas_iounit page 1 */
1662         sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1663             sizeof(Mpi2SasIOUnit1PhyData_t));
1664         sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1665         if (!sas_iounit_pg1) {
1666                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1667                     ioc->name, __FILE__, __LINE__, __func__);
1668                 rc = -ENOMEM;
1669                 goto out;
1670         }
1671         if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1672             sas_iounit_pg1, sz))) {
1673                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1674                     ioc->name, __FILE__, __LINE__, __func__);
1675                 rc = -ENXIO;
1676                 goto out;
1677         }
1678         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1679             MPI2_IOCSTATUS_MASK;
1680         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1681                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1682                     ioc->name, __FILE__, __LINE__, __func__);
1683                 rc = -EIO;
1684                 goto out;
1685         }
1686
1687         for (i = 0; i < ioc->sas_hba.num_phys; i++) {
1688                 if (phy->number != i) {
1689                         sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1690                             (ioc->sas_hba.phy[i].phy->minimum_linkrate +
1691                             (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
1692                 } else {
1693                         sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1694                             (rates->minimum_linkrate +
1695                             (rates->maximum_linkrate << 4));
1696                 }
1697         }
1698
1699         if (mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
1700             sz)) {
1701                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1702                     ioc->name, __FILE__, __LINE__, __func__);
1703                 rc = -ENXIO;
1704                 goto out;
1705         }
1706
1707         /* link reset */
1708         _transport_phy_reset(phy, 0);
1709
1710         /* read phy page 0, then update the rates in the sas transport phy */
1711         if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
1712             phy->number)) {
1713                 phy->minimum_linkrate = _transport_convert_phy_link_rate(
1714                     phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1715                 phy->maximum_linkrate = _transport_convert_phy_link_rate(
1716                     phy_pg0.ProgrammedLinkRate >> 4);
1717                 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1718                     phy_pg0.NegotiatedLinkRate &
1719                     MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1720         }
1721
1722  out:
1723         kfree(sas_iounit_pg1);
1724         return rc;
1725 }
1726
1727
1728 /**
1729  * _transport_smp_handler - transport portal for smp passthru
1730  * @shost: shost object
1731  * @rphy: sas transport rphy object
1732  * @req:
1733  *
1734  * This used primarily for smp_utils.
1735  * Example:
1736  *           smp_rep_general /sys/class/bsg/expander-5:0
1737  */
1738 static int
1739 _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1740     struct request *req)
1741 {
1742         struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1743         Mpi2SmpPassthroughRequest_t *mpi_request;
1744         Mpi2SmpPassthroughReply_t *mpi_reply;
1745         int rc;
1746         u16 smid;
1747         u32 ioc_state;
1748         unsigned long timeleft;
1749         void *psge;
1750         u32 sgl_flags;
1751         u8 issue_reset = 0;
1752         dma_addr_t dma_addr_in = 0;
1753         dma_addr_t dma_addr_out = 0;
1754         u16 wait_state_count;
1755         struct request *rsp = req->next_rq;
1756
1757         if (!rsp) {
1758                 printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
1759                     "missing\n", ioc->name, __func__);
1760                 return -EINVAL;
1761         }
1762
1763         /* do we need to support multiple segments? */
1764         if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
1765                 printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, "
1766                     "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt,
1767                     blk_rq_bytes(req), rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
1768                 return -EINVAL;
1769         }
1770
1771         if (ioc->shost_recovery) {
1772                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1773                     __func__, ioc->name);
1774                 return -EFAULT;
1775         }
1776
1777         rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1778         if (rc)
1779                 return rc;
1780
1781         if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1782                 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
1783                     __func__);
1784                 rc = -EAGAIN;
1785                 goto out;
1786         }
1787         ioc->transport_cmds.status = MPT2_CMD_PENDING;
1788
1789         wait_state_count = 0;
1790         ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1791         while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1792                 if (wait_state_count++ == 10) {
1793                         printk(MPT2SAS_ERR_FMT
1794                             "%s: failed due to ioc not operational\n",
1795                             ioc->name, __func__);
1796                         rc = -EFAULT;
1797                         goto out;
1798                 }
1799                 ssleep(1);
1800                 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1801                 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1802                     "operational state(count=%d)\n", ioc->name,
1803                     __func__, wait_state_count);
1804         }
1805         if (wait_state_count)
1806                 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1807                     ioc->name, __func__);
1808
1809         smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1810         if (!smid) {
1811                 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1812                     ioc->name, __func__);
1813                 rc = -EAGAIN;
1814                 goto out;
1815         }
1816
1817         rc = 0;
1818         mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1819         ioc->transport_cmds.smid = smid;
1820
1821         memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1822         mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1823         mpi_request->PhysicalPort = 0xFF;
1824         mpi_request->VF_ID = 0; /* TODO */
1825         mpi_request->VP_ID = 0;
1826         *((u64 *)&mpi_request->SASAddress) = (rphy) ?
1827             cpu_to_le64(rphy->identify.sas_address) :
1828             cpu_to_le64(ioc->sas_hba.sas_address);
1829         mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
1830         psge = &mpi_request->SGL;
1831
1832         /* WRITE sgel first */
1833         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1834             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1835         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1836         dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
1837                 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
1838         if (!dma_addr_out) {
1839                 mpt2sas_base_free_smid(ioc, smid);
1840                 goto unmap;
1841         }
1842
1843         ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(req) - 4),
1844             dma_addr_out);
1845
1846         /* incr sgel */
1847         psge += ioc->sge_size;
1848
1849         /* READ sgel last */
1850         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1851             MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1852             MPI2_SGE_FLAGS_END_OF_LIST);
1853         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1854         dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
1855                                      blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
1856         if (!dma_addr_in) {
1857                 mpt2sas_base_free_smid(ioc, smid);
1858                 goto unmap;
1859         }
1860
1861         ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4),
1862             dma_addr_in);
1863
1864         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
1865             "sending smp request\n", ioc->name, __func__));
1866
1867         mpt2sas_base_put_smid_default(ioc, smid);
1868         init_completion(&ioc->transport_cmds.done);
1869         timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1870             10*HZ);
1871
1872         if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1873                 printk(MPT2SAS_ERR_FMT "%s : timeout\n",
1874                     __func__, ioc->name);
1875                 _debug_dump_mf(mpi_request,
1876                     sizeof(Mpi2SmpPassthroughRequest_t)/4);
1877                 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1878                         issue_reset = 1;
1879                 goto issue_host_reset;
1880         }
1881
1882         dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
1883             "complete\n", ioc->name, __func__));
1884
1885         if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1886
1887                 mpi_reply = ioc->transport_cmds.reply;
1888
1889                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1890                     "%s - reply data transfer size(%d)\n",
1891                     ioc->name, __func__,
1892                     le16_to_cpu(mpi_reply->ResponseDataLength)));
1893
1894                 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
1895                 req->sense_len = sizeof(*mpi_reply);
1896                 req->resid_len = 0;
1897                 rsp->resid_len -=
1898                     le16_to_cpu(mpi_reply->ResponseDataLength);
1899         } else {
1900                 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1901                     "%s - no reply\n", ioc->name, __func__));
1902                 rc = -ENXIO;
1903         }
1904
1905  issue_host_reset:
1906         if (issue_reset) {
1907                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1908                     FORCE_BIG_HAMMER);
1909                 rc = -ETIMEDOUT;
1910         }
1911
1912  unmap:
1913         if (dma_addr_out)
1914                 pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
1915                     PCI_DMA_BIDIRECTIONAL);
1916         if (dma_addr_in)
1917                 pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
1918                     PCI_DMA_BIDIRECTIONAL);
1919
1920  out:
1921         ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1922         mutex_unlock(&ioc->transport_cmds.mutex);
1923         return rc;
1924 }
1925
1926 struct sas_function_template mpt2sas_transport_functions = {
1927         .get_linkerrors         = _transport_get_linkerrors,
1928         .get_enclosure_identifier = _transport_get_enclosure_identifier,
1929         .get_bay_identifier     = _transport_get_bay_identifier,
1930         .phy_reset              = _transport_phy_reset,
1931         .phy_enable             = _transport_phy_enable,
1932         .set_phy_speed          = _transport_phy_speed,
1933         .smp_handler            = _transport_smp_handler,
1934 };
1935
1936 struct scsi_transport_template *mpt2sas_transport_template;