Avoid beyond bounds copy while caching ACL
[zen-stable.git] / drivers / scsi / mpt2sas / mpt2sas_transport.c
blob831047466a5a9865f0f8da94672dd9f449546eec
1 /*
2 * SAS Transport Layer for MPT (Message Passing Technology) based controllers
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)
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.
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.
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.
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
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.
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>
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>
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.
68 * Search for either hba phys or expander device based on handle, then returns
69 * the sas_node object.
71 static struct _sas_node *
72 _transport_sas_node_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
73 u64 sas_address)
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);
82 /**
83 * _transport_convert_phy_link_rate -
84 * @link_rate: link rate returned from mpt firmware
86 * Convert link_rate from mpi fusion into sas_transport form.
88 static enum sas_linkrate
89 _transport_convert_phy_link_rate(u8 link_rate)
91 enum sas_linkrate rc;
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;
121 return rc;
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
130 * Populates sas identify info.
132 * Returns 0 for success, non-zero for failure.
134 static int
135 _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
136 struct sas_identify *identify)
138 Mpi2SasDevicePage0_t sas_device_pg0;
139 Mpi2ConfigReply_t mpi_reply;
140 u32 device_info;
141 u32 ioc_status;
143 if (ioc->shost_recovery || ioc->pci_error_recovery) {
144 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
145 __func__, ioc->name);
146 return -EFAULT;
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",
153 ioc->name, __FILE__, __LINE__, __func__);
154 return -ENXIO;
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;
166 memset(identify, 0, sizeof(*identify));
167 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
169 /* sas_address */
170 identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
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;
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;
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;
208 return 0;
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)
218 * Callback handler when sending internal generated transport cmds.
219 * The callback index passed is `ioc->transport_cb_idx`
221 * Return 1 meaning mf should be freed from _base_interrupt
222 * 0 means the mf is freed from this function.
225 mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
226 u32 reply)
228 MPI2DefaultReply_t *mpi_reply;
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;
241 ioc->transport_cmds.status &= ~MPT2_CMD_PENDING;
242 complete(&ioc->transport_cmds.done);
243 return 1;
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;
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];
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
280 * Fills in the sas_expander_device object when SMP port is created.
282 * Returns 0 for success, non-zero for failure.
284 static int
285 _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
286 u64 sas_address, struct sas_expander_device *edev)
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 u16 wait_state_count;
304 if (ioc->shost_recovery || ioc->pci_error_recovery) {
305 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
306 __func__, ioc->name);
307 return -EFAULT;
310 mutex_lock(&ioc->transport_cmds.mutex);
312 if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
313 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
314 ioc->name, __func__);
315 rc = -EAGAIN;
316 goto out;
318 ioc->transport_cmds.status = MPT2_CMD_PENDING;
320 wait_state_count = 0;
321 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
322 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
323 if (wait_state_count++ == 10) {
324 printk(MPT2SAS_ERR_FMT
325 "%s: failed due to ioc not operational\n",
326 ioc->name, __func__);
327 rc = -EFAULT;
328 goto out;
330 ssleep(1);
331 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
332 printk(MPT2SAS_INFO_FMT "%s: waiting for "
333 "operational state(count=%d)\n", ioc->name,
334 __func__, wait_state_count);
336 if (wait_state_count)
337 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
338 ioc->name, __func__);
340 smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
341 if (!smid) {
342 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
343 ioc->name, __func__);
344 rc = -EAGAIN;
345 goto out;
348 rc = 0;
349 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
350 ioc->transport_cmds.smid = smid;
352 sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
353 data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
355 if (!data_out) {
356 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
357 __LINE__, __func__);
358 rc = -ENOMEM;
359 mpt2sas_base_free_smid(ioc, smid);
360 goto out;
363 manufacture_request = data_out;
364 manufacture_request->smp_frame_type = 0x40;
365 manufacture_request->function = 1;
366 manufacture_request->reserved = 0;
367 manufacture_request->request_length = 0;
369 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
370 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
371 mpi_request->PhysicalPort = 0xFF;
372 mpi_request->VF_ID = 0; /* TODO */
373 mpi_request->VP_ID = 0;
374 mpi_request->SASAddress = cpu_to_le64(sas_address);
375 mpi_request->RequestDataLength =
376 cpu_to_le16(sizeof(struct rep_manu_request));
377 psge = &mpi_request->SGL;
379 /* WRITE sgel first */
380 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
381 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
382 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
383 ioc->base_add_sg_single(psge, sgl_flags |
384 sizeof(struct rep_manu_request), data_out_dma);
386 /* incr sgel */
387 psge += ioc->sge_size;
389 /* READ sgel last */
390 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
391 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
392 MPI2_SGE_FLAGS_END_OF_LIST);
393 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
394 ioc->base_add_sg_single(psge, sgl_flags |
395 sizeof(struct rep_manu_reply), data_out_dma +
396 sizeof(struct rep_manu_request));
398 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
399 "send to sas_addr(0x%016llx)\n", ioc->name,
400 (unsigned long long)sas_address));
401 init_completion(&ioc->transport_cmds.done);
402 mpt2sas_base_put_smid_default(ioc, smid);
403 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
404 10*HZ);
406 if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
407 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
408 ioc->name, __func__);
409 _debug_dump_mf(mpi_request,
410 sizeof(Mpi2SmpPassthroughRequest_t)/4);
411 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
412 issue_reset = 1;
413 goto issue_host_reset;
416 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
417 "complete\n", ioc->name));
419 if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
420 u8 *tmp;
422 mpi_reply = ioc->transport_cmds.reply;
424 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
425 "report_manufacture - reply data transfer size(%d)\n",
426 ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
428 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
429 sizeof(struct rep_manu_reply))
430 goto out;
432 manufacture_reply = data_out + sizeof(struct rep_manu_request);
433 strncpy(edev->vendor_id, manufacture_reply->vendor_id,
434 SAS_EXPANDER_VENDOR_ID_LEN);
435 strncpy(edev->product_id, manufacture_reply->product_id,
436 SAS_EXPANDER_PRODUCT_ID_LEN);
437 strncpy(edev->product_rev, manufacture_reply->product_rev,
438 SAS_EXPANDER_PRODUCT_REV_LEN);
439 edev->level = manufacture_reply->sas_format & 1;
440 if (edev->level) {
441 strncpy(edev->component_vendor_id,
442 manufacture_reply->component_vendor_id,
443 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
444 tmp = (u8 *)&manufacture_reply->component_id;
445 edev->component_id = tmp[0] << 8 | tmp[1];
446 edev->component_revision_id =
447 manufacture_reply->component_revision_id;
449 } else
450 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
451 "report_manufacture - no reply\n", ioc->name));
453 issue_host_reset:
454 if (issue_reset)
455 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
456 FORCE_BIG_HAMMER);
457 out:
458 ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
459 if (data_out)
460 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
462 mutex_unlock(&ioc->transport_cmds.mutex);
463 return rc;
467 * _transport_delete_port - helper function to removing a port
468 * @ioc: per adapter object
469 * @mpt2sas_port: mpt2sas per port object
471 * Returns nothing.
473 static void
474 _transport_delete_port(struct MPT2SAS_ADAPTER *ioc,
475 struct _sas_port *mpt2sas_port)
477 u64 sas_address = mpt2sas_port->remote_identify.sas_address;
478 enum sas_device_type device_type =
479 mpt2sas_port->remote_identify.device_type;
481 dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
482 "remove: sas_addr(0x%016llx)\n",
483 (unsigned long long) sas_address);
485 ioc->logging_level |= MPT_DEBUG_TRANSPORT;
486 if (device_type == SAS_END_DEVICE)
487 mpt2sas_device_remove(ioc, sas_address);
488 else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
489 device_type == SAS_FANOUT_EXPANDER_DEVICE)
490 mpt2sas_expander_remove(ioc, sas_address);
491 ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
495 * _transport_delete_phy - helper function to removing single phy from port
496 * @ioc: per adapter object
497 * @mpt2sas_port: mpt2sas per port object
498 * @mpt2sas_phy: mpt2sas per phy object
500 * Returns nothing.
502 static void
503 _transport_delete_phy(struct MPT2SAS_ADAPTER *ioc,
504 struct _sas_port *mpt2sas_port, struct _sas_phy *mpt2sas_phy)
506 u64 sas_address = mpt2sas_port->remote_identify.sas_address;
508 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
509 "remove: sas_addr(0x%016llx), phy(%d)\n",
510 (unsigned long long) sas_address, mpt2sas_phy->phy_id);
512 list_del(&mpt2sas_phy->port_siblings);
513 mpt2sas_port->num_phys--;
514 sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
515 mpt2sas_phy->phy_belongs_to_port = 0;
519 * _transport_add_phy - helper function to adding single phy to port
520 * @ioc: per adapter object
521 * @mpt2sas_port: mpt2sas per port object
522 * @mpt2sas_phy: mpt2sas per phy object
524 * Returns nothing.
526 static void
527 _transport_add_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_port *mpt2sas_port,
528 struct _sas_phy *mpt2sas_phy)
530 u64 sas_address = mpt2sas_port->remote_identify.sas_address;
532 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
533 "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
534 sas_address, mpt2sas_phy->phy_id);
536 list_add_tail(&mpt2sas_phy->port_siblings, &mpt2sas_port->phy_list);
537 mpt2sas_port->num_phys++;
538 sas_port_add_phy(mpt2sas_port->port, mpt2sas_phy->phy);
539 mpt2sas_phy->phy_belongs_to_port = 1;
543 * _transport_add_phy_to_an_existing_port - adding new phy to existing port
544 * @ioc: per adapter object
545 * @sas_node: sas node object (either expander or sas host)
546 * @mpt2sas_phy: mpt2sas per phy object
547 * @sas_address: sas address of device/expander were phy needs to be added to
549 * Returns nothing.
551 static void
552 _transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
553 struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy, u64 sas_address)
555 struct _sas_port *mpt2sas_port;
556 struct _sas_phy *phy_srch;
558 if (mpt2sas_phy->phy_belongs_to_port == 1)
559 return;
561 list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list,
562 port_list) {
563 if (mpt2sas_port->remote_identify.sas_address !=
564 sas_address)
565 continue;
566 list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
567 port_siblings) {
568 if (phy_srch == mpt2sas_phy)
569 return;
571 _transport_add_phy(ioc, mpt2sas_port, mpt2sas_phy);
572 return;
578 * _transport_del_phy_from_an_existing_port - delete phy from existing port
579 * @ioc: per adapter object
580 * @sas_node: sas node object (either expander or sas host)
581 * @mpt2sas_phy: mpt2sas per phy object
583 * Returns nothing.
585 static void
586 _transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
587 struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy)
589 struct _sas_port *mpt2sas_port, *next;
590 struct _sas_phy *phy_srch;
592 if (mpt2sas_phy->phy_belongs_to_port == 0)
593 return;
595 list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
596 port_list) {
597 list_for_each_entry(phy_srch, &mpt2sas_port->phy_list,
598 port_siblings) {
599 if (phy_srch != mpt2sas_phy)
600 continue;
601 if (mpt2sas_port->num_phys == 1)
602 _transport_delete_port(ioc, mpt2sas_port);
603 else
604 _transport_delete_phy(ioc, mpt2sas_port,
605 mpt2sas_phy);
606 return;
612 * _transport_sanity_check - sanity check when adding a new port
613 * @ioc: per adapter object
614 * @sas_node: sas node object (either expander or sas host)
615 * @sas_address: sas address of device being added
617 * See the explanation above from _transport_delete_duplicate_port
619 static void
620 _transport_sanity_check(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node,
621 u64 sas_address)
623 int i;
625 for (i = 0; i < sas_node->num_phys; i++) {
626 if (sas_node->phy[i].remote_identify.sas_address != sas_address)
627 continue;
628 if (sas_node->phy[i].phy_belongs_to_port == 1)
629 _transport_del_phy_from_an_existing_port(ioc, sas_node,
630 &sas_node->phy[i]);
635 * mpt2sas_transport_port_add - insert port to the list
636 * @ioc: per adapter object
637 * @handle: handle of attached device
638 * @sas_address: sas address of parent expander or sas host
639 * Context: This function will acquire ioc->sas_node_lock.
641 * Adding new port object to the sas_node->sas_port_list.
643 * Returns mpt2sas_port.
645 struct _sas_port *
646 mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
647 u64 sas_address)
649 struct _sas_phy *mpt2sas_phy, *next;
650 struct _sas_port *mpt2sas_port;
651 unsigned long flags;
652 struct _sas_node *sas_node;
653 struct sas_rphy *rphy;
654 int i;
655 struct sas_port *port;
657 mpt2sas_port = kzalloc(sizeof(struct _sas_port),
658 GFP_KERNEL);
659 if (!mpt2sas_port) {
660 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
661 ioc->name, __FILE__, __LINE__, __func__);
662 return NULL;
665 INIT_LIST_HEAD(&mpt2sas_port->port_list);
666 INIT_LIST_HEAD(&mpt2sas_port->phy_list);
667 spin_lock_irqsave(&ioc->sas_node_lock, flags);
668 sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
669 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
671 if (!sas_node) {
672 printk(MPT2SAS_ERR_FMT "%s: Could not find "
673 "parent sas_address(0x%016llx)!\n", ioc->name,
674 __func__, (unsigned long long)sas_address);
675 goto out_fail;
678 if ((_transport_set_identify(ioc, handle,
679 &mpt2sas_port->remote_identify))) {
680 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
681 ioc->name, __FILE__, __LINE__, __func__);
682 goto out_fail;
685 if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
686 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
687 ioc->name, __FILE__, __LINE__, __func__);
688 goto out_fail;
691 _transport_sanity_check(ioc, sas_node,
692 mpt2sas_port->remote_identify.sas_address);
694 for (i = 0; i < sas_node->num_phys; i++) {
695 if (sas_node->phy[i].remote_identify.sas_address !=
696 mpt2sas_port->remote_identify.sas_address)
697 continue;
698 list_add_tail(&sas_node->phy[i].port_siblings,
699 &mpt2sas_port->phy_list);
700 mpt2sas_port->num_phys++;
703 if (!mpt2sas_port->num_phys) {
704 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
705 ioc->name, __FILE__, __LINE__, __func__);
706 goto out_fail;
709 port = sas_port_alloc_num(sas_node->parent_dev);
710 if ((sas_port_add(port))) {
711 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
712 ioc->name, __FILE__, __LINE__, __func__);
713 goto out_fail;
716 list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
717 port_siblings) {
718 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
719 dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
720 ", sas_addr(0x%016llx), phy(%d)\n", handle,
721 (unsigned long long)
722 mpt2sas_port->remote_identify.sas_address,
723 mpt2sas_phy->phy_id);
724 sas_port_add_phy(port, mpt2sas_phy->phy);
725 mpt2sas_phy->phy_belongs_to_port = 1;
728 mpt2sas_port->port = port;
729 if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
730 rphy = sas_end_device_alloc(port);
731 else
732 rphy = sas_expander_alloc(port,
733 mpt2sas_port->remote_identify.device_type);
735 rphy->identify = mpt2sas_port->remote_identify;
736 if ((sas_rphy_add(rphy))) {
737 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
738 ioc->name, __FILE__, __LINE__, __func__);
740 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
741 dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
742 "sas_addr(0x%016llx)\n", handle,
743 (unsigned long long)
744 mpt2sas_port->remote_identify.sas_address);
745 mpt2sas_port->rphy = rphy;
746 spin_lock_irqsave(&ioc->sas_node_lock, flags);
747 list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
748 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
750 /* fill in report manufacture */
751 if (mpt2sas_port->remote_identify.device_type ==
752 MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
753 mpt2sas_port->remote_identify.device_type ==
754 MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
755 _transport_expander_report_manufacture(ioc,
756 mpt2sas_port->remote_identify.sas_address,
757 rphy_to_expander_device(rphy));
759 return mpt2sas_port;
761 out_fail:
762 list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
763 port_siblings)
764 list_del(&mpt2sas_phy->port_siblings);
765 kfree(mpt2sas_port);
766 return NULL;
770 * mpt2sas_transport_port_remove - remove port from the list
771 * @ioc: per adapter object
772 * @sas_address: sas address of attached device
773 * @sas_address_parent: sas address of parent expander or sas host
774 * Context: This function will acquire ioc->sas_node_lock.
776 * Removing object and freeing associated memory from the
777 * ioc->sas_port_list.
779 * Return nothing.
781 void
782 mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
783 u64 sas_address_parent)
785 int i;
786 unsigned long flags;
787 struct _sas_port *mpt2sas_port, *next;
788 struct _sas_node *sas_node;
789 u8 found = 0;
790 struct _sas_phy *mpt2sas_phy, *next_phy;
792 spin_lock_irqsave(&ioc->sas_node_lock, flags);
793 sas_node = _transport_sas_node_find_by_sas_address(ioc,
794 sas_address_parent);
795 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
796 if (!sas_node)
797 return;
798 list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
799 port_list) {
800 if (mpt2sas_port->remote_identify.sas_address != sas_address)
801 continue;
802 found = 1;
803 list_del(&mpt2sas_port->port_list);
804 goto out;
806 out:
807 if (!found)
808 return;
810 for (i = 0; i < sas_node->num_phys; i++) {
811 if (sas_node->phy[i].remote_identify.sas_address == sas_address)
812 memset(&sas_node->phy[i].remote_identify, 0 ,
813 sizeof(struct sas_identify));
816 list_for_each_entry_safe(mpt2sas_phy, next_phy,
817 &mpt2sas_port->phy_list, port_siblings) {
818 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
819 dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
820 "remove: sas_addr(0x%016llx), phy(%d)\n",
821 (unsigned long long)
822 mpt2sas_port->remote_identify.sas_address,
823 mpt2sas_phy->phy_id);
824 mpt2sas_phy->phy_belongs_to_port = 0;
825 sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
826 list_del(&mpt2sas_phy->port_siblings);
828 sas_port_delete(mpt2sas_port->port);
829 kfree(mpt2sas_port);
833 * mpt2sas_transport_add_host_phy - report sas_host phy to transport
834 * @ioc: per adapter object
835 * @mpt2sas_phy: mpt2sas per phy object
836 * @phy_pg0: sas phy page 0
837 * @parent_dev: parent device class object
839 * Returns 0 for success, non-zero for failure.
842 mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
843 *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
845 struct sas_phy *phy;
846 int phy_index = mpt2sas_phy->phy_id;
849 INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
850 phy = sas_phy_alloc(parent_dev, phy_index);
851 if (!phy) {
852 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
853 ioc->name, __FILE__, __LINE__, __func__);
854 return -1;
856 if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
857 &mpt2sas_phy->identify))) {
858 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
859 ioc->name, __FILE__, __LINE__, __func__);
860 return -1;
862 phy->identify = mpt2sas_phy->identify;
863 mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
864 if (mpt2sas_phy->attached_handle)
865 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
866 &mpt2sas_phy->remote_identify);
867 phy->identify.phy_identifier = mpt2sas_phy->phy_id;
868 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
869 phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
870 phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
871 phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
872 phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
873 phy_pg0.HwLinkRate >> 4);
874 phy->minimum_linkrate = _transport_convert_phy_link_rate(
875 phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
876 phy->maximum_linkrate = _transport_convert_phy_link_rate(
877 phy_pg0.ProgrammedLinkRate >> 4);
879 if ((sas_phy_add(phy))) {
880 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
881 ioc->name, __FILE__, __LINE__, __func__);
882 sas_phy_free(phy);
883 return -1;
885 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
886 dev_printk(KERN_INFO, &phy->dev,
887 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
888 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
889 mpt2sas_phy->handle, (unsigned long long)
890 mpt2sas_phy->identify.sas_address,
891 mpt2sas_phy->attached_handle,
892 (unsigned long long)
893 mpt2sas_phy->remote_identify.sas_address);
894 mpt2sas_phy->phy = phy;
895 return 0;
900 * mpt2sas_transport_add_expander_phy - report expander phy to transport
901 * @ioc: per adapter object
902 * @mpt2sas_phy: mpt2sas per phy object
903 * @expander_pg1: expander page 1
904 * @parent_dev: parent device class object
906 * Returns 0 for success, non-zero for failure.
909 mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
910 *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
912 struct sas_phy *phy;
913 int phy_index = mpt2sas_phy->phy_id;
915 INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
916 phy = sas_phy_alloc(parent_dev, phy_index);
917 if (!phy) {
918 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
919 ioc->name, __FILE__, __LINE__, __func__);
920 return -1;
922 if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
923 &mpt2sas_phy->identify))) {
924 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
925 ioc->name, __FILE__, __LINE__, __func__);
926 return -1;
928 phy->identify = mpt2sas_phy->identify;
929 mpt2sas_phy->attached_handle =
930 le16_to_cpu(expander_pg1.AttachedDevHandle);
931 if (mpt2sas_phy->attached_handle)
932 _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
933 &mpt2sas_phy->remote_identify);
934 phy->identify.phy_identifier = mpt2sas_phy->phy_id;
935 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
936 expander_pg1.NegotiatedLinkRate &
937 MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
938 phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
939 expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
940 phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
941 expander_pg1.HwLinkRate >> 4);
942 phy->minimum_linkrate = _transport_convert_phy_link_rate(
943 expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
944 phy->maximum_linkrate = _transport_convert_phy_link_rate(
945 expander_pg1.ProgrammedLinkRate >> 4);
947 if ((sas_phy_add(phy))) {
948 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
949 ioc->name, __FILE__, __LINE__, __func__);
950 sas_phy_free(phy);
951 return -1;
953 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
954 dev_printk(KERN_INFO, &phy->dev,
955 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
956 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
957 mpt2sas_phy->handle, (unsigned long long)
958 mpt2sas_phy->identify.sas_address,
959 mpt2sas_phy->attached_handle,
960 (unsigned long long)
961 mpt2sas_phy->remote_identify.sas_address);
962 mpt2sas_phy->phy = phy;
963 return 0;
967 * mpt2sas_transport_update_links - refreshing phy link changes
968 * @ioc: per adapter object
969 * @sas_address: sas address of parent expander or sas host
970 * @handle: attached device handle
971 * @phy_numberv: phy number
972 * @link_rate: new link rate
974 * Returns nothing.
976 void
977 mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
978 u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
980 unsigned long flags;
981 struct _sas_node *sas_node;
982 struct _sas_phy *mpt2sas_phy;
984 if (ioc->shost_recovery || ioc->pci_error_recovery)
985 return;
987 spin_lock_irqsave(&ioc->sas_node_lock, flags);
988 sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
989 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
990 if (!sas_node)
991 return;
993 mpt2sas_phy = &sas_node->phy[phy_number];
994 mpt2sas_phy->attached_handle = handle;
995 if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
996 _transport_set_identify(ioc, handle,
997 &mpt2sas_phy->remote_identify);
998 _transport_add_phy_to_an_existing_port(ioc, sas_node,
999 mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address);
1000 } else
1001 memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
1002 sas_identify));
1004 if (mpt2sas_phy->phy)
1005 mpt2sas_phy->phy->negotiated_linkrate =
1006 _transport_convert_phy_link_rate(link_rate);
1008 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
1009 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
1010 "refresh: parent sas_addr(0x%016llx),\n"
1011 "\tlink_rate(0x%02x), phy(%d)\n"
1012 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
1013 (unsigned long long)sas_address,
1014 link_rate, phy_number, handle, (unsigned long long)
1015 mpt2sas_phy->remote_identify.sas_address);
1018 static inline void *
1019 phy_to_ioc(struct sas_phy *phy)
1021 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1022 return shost_priv(shost);
1025 static inline void *
1026 rphy_to_ioc(struct sas_rphy *rphy)
1028 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
1029 return shost_priv(shost);
1033 /* report phy error log structure */
1034 struct phy_error_log_request{
1035 u8 smp_frame_type; /* 0x40 */
1036 u8 function; /* 0x11 */
1037 u8 allocated_response_length;
1038 u8 request_length; /* 02 */
1039 u8 reserved_1[5];
1040 u8 phy_identifier;
1041 u8 reserved_2[2];
1044 /* report phy error log reply structure */
1045 struct phy_error_log_reply{
1046 u8 smp_frame_type; /* 0x41 */
1047 u8 function; /* 0x11 */
1048 u8 function_result;
1049 u8 response_length;
1050 __be16 expander_change_count;
1051 u8 reserved_1[3];
1052 u8 phy_identifier;
1053 u8 reserved_2[2];
1054 __be32 invalid_dword;
1055 __be32 running_disparity_error;
1056 __be32 loss_of_dword_sync;
1057 __be32 phy_reset_problem;
1061 * _transport_get_expander_phy_error_log - return expander counters
1062 * @ioc: per adapter object
1063 * @phy: The sas phy object
1065 * Returns 0 for success, non-zero for failure.
1068 static int
1069 _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
1070 struct sas_phy *phy)
1072 Mpi2SmpPassthroughRequest_t *mpi_request;
1073 Mpi2SmpPassthroughReply_t *mpi_reply;
1074 struct phy_error_log_request *phy_error_log_request;
1075 struct phy_error_log_reply *phy_error_log_reply;
1076 int rc;
1077 u16 smid;
1078 u32 ioc_state;
1079 unsigned long timeleft;
1080 void *psge;
1081 u32 sgl_flags;
1082 u8 issue_reset = 0;
1083 void *data_out = NULL;
1084 dma_addr_t data_out_dma;
1085 u32 sz;
1086 u16 wait_state_count;
1088 if (ioc->shost_recovery || ioc->pci_error_recovery) {
1089 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1090 __func__, ioc->name);
1091 return -EFAULT;
1094 mutex_lock(&ioc->transport_cmds.mutex);
1096 if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1097 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
1098 ioc->name, __func__);
1099 rc = -EAGAIN;
1100 goto out;
1102 ioc->transport_cmds.status = MPT2_CMD_PENDING;
1104 wait_state_count = 0;
1105 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1106 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1107 if (wait_state_count++ == 10) {
1108 printk(MPT2SAS_ERR_FMT
1109 "%s: failed due to ioc not operational\n",
1110 ioc->name, __func__);
1111 rc = -EFAULT;
1112 goto out;
1114 ssleep(1);
1115 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1116 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1117 "operational state(count=%d)\n", ioc->name,
1118 __func__, wait_state_count);
1120 if (wait_state_count)
1121 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1122 ioc->name, __func__);
1124 smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1125 if (!smid) {
1126 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1127 ioc->name, __func__);
1128 rc = -EAGAIN;
1129 goto out;
1132 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1133 ioc->transport_cmds.smid = smid;
1135 sz = sizeof(struct phy_error_log_request) +
1136 sizeof(struct phy_error_log_reply);
1137 data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1138 if (!data_out) {
1139 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
1140 __LINE__, __func__);
1141 rc = -ENOMEM;
1142 mpt2sas_base_free_smid(ioc, smid);
1143 goto out;
1146 rc = -EINVAL;
1147 memset(data_out, 0, sz);
1148 phy_error_log_request = data_out;
1149 phy_error_log_request->smp_frame_type = 0x40;
1150 phy_error_log_request->function = 0x11;
1151 phy_error_log_request->request_length = 2;
1152 phy_error_log_request->allocated_response_length = 0;
1153 phy_error_log_request->phy_identifier = phy->number;
1155 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1156 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1157 mpi_request->PhysicalPort = 0xFF;
1158 mpi_request->VF_ID = 0; /* TODO */
1159 mpi_request->VP_ID = 0;
1160 mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1161 mpi_request->RequestDataLength =
1162 cpu_to_le16(sizeof(struct phy_error_log_request));
1163 psge = &mpi_request->SGL;
1165 /* WRITE sgel first */
1166 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1167 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1168 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1169 ioc->base_add_sg_single(psge, sgl_flags |
1170 sizeof(struct phy_error_log_request), data_out_dma);
1172 /* incr sgel */
1173 psge += ioc->sge_size;
1175 /* READ sgel last */
1176 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1177 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1178 MPI2_SGE_FLAGS_END_OF_LIST);
1179 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1180 ioc->base_add_sg_single(psge, sgl_flags |
1181 sizeof(struct phy_error_log_reply), data_out_dma +
1182 sizeof(struct phy_error_log_request));
1184 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
1185 "send to sas_addr(0x%016llx), phy(%d)\n", ioc->name,
1186 (unsigned long long)phy->identify.sas_address, phy->number));
1187 init_completion(&ioc->transport_cmds.done);
1188 mpt2sas_base_put_smid_default(ioc, smid);
1189 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1190 10*HZ);
1192 if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1193 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
1194 ioc->name, __func__);
1195 _debug_dump_mf(mpi_request,
1196 sizeof(Mpi2SmpPassthroughRequest_t)/4);
1197 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1198 issue_reset = 1;
1199 goto issue_host_reset;
1202 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
1203 "complete\n", ioc->name));
1205 if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1207 mpi_reply = ioc->transport_cmds.reply;
1209 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1210 "phy_error_log - reply data transfer size(%d)\n",
1211 ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1213 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1214 sizeof(struct phy_error_log_reply))
1215 goto out;
1217 phy_error_log_reply = data_out +
1218 sizeof(struct phy_error_log_request);
1220 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1221 "phy_error_log - function_result(%d)\n",
1222 ioc->name, phy_error_log_reply->function_result));
1224 phy->invalid_dword_count =
1225 be32_to_cpu(phy_error_log_reply->invalid_dword);
1226 phy->running_disparity_error_count =
1227 be32_to_cpu(phy_error_log_reply->running_disparity_error);
1228 phy->loss_of_dword_sync_count =
1229 be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
1230 phy->phy_reset_problem_count =
1231 be32_to_cpu(phy_error_log_reply->phy_reset_problem);
1232 rc = 0;
1233 } else
1234 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1235 "phy_error_log - no reply\n", ioc->name));
1237 issue_host_reset:
1238 if (issue_reset)
1239 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1240 FORCE_BIG_HAMMER);
1241 out:
1242 ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1243 if (data_out)
1244 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1246 mutex_unlock(&ioc->transport_cmds.mutex);
1247 return rc;
1251 * _transport_get_linkerrors - return phy counters for both hba and expanders
1252 * @phy: The sas phy object
1254 * Returns 0 for success, non-zero for failure.
1257 static int
1258 _transport_get_linkerrors(struct sas_phy *phy)
1260 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1261 unsigned long flags;
1262 Mpi2ConfigReply_t mpi_reply;
1263 Mpi2SasPhyPage1_t phy_pg1;
1265 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1266 if (_transport_sas_node_find_by_sas_address(ioc,
1267 phy->identify.sas_address) == NULL) {
1268 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1269 return -EINVAL;
1271 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1273 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1274 return _transport_get_expander_phy_error_log(ioc, phy);
1276 /* get hba phy error logs */
1277 if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
1278 phy->number))) {
1279 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1280 ioc->name, __FILE__, __LINE__, __func__);
1281 return -ENXIO;
1284 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1285 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1286 "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1287 phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1288 le32_to_cpu(mpi_reply.IOCLogInfo));
1290 phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
1291 phy->running_disparity_error_count =
1292 le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
1293 phy->loss_of_dword_sync_count =
1294 le32_to_cpu(phy_pg1.LossDwordSynchCount);
1295 phy->phy_reset_problem_count =
1296 le32_to_cpu(phy_pg1.PhyResetProblemCount);
1297 return 0;
1301 * _transport_get_enclosure_identifier -
1302 * @phy: The sas phy object
1304 * Obtain the enclosure logical id for an expander.
1305 * Returns 0 for success, non-zero for failure.
1307 static int
1308 _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1310 struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1311 struct _sas_device *sas_device;
1312 unsigned long flags;
1314 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1315 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1316 rphy->identify.sas_address);
1317 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1319 if (!sas_device)
1320 return -ENXIO;
1322 *identifier = sas_device->enclosure_logical_id;
1323 return 0;
1327 * _transport_get_bay_identifier -
1328 * @phy: The sas phy object
1330 * Returns the slot id for a device that resides inside an enclosure.
1332 static int
1333 _transport_get_bay_identifier(struct sas_rphy *rphy)
1335 struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1336 struct _sas_device *sas_device;
1337 unsigned long flags;
1339 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1340 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
1341 rphy->identify.sas_address);
1342 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1344 if (!sas_device)
1345 return -ENXIO;
1347 return sas_device->slot;
1350 /* phy control request structure */
1351 struct phy_control_request{
1352 u8 smp_frame_type; /* 0x40 */
1353 u8 function; /* 0x91 */
1354 u8 allocated_response_length;
1355 u8 request_length; /* 0x09 */
1356 u16 expander_change_count;
1357 u8 reserved_1[3];
1358 u8 phy_identifier;
1359 u8 phy_operation;
1360 u8 reserved_2[13];
1361 u64 attached_device_name;
1362 u8 programmed_min_physical_link_rate;
1363 u8 programmed_max_physical_link_rate;
1364 u8 reserved_3[6];
1367 /* phy control reply structure */
1368 struct phy_control_reply{
1369 u8 smp_frame_type; /* 0x41 */
1370 u8 function; /* 0x11 */
1371 u8 function_result;
1372 u8 response_length;
1375 #define SMP_PHY_CONTROL_LINK_RESET (0x01)
1376 #define SMP_PHY_CONTROL_HARD_RESET (0x02)
1377 #define SMP_PHY_CONTROL_DISABLE (0x03)
1380 * _transport_expander_phy_control - expander phy control
1381 * @ioc: per adapter object
1382 * @phy: The sas phy object
1384 * Returns 0 for success, non-zero for failure.
1387 static int
1388 _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
1389 struct sas_phy *phy, u8 phy_operation)
1391 Mpi2SmpPassthroughRequest_t *mpi_request;
1392 Mpi2SmpPassthroughReply_t *mpi_reply;
1393 struct phy_control_request *phy_control_request;
1394 struct phy_control_reply *phy_control_reply;
1395 int rc;
1396 u16 smid;
1397 u32 ioc_state;
1398 unsigned long timeleft;
1399 void *psge;
1400 u32 sgl_flags;
1401 u8 issue_reset = 0;
1402 void *data_out = NULL;
1403 dma_addr_t data_out_dma;
1404 u32 sz;
1405 u16 wait_state_count;
1407 if (ioc->shost_recovery) {
1408 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1409 __func__, ioc->name);
1410 return -EFAULT;
1413 mutex_lock(&ioc->transport_cmds.mutex);
1415 if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1416 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
1417 ioc->name, __func__);
1418 rc = -EAGAIN;
1419 goto out;
1421 ioc->transport_cmds.status = MPT2_CMD_PENDING;
1423 wait_state_count = 0;
1424 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1425 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1426 if (wait_state_count++ == 10) {
1427 printk(MPT2SAS_ERR_FMT
1428 "%s: failed due to ioc not operational\n",
1429 ioc->name, __func__);
1430 rc = -EFAULT;
1431 goto out;
1433 ssleep(1);
1434 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1435 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1436 "operational state(count=%d)\n", ioc->name,
1437 __func__, wait_state_count);
1439 if (wait_state_count)
1440 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1441 ioc->name, __func__);
1443 smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1444 if (!smid) {
1445 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1446 ioc->name, __func__);
1447 rc = -EAGAIN;
1448 goto out;
1451 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1452 ioc->transport_cmds.smid = smid;
1454 sz = sizeof(struct phy_control_request) +
1455 sizeof(struct phy_control_reply);
1456 data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
1457 if (!data_out) {
1458 printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
1459 __LINE__, __func__);
1460 rc = -ENOMEM;
1461 mpt2sas_base_free_smid(ioc, smid);
1462 goto out;
1465 rc = -EINVAL;
1466 memset(data_out, 0, sz);
1467 phy_control_request = data_out;
1468 phy_control_request->smp_frame_type = 0x40;
1469 phy_control_request->function = 0x91;
1470 phy_control_request->request_length = 9;
1471 phy_control_request->allocated_response_length = 0;
1472 phy_control_request->phy_identifier = phy->number;
1473 phy_control_request->phy_operation = phy_operation;
1474 phy_control_request->programmed_min_physical_link_rate =
1475 phy->minimum_linkrate << 4;
1476 phy_control_request->programmed_max_physical_link_rate =
1477 phy->maximum_linkrate << 4;
1479 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1480 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1481 mpi_request->PhysicalPort = 0xFF;
1482 mpi_request->VF_ID = 0; /* TODO */
1483 mpi_request->VP_ID = 0;
1484 mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1485 mpi_request->RequestDataLength =
1486 cpu_to_le16(sizeof(struct phy_error_log_request));
1487 psge = &mpi_request->SGL;
1489 /* WRITE sgel first */
1490 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1491 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1492 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1493 ioc->base_add_sg_single(psge, sgl_flags |
1494 sizeof(struct phy_control_request), data_out_dma);
1496 /* incr sgel */
1497 psge += ioc->sge_size;
1499 /* READ sgel last */
1500 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1501 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1502 MPI2_SGE_FLAGS_END_OF_LIST);
1503 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1504 ioc->base_add_sg_single(psge, sgl_flags |
1505 sizeof(struct phy_control_reply), data_out_dma +
1506 sizeof(struct phy_control_request));
1508 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
1509 "send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", ioc->name,
1510 (unsigned long long)phy->identify.sas_address, phy->number,
1511 phy_operation));
1513 init_completion(&ioc->transport_cmds.done);
1514 mpt2sas_base_put_smid_default(ioc, smid);
1515 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1516 10*HZ);
1518 if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1519 printk(MPT2SAS_ERR_FMT "%s: timeout\n",
1520 ioc->name, __func__);
1521 _debug_dump_mf(mpi_request,
1522 sizeof(Mpi2SmpPassthroughRequest_t)/4);
1523 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1524 issue_reset = 1;
1525 goto issue_host_reset;
1528 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
1529 "complete\n", ioc->name));
1531 if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1533 mpi_reply = ioc->transport_cmds.reply;
1535 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1536 "phy_control - reply data transfer size(%d)\n",
1537 ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
1539 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1540 sizeof(struct phy_control_reply))
1541 goto out;
1543 phy_control_reply = data_out +
1544 sizeof(struct phy_control_request);
1546 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1547 "phy_control - function_result(%d)\n",
1548 ioc->name, phy_control_reply->function_result));
1550 rc = 0;
1551 } else
1552 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1553 "phy_control - no reply\n", ioc->name));
1555 issue_host_reset:
1556 if (issue_reset)
1557 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1558 FORCE_BIG_HAMMER);
1559 out:
1560 ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
1561 if (data_out)
1562 pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
1564 mutex_unlock(&ioc->transport_cmds.mutex);
1565 return rc;
1569 * _transport_phy_reset -
1570 * @phy: The sas phy object
1571 * @hard_reset:
1573 * Returns 0 for success, non-zero for failure.
1575 static int
1576 _transport_phy_reset(struct sas_phy *phy, int hard_reset)
1578 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1579 Mpi2SasIoUnitControlReply_t mpi_reply;
1580 Mpi2SasIoUnitControlRequest_t mpi_request;
1581 unsigned long flags;
1583 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1584 if (_transport_sas_node_find_by_sas_address(ioc,
1585 phy->identify.sas_address) == NULL) {
1586 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1587 return -EINVAL;
1589 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1591 /* handle expander phys */
1592 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1593 return _transport_expander_phy_control(ioc, phy,
1594 (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
1595 SMP_PHY_CONTROL_LINK_RESET);
1597 /* handle hba phys */
1598 memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
1599 mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
1600 mpi_request.Operation = hard_reset ?
1601 MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
1602 mpi_request.PhyNum = phy->number;
1604 if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
1605 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1606 ioc->name, __FILE__, __LINE__, __func__);
1607 return -ENXIO;
1610 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1611 printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
1612 "(0x%04x), loginfo(0x%08x)\n", ioc->name,
1613 phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1614 le32_to_cpu(mpi_reply.IOCLogInfo));
1616 return 0;
1620 * _transport_phy_enable - enable/disable phys
1621 * @phy: The sas phy object
1622 * @enable: enable phy when true
1624 * Only support sas_host direct attached phys.
1625 * Returns 0 for success, non-zero for failure.
1627 static int
1628 _transport_phy_enable(struct sas_phy *phy, int enable)
1630 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1631 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1632 Mpi2ConfigReply_t mpi_reply;
1633 u16 ioc_status;
1634 u16 sz;
1635 int rc = 0;
1636 unsigned long flags;
1638 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1639 if (_transport_sas_node_find_by_sas_address(ioc,
1640 phy->identify.sas_address) == NULL) {
1641 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1642 return -EINVAL;
1644 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1646 /* handle expander phys */
1647 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1648 return _transport_expander_phy_control(ioc, phy,
1649 (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
1650 SMP_PHY_CONTROL_DISABLE);
1652 /* handle hba phys */
1654 /* sas_iounit page 1 */
1655 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1656 sizeof(Mpi2SasIOUnit1PhyData_t));
1657 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1658 if (!sas_iounit_pg1) {
1659 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1660 ioc->name, __FILE__, __LINE__, __func__);
1661 rc = -ENOMEM;
1662 goto out;
1664 if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1665 sas_iounit_pg1, sz))) {
1666 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1667 ioc->name, __FILE__, __LINE__, __func__);
1668 rc = -ENXIO;
1669 goto out;
1671 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1672 MPI2_IOCSTATUS_MASK;
1673 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1674 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1675 ioc->name, __FILE__, __LINE__, __func__);
1676 rc = -EIO;
1677 goto out;
1680 if (enable)
1681 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1682 &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1683 else
1684 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1685 |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1687 mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1689 /* link reset */
1690 if (enable)
1691 _transport_phy_reset(phy, 0);
1693 out:
1694 kfree(sas_iounit_pg1);
1695 return rc;
1699 * _transport_phy_speed - set phy min/max link rates
1700 * @phy: The sas phy object
1701 * @rates: rates defined in sas_phy_linkrates
1703 * Only support sas_host direct attached phys.
1704 * Returns 0 for success, non-zero for failure.
1706 static int
1707 _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1709 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
1710 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1711 Mpi2SasPhyPage0_t phy_pg0;
1712 Mpi2ConfigReply_t mpi_reply;
1713 u16 ioc_status;
1714 u16 sz;
1715 int i;
1716 int rc = 0;
1717 unsigned long flags;
1719 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1720 if (_transport_sas_node_find_by_sas_address(ioc,
1721 phy->identify.sas_address) == NULL) {
1722 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1723 return -EINVAL;
1725 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1727 if (!rates->minimum_linkrate)
1728 rates->minimum_linkrate = phy->minimum_linkrate;
1729 else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
1730 rates->minimum_linkrate = phy->minimum_linkrate_hw;
1732 if (!rates->maximum_linkrate)
1733 rates->maximum_linkrate = phy->maximum_linkrate;
1734 else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
1735 rates->maximum_linkrate = phy->maximum_linkrate_hw;
1737 /* handle expander phys */
1738 if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
1739 phy->minimum_linkrate = rates->minimum_linkrate;
1740 phy->maximum_linkrate = rates->maximum_linkrate;
1741 return _transport_expander_phy_control(ioc, phy,
1742 SMP_PHY_CONTROL_LINK_RESET);
1745 /* handle hba phys */
1747 /* sas_iounit page 1 */
1748 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1749 sizeof(Mpi2SasIOUnit1PhyData_t));
1750 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1751 if (!sas_iounit_pg1) {
1752 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1753 ioc->name, __FILE__, __LINE__, __func__);
1754 rc = -ENOMEM;
1755 goto out;
1757 if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1758 sas_iounit_pg1, sz))) {
1759 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1760 ioc->name, __FILE__, __LINE__, __func__);
1761 rc = -ENXIO;
1762 goto out;
1764 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1765 MPI2_IOCSTATUS_MASK;
1766 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1767 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1768 ioc->name, __FILE__, __LINE__, __func__);
1769 rc = -EIO;
1770 goto out;
1773 for (i = 0; i < ioc->sas_hba.num_phys; i++) {
1774 if (phy->number != i) {
1775 sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1776 (ioc->sas_hba.phy[i].phy->minimum_linkrate +
1777 (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
1778 } else {
1779 sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1780 (rates->minimum_linkrate +
1781 (rates->maximum_linkrate << 4));
1785 if (mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
1786 sz)) {
1787 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1788 ioc->name, __FILE__, __LINE__, __func__);
1789 rc = -ENXIO;
1790 goto out;
1793 /* link reset */
1794 _transport_phy_reset(phy, 0);
1796 /* read phy page 0, then update the rates in the sas transport phy */
1797 if (!mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
1798 phy->number)) {
1799 phy->minimum_linkrate = _transport_convert_phy_link_rate(
1800 phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1801 phy->maximum_linkrate = _transport_convert_phy_link_rate(
1802 phy_pg0.ProgrammedLinkRate >> 4);
1803 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1804 phy_pg0.NegotiatedLinkRate &
1805 MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1808 out:
1809 kfree(sas_iounit_pg1);
1810 return rc;
1815 * _transport_smp_handler - transport portal for smp passthru
1816 * @shost: shost object
1817 * @rphy: sas transport rphy object
1818 * @req:
1820 * This used primarily for smp_utils.
1821 * Example:
1822 * smp_rep_general /sys/class/bsg/expander-5:0
1824 static int
1825 _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1826 struct request *req)
1828 struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
1829 Mpi2SmpPassthroughRequest_t *mpi_request;
1830 Mpi2SmpPassthroughReply_t *mpi_reply;
1831 int rc;
1832 u16 smid;
1833 u32 ioc_state;
1834 unsigned long timeleft;
1835 void *psge;
1836 u32 sgl_flags;
1837 u8 issue_reset = 0;
1838 dma_addr_t dma_addr_in = 0;
1839 dma_addr_t dma_addr_out = 0;
1840 u16 wait_state_count;
1841 struct request *rsp = req->next_rq;
1843 if (!rsp) {
1844 printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
1845 "missing\n", ioc->name, __func__);
1846 return -EINVAL;
1849 /* do we need to support multiple segments? */
1850 if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
1851 printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, "
1852 "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt,
1853 blk_rq_bytes(req), rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
1854 return -EINVAL;
1857 if (ioc->shost_recovery) {
1858 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1859 __func__, ioc->name);
1860 return -EFAULT;
1863 rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1864 if (rc)
1865 return rc;
1867 if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
1868 printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
1869 __func__);
1870 rc = -EAGAIN;
1871 goto out;
1873 ioc->transport_cmds.status = MPT2_CMD_PENDING;
1875 wait_state_count = 0;
1876 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1877 while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
1878 if (wait_state_count++ == 10) {
1879 printk(MPT2SAS_ERR_FMT
1880 "%s: failed due to ioc not operational\n",
1881 ioc->name, __func__);
1882 rc = -EFAULT;
1883 goto out;
1885 ssleep(1);
1886 ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
1887 printk(MPT2SAS_INFO_FMT "%s: waiting for "
1888 "operational state(count=%d)\n", ioc->name,
1889 __func__, wait_state_count);
1891 if (wait_state_count)
1892 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1893 ioc->name, __func__);
1895 smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
1896 if (!smid) {
1897 printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
1898 ioc->name, __func__);
1899 rc = -EAGAIN;
1900 goto out;
1903 rc = 0;
1904 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1905 ioc->transport_cmds.smid = smid;
1907 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1908 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1909 mpi_request->PhysicalPort = 0xFF;
1910 mpi_request->VF_ID = 0; /* TODO */
1911 mpi_request->VP_ID = 0;
1912 mpi_request->SASAddress = (rphy) ?
1913 cpu_to_le64(rphy->identify.sas_address) :
1914 cpu_to_le64(ioc->sas_hba.sas_address);
1915 mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
1916 psge = &mpi_request->SGL;
1918 /* WRITE sgel first */
1919 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1920 MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
1921 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1922 dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
1923 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
1924 if (!dma_addr_out) {
1925 mpt2sas_base_free_smid(ioc, smid);
1926 goto unmap;
1929 ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(req) - 4),
1930 dma_addr_out);
1932 /* incr sgel */
1933 psge += ioc->sge_size;
1935 /* READ sgel last */
1936 sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
1937 MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
1938 MPI2_SGE_FLAGS_END_OF_LIST);
1939 sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
1940 dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
1941 blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
1942 if (!dma_addr_in) {
1943 mpt2sas_base_free_smid(ioc, smid);
1944 goto unmap;
1947 ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4),
1948 dma_addr_in);
1950 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
1951 "sending smp request\n", ioc->name, __func__));
1953 init_completion(&ioc->transport_cmds.done);
1954 mpt2sas_base_put_smid_default(ioc, smid);
1955 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1956 10*HZ);
1958 if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
1959 printk(MPT2SAS_ERR_FMT "%s : timeout\n",
1960 __func__, ioc->name);
1961 _debug_dump_mf(mpi_request,
1962 sizeof(Mpi2SmpPassthroughRequest_t)/4);
1963 if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
1964 issue_reset = 1;
1965 goto issue_host_reset;
1968 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
1969 "complete\n", ioc->name, __func__));
1971 if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1973 mpi_reply = ioc->transport_cmds.reply;
1975 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1976 "%s - reply data transfer size(%d)\n",
1977 ioc->name, __func__,
1978 le16_to_cpu(mpi_reply->ResponseDataLength)));
1980 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
1981 req->sense_len = sizeof(*mpi_reply);
1982 req->resid_len = 0;
1983 rsp->resid_len -=
1984 le16_to_cpu(mpi_reply->ResponseDataLength);
1985 } else {
1986 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1987 "%s - no reply\n", ioc->name, __func__));
1988 rc = -ENXIO;
1991 issue_host_reset:
1992 if (issue_reset) {
1993 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1994 FORCE_BIG_HAMMER);
1995 rc = -ETIMEDOUT;
1998 unmap:
1999 if (dma_addr_out)
2000 pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
2001 PCI_DMA_BIDIRECTIONAL);
2002 if (dma_addr_in)
2003 pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
2004 PCI_DMA_BIDIRECTIONAL);
2006 out:
2007 ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
2008 mutex_unlock(&ioc->transport_cmds.mutex);
2009 return rc;
2012 struct sas_function_template mpt2sas_transport_functions = {
2013 .get_linkerrors = _transport_get_linkerrors,
2014 .get_enclosure_identifier = _transport_get_enclosure_identifier,
2015 .get_bay_identifier = _transport_get_bay_identifier,
2016 .phy_reset = _transport_phy_reset,
2017 .phy_enable = _transport_phy_enable,
2018 .set_phy_speed = _transport_phy_speed,
2019 .smp_handler = _transport_smp_handler,
2022 struct scsi_transport_template *mpt2sas_transport_template;