Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / scsi / mpt2sas / mpt2sas_transport.c
CommitLineData
635374e7
EM
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
31b7f2e2 5 * Copyright (C) 2007-2010 LSI Corporation
635374e7
EM
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>
5a0e3ad6 52#include <linux/slab.h>
635374e7
EM
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/**
c5e039be 63 * _transport_sas_node_find_by_sas_address - sas node search
635374e7 64 * @ioc: per adapter object
c5e039be 65 * @sas_address: sas address of expander or sas host
635374e7
EM
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 */
71static struct _sas_node *
c5e039be
KD
72_transport_sas_node_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
73 u64 sas_address)
635374e7 74{
c5e039be
KD
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);
635374e7
EM
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 */
88static 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 */
134static 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
3cb5469a 143 if (ioc->shost_recovery || ioc->pci_error_recovery) {
155dd4c7
KD
144 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
145 __func__, ioc->name);
146 return -EFAULT;
147 }
148
635374e7
EM
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",
155dd4c7 152
635374e7 153 ioc->name, __FILE__, __LINE__, __func__);
155dd4c7 154 return -ENXIO;
635374e7
EM
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__);
155dd4c7 163 return -EIO;
635374e7
EM
164 }
165
96a99501 166 memset(identify, 0, sizeof(*identify));
635374e7
EM
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
7b936b02 215 * @msix_index: MSIX table index supplied by the OS
635374e7
EM
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 *
77e63ed4
KD
221 * Return 1 meaning mf should be freed from _base_interrupt
222 * 0 means the mf is freed from this function.
635374e7 223 */
77e63ed4 224u8
7b936b02 225mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
635374e7
EM
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)
77e63ed4 232 return 1;
635374e7 233 if (ioc->transport_cmds.smid != smid)
77e63ed4 234 return 1;
635374e7
EM
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);
77e63ed4 243 return 1;
635374e7
EM
244}
245
246/* report manufacture request structure */
247struct 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 */
255struct 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];
463217bf 262 u8 sas_format;
635374e7
EM
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/**
d5d135b3 275 * _transport_expander_report_manufacture - obtain SMP report_manufacture
635374e7
EM
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 */
284static int
d5d135b3 285_transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
635374e7
EM
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;
635374e7
EM
299 void *data_out = NULL;
300 dma_addr_t data_out_dma;
301 u32 sz;
635374e7
EM
302 u16 wait_state_count;
303
3cb5469a 304 if (ioc->shost_recovery || ioc->pci_error_recovery) {
635374e7
EM
305 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
306 __func__, ioc->name);
307 return -EFAULT;
308 }
635374e7
EM
309
310 mutex_lock(&ioc->transport_cmds.mutex);
311
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;
317 }
318 ioc->transport_cmds.status = MPT2_CMD_PENDING;
319
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;
329 }
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);
335 }
336 if (wait_state_count)
337 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
338 ioc->name, __func__);
339
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;
346 }
347
348 rc = 0;
349 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
350 ioc->transport_cmds.smid = smid;
351
352 sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
353 data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
354
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;
361 }
362
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;
368
369 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
370 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
371 mpi_request->PhysicalPort = 0xFF;
7b936b02
KD
372 mpi_request->VF_ID = 0; /* TODO */
373 mpi_request->VP_ID = 0;
c97951ec 374 mpi_request->SASAddress = cpu_to_le64(sas_address);
463217bf
KD
375 mpi_request->RequestDataLength =
376 cpu_to_le16(sizeof(struct rep_manu_request));
635374e7
EM
377 psge = &mpi_request->SGL;
378
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);
385
386 /* incr sgel */
387 psge += ioc->sge_size;
388
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));
397
eabb08ad 398 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
635374e7
EM
399 "send to sas_addr(0x%016llx)\n", ioc->name,
400 (unsigned long long)sas_address));
bcfb6e6e 401 init_completion(&ioc->transport_cmds.done);
f01690d3 402 mpt2sas_base_put_smid_default(ioc, smid);
635374e7
EM
403 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
404 10*HZ);
405
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;
414 }
415
eabb08ad 416 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "report_manufacture - "
635374e7
EM
417 "complete\n", ioc->name));
418
419 if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
420 u8 *tmp;
421
422 mpi_reply = ioc->transport_cmds.reply;
423
eabb08ad 424 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
635374e7
EM
425 "report_manufacture - reply data transfer size(%d)\n",
426 ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
427
428 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
429 sizeof(struct rep_manu_reply))
430 goto out;
431
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);
463217bf
KD
439 edev->level = manufacture_reply->sas_format & 1;
440 if (edev->level) {
635374e7
EM
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;
448 }
449 } else
eabb08ad 450 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
635374e7
EM
451 "report_manufacture - no reply\n", ioc->name));
452
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);
461
462 mutex_unlock(&ioc->transport_cmds.mutex);
463 return rc;
464}
465
7f6f794d
KD
466/**
467 * _transport_delete_port - helper function to removing a port
468 * @ioc: per adapter object
469 * @mpt2sas_port: mpt2sas per port object
470 *
471 * Returns nothing.
472 */
473static void
474_transport_delete_port(struct MPT2SAS_ADAPTER *ioc,
475 struct _sas_port *mpt2sas_port)
476{
477 u64 sas_address = mpt2sas_port->remote_identify.sas_address;
478 enum sas_device_type device_type =
479 mpt2sas_port->remote_identify.device_type;
480
481 dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
482 "remove: sas_addr(0x%016llx)\n",
483 (unsigned long long) sas_address);
484
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;
492}
38c29114
KD
493
494/**
7f6f794d 495 * _transport_delete_phy - helper function to removing single phy from port
38c29114 496 * @ioc: per adapter object
7f6f794d
KD
497 * @mpt2sas_port: mpt2sas per port object
498 * @mpt2sas_phy: mpt2sas per phy object
38c29114 499 *
7f6f794d
KD
500 * Returns nothing.
501 */
502static void
503_transport_delete_phy(struct MPT2SAS_ADAPTER *ioc,
504 struct _sas_port *mpt2sas_port, struct _sas_phy *mpt2sas_phy)
505{
506 u64 sas_address = mpt2sas_port->remote_identify.sas_address;
507
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);
511
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;
516}
517
518/**
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
38c29114 523 *
7f6f794d 524 * Returns nothing.
38c29114
KD
525 */
526static void
7f6f794d
KD
527_transport_add_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_port *mpt2sas_port,
528 struct _sas_phy *mpt2sas_phy)
38c29114 529{
7f6f794d 530 u64 sas_address = mpt2sas_port->remote_identify.sas_address;
38c29114 531
7f6f794d
KD
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);
38c29114 535
7f6f794d
KD
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;
540}
541
542/**
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
548 *
549 * Returns nothing.
550 */
551static void
552_transport_add_phy_to_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
553struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy, u64 sas_address)
554{
555 struct _sas_port *mpt2sas_port;
556 struct _sas_phy *phy_srch;
557
558 if (mpt2sas_phy->phy_belongs_to_port == 1)
559 return;
560
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,
38c29114 567 port_siblings) {
7f6f794d
KD
568 if (phy_srch == mpt2sas_phy)
569 return;
38c29114 570 }
7f6f794d
KD
571 _transport_add_phy(ioc, mpt2sas_port, mpt2sas_phy);
572 return;
38c29114
KD
573 }
574
7f6f794d
KD
575}
576
577/**
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
582 *
583 * Returns nothing.
584 */
585static void
586_transport_del_phy_from_an_existing_port(struct MPT2SAS_ADAPTER *ioc,
587 struct _sas_node *sas_node, struct _sas_phy *mpt2sas_phy)
588{
589 struct _sas_port *mpt2sas_port, *next;
590 struct _sas_phy *phy_srch;
591
592 if (mpt2sas_phy->phy_belongs_to_port == 0)
38c29114
KD
593 return;
594
7f6f794d
KD
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;
607 }
608 }
38c29114
KD
609}
610
611/**
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
616 *
617 * See the explanation above from _transport_delete_duplicate_port
618 */
619static void
620_transport_sanity_check(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node,
621 u64 sas_address)
622{
623 int i;
624
7f6f794d
KD
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]);
631 }
38c29114
KD
632}
633
635374e7
EM
634/**
635 * mpt2sas_transport_port_add - insert port to the list
636 * @ioc: per adapter object
637 * @handle: handle of attached device
c5e039be 638 * @sas_address: sas address of parent expander or sas host
635374e7
EM
639 * Context: This function will acquire ioc->sas_node_lock.
640 *
641 * Adding new port object to the sas_node->sas_port_list.
642 *
643 * Returns mpt2sas_port.
644 */
645struct _sas_port *
646mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
c5e039be 647 u64 sas_address)
635374e7
EM
648{
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;
656
635374e7
EM
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;
663 }
664
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);
c5e039be 668 sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
635374e7
EM
669 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
670
671 if (!sas_node) {
c5e039be
KD
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);
635374e7
EM
675 goto out_fail;
676 }
677
635374e7
EM
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;
683 }
684
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;
689 }
690
38c29114
KD
691 _transport_sanity_check(ioc, sas_node,
692 mpt2sas_port->remote_identify.sas_address);
693
635374e7
EM
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++;
701 }
702
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;
707 }
708
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;
714 }
715
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);
38c29114 725 mpt2sas_phy->phy_belongs_to_port = 1;
635374e7
EM
726 }
727
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);
734
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__);
739 }
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);
749
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)
d5d135b3 755 _transport_expander_report_manufacture(ioc,
635374e7
EM
756 mpt2sas_port->remote_identify.sas_address,
757 rphy_to_expander_device(rphy));
758
759 return mpt2sas_port;
760
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;
767}
768
769/**
770 * mpt2sas_transport_port_remove - remove port from the list
771 * @ioc: per adapter object
772 * @sas_address: sas address of attached device
c5e039be 773 * @sas_address_parent: sas address of parent expander or sas host
635374e7
EM
774 * Context: This function will acquire ioc->sas_node_lock.
775 *
776 * Removing object and freeing associated memory from the
777 * ioc->sas_port_list.
778 *
779 * Return nothing.
780 */
781void
782mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
c5e039be 783 u64 sas_address_parent)
635374e7
EM
784{
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;
791
792 spin_lock_irqsave(&ioc->sas_node_lock, flags);
c5e039be
KD
793 sas_node = _transport_sas_node_find_by_sas_address(ioc,
794 sas_address_parent);
635374e7
EM
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;
805 }
806 out:
807 if (!found)
808 return;
809
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));
814 }
815
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,
c5e039be 820 "remove: sas_addr(0x%016llx), phy(%d)\n",
635374e7
EM
821 (unsigned long long)
822 mpt2sas_port->remote_identify.sas_address,
823 mpt2sas_phy->phy_id);
38c29114 824 mpt2sas_phy->phy_belongs_to_port = 0;
635374e7
EM
825 sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
826 list_del(&mpt2sas_phy->port_siblings);
827 }
828 sas_port_delete(mpt2sas_port->port);
829 kfree(mpt2sas_port);
830}
831
832/**
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
838 *
839 * Returns 0 for success, non-zero for failure.
840 */
841int
842mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
843 *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
844{
845 struct sas_phy *phy;
846 int phy_index = mpt2sas_phy->phy_id;
847
848
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;
855 }
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;
861 }
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);
878
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;
884 }
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;
896}
897
898
899/**
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
905 *
906 * Returns 0 for success, non-zero for failure.
907 */
908int
909mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
910 *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
911{
912 struct sas_phy *phy;
913 int phy_index = mpt2sas_phy->phy_id;
914
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;
921 }
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;
927 }
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);
946
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;
952 }
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;
964}
965
966/**
cc0f5207 967 * mpt2sas_transport_update_links - refreshing phy link changes
635374e7 968 * @ioc: per adapter object
c5e039be
KD
969 * @sas_address: sas address of parent expander or sas host
970 * @handle: attached device handle
635374e7
EM
971 * @phy_numberv: phy number
972 * @link_rate: new link rate
973 *
974 * Returns nothing.
975 */
976void
cc0f5207 977mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc,
c5e039be 978 u64 sas_address, u16 handle, u8 phy_number, u8 link_rate)
635374e7
EM
979{
980 unsigned long flags;
981 struct _sas_node *sas_node;
982 struct _sas_phy *mpt2sas_phy;
983
3cb5469a 984 if (ioc->shost_recovery || ioc->pci_error_recovery)
155dd4c7 985 return;
155dd4c7 986
635374e7 987 spin_lock_irqsave(&ioc->sas_node_lock, flags);
c5e039be 988 sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address);
635374e7
EM
989 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
990 if (!sas_node)
991 return;
992
993 mpt2sas_phy = &sas_node->phy[phy_number];
c5e039be 994 mpt2sas_phy->attached_handle = handle;
7f6f794d 995 if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
c5e039be 996 _transport_set_identify(ioc, handle,
635374e7 997 &mpt2sas_phy->remote_identify);
7f6f794d
KD
998 _transport_add_phy_to_an_existing_port(ioc, sas_node,
999 mpt2sas_phy, mpt2sas_phy->remote_identify.sas_address);
1000 } else
635374e7
EM
1001 memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
1002 sas_identify));
1003
1004 if (mpt2sas_phy->phy)
1005 mpt2sas_phy->phy->negotiated_linkrate =
1006 _transport_convert_phy_link_rate(link_rate);
1007
1008 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
1009 dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
c5e039be 1010 "refresh: parent sas_addr(0x%016llx),\n"
635374e7
EM
1011 "\tlink_rate(0x%02x), phy(%d)\n"
1012 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
c5e039be
KD
1013 (unsigned long long)sas_address,
1014 link_rate, phy_number, handle, (unsigned long long)
635374e7
EM
1015 mpt2sas_phy->remote_identify.sas_address);
1016}
1017
1018static inline void *
1019phy_to_ioc(struct sas_phy *phy)
1020{
1021 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1022 return shost_priv(shost);
1023}
1024
1025static inline void *
1026rphy_to_ioc(struct sas_rphy *rphy)
1027{
1028 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
1029 return shost_priv(shost);
1030}
1031
50d5c606 1032
d5f491e6
KD
1033/* report phy error log structure */
1034struct 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];
1042};
1043
1044/* report phy error log reply structure */
1045struct phy_error_log_reply{
1046 u8 smp_frame_type; /* 0x41 */
1047 u8 function; /* 0x11 */
1048 u8 function_result;
1049 u8 response_length;
c97951ec 1050 __be16 expander_change_count;
d5f491e6
KD
1051 u8 reserved_1[3];
1052 u8 phy_identifier;
1053 u8 reserved_2[2];
c97951ec
KD
1054 __be32 invalid_dword;
1055 __be32 running_disparity_error;
1056 __be32 loss_of_dword_sync;
1057 __be32 phy_reset_problem;
d5f491e6
KD
1058};
1059
1060/**
1061 * _transport_get_expander_phy_error_log - return expander counters
1062 * @ioc: per adapter object
1063 * @phy: The sas phy object
1064 *
1065 * Returns 0 for success, non-zero for failure.
1066 *
1067 */
1068static int
1069_transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
1070 struct sas_phy *phy)
1071{
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;
d5f491e6
KD
1086 u16 wait_state_count;
1087
3cb5469a 1088 if (ioc->shost_recovery || ioc->pci_error_recovery) {
d5f491e6
KD
1089 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1090 __func__, ioc->name);
1091 return -EFAULT;
1092 }
1093
1094 mutex_lock(&ioc->transport_cmds.mutex);
1095
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;
1101 }
1102 ioc->transport_cmds.status = MPT2_CMD_PENDING;
1103
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;
1113 }
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);
1119 }
1120 if (wait_state_count)
1121 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1122 ioc->name, __func__);
1123
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;
1130 }
1131
1132 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1133 ioc->transport_cmds.smid = smid;
1134
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;
1144 }
1145
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;
1154
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;
c97951ec 1160 mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
d5f491e6
KD
1161 mpi_request->RequestDataLength =
1162 cpu_to_le16(sizeof(struct phy_error_log_request));
1163 psge = &mpi_request->SGL;
1164
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);
1171
1172 /* incr sgel */
1173 psge += ioc->sge_size;
1174
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));
1183
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));
d5f491e6 1187 init_completion(&ioc->transport_cmds.done);
f01690d3 1188 mpt2sas_base_put_smid_default(ioc, smid);
d5f491e6
KD
1189 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1190 10*HZ);
1191
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;
1200 }
1201
1202 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_error_log - "
1203 "complete\n", ioc->name));
1204
1205 if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1206
1207 mpi_reply = ioc->transport_cmds.reply;
1208
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)));
1212
1213 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1214 sizeof(struct phy_error_log_reply))
1215 goto out;
1216
1217 phy_error_log_reply = data_out +
1218 sizeof(struct phy_error_log_request);
1219
1220 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1221 "phy_error_log - function_result(%d)\n",
1222 ioc->name, phy_error_log_reply->function_result));
1223
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));
1236
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);
1245
1246 mutex_unlock(&ioc->transport_cmds.mutex);
1247 return rc;
1248}
1249
635374e7 1250/**
d5f491e6 1251 * _transport_get_linkerrors - return phy counters for both hba and expanders
635374e7
EM
1252 * @phy: The sas phy object
1253 *
635374e7
EM
1254 * Returns 0 for success, non-zero for failure.
1255 *
1256 */
1257static int
d5d135b3 1258_transport_get_linkerrors(struct sas_phy *phy)
635374e7
EM
1259{
1260 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
d5f491e6 1261 unsigned long flags;
635374e7
EM
1262 Mpi2ConfigReply_t mpi_reply;
1263 Mpi2SasPhyPage1_t phy_pg1;
635374e7 1264
d5f491e6
KD
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);
635374e7 1269 return -EINVAL;
d5f491e6
KD
1270 }
1271 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1272
1273 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1274 return _transport_get_expander_phy_error_log(ioc, phy);
635374e7 1275
d5f491e6 1276 /* get hba phy error logs */
635374e7 1277 if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
d5f491e6 1278 phy->number))) {
635374e7
EM
1279 printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
1280 ioc->name, __FILE__, __LINE__, __func__);
1281 return -ENXIO;
1282 }
1283
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,
d5f491e6 1287 phy->number, le16_to_cpu(mpi_reply.IOCStatus),
635374e7
EM
1288 le32_to_cpu(mpi_reply.IOCLogInfo));
1289
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;
1298}
1299
1300/**
d5d135b3 1301 * _transport_get_enclosure_identifier -
635374e7
EM
1302 * @phy: The sas phy object
1303 *
1304 * Obtain the enclosure logical id for an expander.
1305 * Returns 0 for success, non-zero for failure.
1306 */
1307static int
d5d135b3 1308_transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
635374e7
EM
1309{
1310 struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
ab6ce925 1311 struct _sas_device *sas_device;
635374e7
EM
1312 unsigned long flags;
1313
ab6ce925
KD
1314 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1315 sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
635374e7 1316 rphy->identify.sas_address);
ab6ce925 1317 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
635374e7 1318
ab6ce925 1319 if (!sas_device)
635374e7
EM
1320 return -ENXIO;
1321
ab6ce925 1322 *identifier = sas_device->enclosure_logical_id;
635374e7
EM
1323 return 0;
1324}
1325
1326/**
d5d135b3 1327 * _transport_get_bay_identifier -
635374e7
EM
1328 * @phy: The sas phy object
1329 *
1330 * Returns the slot id for a device that resides inside an enclosure.
1331 */
1332static int
d5d135b3 1333_transport_get_bay_identifier(struct sas_rphy *rphy)
635374e7
EM
1334{
1335 struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1336 struct _sas_device *sas_device;
1337 unsigned long flags;
1338
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);
1343
1344 if (!sas_device)
1345 return -ENXIO;
1346
1347 return sas_device->slot;
1348}
1349
b8d7d7bb
KD
1350/* phy control request structure */
1351struct 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];
1365};
1366
1367/* phy control reply structure */
1368struct phy_control_reply{
1369 u8 smp_frame_type; /* 0x41 */
1370 u8 function; /* 0x11 */
1371 u8 function_result;
1372 u8 response_length;
1373};
1374
1375#define SMP_PHY_CONTROL_LINK_RESET (0x01)
1376#define SMP_PHY_CONTROL_HARD_RESET (0x02)
1377#define SMP_PHY_CONTROL_DISABLE (0x03)
1378
1379/**
1380 * _transport_expander_phy_control - expander phy control
1381 * @ioc: per adapter object
1382 * @phy: The sas phy object
1383 *
1384 * Returns 0 for success, non-zero for failure.
1385 *
1386 */
1387static int
1388_transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
1389 struct sas_phy *phy, u8 phy_operation)
1390{
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;
b8d7d7bb
KD
1405 u16 wait_state_count;
1406
1407 if (ioc->shost_recovery) {
1408 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1409 __func__, ioc->name);
1410 return -EFAULT;
1411 }
1412
1413 mutex_lock(&ioc->transport_cmds.mutex);
1414
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;
1420 }
1421 ioc->transport_cmds.status = MPT2_CMD_PENDING;
1422
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;
1432 }
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);
1438 }
1439 if (wait_state_count)
1440 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1441 ioc->name, __func__);
1442
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;
1449 }
1450
1451 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1452 ioc->transport_cmds.smid = smid;
1453
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;
1463 }
1464
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;
1478
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;
c97951ec 1484 mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
b8d7d7bb
KD
1485 mpi_request->RequestDataLength =
1486 cpu_to_le16(sizeof(struct phy_error_log_request));
1487 psge = &mpi_request->SGL;
1488
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);
1495
1496 /* incr sgel */
1497 psge += ioc->sge_size;
1498
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));
1507
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));
f01690d3 1512
b8d7d7bb 1513 init_completion(&ioc->transport_cmds.done);
f01690d3 1514 mpt2sas_base_put_smid_default(ioc, smid);
b8d7d7bb
KD
1515 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1516 10*HZ);
1517
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;
1526 }
1527
1528 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "phy_control - "
1529 "complete\n", ioc->name));
1530
1531 if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1532
1533 mpi_reply = ioc->transport_cmds.reply;
1534
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)));
1538
1539 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1540 sizeof(struct phy_control_reply))
1541 goto out;
1542
1543 phy_control_reply = data_out +
1544 sizeof(struct phy_control_request);
1545
1546 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1547 "phy_control - function_result(%d)\n",
1548 ioc->name, phy_control_reply->function_result));
1549
1550 rc = 0;
1551 } else
1552 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
1553 "phy_control - no reply\n", ioc->name));
1554
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);
1563
1564 mutex_unlock(&ioc->transport_cmds.mutex);
1565 return rc;
1566}
1567
635374e7 1568/**
d5d135b3 1569 * _transport_phy_reset -
635374e7
EM
1570 * @phy: The sas phy object
1571 * @hard_reset:
1572 *
635374e7
EM
1573 * Returns 0 for success, non-zero for failure.
1574 */
1575static int
d5d135b3 1576_transport_phy_reset(struct sas_phy *phy, int hard_reset)
635374e7
EM
1577{
1578 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
635374e7
EM
1579 Mpi2SasIoUnitControlReply_t mpi_reply;
1580 Mpi2SasIoUnitControlRequest_t mpi_request;
b8d7d7bb 1581 unsigned long flags;
635374e7 1582
b8d7d7bb
KD
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);
635374e7 1587 return -EINVAL;
b8d7d7bb
KD
1588 }
1589 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
635374e7 1590
b8d7d7bb
KD
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);
1596
1597 /* handle hba phys */
635374e7
EM
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;
b8d7d7bb 1602 mpi_request.PhyNum = phy->number;
635374e7
EM
1603
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;
1608 }
1609
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,
b8d7d7bb 1613 phy->number, le16_to_cpu(mpi_reply.IOCStatus),
635374e7
EM
1614 le32_to_cpu(mpi_reply.IOCLogInfo));
1615
1616 return 0;
1617}
1618
50d5c606
KD
1619/**
1620 * _transport_phy_enable - enable/disable phys
1621 * @phy: The sas phy object
1622 * @enable: enable phy when true
1623 *
1624 * Only support sas_host direct attached phys.
1625 * Returns 0 for success, non-zero for failure.
1626 */
1627static int
1628_transport_phy_enable(struct sas_phy *phy, int enable)
1629{
1630 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
50d5c606
KD
1631 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1632 Mpi2ConfigReply_t mpi_reply;
1633 u16 ioc_status;
1634 u16 sz;
1635 int rc = 0;
b8d7d7bb 1636 unsigned long flags;
50d5c606 1637
b8d7d7bb
KD
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);
50d5c606 1642 return -EINVAL;
b8d7d7bb
KD
1643 }
1644 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1645
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);
1651
1652 /* handle hba phys */
50d5c606
KD
1653
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;
1663 }
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;
1670 }
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;
1678 }
1679
1680 if (enable)
b8d7d7bb 1681 sas_iounit_pg1->PhyData[phy->number].PhyFlags
50d5c606
KD
1682 &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1683 else
b8d7d7bb 1684 sas_iounit_pg1->PhyData[phy->number].PhyFlags
50d5c606
KD
1685 |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1686
1687 mpt2sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1688
b8d7d7bb
KD
1689 /* link reset */
1690 if (enable)
1691 _transport_phy_reset(phy, 0);
1692
50d5c606
KD
1693 out:
1694 kfree(sas_iounit_pg1);
1695 return rc;
1696}
1697
1698/**
1699 * _transport_phy_speed - set phy min/max link rates
1700 * @phy: The sas phy object
1701 * @rates: rates defined in sas_phy_linkrates
1702 *
1703 * Only support sas_host direct attached phys.
1704 * Returns 0 for success, non-zero for failure.
1705 */
1706static int
1707_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1708{
1709 struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
50d5c606
KD
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;
b8d7d7bb 1717 unsigned long flags;
50d5c606 1718
b8d7d7bb
KD
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);
50d5c606 1723 return -EINVAL;
b8d7d7bb
KD
1724 }
1725 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
50d5c606
KD
1726
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;
1731
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;
1736
b8d7d7bb
KD
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);
1743 }
1744
1745 /* handle hba phys */
1746
50d5c606
KD
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;
1756 }
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;
1763 }
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;
1771 }
1772
1773 for (i = 0; i < ioc->sas_hba.num_phys; i++) {
b8d7d7bb 1774 if (phy->number != i) {
50d5c606
KD
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));
1782 }
1783 }
1784
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;
1791 }
1792
1793 /* link reset */
1794 _transport_phy_reset(phy, 0);
1795
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,
b8d7d7bb 1798 phy->number)) {
50d5c606
KD
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);
1806 }
1807
1808 out:
1809 kfree(sas_iounit_pg1);
1810 return rc;
1811}
1812
1813
635374e7 1814/**
d5d135b3 1815 * _transport_smp_handler - transport portal for smp passthru
635374e7
EM
1816 * @shost: shost object
1817 * @rphy: sas transport rphy object
1818 * @req:
1819 *
1820 * This used primarily for smp_utils.
1821 * Example:
1822 * smp_rep_general /sys/class/bsg/expander-5:0
1823 */
1824static int
d5d135b3 1825_transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
635374e7
EM
1826 struct request *req)
1827{
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;
635374e7
EM
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;
1842
1843 if (!rsp) {
1844 printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
1845 "missing\n", ioc->name, __func__);
1846 return -EINVAL;
1847 }
1848
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,
b0790410 1853 blk_rq_bytes(req), rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
635374e7
EM
1854 return -EINVAL;
1855 }
1856
155dd4c7 1857 if (ioc->shost_recovery) {
635374e7
EM
1858 printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1859 __func__, ioc->name);
1860 return -EFAULT;
1861 }
635374e7
EM
1862
1863 rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
1864 if (rc)
1865 return rc;
1866
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;
1872 }
1873 ioc->transport_cmds.status = MPT2_CMD_PENDING;
1874
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;
1884 }
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);
1890 }
1891 if (wait_state_count)
1892 printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
1893 ioc->name, __func__);
1894
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;
1901 }
1902
1903 rc = 0;
1904 mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
1905 ioc->transport_cmds.smid = smid;
1906
1907 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1908 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1909 mpi_request->PhysicalPort = 0xFF;
7b936b02
KD
1910 mpi_request->VF_ID = 0; /* TODO */
1911 mpi_request->VP_ID = 0;
c97951ec 1912 mpi_request->SASAddress = (rphy) ?
635374e7
EM
1913 cpu_to_le64(rphy->identify.sas_address) :
1914 cpu_to_le64(ioc->sas_hba.sas_address);
b0790410 1915 mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
635374e7
EM
1916 psge = &mpi_request->SGL;
1917
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),
b0790410 1923 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
635374e7 1924 if (!dma_addr_out) {
463217bf 1925 mpt2sas_base_free_smid(ioc, smid);
635374e7
EM
1926 goto unmap;
1927 }
1928
b0790410 1929 ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(req) - 4),
635374e7
EM
1930 dma_addr_out);
1931
1932 /* incr sgel */
1933 psge += ioc->sge_size;
1934
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;
b0790410
TH
1940 dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
1941 blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
635374e7 1942 if (!dma_addr_in) {
463217bf 1943 mpt2sas_base_free_smid(ioc, smid);
635374e7
EM
1944 goto unmap;
1945 }
1946
b0790410 1947 ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4),
635374e7
EM
1948 dma_addr_in);
1949
eabb08ad 1950 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
635374e7
EM
1951 "sending smp request\n", ioc->name, __func__));
1952
bcfb6e6e 1953 init_completion(&ioc->transport_cmds.done);
f01690d3 1954 mpt2sas_base_put_smid_default(ioc, smid);
635374e7
EM
1955 timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
1956 10*HZ);
1957
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;
1966 }
1967
eabb08ad 1968 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT "%s - "
635374e7
EM
1969 "complete\n", ioc->name, __func__));
1970
1971 if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
1972
1973 mpi_reply = ioc->transport_cmds.reply;
1974
eabb08ad 1975 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
635374e7
EM
1976 "%s - reply data transfer size(%d)\n",
1977 ioc->name, __func__,
1978 le16_to_cpu(mpi_reply->ResponseDataLength)));
1979
1980 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
1981 req->sense_len = sizeof(*mpi_reply);
5f49f631 1982 req->resid_len = 0;
e94f6747
KD
1983 rsp->resid_len -=
1984 le16_to_cpu(mpi_reply->ResponseDataLength);
635374e7 1985 } else {
eabb08ad 1986 dtransportprintk(ioc, printk(MPT2SAS_INFO_FMT
635374e7
EM
1987 "%s - no reply\n", ioc->name, __func__));
1988 rc = -ENXIO;
1989 }
1990
1991 issue_host_reset:
1992 if (issue_reset) {
1993 mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
1994 FORCE_BIG_HAMMER);
1995 rc = -ETIMEDOUT;
1996 }
1997
1998 unmap:
1999 if (dma_addr_out)
b0790410 2000 pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req),
635374e7
EM
2001 PCI_DMA_BIDIRECTIONAL);
2002 if (dma_addr_in)
b0790410 2003 pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp),
635374e7
EM
2004 PCI_DMA_BIDIRECTIONAL);
2005
2006 out:
2007 ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
2008 mutex_unlock(&ioc->transport_cmds.mutex);
2009 return rc;
2010}
2011
2012struct sas_function_template mpt2sas_transport_functions = {
d5d135b3
EM
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,
50d5c606
KD
2017 .phy_enable = _transport_phy_enable,
2018 .set_phy_speed = _transport_phy_speed,
d5d135b3 2019 .smp_handler = _transport_smp_handler,
635374e7
EM
2020};
2021
2022struct scsi_transport_template *mpt2sas_transport_template;