include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / scsi / mpt2sas / mpt2sas_transport.c
1 /*
2  * SAS Transport Layer for MPT (Message Passing Technology) based controllers
3  *
4  * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c
5  * Copyright (C) 2007-2009  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) {
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) {
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_DEBUG_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_DEBUG_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_DEBUG_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_DEBUG_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  * mpt2sas_transport_port_add - insert port to the list
470  * @ioc: per adapter object
471  * @handle: handle of attached device
472  * @sas_address: sas address of parent expander or sas host
473  * Context: This function will acquire ioc->sas_node_lock.
474  *
475  * Adding new port object to the sas_node->sas_port_list.
476  *
477  * Returns mpt2sas_port.
478  */
479 struct _sas_port *
480 mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
481     u64 sas_address)
482 {
483         struct _sas_phy *mpt2sas_phy, *next;
484         struct _sas_port *mpt2sas_port;
485         unsigned long flags;
486         struct _sas_node *sas_node;
487         struct sas_rphy *rphy;
488         int i;
489         struct sas_port *port;
490
491         mpt2sas_port = kzalloc(sizeof(struct _sas_port),
492             GFP_KERNEL);
493         if (!mpt2sas_port) {
494                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
495                     ioc->name, __FILE__, __LINE__, __func__);
496                 return NULL;
497         }
498
499         INIT_LIST_HEAD(&mpt2sas_port->port_list);
500         INIT_LIST_HEAD(&mpt2sas_port->phy_list);
501         spin_lock_irqsave(&ioc->sas_node_lock, flags);
502         sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
503         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
504
505         if (!sas_node) {
506                 printk(MPT2SAS_ERR_FMT "%s: Could not find "
507                     "parent sas_address(0x%016llx)!\n", ioc->name,
508                     __func__, (unsigned long long)sas_address);
509                 goto out_fail;
510         }
511
512         if ((_transport_set_identify(ioc, handle,
513             &mpt2sas_port->remote_identify))) {
514                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
515                     ioc->name, __FILE__, __LINE__, __func__);
516                 goto out_fail;
517         }
518
519         if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
520                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
521                     ioc->name, __FILE__, __LINE__, __func__);
522                 goto out_fail;
523         }
524
525         for (i = 0; i < sas_node->num_phys; i++) {
526                 if (sas_node->phy[i].remote_identify.sas_address !=
527                     mpt2sas_port->remote_identify.sas_address)
528                         continue;
529                 list_add_tail(&sas_node->phy[i].port_siblings,
530                     &mpt2sas_port->phy_list);
531                 mpt2sas_port->num_phys++;
532         }
533
534         if (!mpt2sas_port->num_phys) {
535                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
536                     ioc->name, __FILE__, __LINE__, __func__);
537                 goto out_fail;
538         }
539
540         port = sas_port_alloc_num(sas_node->parent_dev);
541         if ((sas_port_add(port))) {
542                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
543                     ioc->name, __FILE__, __LINE__, __func__);
544                 goto out_fail;
545         }
546
547         list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
548             port_siblings) {
549                 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
550                         dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
551                             ", sas_addr(0x%016llx), phy(%d)\n", handle,
552                             (unsigned long long)
553                             mpt2sas_port->remote_identify.sas_address,
554                             mpt2sas_phy->phy_id);
555                 sas_port_add_phy(port, mpt2sas_phy->phy);
556         }
557
558         mpt2sas_port->port = port;
559         if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
560                 rphy = sas_end_device_alloc(port);
561         else
562                 rphy = sas_expander_alloc(port,
563                     mpt2sas_port->remote_identify.device_type);
564
565         rphy->identify = mpt2sas_port->remote_identify;
566         if ((sas_rphy_add(rphy))) {
567                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
568                     ioc->name, __FILE__, __LINE__, __func__);
569         }
570         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
571                 dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
572                     "sas_addr(0x%016llx)\n", handle,
573                     (unsigned long long)
574                     mpt2sas_port->remote_identify.sas_address);
575         mpt2sas_port->rphy = rphy;
576         spin_lock_irqsave(&ioc->sas_node_lock, flags);
577         list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
578         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
579
580         /* fill in report manufacture */
581         if (mpt2sas_port->remote_identify.device_type ==
582             MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
583             mpt2sas_port->remote_identify.device_type ==
584             MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
585                 _transport_expander_report_manufacture(ioc,
586                     mpt2sas_port->remote_identify.sas_address,
587                     rphy_to_expander_device(rphy));
588
589         return mpt2sas_port;
590
591  out_fail:
592         list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
593             port_siblings)
594                 list_del(&mpt2sas_phy->port_siblings);
595         kfree(mpt2sas_port);
596         return NULL;
597 }
598
599 /**
600  * mpt2sas_transport_port_remove - remove port from the list
601  * @ioc: per adapter object
602  * @sas_address: sas address of attached device
603  * @sas_address_parent: sas address of parent expander or sas host
604  * Context: This function will acquire ioc->sas_node_lock.
605  *
606  * Removing object and freeing associated memory from the
607  * ioc->sas_port_list.
608  *
609  * Return nothing.
610  */
611 void
612 mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
613     u64 sas_address_parent)
614 {
615         int i;
616         unsigned long flags;
617         struct _sas_port *mpt2sas_port, *next;
618         struct _sas_node *sas_node;
619         u8 found = 0;
620         struct _sas_phy *mpt2sas_phy, *next_phy;
621
622         spin_lock_irqsave(&ioc->sas_node_lock, flags);
623         sas_node = _transport_sas_node_find_by_sas_address(ioc,
624             sas_address_parent);
625         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
626         if (!sas_node)
627                 return;
628         list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
629             port_list) {
630                 if (mpt2sas_port->remote_identify.sas_address != sas_address)
631                         continue;
632                 found = 1;
633                 list_del(&mpt2sas_port->port_list);
634                 goto out;
635         }
636  out:
637         if (!found)
638                 return;
639
640         for (i = 0; i < sas_node->num_phys; i++) {
641                 if (sas_node->phy[i].remote_identify.sas_address == sas_address)
642                         memset(&sas_node->phy[i].remote_identify, 0 ,
643                             sizeof(struct sas_identify));
644         }
645
646         list_for_each_entry_safe(mpt2sas_phy, next_phy,
647             &mpt2sas_port->phy_list, port_siblings) {
648                 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
649                         dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
650                             "remove: sas_addr(0x%016llx), phy(%d)\n",
651                             (unsigned long long)
652                             mpt2sas_port->remote_identify.sas_address,
653                             mpt2sas_phy->phy_id);
654                 sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
655                 list_del(&mpt2sas_phy->port_siblings);
656         }
657         sas_port_delete(mpt2sas_port->port);
658         kfree(mpt2sas_port);
659 }
660
661 /**
662  * mpt2sas_transport_add_host_phy - report sas_host phy to transport
663  * @ioc: per adapter object
664  * @mpt2sas_phy: mpt2sas per phy object
665  * @phy_pg0: sas phy page 0
666  * @parent_dev: parent device class object
667  *
668  * Returns 0 for success, non-zero for failure.
669  */
670 int
671 mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
672     *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
673 {
674         struct sas_phy *phy;
675         int phy_index = mpt2sas_phy->phy_id;
676
677
678         INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
679         phy = sas_phy_alloc(parent_dev, phy_index);
680         if (!phy) {
681                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
682                     ioc->name, __FILE__, __LINE__, __func__);
683                 return -1;
684         }
685         if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
686             &mpt2sas_phy->identify))) {
687                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
688                     ioc->name, __FILE__, __LINE__, __func__);
689                 return -1;
690         }
691         phy->identify = mpt2sas_phy->identify;
692         mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
693         if (mpt2sas_phy->attached_handle)
694                 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
695                     &mpt2sas_phy->remote_identify);
696         phy->identify.phy_identifier = mpt2sas_phy->phy_id;
697         phy->negotiated_linkrate = _transport_convert_phy_link_rate(
698             phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
699         phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
700             phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
701         phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
702             phy_pg0.HwLinkRate >> 4);
703         phy->minimum_linkrate = _transport_convert_phy_link_rate(
704             phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
705         phy->maximum_linkrate = _transport_convert_phy_link_rate(
706             phy_pg0.ProgrammedLinkRate >> 4);
707
708         if ((sas_phy_add(phy))) {
709                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
710                     ioc->name, __FILE__, __LINE__, __func__);
711                 sas_phy_free(phy);
712                 return -1;
713         }
714         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
715                 dev_printk(KERN_INFO, &phy->dev,
716                     "add: handle(0x%04x), sas_addr(0x%016llx)\n"
717                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
718                     mpt2sas_phy->handle, (unsigned long long)
719                     mpt2sas_phy->identify.sas_address,
720                     mpt2sas_phy->attached_handle,
721                     (unsigned long long)
722                     mpt2sas_phy->remote_identify.sas_address);
723         mpt2sas_phy->phy = phy;
724         return 0;
725 }
726
727
728 /**
729  * mpt2sas_transport_add_expander_phy - report expander phy to transport
730  * @ioc: per adapter object
731  * @mpt2sas_phy: mpt2sas per phy object
732  * @expander_pg1: expander page 1
733  * @parent_dev: parent device class object
734  *
735  * Returns 0 for success, non-zero for failure.
736  */
737 int
738 mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
739     *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
740 {
741         struct sas_phy *phy;
742         int phy_index = mpt2sas_phy->phy_id;
743
744         INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
745         phy = sas_phy_alloc(parent_dev, phy_index);
746         if (!phy) {
747                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
748                     ioc->name, __FILE__, __LINE__, __func__);
749                 return -1;
750         }
751         if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
752             &mpt2sas_phy->identify))) {
753                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
754                     ioc->name, __FILE__, __LINE__, __func__);
755                 return -1;
756         }
757         phy->identify = mpt2sas_phy->identify;
758         mpt2sas_phy->attached_handle =
759             le16_to_cpu(expander_pg1.AttachedDevHandle);
760         if (mpt2sas_phy->attached_handle)
761                 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
762                     &mpt2sas_phy->remote_identify);
763         phy->identify.phy_identifier = mpt2sas_phy->phy_id;
764         phy->negotiated_linkrate = _transport_convert_phy_link_rate(
765             expander_pg1.NegotiatedLinkRate &
766             MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
767         phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
768             expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
769         phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
770             expander_pg1.HwLinkRate >> 4);
771         phy->minimum_linkrate = _transport_convert_phy_link_rate(
772             expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
773         phy->maximum_linkrate = _transport_convert_phy_link_rate(
774             expander_pg1.ProgrammedLinkRate >> 4);
775
776         if ((sas_phy_add(phy))) {
777                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
778                     ioc->name, __FILE__, __LINE__, __func__);
779                 sas_phy_free(phy);
780                 return -1;
781         }
782         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
783                 dev_printk(KERN_INFO, &phy->dev,
784                     "add: handle(0x%04x), sas_addr(0x%016llx)\n"
785                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
786                     mpt2sas_phy->handle, (unsigned long long)
787                     mpt2sas_phy->identify.sas_address,
788                     mpt2sas_phy->attached_handle,
789                     (unsigned long long)
790                     mpt2sas_phy->remote_identify.sas_address);
791         mpt2sas_phy->phy = phy;
792         return 0;
793 }
794
795 /**
796  * mpt2sas_transport_update_links - refreshing phy link changes
797  * @ioc: per adapter object
798  * @sas_address: sas address of parent expander or sas host
799  * @handle: attached device handle
800  * @phy_numberv: phy number
801  * @link_rate: new link rate
802  *
803  * Returns nothing.
804  */
805 void
806 mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
807      u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
808 {
809         unsigned long flags;
810         struct _sas_node *sas_node;
811         struct _sas_phy *mpt2sas_phy;
812
813         if (ioc->shost_recovery)
814                 return;
815
816         spin_lock_irqsave(&ioc->sas_node_lock, flags);
817         sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
818         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
819         if (!sas_node)
820                 return;
821
822         mpt2sas_phy = &sas_node->phy[phy_number];
823         mpt2sas_phy->attached_handle = handle;
824         if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5))
825                 _transport_set_identify(ioc, handle,
826                     &mpt2sas_phy->remote_identify);
827         else
828                 memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
829                     sas_identify));
830
831         if (mpt2sas_phy->phy)
832                 mpt2sas_phy->phy->negotiated_linkrate =
833                     _transport_convert_phy_link_rate(link_rate);
834
835         if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
836                 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
837                     "refresh: parent sas_addr(0x%016llx),\n"
838                     "\tlink_rate(0x%02x), phy(%d)\n"
839                     "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
840                     (unsigned long long)sas_address,
841                     link_rate, phy_number, handle, (unsigned long long)
842                     mpt2sas_phy->remote_identify.sas_address);
843 }
844
845 static inline void *
846 phy_to_ioc(struct sas_phy *phy)
847 {
848         struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
849         return shost_priv(shost);
850 }
851
852 static inline void *
853 rphy_to_ioc(struct sas_rphy *rphy)
854 {
855         struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
856         return shost_priv(shost);
857 }
858
859 static struct _sas_phy *
860 _transport_find_local_phy(struct MPT2SAS_ADAPTER *ioc, struct sas_phy *phy)
861 {
862         int i;
863
864         for (i = 0; i < ioc->sas_hba.num_phys; i++)
865                 if (ioc->sas_hba.phy[i].phy == phy)
866                         return(&ioc->sas_hba.phy[i]);
867         return NULL;
868 }
869
870 /**
871  * _transport_get_linkerrors -
872  * @phy: The sas phy object
873  *
874  * Only support sas_host direct attached phys.
875  * Returns 0 for success, non-zero for failure.
876  *
877  */
878 static int
879 _transport_get_linkerrors(struct sas_phy *phy)
880 {
881         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
882         struct _sas_phy *mpt2sas_phy;
883         Mpi2ConfigReply_t mpi_reply;
884         Mpi2SasPhyPage1_t phy_pg1;
885
886         mpt2sas_phy = _transport_find_local_phy(ioc, phy);
887
888         if (!mpt2sas_phy) /* this phy not on sas_host */
889                 return -EINVAL;
890
891         if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
892                     mpt2sas_phy->phy_id))) {
893                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
894                     ioc->name, __FILE__, __LINE__, __func__);
895                 return -ENXIO;
896         }
897
898         if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
899                 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
900                     "(0x%04x), loginfo(0x%08x)\n", ioc->name,
901                     mpt2sas_phy->phy_id,
902                     le16_to_cpu(mpi_reply.IOCStatus),
903                     le32_to_cpu(mpi_reply.IOCLogInfo));
904
905         phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
906         phy->running_disparity_error_count =
907             le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
908         phy->loss_of_dword_sync_count =
909             le32_to_cpu(phy_pg1.LossDwordSynchCount);
910         phy->phy_reset_problem_count =
911             le32_to_cpu(phy_pg1.PhyResetProblemCount);
912         return 0;
913 }
914
915 /**
916  * _transport_get_enclosure_identifier -
917  * @phy: The sas phy object
918  *
919  * Obtain the enclosure logical id for an expander.
920  * Returns 0 for success, non-zero for failure.
921  */
922 static int
923 _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
924 {
925         struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
926         struct _sas_node *sas_expander;
927         unsigned long flags;
928
929         spin_lock_irqsave(&ioc->sas_node_lock, flags);
930         sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
931             rphy->identify.sas_address);
932         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
933
934         if (!sas_expander)
935                 return -ENXIO;
936
937         *identifier = sas_expander->enclosure_logical_id;
938         return 0;
939 }
940
941 /**
942  * _transport_get_bay_identifier -
943  * @phy: The sas phy object
944  *
945  * Returns the slot id for a device that resides inside an enclosure.
946  */
947 static int
948 _transport_get_bay_identifier(struct sas_rphy *rphy)
949 {
950         struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
951         struct _sas_device *sas_device;
952         unsigned long flags;
953
954         spin_lock_irqsave(&ioc->sas_device_lock, flags);
955         sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
956             rphy->identify.sas_address);
957         spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
958
959         if (!sas_device)
960                 return -ENXIO;
961
962         return sas_device->slot;
963 }
964
965 /**
966  * _transport_phy_reset -
967  * @phy: The sas phy object
968  * @hard_reset:
969  *
970  * Only support sas_host direct attached phys.
971  * Returns 0 for success, non-zero for failure.
972  */
973 static int
974 _transport_phy_reset(struct sas_phy *phy, int hard_reset)
975 {
976         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
977         struct _sas_phy *mpt2sas_phy;
978         Mpi2SasIoUnitControlReply_t mpi_reply;
979         Mpi2SasIoUnitControlRequest_t mpi_request;
980
981         mpt2sas_phy = _transport_find_local_phy(ioc, phy);
982
983         if (!mpt2sas_phy) /* this phy not on sas_host */
984                 return -EINVAL;
985
986         memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
987         mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
988         mpi_request.Operation = hard_reset ?
989             MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
990         mpi_request.PhyNum = mpt2sas_phy->phy_id;
991
992         if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
993                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
994                     ioc->name, __FILE__, __LINE__, __func__);
995                 return -ENXIO;
996         }
997
998         if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
999                 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1000                     "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1001                     mpt2sas_phy->phy_id,
1002                     le16_to_cpu(mpi_reply.IOCStatus),
1003                     le32_to_cpu(mpi_reply.IOCLogInfo));
1004
1005         return 0;
1006 }
1007
1008 /**
1009  * _transport_phy_enable - enable/disable phys
1010  * @phy: The sas phy object
1011  * @enable: enable phy when true
1012  *
1013  * Only support sas_host direct attached phys.
1014  * Returns 0 for success, non-zero for failure.
1015  */
1016 static int
1017 _transport_phy_enable(struct sas_phy *phy, int enable)
1018 {
1019         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1020         struct _sas_phy *mpt2sas_phy;
1021         Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1022         Mpi2ConfigReply_t mpi_reply;
1023         u16 ioc_status;
1024         u16 sz;
1025         int rc = 0;
1026
1027         mpt2sas_phy = _transport_find_local_phy(ioc, phy);
1028
1029         if (!mpt2sas_phy) /* this phy not on sas_host */
1030                 return -EINVAL;
1031
1032         /* sas_iounit page 1 */
1033         sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1034             sizeof(Mpi2SasIOUnit1PhyData_t));
1035         sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1036         if (!sas_iounit_pg1) {
1037                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1038                     ioc->name, __FILE__, __LINE__, __func__);
1039                 rc = -ENOMEM;
1040                 goto out;
1041         }
1042         if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1043             sas_iounit_pg1, sz))) {
1044                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1045                     ioc->name, __FILE__, __LINE__, __func__);
1046                 rc = -ENXIO;
1047                 goto out;
1048         }
1049         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1050             MPI2_IOCSTATUS_MASK;
1051         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1052                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1053                     ioc->name, __FILE__, __LINE__, __func__);
1054                 rc = -EIO;
1055                 goto out;
1056         }
1057
1058         if (enable)
1059                 sas_iounit_pg1->PhyData[mpt2sas_phy->phy_id].PhyFlags
1060                     &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1061         else
1062                 sas_iounit_pg1->PhyData[mpt2sas_phy->phy_id].PhyFlags
1063                     |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1064
1065         mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1066
1067  out:
1068         kfree(sas_iounit_pg1);
1069         return rc;
1070 }
1071
1072 /**
1073  * _transport_phy_speed - set phy min/max link rates
1074  * @phy: The sas phy object
1075  * @rates: rates defined in sas_phy_linkrates
1076  *
1077  * Only support sas_host direct attached phys.
1078  * Returns 0 for success, non-zero for failure.
1079  */
1080 static int
1081 _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1082 {
1083         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1084         struct _sas_phy *mpt2sas_phy;
1085         Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1086         Mpi2SasPhyPage0_t phy_pg0;
1087         Mpi2ConfigReply_t mpi_reply;
1088         u16 ioc_status;
1089         u16 sz;
1090         int i;
1091         int rc = 0;
1092
1093         mpt2sas_phy = _transport_find_local_phy(ioc, phy);
1094
1095         if (!mpt2sas_phy) /* this phy not on sas_host */
1096                 return -EINVAL;
1097
1098         if (!rates->minimum_linkrate)
1099                 rates->minimum_linkrate = phy->minimum_linkrate;
1100         else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
1101                 rates->minimum_linkrate = phy->minimum_linkrate_hw;
1102
1103         if (!rates->maximum_linkrate)
1104                 rates->maximum_linkrate = phy->maximum_linkrate;
1105         else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
1106                 rates->maximum_linkrate = phy->maximum_linkrate_hw;
1107
1108         /* sas_iounit page 1 */
1109         sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1110             sizeof(Mpi2SasIOUnit1PhyData_t));
1111         sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1112         if (!sas_iounit_pg1) {
1113                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1114                     ioc->name, __FILE__, __LINE__, __func__);
1115                 rc = -ENOMEM;
1116                 goto out;
1117         }
1118         if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1119             sas_iounit_pg1, sz))) {
1120                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1121                     ioc->name, __FILE__, __LINE__, __func__);
1122                 rc = -ENXIO;
1123                 goto out;
1124         }
1125         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1126             MPI2_IOCSTATUS_MASK;
1127         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1128                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1129                     ioc->name, __FILE__, __LINE__, __func__);
1130                 rc = -EIO;
1131                 goto out;
1132         }
1133
1134         for (i = 0; i < ioc->sas_hba.num_phys; i++) {
1135                 if (mpt2sas_phy->phy_id != i) {
1136                         sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1137                             (ioc->sas_hba.phy[i].phy->minimum_linkrate +
1138                             (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
1139                 } else {
1140                         sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1141                             (rates->minimum_linkrate +
1142                             (rates->maximum_linkrate << 4));
1143                 }
1144         }
1145
1146         if (mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
1147             sz)) {
1148                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1149                     ioc->name, __FILE__, __LINE__, __func__);
1150                 rc = -ENXIO;
1151                 goto out;
1152         }
1153
1154         /* link reset */
1155         _transport_phy_reset(phy, 0);
1156
1157         /* read phy page 0, then update the rates in the sas transport phy */
1158         if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
1159             mpt2sas_phy->phy_id)) {
1160                 phy->minimum_linkrate = _transport_convert_phy_link_rate(
1161                     phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1162                 phy->maximum_linkrate = _transport_convert_phy_link_rate(
1163                     phy_pg0.ProgrammedLinkRate >> 4);
1164                 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1165                     phy_pg0.NegotiatedLinkRate &
1166                     MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1167         }
1168
1169  out:
1170         kfree(sas_iounit_pg1);
1171         return rc;
1172 }
1173
1174
1175 /**
1176  * _transport_smp_handler - transport portal for smp passthru
1177  * @shost: shost object
1178  * @rphy: sas transport rphy object
1179  * @req:
1180  *
1181  * This used primarily for smp_utils.
1182  * Example:
1183  *           smp_rep_general /sys/class/bsg/expander-5:0
1184  */
1185 static int
1186 _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1187     struct request *req)
1188 {
1189         struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1190         Mpi2SmpPassthroughRequest_t *mpi_request;
1191         Mpi2SmpPassthroughReply_t *mpi_reply;
1192         int rc;
1193         u16 smid;
1194         u32 ioc_state;
1195         unsigned long timeleft;
1196         void *psge;
1197         u32 sgl_flags;
1198         u8 issue_reset = 0;
1199         dma_addr_t dma_addr_in = 0;
1200         dma_addr_t dma_addr_out = 0;
1201         u16 wait_state_count;
1202         struct request *rsp = req->next_rq;
1203
1204         if (!rsp) {
1205                 printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
1206                     "missing\n", ioc->name, __func__);
1207                 return -EINVAL;
1208         }
1209
1210         /* do we need to support multiple segments? */
1211         if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
1212                 printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, "
1213                     "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt,
1214                     blk_rq_bytes(req), rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
1215                 return -EINVAL;
1216         }
1217
1218         if (ioc->shost_recovery) {
1219                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1220                     __func__, ioc->name);
1221                 return -EFAULT;
1222         }
1223
1224         rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1225         if (rc)
1226                 return rc;
1227
1228         if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1229                 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
1230                     __func__);
1231                 rc = -EAGAIN;
1232                 goto out;
1233         }
1234         ioc->transport_cmds.status = MPT2_CMD_PENDING;
1235
1236         wait_state_count = 0;
1237         ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1238         while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1239                 if (wait_state_count++ == 10) {
1240                         printk(MPT2SAS_ERR_FMT
1241                             "%s: failed due to ioc not operational\n",
1242                             ioc->name, __func__);
1243                         rc = -EFAULT;
1244                         goto out;
1245                 }
1246                 ssleep(1);
1247                 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1248                 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1249                     "operational state(count=%d)\n", ioc->name,
1250                     __func__, wait_state_count);
1251         }
1252         if (wait_state_count)
1253                 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1254                     ioc->name, __func__);
1255
1256         smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1257         if (!smid) {
1258                 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1259                     ioc->name, __func__);
1260                 rc = -EAGAIN;
1261                 goto out;
1262         }
1263
1264         rc = 0;
1265         mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1266         ioc->transport_cmds.smid = smid;
1267
1268         memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1269         mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1270         mpi_request->PhysicalPort = 0xFF;
1271         mpi_request->VF_ID = 0; /* TODO */
1272         mpi_request->VP_ID = 0;
1273         *((u64 *)&mpi_request->SASAddress) = (rphy) ?
1274             cpu_to_le64(rphy->identify.sas_address) :
1275             cpu_to_le64(ioc->sas_hba.sas_address);
1276         mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
1277         psge = &mpi_request->SGL;
1278
1279         /* WRITE sgel first */
1280         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1281             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1282         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1283         dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
1284                 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
1285         if (!dma_addr_out) {
1286                 mpt2sas_base_free_smid(ioc, smid);
1287                 goto unmap;
1288         }
1289
1290         ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(req) - 4),
1291             dma_addr_out);
1292
1293         /* incr sgel */
1294         psge += ioc->sge_size;
1295
1296         /* READ sgel last */
1297         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1298             MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1299             MPI2_SGE_FLAGS_END_OF_LIST);
1300         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1301         dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
1302                                      blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
1303         if (!dma_addr_in) {
1304                 mpt2sas_base_free_smid(ioc, smid);
1305                 goto unmap;
1306         }
1307
1308         ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4),
1309             dma_addr_in);
1310
1311         dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
1312             "sending smp request\n", ioc->name, __func__));
1313
1314         mpt2sas_base_put_smid_default(ioc, smid);
1315         init_completion(&ioc->transport_cmds.done);
1316         timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1317             10*HZ);
1318
1319         if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1320                 printk(MPT2SAS_ERR_FMT "%s : timeout\n",
1321                     __func__, ioc->name);
1322                 _debug_dump_mf(mpi_request,
1323                     sizeof(Mpi2SmpPassthroughRequest_t)/4);
1324                 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1325                         issue_reset = 1;
1326                 goto issue_host_reset;
1327         }
1328
1329         dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
1330             "complete\n", ioc->name, __func__));
1331
1332         if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1333
1334                 mpi_reply = ioc->transport_cmds.reply;
1335
1336                 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
1337                     "%s - reply data transfer size(%d)\n",
1338                     ioc->name, __func__,
1339                     le16_to_cpu(mpi_reply->ResponseDataLength)));
1340
1341                 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
1342                 req->sense_len = sizeof(*mpi_reply);
1343                 req->resid_len = 0;
1344                 rsp->resid_len -= mpi_reply->ResponseDataLength;
1345         } else {
1346                 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
1347                     "%s - no reply\n", ioc->name, __func__));
1348                 rc = -ENXIO;
1349         }
1350
1351  issue_host_reset:
1352         if (issue_reset) {
1353                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1354                     FORCE_BIG_HAMMER);
1355                 rc = -ETIMEDOUT;
1356         }
1357
1358  unmap:
1359         if (dma_addr_out)
1360                 pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
1361                     PCI_DMA_BIDIRECTIONAL);
1362         if (dma_addr_in)
1363                 pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
1364                     PCI_DMA_BIDIRECTIONAL);
1365
1366  out:
1367         ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1368         mutex_unlock(&ioc->transport_cmds.mutex);
1369         return rc;
1370 }
1371
1372 struct sas_function_template mpt2sas_transport_functions = {
1373         .get_linkerrors         = _transport_get_linkerrors,
1374         .get_enclosure_identifier = _transport_get_enclosure_identifier,
1375         .get_bay_identifier     = _transport_get_bay_identifier,
1376         .phy_reset              = _transport_phy_reset,
1377         .phy_enable             = _transport_phy_enable,
1378         .set_phy_speed          = _transport_phy_speed,
1379         .smp_handler            = _transport_smp_handler,
1380 };
1381
1382 struct scsi_transport_template *mpt2sas_transport_template;