Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvar...
[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) {
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 /**
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)
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 static struct _sas_phy *
944 _transport_find_local_phy(struct MPT2SAS_ADAPTER *ioc, struct sas_phy *phy)
945 {
946         int i;
947
948         for (i = 0; i < ioc->sas_hba.num_phys; i++)
949                 if (ioc->sas_hba.phy[i].phy == phy)
950                         return(&ioc->sas_hba.phy[i]);
951         return NULL;
952 }
953
954 /**
955  * _transport_get_linkerrors -
956  * @phy: The sas phy object
957  *
958  * Only support sas_host direct attached phys.
959  * Returns 0 for success, non-zero for failure.
960  *
961  */
962 static int
963 _transport_get_linkerrors(struct sas_phy *phy)
964 {
965         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
966         struct _sas_phy *mpt2sas_phy;
967         Mpi2ConfigReply_t mpi_reply;
968         Mpi2SasPhyPage1_t phy_pg1;
969
970         mpt2sas_phy = _transport_find_local_phy(ioc, phy);
971
972         if (!mpt2sas_phy) /* this phy not on sas_host */
973                 return -EINVAL;
974
975         if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
976                     mpt2sas_phy->phy_id))) {
977                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
978                     ioc->name, __FILE__, __LINE__, __func__);
979                 return -ENXIO;
980         }
981
982         if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
983                 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
984                     "(0x%04x), loginfo(0x%08x)\n", ioc->name,
985                     mpt2sas_phy->phy_id,
986                     le16_to_cpu(mpi_reply.IOCStatus),
987                     le32_to_cpu(mpi_reply.IOCLogInfo));
988
989         phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
990         phy->running_disparity_error_count =
991             le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
992         phy->loss_of_dword_sync_count =
993             le32_to_cpu(phy_pg1.LossDwordSynchCount);
994         phy->phy_reset_problem_count =
995             le32_to_cpu(phy_pg1.PhyResetProblemCount);
996         return 0;
997 }
998
999 /**
1000  * _transport_get_enclosure_identifier -
1001  * @phy: The sas phy object
1002  *
1003  * Obtain the enclosure logical id for an expander.
1004  * Returns 0 for success, non-zero for failure.
1005  */
1006 static int
1007 _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1008 {
1009         struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1010         struct _sas_node *sas_expander;
1011         unsigned long flags;
1012
1013         spin_lock_irqsave(&ioc->sas_node_lock, flags);
1014         sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
1015             rphy->identify.sas_address);
1016         spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1017
1018         if (!sas_expander)
1019                 return -ENXIO;
1020
1021         *identifier = sas_expander->enclosure_logical_id;
1022         return 0;
1023 }
1024
1025 /**
1026  * _transport_get_bay_identifier -
1027  * @phy: The sas phy object
1028  *
1029  * Returns the slot id for a device that resides inside an enclosure.
1030  */
1031 static int
1032 _transport_get_bay_identifier(struct sas_rphy *rphy)
1033 {
1034         struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1035         struct _sas_device *sas_device;
1036         unsigned long flags;
1037
1038         spin_lock_irqsave(&ioc->sas_device_lock, flags);
1039         sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1040             rphy->identify.sas_address);
1041         spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1042
1043         if (!sas_device)
1044                 return -ENXIO;
1045
1046         return sas_device->slot;
1047 }
1048
1049 /**
1050  * _transport_phy_reset -
1051  * @phy: The sas phy object
1052  * @hard_reset:
1053  *
1054  * Only support sas_host direct attached phys.
1055  * Returns 0 for success, non-zero for failure.
1056  */
1057 static int
1058 _transport_phy_reset(struct sas_phy *phy, int hard_reset)
1059 {
1060         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1061         struct _sas_phy *mpt2sas_phy;
1062         Mpi2SasIoUnitControlReply_t mpi_reply;
1063         Mpi2SasIoUnitControlRequest_t mpi_request;
1064
1065         mpt2sas_phy = _transport_find_local_phy(ioc, phy);
1066
1067         if (!mpt2sas_phy) /* this phy not on sas_host */
1068                 return -EINVAL;
1069
1070         memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
1071         mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
1072         mpi_request.Operation = hard_reset ?
1073             MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
1074         mpi_request.PhyNum = mpt2sas_phy->phy_id;
1075
1076         if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
1077                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1078                     ioc->name, __FILE__, __LINE__, __func__);
1079                 return -ENXIO;
1080         }
1081
1082         if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1083                 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1084                     "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1085                     mpt2sas_phy->phy_id,
1086                     le16_to_cpu(mpi_reply.IOCStatus),
1087                     le32_to_cpu(mpi_reply.IOCLogInfo));
1088
1089         return 0;
1090 }
1091
1092 /**
1093  * _transport_phy_enable - enable/disable phys
1094  * @phy: The sas phy object
1095  * @enable: enable phy when true
1096  *
1097  * Only support sas_host direct attached phys.
1098  * Returns 0 for success, non-zero for failure.
1099  */
1100 static int
1101 _transport_phy_enable(struct sas_phy *phy, int enable)
1102 {
1103         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1104         struct _sas_phy *mpt2sas_phy;
1105         Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1106         Mpi2ConfigReply_t mpi_reply;
1107         u16 ioc_status;
1108         u16 sz;
1109         int rc = 0;
1110
1111         mpt2sas_phy = _transport_find_local_phy(ioc, phy);
1112
1113         if (!mpt2sas_phy) /* this phy not on sas_host */
1114                 return -EINVAL;
1115
1116         /* sas_iounit page 1 */
1117         sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1118             sizeof(Mpi2SasIOUnit1PhyData_t));
1119         sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1120         if (!sas_iounit_pg1) {
1121                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1122                     ioc->name, __FILE__, __LINE__, __func__);
1123                 rc = -ENOMEM;
1124                 goto out;
1125         }
1126         if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1127             sas_iounit_pg1, sz))) {
1128                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1129                     ioc->name, __FILE__, __LINE__, __func__);
1130                 rc = -ENXIO;
1131                 goto out;
1132         }
1133         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1134             MPI2_IOCSTATUS_MASK;
1135         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1136                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1137                     ioc->name, __FILE__, __LINE__, __func__);
1138                 rc = -EIO;
1139                 goto out;
1140         }
1141
1142         if (enable)
1143                 sas_iounit_pg1->PhyData[mpt2sas_phy->phy_id].PhyFlags
1144                     &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1145         else
1146                 sas_iounit_pg1->PhyData[mpt2sas_phy->phy_id].PhyFlags
1147                     |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1148
1149         mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1150
1151  out:
1152         kfree(sas_iounit_pg1);
1153         return rc;
1154 }
1155
1156 /**
1157  * _transport_phy_speed - set phy min/max link rates
1158  * @phy: The sas phy object
1159  * @rates: rates defined in sas_phy_linkrates
1160  *
1161  * Only support sas_host direct attached phys.
1162  * Returns 0 for success, non-zero for failure.
1163  */
1164 static int
1165 _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1166 {
1167         struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1168         struct _sas_phy *mpt2sas_phy;
1169         Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1170         Mpi2SasPhyPage0_t phy_pg0;
1171         Mpi2ConfigReply_t mpi_reply;
1172         u16 ioc_status;
1173         u16 sz;
1174         int i;
1175         int rc = 0;
1176
1177         mpt2sas_phy = _transport_find_local_phy(ioc, phy);
1178
1179         if (!mpt2sas_phy) /* this phy not on sas_host */
1180                 return -EINVAL;
1181
1182         if (!rates->minimum_linkrate)
1183                 rates->minimum_linkrate = phy->minimum_linkrate;
1184         else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
1185                 rates->minimum_linkrate = phy->minimum_linkrate_hw;
1186
1187         if (!rates->maximum_linkrate)
1188                 rates->maximum_linkrate = phy->maximum_linkrate;
1189         else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
1190                 rates->maximum_linkrate = phy->maximum_linkrate_hw;
1191
1192         /* sas_iounit page 1 */
1193         sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1194             sizeof(Mpi2SasIOUnit1PhyData_t));
1195         sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1196         if (!sas_iounit_pg1) {
1197                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1198                     ioc->name, __FILE__, __LINE__, __func__);
1199                 rc = -ENOMEM;
1200                 goto out;
1201         }
1202         if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1203             sas_iounit_pg1, sz))) {
1204                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1205                     ioc->name, __FILE__, __LINE__, __func__);
1206                 rc = -ENXIO;
1207                 goto out;
1208         }
1209         ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1210             MPI2_IOCSTATUS_MASK;
1211         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1212                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1213                     ioc->name, __FILE__, __LINE__, __func__);
1214                 rc = -EIO;
1215                 goto out;
1216         }
1217
1218         for (i = 0; i < ioc->sas_hba.num_phys; i++) {
1219                 if (mpt2sas_phy->phy_id != i) {
1220                         sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1221                             (ioc->sas_hba.phy[i].phy->minimum_linkrate +
1222                             (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
1223                 } else {
1224                         sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1225                             (rates->minimum_linkrate +
1226                             (rates->maximum_linkrate << 4));
1227                 }
1228         }
1229
1230         if (mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
1231             sz)) {
1232                 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1233                     ioc->name, __FILE__, __LINE__, __func__);
1234                 rc = -ENXIO;
1235                 goto out;
1236         }
1237
1238         /* link reset */
1239         _transport_phy_reset(phy, 0);
1240
1241         /* read phy page 0, then update the rates in the sas transport phy */
1242         if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
1243             mpt2sas_phy->phy_id)) {
1244                 phy->minimum_linkrate = _transport_convert_phy_link_rate(
1245                     phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1246                 phy->maximum_linkrate = _transport_convert_phy_link_rate(
1247                     phy_pg0.ProgrammedLinkRate >> 4);
1248                 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1249                     phy_pg0.NegotiatedLinkRate &
1250                     MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1251         }
1252
1253  out:
1254         kfree(sas_iounit_pg1);
1255         return rc;
1256 }
1257
1258
1259 /**
1260  * _transport_smp_handler - transport portal for smp passthru
1261  * @shost: shost object
1262  * @rphy: sas transport rphy object
1263  * @req:
1264  *
1265  * This used primarily for smp_utils.
1266  * Example:
1267  *           smp_rep_general /sys/class/bsg/expander-5:0
1268  */
1269 static int
1270 _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1271     struct request *req)
1272 {
1273         struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1274         Mpi2SmpPassthroughRequest_t *mpi_request;
1275         Mpi2SmpPassthroughReply_t *mpi_reply;
1276         int rc;
1277         u16 smid;
1278         u32 ioc_state;
1279         unsigned long timeleft;
1280         void *psge;
1281         u32 sgl_flags;
1282         u8 issue_reset = 0;
1283         dma_addr_t dma_addr_in = 0;
1284         dma_addr_t dma_addr_out = 0;
1285         u16 wait_state_count;
1286         struct request *rsp = req->next_rq;
1287
1288         if (!rsp) {
1289                 printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
1290                     "missing\n", ioc->name, __func__);
1291                 return -EINVAL;
1292         }
1293
1294         /* do we need to support multiple segments? */
1295         if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
1296                 printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, "
1297                     "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt,
1298                     blk_rq_bytes(req), rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
1299                 return -EINVAL;
1300         }
1301
1302         if (ioc->shost_recovery) {
1303                 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1304                     __func__, ioc->name);
1305                 return -EFAULT;
1306         }
1307
1308         rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1309         if (rc)
1310                 return rc;
1311
1312         if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1313                 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
1314                     __func__);
1315                 rc = -EAGAIN;
1316                 goto out;
1317         }
1318         ioc->transport_cmds.status = MPT2_CMD_PENDING;
1319
1320         wait_state_count = 0;
1321         ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1322         while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1323                 if (wait_state_count++ == 10) {
1324                         printk(MPT2SAS_ERR_FMT
1325                             "%s: failed due to ioc not operational\n",
1326                             ioc->name, __func__);
1327                         rc = -EFAULT;
1328                         goto out;
1329                 }
1330                 ssleep(1);
1331                 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1332                 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1333                     "operational state(count=%d)\n", ioc->name,
1334                     __func__, wait_state_count);
1335         }
1336         if (wait_state_count)
1337                 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1338                     ioc->name, __func__);
1339
1340         smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1341         if (!smid) {
1342                 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1343                     ioc->name, __func__);
1344                 rc = -EAGAIN;
1345                 goto out;
1346         }
1347
1348         rc = 0;
1349         mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1350         ioc->transport_cmds.smid = smid;
1351
1352         memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1353         mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1354         mpi_request->PhysicalPort = 0xFF;
1355         mpi_request->VF_ID = 0; /* TODO */
1356         mpi_request->VP_ID = 0;
1357         *((u64 *)&mpi_request->SASAddress) = (rphy) ?
1358             cpu_to_le64(rphy->identify.sas_address) :
1359             cpu_to_le64(ioc->sas_hba.sas_address);
1360         mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
1361         psge = &mpi_request->SGL;
1362
1363         /* WRITE sgel first */
1364         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1365             MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1366         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1367         dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
1368                 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
1369         if (!dma_addr_out) {
1370                 mpt2sas_base_free_smid(ioc, smid);
1371                 goto unmap;
1372         }
1373
1374         ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(req) - 4),
1375             dma_addr_out);
1376
1377         /* incr sgel */
1378         psge += ioc->sge_size;
1379
1380         /* READ sgel last */
1381         sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1382             MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1383             MPI2_SGE_FLAGS_END_OF_LIST);
1384         sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1385         dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
1386                                      blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
1387         if (!dma_addr_in) {
1388                 mpt2sas_base_free_smid(ioc, smid);
1389                 goto unmap;
1390         }
1391
1392         ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4),
1393             dma_addr_in);
1394
1395         dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
1396             "sending smp request\n", ioc->name, __func__));
1397
1398         mpt2sas_base_put_smid_default(ioc, smid);
1399         init_completion(&ioc->transport_cmds.done);
1400         timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1401             10*HZ);
1402
1403         if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1404                 printk(MPT2SAS_ERR_FMT "%s : timeout\n",
1405                     __func__, ioc->name);
1406                 _debug_dump_mf(mpi_request,
1407                     sizeof(Mpi2SmpPassthroughRequest_t)/4);
1408                 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1409                         issue_reset = 1;
1410                 goto issue_host_reset;
1411         }
1412
1413         dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
1414             "complete\n", ioc->name, __func__));
1415
1416         if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1417
1418                 mpi_reply = ioc->transport_cmds.reply;
1419
1420                 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
1421                     "%s - reply data transfer size(%d)\n",
1422                     ioc->name, __func__,
1423                     le16_to_cpu(mpi_reply->ResponseDataLength)));
1424
1425                 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
1426                 req->sense_len = sizeof(*mpi_reply);
1427                 req->resid_len = 0;
1428                 rsp->resid_len -=
1429                     le16_to_cpu(mpi_reply->ResponseDataLength);
1430         } else {
1431                 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
1432                     "%s - no reply\n", ioc->name, __func__));
1433                 rc = -ENXIO;
1434         }
1435
1436  issue_host_reset:
1437         if (issue_reset) {
1438                 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1439                     FORCE_BIG_HAMMER);
1440                 rc = -ETIMEDOUT;
1441         }
1442
1443  unmap:
1444         if (dma_addr_out)
1445                 pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
1446                     PCI_DMA_BIDIRECTIONAL);
1447         if (dma_addr_in)
1448                 pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
1449                     PCI_DMA_BIDIRECTIONAL);
1450
1451  out:
1452         ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1453         mutex_unlock(&ioc->transport_cmds.mutex);
1454         return rc;
1455 }
1456
1457 struct sas_function_template mpt2sas_transport_functions = {
1458         .get_linkerrors         = _transport_get_linkerrors,
1459         .get_enclosure_identifier = _transport_get_enclosure_identifier,
1460         .get_bay_identifier     = _transport_get_bay_identifier,
1461         .phy_reset              = _transport_phy_reset,
1462         .phy_enable             = _transport_phy_enable,
1463         .set_phy_speed          = _transport_phy_speed,
1464         .smp_handler            = _transport_smp_handler,
1465 };
1466
1467 struct scsi_transport_template *mpt2sas_transport_template;