~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/scsi/isci/port.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is provided under a dual BSD/GPLv2 license.  When using or
 
3
 * redistributing this file, you may do so under either license.
 
4
 *
 
5
 * GPL LICENSE SUMMARY
 
6
 *
 
7
 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
 
8
 *
 
9
 * This program is free software; you can redistribute it and/or modify
 
10
 * it under the terms of version 2 of the GNU General Public License as
 
11
 * published by the Free Software Foundation.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful, but
 
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
 * General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program; if not, write to the Free Software
 
20
 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 
21
 * The full GNU General Public License is included in this distribution
 
22
 * in the file called LICENSE.GPL.
 
23
 *
 
24
 * BSD LICENSE
 
25
 *
 
26
 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
 
27
 * All rights reserved.
 
28
 *
 
29
 * Redistribution and use in source and binary forms, with or without
 
30
 * modification, are permitted provided that the following conditions
 
31
 * are met:
 
32
 *
 
33
 *   * Redistributions of source code must retain the above copyright
 
34
 *     notice, this list of conditions and the following disclaimer.
 
35
 *   * Redistributions in binary form must reproduce the above copyright
 
36
 *     notice, this list of conditions and the following disclaimer in
 
37
 *     the documentation and/or other materials provided with the
 
38
 *     distribution.
 
39
 *   * Neither the name of Intel Corporation nor the names of its
 
40
 *     contributors may be used to endorse or promote products derived
 
41
 *     from this software without specific prior written permission.
 
42
 *
 
43
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
44
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
45
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
46
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
47
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
48
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
49
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
50
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
51
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
52
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
53
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
54
 */
 
55
 
 
56
#include "isci.h"
 
57
#include "port.h"
 
58
#include "request.h"
 
59
 
 
60
#define SCIC_SDS_PORT_HARD_RESET_TIMEOUT  (1000)
 
61
#define SCU_DUMMY_INDEX    (0xFFFF)
 
62
 
 
63
static void isci_port_change_state(struct isci_port *iport, enum isci_status status)
 
64
{
 
65
        unsigned long flags;
 
66
 
 
67
        dev_dbg(&iport->isci_host->pdev->dev,
 
68
                "%s: iport = %p, state = 0x%x\n",
 
69
                __func__, iport, status);
 
70
 
 
71
        /* XXX pointless lock */
 
72
        spin_lock_irqsave(&iport->state_lock, flags);
 
73
        iport->status = status;
 
74
        spin_unlock_irqrestore(&iport->state_lock, flags);
 
75
}
 
76
 
 
77
static void sci_port_get_protocols(struct isci_port *iport, struct sci_phy_proto *proto)
 
78
{
 
79
        u8 index;
 
80
 
 
81
        proto->all = 0;
 
82
        for (index = 0; index < SCI_MAX_PHYS; index++) {
 
83
                struct isci_phy *iphy = iport->phy_table[index];
 
84
 
 
85
                if (!iphy)
 
86
                        continue;
 
87
                sci_phy_get_protocols(iphy, proto);
 
88
        }
 
89
}
 
90
 
 
91
static u32 sci_port_get_phys(struct isci_port *iport)
 
92
{
 
93
        u32 index;
 
94
        u32 mask;
 
95
 
 
96
        mask = 0;
 
97
        for (index = 0; index < SCI_MAX_PHYS; index++)
 
98
                if (iport->phy_table[index])
 
99
                        mask |= (1 << index);
 
100
 
 
101
        return mask;
 
102
}
 
103
 
 
104
/**
 
105
 * sci_port_get_properties() - This method simply returns the properties
 
106
 *    regarding the port, such as: physical index, protocols, sas address, etc.
 
107
 * @port: this parameter specifies the port for which to retrieve the physical
 
108
 *    index.
 
109
 * @properties: This parameter specifies the properties structure into which to
 
110
 *    copy the requested information.
 
111
 *
 
112
 * Indicate if the user specified a valid port. SCI_SUCCESS This value is
 
113
 * returned if the specified port was valid. SCI_FAILURE_INVALID_PORT This
 
114
 * value is returned if the specified port is not valid.  When this value is
 
115
 * returned, no data is copied to the properties output parameter.
 
116
 */
 
117
static enum sci_status sci_port_get_properties(struct isci_port *iport,
 
118
                                                struct sci_port_properties *prop)
 
119
{
 
120
        if (!iport || iport->logical_port_index == SCIC_SDS_DUMMY_PORT)
 
121
                return SCI_FAILURE_INVALID_PORT;
 
122
 
 
123
        prop->index = iport->logical_port_index;
 
124
        prop->phy_mask = sci_port_get_phys(iport);
 
125
        sci_port_get_sas_address(iport, &prop->local.sas_address);
 
126
        sci_port_get_protocols(iport, &prop->local.protocols);
 
127
        sci_port_get_attached_sas_address(iport, &prop->remote.sas_address);
 
128
 
 
129
        return SCI_SUCCESS;
 
130
}
 
131
 
 
132
static void sci_port_bcn_enable(struct isci_port *iport)
 
133
{
 
134
        struct isci_phy *iphy;
 
135
        u32 val;
 
136
        int i;
 
137
 
 
138
        for (i = 0; i < ARRAY_SIZE(iport->phy_table); i++) {
 
139
                iphy = iport->phy_table[i];
 
140
                if (!iphy)
 
141
                        continue;
 
142
                val = readl(&iphy->link_layer_registers->link_layer_control);
 
143
                /* clear the bit by writing 1. */
 
144
                writel(val, &iphy->link_layer_registers->link_layer_control);
 
145
        }
 
146
}
 
147
 
 
148
static void isci_port_bc_change_received(struct isci_host *ihost,
 
149
                                         struct isci_port *iport,
 
150
                                         struct isci_phy *iphy)
 
151
{
 
152
        dev_dbg(&ihost->pdev->dev,
 
153
                "%s: isci_phy = %p, sas_phy = %p\n",
 
154
                __func__, iphy, &iphy->sas_phy);
 
155
 
 
156
        ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD);
 
157
        sci_port_bcn_enable(iport);
 
158
}
 
159
 
 
160
static void isci_port_link_up(struct isci_host *isci_host,
 
161
                              struct isci_port *iport,
 
162
                              struct isci_phy *iphy)
 
163
{
 
164
        unsigned long flags;
 
165
        struct sci_port_properties properties;
 
166
        unsigned long success = true;
 
167
 
 
168
        BUG_ON(iphy->isci_port != NULL);
 
169
 
 
170
        iphy->isci_port = iport;
 
171
 
 
172
        dev_dbg(&isci_host->pdev->dev,
 
173
                "%s: isci_port = %p\n",
 
174
                __func__, iport);
 
175
 
 
176
        spin_lock_irqsave(&iphy->sas_phy.frame_rcvd_lock, flags);
 
177
 
 
178
        isci_port_change_state(iphy->isci_port, isci_starting);
 
179
 
 
180
        sci_port_get_properties(iport, &properties);
 
181
 
 
182
        if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) {
 
183
                u64 attached_sas_address;
 
184
 
 
185
                iphy->sas_phy.oob_mode = SATA_OOB_MODE;
 
186
                iphy->sas_phy.frame_rcvd_size = sizeof(struct dev_to_host_fis);
 
187
 
 
188
                /*
 
189
                 * For direct-attached SATA devices, the SCI core will
 
190
                 * automagically assign a SAS address to the end device
 
191
                 * for the purpose of creating a port. This SAS address
 
192
                 * will not be the same as assigned to the PHY and needs
 
193
                 * to be obtained from struct sci_port_properties properties.
 
194
                 */
 
195
                attached_sas_address = properties.remote.sas_address.high;
 
196
                attached_sas_address <<= 32;
 
197
                attached_sas_address |= properties.remote.sas_address.low;
 
198
                swab64s(&attached_sas_address);
 
199
 
 
200
                memcpy(&iphy->sas_phy.attached_sas_addr,
 
201
                       &attached_sas_address, sizeof(attached_sas_address));
 
202
        } else if (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) {
 
203
                iphy->sas_phy.oob_mode = SAS_OOB_MODE;
 
204
                iphy->sas_phy.frame_rcvd_size = sizeof(struct sas_identify_frame);
 
205
 
 
206
                /* Copy the attached SAS address from the IAF */
 
207
                memcpy(iphy->sas_phy.attached_sas_addr,
 
208
                       iphy->frame_rcvd.iaf.sas_addr, SAS_ADDR_SIZE);
 
209
        } else {
 
210
                dev_err(&isci_host->pdev->dev, "%s: unkown target\n", __func__);
 
211
                success = false;
 
212
        }
 
213
 
 
214
        iphy->sas_phy.phy->negotiated_linkrate = sci_phy_linkrate(iphy);
 
215
 
 
216
        spin_unlock_irqrestore(&iphy->sas_phy.frame_rcvd_lock, flags);
 
217
 
 
218
        /* Notify libsas that we have an address frame, if indeed
 
219
         * we've found an SSP, SMP, or STP target */
 
220
        if (success)
 
221
                isci_host->sas_ha.notify_port_event(&iphy->sas_phy,
 
222
                                                    PORTE_BYTES_DMAED);
 
223
}
 
224
 
 
225
 
 
226
/**
 
227
 * isci_port_link_down() - This function is called by the sci core when a link
 
228
 *    becomes inactive.
 
229
 * @isci_host: This parameter specifies the isci host object.
 
230
 * @phy: This parameter specifies the isci phy with the active link.
 
231
 * @port: This parameter specifies the isci port with the active link.
 
232
 *
 
233
 */
 
234
static void isci_port_link_down(struct isci_host *isci_host,
 
235
                                struct isci_phy *isci_phy,
 
236
                                struct isci_port *isci_port)
 
237
{
 
238
        struct isci_remote_device *isci_device;
 
239
 
 
240
        dev_dbg(&isci_host->pdev->dev,
 
241
                "%s: isci_port = %p\n", __func__, isci_port);
 
242
 
 
243
        if (isci_port) {
 
244
 
 
245
                /* check to see if this is the last phy on this port. */
 
246
                if (isci_phy->sas_phy.port &&
 
247
                    isci_phy->sas_phy.port->num_phys == 1) {
 
248
                        /* change the state for all devices on this port.  The
 
249
                         * next task sent to this device will be returned as
 
250
                         * SAS_TASK_UNDELIVERED, and the scsi mid layer will
 
251
                         * remove the target
 
252
                         */
 
253
                        list_for_each_entry(isci_device,
 
254
                                            &isci_port->remote_dev_list,
 
255
                                            node) {
 
256
                                dev_dbg(&isci_host->pdev->dev,
 
257
                                        "%s: isci_device = %p\n",
 
258
                                        __func__, isci_device);
 
259
                                set_bit(IDEV_GONE, &isci_device->flags);
 
260
                        }
 
261
                        isci_port_change_state(isci_port, isci_stopping);
 
262
                }
 
263
        }
 
264
 
 
265
        /* Notify libsas of the borken link, this will trigger calls to our
 
266
         * isci_port_deformed and isci_dev_gone functions.
 
267
         */
 
268
        sas_phy_disconnected(&isci_phy->sas_phy);
 
269
        isci_host->sas_ha.notify_phy_event(&isci_phy->sas_phy,
 
270
                                           PHYE_LOSS_OF_SIGNAL);
 
271
 
 
272
        isci_phy->isci_port = NULL;
 
273
 
 
274
        dev_dbg(&isci_host->pdev->dev,
 
275
                "%s: isci_port = %p - Done\n", __func__, isci_port);
 
276
}
 
277
 
 
278
 
 
279
/**
 
280
 * isci_port_ready() - This function is called by the sci core when a link
 
281
 *    becomes ready.
 
282
 * @isci_host: This parameter specifies the isci host object.
 
283
 * @port: This parameter specifies the sci port with the active link.
 
284
 *
 
285
 */
 
286
static void isci_port_ready(struct isci_host *isci_host, struct isci_port *isci_port)
 
287
{
 
288
        dev_dbg(&isci_host->pdev->dev,
 
289
                "%s: isci_port = %p\n", __func__, isci_port);
 
290
 
 
291
        complete_all(&isci_port->start_complete);
 
292
        isci_port_change_state(isci_port, isci_ready);
 
293
        return;
 
294
}
 
295
 
 
296
/**
 
297
 * isci_port_not_ready() - This function is called by the sci core when a link
 
298
 *    is not ready. All remote devices on this link will be removed if they are
 
299
 *    in the stopping state.
 
300
 * @isci_host: This parameter specifies the isci host object.
 
301
 * @port: This parameter specifies the sci port with the active link.
 
302
 *
 
303
 */
 
304
static void isci_port_not_ready(struct isci_host *isci_host, struct isci_port *isci_port)
 
305
{
 
306
        dev_dbg(&isci_host->pdev->dev,
 
307
                "%s: isci_port = %p\n", __func__, isci_port);
 
308
}
 
309
 
 
310
static void isci_port_stop_complete(struct isci_host *ihost,
 
311
                                    struct isci_port *iport,
 
312
                                    enum sci_status completion_status)
 
313
{
 
314
        dev_dbg(&ihost->pdev->dev, "Port stop complete\n");
 
315
}
 
316
 
 
317
 
 
318
static bool is_port_ready_state(enum sci_port_states state)
 
319
{
 
320
        switch (state) {
 
321
        case SCI_PORT_READY:
 
322
        case SCI_PORT_SUB_WAITING:
 
323
        case SCI_PORT_SUB_OPERATIONAL:
 
324
        case SCI_PORT_SUB_CONFIGURING:
 
325
                return true;
 
326
        default:
 
327
                return false;
 
328
        }
 
329
}
 
330
 
 
331
/* flag dummy rnc hanling when exiting a ready state */
 
332
static void port_state_machine_change(struct isci_port *iport,
 
333
                                      enum sci_port_states state)
 
334
{
 
335
        struct sci_base_state_machine *sm = &iport->sm;
 
336
        enum sci_port_states old_state = sm->current_state_id;
 
337
 
 
338
        if (is_port_ready_state(old_state) && !is_port_ready_state(state))
 
339
                iport->ready_exit = true;
 
340
 
 
341
        sci_change_state(sm, state);
 
342
        iport->ready_exit = false;
 
343
}
 
344
 
 
345
/**
 
346
 * isci_port_hard_reset_complete() - This function is called by the sci core
 
347
 *    when the hard reset complete notification has been received.
 
348
 * @port: This parameter specifies the sci port with the active link.
 
349
 * @completion_status: This parameter specifies the core status for the reset
 
350
 *    process.
 
351
 *
 
352
 */
 
353
static void isci_port_hard_reset_complete(struct isci_port *isci_port,
 
354
                                          enum sci_status completion_status)
 
355
{
 
356
        dev_dbg(&isci_port->isci_host->pdev->dev,
 
357
                "%s: isci_port = %p, completion_status=%x\n",
 
358
                     __func__, isci_port, completion_status);
 
359
 
 
360
        /* Save the status of the hard reset from the port. */
 
361
        isci_port->hard_reset_status = completion_status;
 
362
 
 
363
        if (completion_status != SCI_SUCCESS) {
 
364
 
 
365
                /* The reset failed.  The port state is now SCI_PORT_FAILED. */
 
366
                if (isci_port->active_phy_mask == 0) {
 
367
 
 
368
                        /* Generate the link down now to the host, since it
 
369
                         * was intercepted by the hard reset state machine when
 
370
                         * it really happened.
 
371
                         */
 
372
                        isci_port_link_down(isci_port->isci_host,
 
373
                                            &isci_port->isci_host->phys[
 
374
                                                   isci_port->last_active_phy],
 
375
                                            isci_port);
 
376
                }
 
377
                /* Advance the port state so that link state changes will be
 
378
                * noticed.
 
379
                */
 
380
                port_state_machine_change(isci_port, SCI_PORT_SUB_WAITING);
 
381
 
 
382
        }
 
383
        complete_all(&isci_port->hard_reset_complete);
 
384
}
 
385
 
 
386
/* This method will return a true value if the specified phy can be assigned to
 
387
 * this port The following is a list of phys for each port that are allowed: -
 
388
 * Port 0 - 3 2 1 0 - Port 1 -     1 - Port 2 - 3 2 - Port 3 - 3 This method
 
389
 * doesn't preclude all configurations.  It merely ensures that a phy is part
 
390
 * of the allowable set of phy identifiers for that port.  For example, one
 
391
 * could assign phy 3 to port 0 and no other phys.  Please refer to
 
392
 * sci_port_is_phy_mask_valid() for information regarding whether the
 
393
 * phy_mask for a port can be supported. bool true if this is a valid phy
 
394
 * assignment for the port false if this is not a valid phy assignment for the
 
395
 * port
 
396
 */
 
397
bool sci_port_is_valid_phy_assignment(struct isci_port *iport, u32 phy_index)
 
398
{
 
399
        struct isci_host *ihost = iport->owning_controller;
 
400
        struct sci_user_parameters *user = &ihost->user_parameters;
 
401
 
 
402
        /* Initialize to invalid value. */
 
403
        u32 existing_phy_index = SCI_MAX_PHYS;
 
404
        u32 index;
 
405
 
 
406
        if ((iport->physical_port_index == 1) && (phy_index != 1))
 
407
                return false;
 
408
 
 
409
        if (iport->physical_port_index == 3 && phy_index != 3)
 
410
                return false;
 
411
 
 
412
        if (iport->physical_port_index == 2 &&
 
413
            (phy_index == 0 || phy_index == 1))
 
414
                return false;
 
415
 
 
416
        for (index = 0; index < SCI_MAX_PHYS; index++)
 
417
                if (iport->phy_table[index] && index != phy_index)
 
418
                        existing_phy_index = index;
 
419
 
 
420
        /* Ensure that all of the phys in the port are capable of
 
421
         * operating at the same maximum link rate.
 
422
         */
 
423
        if (existing_phy_index < SCI_MAX_PHYS &&
 
424
            user->phys[phy_index].max_speed_generation !=
 
425
            user->phys[existing_phy_index].max_speed_generation)
 
426
                return false;
 
427
 
 
428
        return true;
 
429
}
 
430
 
 
431
/**
 
432
 *
 
433
 * @sci_port: This is the port object for which to determine if the phy mask
 
434
 *    can be supported.
 
435
 *
 
436
 * This method will return a true value if the port's phy mask can be supported
 
437
 * by the SCU. The following is a list of valid PHY mask configurations for
 
438
 * each port: - Port 0 - [[3  2] 1] 0 - Port 1 -        [1] - Port 2 - [[3] 2]
 
439
 * - Port 3 -  [3] This method returns a boolean indication specifying if the
 
440
 * phy mask can be supported. true if this is a valid phy assignment for the
 
441
 * port false if this is not a valid phy assignment for the port
 
442
 */
 
443
static bool sci_port_is_phy_mask_valid(
 
444
        struct isci_port *iport,
 
445
        u32 phy_mask)
 
446
{
 
447
        if (iport->physical_port_index == 0) {
 
448
                if (((phy_mask & 0x0F) == 0x0F)
 
449
                    || ((phy_mask & 0x03) == 0x03)
 
450
                    || ((phy_mask & 0x01) == 0x01)
 
451
                    || (phy_mask == 0))
 
452
                        return true;
 
453
        } else if (iport->physical_port_index == 1) {
 
454
                if (((phy_mask & 0x02) == 0x02)
 
455
                    || (phy_mask == 0))
 
456
                        return true;
 
457
        } else if (iport->physical_port_index == 2) {
 
458
                if (((phy_mask & 0x0C) == 0x0C)
 
459
                    || ((phy_mask & 0x04) == 0x04)
 
460
                    || (phy_mask == 0))
 
461
                        return true;
 
462
        } else if (iport->physical_port_index == 3) {
 
463
                if (((phy_mask & 0x08) == 0x08)
 
464
                    || (phy_mask == 0))
 
465
                        return true;
 
466
        }
 
467
 
 
468
        return false;
 
469
}
 
470
 
 
471
/*
 
472
 * This method retrieves a currently active (i.e. connected) phy contained in
 
473
 * the port.  Currently, the lowest order phy that is connected is returned.
 
474
 * This method returns a pointer to a SCIS_SDS_PHY object. NULL This value is
 
475
 * returned if there are no currently active (i.e. connected to a remote end
 
476
 * point) phys contained in the port. All other values specify a struct sci_phy
 
477
 * object that is active in the port.
 
478
 */
 
479
static struct isci_phy *sci_port_get_a_connected_phy(struct isci_port *iport)
 
480
{
 
481
        u32 index;
 
482
        struct isci_phy *iphy;
 
483
 
 
484
        for (index = 0; index < SCI_MAX_PHYS; index++) {
 
485
                /* Ensure that the phy is both part of the port and currently
 
486
                 * connected to the remote end-point.
 
487
                 */
 
488
                iphy = iport->phy_table[index];
 
489
                if (iphy && sci_port_active_phy(iport, iphy))
 
490
                        return iphy;
 
491
        }
 
492
 
 
493
        return NULL;
 
494
}
 
495
 
 
496
static enum sci_status sci_port_set_phy(struct isci_port *iport, struct isci_phy *iphy)
 
497
{
 
498
        /* Check to see if we can add this phy to a port
 
499
         * that means that the phy is not part of a port and that the port does
 
500
         * not already have a phy assinged to the phy index.
 
501
         */
 
502
        if (!iport->phy_table[iphy->phy_index] &&
 
503
            !phy_get_non_dummy_port(iphy) &&
 
504
            sci_port_is_valid_phy_assignment(iport, iphy->phy_index)) {
 
505
                /* Phy is being added in the stopped state so we are in MPC mode
 
506
                 * make logical port index = physical port index
 
507
                 */
 
508
                iport->logical_port_index = iport->physical_port_index;
 
509
                iport->phy_table[iphy->phy_index] = iphy;
 
510
                sci_phy_set_port(iphy, iport);
 
511
 
 
512
                return SCI_SUCCESS;
 
513
        }
 
514
 
 
515
        return SCI_FAILURE;
 
516
}
 
517
 
 
518
static enum sci_status sci_port_clear_phy(struct isci_port *iport, struct isci_phy *iphy)
 
519
{
 
520
        /* Make sure that this phy is part of this port */
 
521
        if (iport->phy_table[iphy->phy_index] == iphy &&
 
522
            phy_get_non_dummy_port(iphy) == iport) {
 
523
                struct isci_host *ihost = iport->owning_controller;
 
524
 
 
525
                /* Yep it is assigned to this port so remove it */
 
526
                sci_phy_set_port(iphy, &ihost->ports[SCI_MAX_PORTS]);
 
527
                iport->phy_table[iphy->phy_index] = NULL;
 
528
                return SCI_SUCCESS;
 
529
        }
 
530
 
 
531
        return SCI_FAILURE;
 
532
}
 
533
 
 
534
void sci_port_get_sas_address(struct isci_port *iport, struct sci_sas_address *sas)
 
535
{
 
536
        u32 index;
 
537
 
 
538
        sas->high = 0;
 
539
        sas->low  = 0;
 
540
        for (index = 0; index < SCI_MAX_PHYS; index++)
 
541
                if (iport->phy_table[index])
 
542
                        sci_phy_get_sas_address(iport->phy_table[index], sas);
 
543
}
 
544
 
 
545
void sci_port_get_attached_sas_address(struct isci_port *iport, struct sci_sas_address *sas)
 
546
{
 
547
        struct isci_phy *iphy;
 
548
 
 
549
        /*
 
550
         * Ensure that the phy is both part of the port and currently
 
551
         * connected to the remote end-point.
 
552
         */
 
553
        iphy = sci_port_get_a_connected_phy(iport);
 
554
        if (iphy) {
 
555
                if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA) {
 
556
                        sci_phy_get_attached_sas_address(iphy, sas);
 
557
                } else {
 
558
                        sci_phy_get_sas_address(iphy, sas);
 
559
                        sas->low += iphy->phy_index;
 
560
                }
 
561
        } else {
 
562
                sas->high = 0;
 
563
                sas->low  = 0;
 
564
        }
 
565
}
 
566
 
 
567
/**
 
568
 * sci_port_construct_dummy_rnc() - create dummy rnc for si workaround
 
569
 *
 
570
 * @sci_port: logical port on which we need to create the remote node context
 
571
 * @rni: remote node index for this remote node context.
 
572
 *
 
573
 * This routine will construct a dummy remote node context data structure
 
574
 * This structure will be posted to the hardware to work around a scheduler
 
575
 * error in the hardware.
 
576
 */
 
577
static void sci_port_construct_dummy_rnc(struct isci_port *iport, u16 rni)
 
578
{
 
579
        union scu_remote_node_context *rnc;
 
580
 
 
581
        rnc = &iport->owning_controller->remote_node_context_table[rni];
 
582
 
 
583
        memset(rnc, 0, sizeof(union scu_remote_node_context));
 
584
 
 
585
        rnc->ssp.remote_sas_address_hi = 0;
 
586
        rnc->ssp.remote_sas_address_lo = 0;
 
587
 
 
588
        rnc->ssp.remote_node_index = rni;
 
589
        rnc->ssp.remote_node_port_width = 1;
 
590
        rnc->ssp.logical_port_index = iport->physical_port_index;
 
591
 
 
592
        rnc->ssp.nexus_loss_timer_enable = false;
 
593
        rnc->ssp.check_bit = false;
 
594
        rnc->ssp.is_valid = true;
 
595
        rnc->ssp.is_remote_node_context = true;
 
596
        rnc->ssp.function_number = 0;
 
597
        rnc->ssp.arbitration_wait_time = 0;
 
598
}
 
599
 
 
600
/*
 
601
 * construct a dummy task context data structure.  This
 
602
 * structure will be posted to the hardwre to work around a scheduler error
 
603
 * in the hardware.
 
604
 */
 
605
static void sci_port_construct_dummy_task(struct isci_port *iport, u16 tag)
 
606
{
 
607
        struct isci_host *ihost = iport->owning_controller;
 
608
        struct scu_task_context *task_context;
 
609
 
 
610
        task_context = &ihost->task_context_table[ISCI_TAG_TCI(tag)];
 
611
        memset(task_context, 0, sizeof(struct scu_task_context));
 
612
 
 
613
        task_context->initiator_request = 1;
 
614
        task_context->connection_rate = 1;
 
615
        task_context->logical_port_index = iport->physical_port_index;
 
616
        task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SSP;
 
617
        task_context->task_index = ISCI_TAG_TCI(tag);
 
618
        task_context->valid = SCU_TASK_CONTEXT_VALID;
 
619
        task_context->context_type = SCU_TASK_CONTEXT_TYPE;
 
620
        task_context->remote_node_index = iport->reserved_rni;
 
621
        task_context->do_not_dma_ssp_good_response = 1;
 
622
        task_context->task_phase = 0x01;
 
623
}
 
624
 
 
625
static void sci_port_destroy_dummy_resources(struct isci_port *iport)
 
626
{
 
627
        struct isci_host *ihost = iport->owning_controller;
 
628
 
 
629
        if (iport->reserved_tag != SCI_CONTROLLER_INVALID_IO_TAG)
 
630
                isci_free_tag(ihost, iport->reserved_tag);
 
631
 
 
632
        if (iport->reserved_rni != SCU_DUMMY_INDEX)
 
633
                sci_remote_node_table_release_remote_node_index(&ihost->available_remote_nodes,
 
634
                                                                     1, iport->reserved_rni);
 
635
 
 
636
        iport->reserved_rni = SCU_DUMMY_INDEX;
 
637
        iport->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG;
 
638
}
 
639
 
 
640
void sci_port_setup_transports(struct isci_port *iport, u32 device_id)
 
641
{
 
642
        u8 index;
 
643
 
 
644
        for (index = 0; index < SCI_MAX_PHYS; index++) {
 
645
                if (iport->active_phy_mask & (1 << index))
 
646
                        sci_phy_setup_transport(iport->phy_table[index], device_id);
 
647
        }
 
648
}
 
649
 
 
650
static void sci_port_activate_phy(struct isci_port *iport, struct isci_phy *iphy,
 
651
                                  bool do_notify_user)
 
652
{
 
653
        struct isci_host *ihost = iport->owning_controller;
 
654
 
 
655
        if (iphy->protocol != SCIC_SDS_PHY_PROTOCOL_SATA)
 
656
                sci_phy_resume(iphy);
 
657
 
 
658
        iport->active_phy_mask |= 1 << iphy->phy_index;
 
659
 
 
660
        sci_controller_clear_invalid_phy(ihost, iphy);
 
661
 
 
662
        if (do_notify_user == true)
 
663
                isci_port_link_up(ihost, iport, iphy);
 
664
}
 
665
 
 
666
void sci_port_deactivate_phy(struct isci_port *iport, struct isci_phy *iphy,
 
667
                             bool do_notify_user)
 
668
{
 
669
        struct isci_host *ihost = iport->owning_controller;
 
670
 
 
671
        iport->active_phy_mask &= ~(1 << iphy->phy_index);
 
672
        if (!iport->active_phy_mask)
 
673
                iport->last_active_phy = iphy->phy_index;
 
674
 
 
675
        iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;
 
676
 
 
677
        /* Re-assign the phy back to the LP as if it were a narrow port */
 
678
        writel(iphy->phy_index,
 
679
                &iport->port_pe_configuration_register[iphy->phy_index]);
 
680
 
 
681
        if (do_notify_user == true)
 
682
                isci_port_link_down(ihost, iphy, iport);
 
683
}
 
684
 
 
685
static void sci_port_invalid_link_up(struct isci_port *iport, struct isci_phy *iphy)
 
686
{
 
687
        struct isci_host *ihost = iport->owning_controller;
 
688
 
 
689
        /*
 
690
         * Check to see if we have alreay reported this link as bad and if
 
691
         * not go ahead and tell the SCI_USER that we have discovered an
 
692
         * invalid link.
 
693
         */
 
694
        if ((ihost->invalid_phy_mask & (1 << iphy->phy_index)) == 0) {
 
695
                ihost->invalid_phy_mask |= 1 << iphy->phy_index;
 
696
                dev_warn(&ihost->pdev->dev, "Invalid link up!\n");
 
697
        }
 
698
}
 
699
 
 
700
/**
 
701
 * sci_port_general_link_up_handler - phy can be assigned to port?
 
702
 * @sci_port: sci_port object for which has a phy that has gone link up.
 
703
 * @sci_phy: This is the struct isci_phy object that has gone link up.
 
704
 * @do_notify_user: This parameter specifies whether to inform the user (via
 
705
 *    sci_port_link_up()) as to the fact that a new phy as become ready.
 
706
 *
 
707
 * Determine if this phy can be assigned to this
 
708
 * port . If the phy is not a valid PHY for
 
709
 * this port then the function will notify the user. A PHY can only be
 
710
 * part of a port if it's attached SAS ADDRESS is the same as all other PHYs in
 
711
 * the same port. none
 
712
 */
 
713
static void sci_port_general_link_up_handler(struct isci_port *iport,
 
714
                                                  struct isci_phy *iphy,
 
715
                                                  bool do_notify_user)
 
716
{
 
717
        struct sci_sas_address port_sas_address;
 
718
        struct sci_sas_address phy_sas_address;
 
719
 
 
720
        sci_port_get_attached_sas_address(iport, &port_sas_address);
 
721
        sci_phy_get_attached_sas_address(iphy, &phy_sas_address);
 
722
 
 
723
        /* If the SAS address of the new phy matches the SAS address of
 
724
         * other phys in the port OR this is the first phy in the port,
 
725
         * then activate the phy and allow it to be used for operations
 
726
         * in this port.
 
727
         */
 
728
        if ((phy_sas_address.high == port_sas_address.high &&
 
729
             phy_sas_address.low  == port_sas_address.low) ||
 
730
            iport->active_phy_mask == 0) {
 
731
                struct sci_base_state_machine *sm = &iport->sm;
 
732
 
 
733
                sci_port_activate_phy(iport, iphy, do_notify_user);
 
734
                if (sm->current_state_id == SCI_PORT_RESETTING)
 
735
                        port_state_machine_change(iport, SCI_PORT_READY);
 
736
        } else
 
737
                sci_port_invalid_link_up(iport, iphy);
 
738
}
 
739
 
 
740
 
 
741
 
 
742
/**
 
743
 * This method returns false if the port only has a single phy object assigned.
 
744
 *     If there are no phys or more than one phy then the method will return
 
745
 *    true.
 
746
 * @sci_port: The port for which the wide port condition is to be checked.
 
747
 *
 
748
 * bool true Is returned if this is a wide ported port. false Is returned if
 
749
 * this is a narrow port.
 
750
 */
 
751
static bool sci_port_is_wide(struct isci_port *iport)
 
752
{
 
753
        u32 index;
 
754
        u32 phy_count = 0;
 
755
 
 
756
        for (index = 0; index < SCI_MAX_PHYS; index++) {
 
757
                if (iport->phy_table[index] != NULL) {
 
758
                        phy_count++;
 
759
                }
 
760
        }
 
761
 
 
762
        return phy_count != 1;
 
763
}
 
764
 
 
765
/**
 
766
 * This method is called by the PHY object when the link is detected. if the
 
767
 *    port wants the PHY to continue on to the link up state then the port
 
768
 *    layer must return true.  If the port object returns false the phy object
 
769
 *    must halt its attempt to go link up.
 
770
 * @sci_port: The port associated with the phy object.
 
771
 * @sci_phy: The phy object that is trying to go link up.
 
772
 *
 
773
 * true if the phy object can continue to the link up condition. true Is
 
774
 * returned if this phy can continue to the ready state. false Is returned if
 
775
 * can not continue on to the ready state. This notification is in place for
 
776
 * wide ports and direct attached phys.  Since there are no wide ported SATA
 
777
 * devices this could become an invalid port configuration.
 
778
 */
 
779
bool sci_port_link_detected(
 
780
        struct isci_port *iport,
 
781
        struct isci_phy *iphy)
 
782
{
 
783
        if ((iport->logical_port_index != SCIC_SDS_DUMMY_PORT) &&
 
784
            (iphy->protocol == SCIC_SDS_PHY_PROTOCOL_SATA) &&
 
785
            sci_port_is_wide(iport)) {
 
786
                sci_port_invalid_link_up(iport, iphy);
 
787
 
 
788
                return false;
 
789
        }
 
790
 
 
791
        return true;
 
792
}
 
793
 
 
794
static void port_timeout(unsigned long data)
 
795
{
 
796
        struct sci_timer *tmr = (struct sci_timer *)data;
 
797
        struct isci_port *iport = container_of(tmr, typeof(*iport), timer);
 
798
        struct isci_host *ihost = iport->owning_controller;
 
799
        unsigned long flags;
 
800
        u32 current_state;
 
801
 
 
802
        spin_lock_irqsave(&ihost->scic_lock, flags);
 
803
 
 
804
        if (tmr->cancel)
 
805
                goto done;
 
806
 
 
807
        current_state = iport->sm.current_state_id;
 
808
 
 
809
        if (current_state == SCI_PORT_RESETTING) {
 
810
                /* if the port is still in the resetting state then the timeout
 
811
                 * fired before the reset completed.
 
812
                 */
 
813
                port_state_machine_change(iport, SCI_PORT_FAILED);
 
814
        } else if (current_state == SCI_PORT_STOPPED) {
 
815
                /* if the port is stopped then the start request failed In this
 
816
                 * case stay in the stopped state.
 
817
                 */
 
818
                dev_err(sciport_to_dev(iport),
 
819
                        "%s: SCIC Port 0x%p failed to stop before tiemout.\n",
 
820
                        __func__,
 
821
                        iport);
 
822
        } else if (current_state == SCI_PORT_STOPPING) {
 
823
                /* if the port is still stopping then the stop has not completed */
 
824
                isci_port_stop_complete(iport->owning_controller,
 
825
                                        iport,
 
826
                                        SCI_FAILURE_TIMEOUT);
 
827
        } else {
 
828
                /* The port is in the ready state and we have a timer
 
829
                 * reporting a timeout this should not happen.
 
830
                 */
 
831
                dev_err(sciport_to_dev(iport),
 
832
                        "%s: SCIC Port 0x%p is processing a timeout operation "
 
833
                        "in state %d.\n", __func__, iport, current_state);
 
834
        }
 
835
 
 
836
done:
 
837
        spin_unlock_irqrestore(&ihost->scic_lock, flags);
 
838
}
 
839
 
 
840
/* --------------------------------------------------------------------------- */
 
841
 
 
842
/**
 
843
 * This function updates the hardwares VIIT entry for this port.
 
844
 *
 
845
 *
 
846
 */
 
847
static void sci_port_update_viit_entry(struct isci_port *iport)
 
848
{
 
849
        struct sci_sas_address sas_address;
 
850
 
 
851
        sci_port_get_sas_address(iport, &sas_address);
 
852
 
 
853
        writel(sas_address.high,
 
854
                &iport->viit_registers->initiator_sas_address_hi);
 
855
        writel(sas_address.low,
 
856
                &iport->viit_registers->initiator_sas_address_lo);
 
857
 
 
858
        /* This value get cleared just in case its not already cleared */
 
859
        writel(0, &iport->viit_registers->reserved);
 
860
 
 
861
        /* We are required to update the status register last */
 
862
        writel(SCU_VIIT_ENTRY_ID_VIIT |
 
863
               SCU_VIIT_IPPT_INITIATOR |
 
864
               ((1 << iport->physical_port_index) << SCU_VIIT_ENTRY_LPVIE_SHIFT) |
 
865
               SCU_VIIT_STATUS_ALL_VALID,
 
866
               &iport->viit_registers->status);
 
867
}
 
868
 
 
869
enum sas_linkrate sci_port_get_max_allowed_speed(struct isci_port *iport)
 
870
{
 
871
        u16 index;
 
872
        struct isci_phy *iphy;
 
873
        enum sas_linkrate max_allowed_speed = SAS_LINK_RATE_6_0_GBPS;
 
874
 
 
875
        /*
 
876
         * Loop through all of the phys in this port and find the phy with the
 
877
         * lowest maximum link rate. */
 
878
        for (index = 0; index < SCI_MAX_PHYS; index++) {
 
879
                iphy = iport->phy_table[index];
 
880
                if (iphy && sci_port_active_phy(iport, iphy) &&
 
881
                    iphy->max_negotiated_speed < max_allowed_speed)
 
882
                        max_allowed_speed = iphy->max_negotiated_speed;
 
883
        }
 
884
 
 
885
        return max_allowed_speed;
 
886
}
 
887
 
 
888
static void sci_port_suspend_port_task_scheduler(struct isci_port *iport)
 
889
{
 
890
        u32 pts_control_value;
 
891
 
 
892
        pts_control_value = readl(&iport->port_task_scheduler_registers->control);
 
893
        pts_control_value |= SCU_PTSxCR_GEN_BIT(SUSPEND);
 
894
        writel(pts_control_value, &iport->port_task_scheduler_registers->control);
 
895
}
 
896
 
 
897
/**
 
898
 * sci_port_post_dummy_request() - post dummy/workaround request
 
899
 * @sci_port: port to post task
 
900
 *
 
901
 * Prevent the hardware scheduler from posting new requests to the front
 
902
 * of the scheduler queue causing a starvation problem for currently
 
903
 * ongoing requests.
 
904
 *
 
905
 */
 
906
static void sci_port_post_dummy_request(struct isci_port *iport)
 
907
{
 
908
        struct isci_host *ihost = iport->owning_controller;
 
909
        u16 tag = iport->reserved_tag;
 
910
        struct scu_task_context *tc;
 
911
        u32 command;
 
912
 
 
913
        tc = &ihost->task_context_table[ISCI_TAG_TCI(tag)];
 
914
        tc->abort = 0;
 
915
 
 
916
        command = SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC |
 
917
                  iport->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT |
 
918
                  ISCI_TAG_TCI(tag);
 
919
 
 
920
        sci_controller_post_request(ihost, command);
 
921
}
 
922
 
 
923
/**
 
924
 * This routine will abort the dummy request.  This will alow the hardware to
 
925
 * power down parts of the silicon to save power.
 
926
 *
 
927
 * @sci_port: The port on which the task must be aborted.
 
928
 *
 
929
 */
 
930
static void sci_port_abort_dummy_request(struct isci_port *iport)
 
931
{
 
932
        struct isci_host *ihost = iport->owning_controller;
 
933
        u16 tag = iport->reserved_tag;
 
934
        struct scu_task_context *tc;
 
935
        u32 command;
 
936
 
 
937
        tc = &ihost->task_context_table[ISCI_TAG_TCI(tag)];
 
938
        tc->abort = 1;
 
939
 
 
940
        command = SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT |
 
941
                  iport->physical_port_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT |
 
942
                  ISCI_TAG_TCI(tag);
 
943
 
 
944
        sci_controller_post_request(ihost, command);
 
945
}
 
946
 
 
947
/**
 
948
 *
 
949
 * @sci_port: This is the struct isci_port object to resume.
 
950
 *
 
951
 * This method will resume the port task scheduler for this port object. none
 
952
 */
 
953
static void
 
954
sci_port_resume_port_task_scheduler(struct isci_port *iport)
 
955
{
 
956
        u32 pts_control_value;
 
957
 
 
958
        pts_control_value = readl(&iport->port_task_scheduler_registers->control);
 
959
        pts_control_value &= ~SCU_PTSxCR_GEN_BIT(SUSPEND);
 
960
        writel(pts_control_value, &iport->port_task_scheduler_registers->control);
 
961
}
 
962
 
 
963
static void sci_port_ready_substate_waiting_enter(struct sci_base_state_machine *sm)
 
964
{
 
965
        struct isci_port *iport = container_of(sm, typeof(*iport), sm);
 
966
 
 
967
        sci_port_suspend_port_task_scheduler(iport);
 
968
 
 
969
        iport->not_ready_reason = SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS;
 
970
 
 
971
        if (iport->active_phy_mask != 0) {
 
972
                /* At least one of the phys on the port is ready */
 
973
                port_state_machine_change(iport,
 
974
                                          SCI_PORT_SUB_OPERATIONAL);
 
975
        }
 
976
}
 
977
 
 
978
static void sci_port_ready_substate_operational_enter(struct sci_base_state_machine *sm)
 
979
{
 
980
        u32 index;
 
981
        struct isci_port *iport = container_of(sm, typeof(*iport), sm);
 
982
        struct isci_host *ihost = iport->owning_controller;
 
983
 
 
984
        isci_port_ready(ihost, iport);
 
985
 
 
986
        for (index = 0; index < SCI_MAX_PHYS; index++) {
 
987
                if (iport->phy_table[index]) {
 
988
                        writel(iport->physical_port_index,
 
989
                                &iport->port_pe_configuration_register[
 
990
                                        iport->phy_table[index]->phy_index]);
 
991
                }
 
992
        }
 
993
 
 
994
        sci_port_update_viit_entry(iport);
 
995
 
 
996
        sci_port_resume_port_task_scheduler(iport);
 
997
 
 
998
        /*
 
999
         * Post the dummy task for the port so the hardware can schedule
 
1000
         * io correctly
 
1001
         */
 
1002
        sci_port_post_dummy_request(iport);
 
1003
}
 
1004
 
 
1005
static void sci_port_invalidate_dummy_remote_node(struct isci_port *iport)
 
1006
{
 
1007
        struct isci_host *ihost = iport->owning_controller;
 
1008
        u8 phys_index = iport->physical_port_index;
 
1009
        union scu_remote_node_context *rnc;
 
1010
        u16 rni = iport->reserved_rni;
 
1011
        u32 command;
 
1012
 
 
1013
        rnc = &ihost->remote_node_context_table[rni];
 
1014
 
 
1015
        rnc->ssp.is_valid = false;
 
1016
 
 
1017
        /* ensure the preceding tc abort request has reached the
 
1018
         * controller and give it ample time to act before posting the rnc
 
1019
         * invalidate
 
1020
         */
 
1021
        readl(&ihost->smu_registers->interrupt_status); /* flush */
 
1022
        udelay(10);
 
1023
 
 
1024
        command = SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE |
 
1025
                  phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
 
1026
 
 
1027
        sci_controller_post_request(ihost, command);
 
1028
}
 
1029
 
 
1030
/**
 
1031
 *
 
1032
 * @object: This is the object which is cast to a struct isci_port object.
 
1033
 *
 
1034
 * This method will perform the actions required by the struct isci_port on
 
1035
 * exiting the SCI_PORT_SUB_OPERATIONAL. This function reports
 
1036
 * the port not ready and suspends the port task scheduler. none
 
1037
 */
 
1038
static void sci_port_ready_substate_operational_exit(struct sci_base_state_machine *sm)
 
1039
{
 
1040
        struct isci_port *iport = container_of(sm, typeof(*iport), sm);
 
1041
        struct isci_host *ihost = iport->owning_controller;
 
1042
 
 
1043
        /*
 
1044
         * Kill the dummy task for this port if it has not yet posted
 
1045
         * the hardware will treat this as a NOP and just return abort
 
1046
         * complete.
 
1047
         */
 
1048
        sci_port_abort_dummy_request(iport);
 
1049
 
 
1050
        isci_port_not_ready(ihost, iport);
 
1051
 
 
1052
        if (iport->ready_exit)
 
1053
                sci_port_invalidate_dummy_remote_node(iport);
 
1054
}
 
1055
 
 
1056
static void sci_port_ready_substate_configuring_enter(struct sci_base_state_machine *sm)
 
1057
{
 
1058
        struct isci_port *iport = container_of(sm, typeof(*iport), sm);
 
1059
        struct isci_host *ihost = iport->owning_controller;
 
1060
 
 
1061
        if (iport->active_phy_mask == 0) {
 
1062
                isci_port_not_ready(ihost, iport);
 
1063
 
 
1064
                port_state_machine_change(iport,
 
1065
                                          SCI_PORT_SUB_WAITING);
 
1066
        } else if (iport->started_request_count == 0)
 
1067
                port_state_machine_change(iport,
 
1068
                                          SCI_PORT_SUB_OPERATIONAL);
 
1069
}
 
1070
 
 
1071
static void sci_port_ready_substate_configuring_exit(struct sci_base_state_machine *sm)
 
1072
{
 
1073
        struct isci_port *iport = container_of(sm, typeof(*iport), sm);
 
1074
 
 
1075
        sci_port_suspend_port_task_scheduler(iport);
 
1076
        if (iport->ready_exit)
 
1077
                sci_port_invalidate_dummy_remote_node(iport);
 
1078
}
 
1079
 
 
1080
enum sci_status sci_port_start(struct isci_port *iport)
 
1081
{
 
1082
        struct isci_host *ihost = iport->owning_controller;
 
1083
        enum sci_status status = SCI_SUCCESS;
 
1084
        enum sci_port_states state;
 
1085
        u32 phy_mask;
 
1086
 
 
1087
        state = iport->sm.current_state_id;
 
1088
        if (state != SCI_PORT_STOPPED) {
 
1089
                dev_warn(sciport_to_dev(iport),
 
1090
                         "%s: in wrong state: %d\n", __func__, state);
 
1091
                return SCI_FAILURE_INVALID_STATE;
 
1092
        }
 
1093
 
 
1094
        if (iport->assigned_device_count > 0) {
 
1095
                /* TODO This is a start failure operation because
 
1096
                 * there are still devices assigned to this port.
 
1097
                 * There must be no devices assigned to a port on a
 
1098
                 * start operation.
 
1099
                 */
 
1100
                return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
 
1101
        }
 
1102
 
 
1103
        if (iport->reserved_rni == SCU_DUMMY_INDEX) {
 
1104
                u16 rni = sci_remote_node_table_allocate_remote_node(
 
1105
                                &ihost->available_remote_nodes, 1);
 
1106
 
 
1107
                if (rni != SCU_DUMMY_INDEX)
 
1108
                        sci_port_construct_dummy_rnc(iport, rni);
 
1109
                else
 
1110
                        status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
 
1111
                iport->reserved_rni = rni;
 
1112
        }
 
1113
 
 
1114
        if (iport->reserved_tag == SCI_CONTROLLER_INVALID_IO_TAG) {
 
1115
                u16 tag;
 
1116
 
 
1117
                tag = isci_alloc_tag(ihost);
 
1118
                if (tag == SCI_CONTROLLER_INVALID_IO_TAG)
 
1119
                        status = SCI_FAILURE_INSUFFICIENT_RESOURCES;
 
1120
                else
 
1121
                        sci_port_construct_dummy_task(iport, tag);
 
1122
                iport->reserved_tag = tag;
 
1123
        }
 
1124
 
 
1125
        if (status == SCI_SUCCESS) {
 
1126
                phy_mask = sci_port_get_phys(iport);
 
1127
 
 
1128
                /*
 
1129
                 * There are one or more phys assigned to this port.  Make sure
 
1130
                 * the port's phy mask is in fact legal and supported by the
 
1131
                 * silicon.
 
1132
                 */
 
1133
                if (sci_port_is_phy_mask_valid(iport, phy_mask) == true) {
 
1134
                        port_state_machine_change(iport,
 
1135
                                                  SCI_PORT_READY);
 
1136
 
 
1137
                        return SCI_SUCCESS;
 
1138
                }
 
1139
                status = SCI_FAILURE;
 
1140
        }
 
1141
 
 
1142
        if (status != SCI_SUCCESS)
 
1143
                sci_port_destroy_dummy_resources(iport);
 
1144
 
 
1145
        return status;
 
1146
}
 
1147
 
 
1148
enum sci_status sci_port_stop(struct isci_port *iport)
 
1149
{
 
1150
        enum sci_port_states state;
 
1151
 
 
1152
        state = iport->sm.current_state_id;
 
1153
        switch (state) {
 
1154
        case SCI_PORT_STOPPED:
 
1155
                return SCI_SUCCESS;
 
1156
        case SCI_PORT_SUB_WAITING:
 
1157
        case SCI_PORT_SUB_OPERATIONAL:
 
1158
        case SCI_PORT_SUB_CONFIGURING:
 
1159
        case SCI_PORT_RESETTING:
 
1160
                port_state_machine_change(iport,
 
1161
                                          SCI_PORT_STOPPING);
 
1162
                return SCI_SUCCESS;
 
1163
        default:
 
1164
                dev_warn(sciport_to_dev(iport),
 
1165
                         "%s: in wrong state: %d\n", __func__, state);
 
1166
                return SCI_FAILURE_INVALID_STATE;
 
1167
        }
 
1168
}
 
1169
 
 
1170
static enum sci_status sci_port_hard_reset(struct isci_port *iport, u32 timeout)
 
1171
{
 
1172
        enum sci_status status = SCI_FAILURE_INVALID_PHY;
 
1173
        struct isci_phy *iphy = NULL;
 
1174
        enum sci_port_states state;
 
1175
        u32 phy_index;
 
1176
 
 
1177
        state = iport->sm.current_state_id;
 
1178
        if (state != SCI_PORT_SUB_OPERATIONAL) {
 
1179
                dev_warn(sciport_to_dev(iport),
 
1180
                         "%s: in wrong state: %d\n", __func__, state);
 
1181
                return SCI_FAILURE_INVALID_STATE;
 
1182
        }
 
1183
 
 
1184
        /* Select a phy on which we can send the hard reset request. */
 
1185
        for (phy_index = 0; phy_index < SCI_MAX_PHYS && !iphy; phy_index++) {
 
1186
                iphy = iport->phy_table[phy_index];
 
1187
                if (iphy && !sci_port_active_phy(iport, iphy)) {
 
1188
                        /*
 
1189
                         * We found a phy but it is not ready select
 
1190
                         * different phy
 
1191
                         */
 
1192
                        iphy = NULL;
 
1193
                }
 
1194
        }
 
1195
 
 
1196
        /* If we have a phy then go ahead and start the reset procedure */
 
1197
        if (!iphy)
 
1198
                return status;
 
1199
        status = sci_phy_reset(iphy);
 
1200
 
 
1201
        if (status != SCI_SUCCESS)
 
1202
                return status;
 
1203
 
 
1204
        sci_mod_timer(&iport->timer, timeout);
 
1205
        iport->not_ready_reason = SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED;
 
1206
 
 
1207
        port_state_machine_change(iport, SCI_PORT_RESETTING);
 
1208
        return SCI_SUCCESS;
 
1209
}
 
1210
 
 
1211
/**
 
1212
 * sci_port_add_phy() -
 
1213
 * @sci_port: This parameter specifies the port in which the phy will be added.
 
1214
 * @sci_phy: This parameter is the phy which is to be added to the port.
 
1215
 *
 
1216
 * This method will add a PHY to the selected port. This method returns an
 
1217
 * enum sci_status. SCI_SUCCESS the phy has been added to the port. Any other
 
1218
 * status is a failure to add the phy to the port.
 
1219
 */
 
1220
enum sci_status sci_port_add_phy(struct isci_port *iport,
 
1221
                                      struct isci_phy *iphy)
 
1222
{
 
1223
        enum sci_status status;
 
1224
        enum sci_port_states state;
 
1225
 
 
1226
        state = iport->sm.current_state_id;
 
1227
        switch (state) {
 
1228
        case SCI_PORT_STOPPED: {
 
1229
                struct sci_sas_address port_sas_address;
 
1230
 
 
1231
                /* Read the port assigned SAS Address if there is one */
 
1232
                sci_port_get_sas_address(iport, &port_sas_address);
 
1233
 
 
1234
                if (port_sas_address.high != 0 && port_sas_address.low != 0) {
 
1235
                        struct sci_sas_address phy_sas_address;
 
1236
 
 
1237
                        /* Make sure that the PHY SAS Address matches the SAS Address
 
1238
                         * for this port
 
1239
                         */
 
1240
                        sci_phy_get_sas_address(iphy, &phy_sas_address);
 
1241
 
 
1242
                        if (port_sas_address.high != phy_sas_address.high ||
 
1243
                            port_sas_address.low  != phy_sas_address.low)
 
1244
                                return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
 
1245
                }
 
1246
                return sci_port_set_phy(iport, iphy);
 
1247
        }
 
1248
        case SCI_PORT_SUB_WAITING:
 
1249
        case SCI_PORT_SUB_OPERATIONAL:
 
1250
                status = sci_port_set_phy(iport, iphy);
 
1251
 
 
1252
                if (status != SCI_SUCCESS)
 
1253
                        return status;
 
1254
 
 
1255
                sci_port_general_link_up_handler(iport, iphy, true);
 
1256
                iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
 
1257
                port_state_machine_change(iport, SCI_PORT_SUB_CONFIGURING);
 
1258
 
 
1259
                return status;
 
1260
        case SCI_PORT_SUB_CONFIGURING:
 
1261
                status = sci_port_set_phy(iport, iphy);
 
1262
 
 
1263
                if (status != SCI_SUCCESS)
 
1264
                        return status;
 
1265
                sci_port_general_link_up_handler(iport, iphy, true);
 
1266
 
 
1267
                /* Re-enter the configuring state since this may be the last phy in
 
1268
                 * the port.
 
1269
                 */
 
1270
                port_state_machine_change(iport,
 
1271
                                          SCI_PORT_SUB_CONFIGURING);
 
1272
                return SCI_SUCCESS;
 
1273
        default:
 
1274
                dev_warn(sciport_to_dev(iport),
 
1275
                         "%s: in wrong state: %d\n", __func__, state);
 
1276
                return SCI_FAILURE_INVALID_STATE;
 
1277
        }
 
1278
}
 
1279
 
 
1280
/**
 
1281
 * sci_port_remove_phy() -
 
1282
 * @sci_port: This parameter specifies the port in which the phy will be added.
 
1283
 * @sci_phy: This parameter is the phy which is to be added to the port.
 
1284
 *
 
1285
 * This method will remove the PHY from the selected PORT. This method returns
 
1286
 * an enum sci_status. SCI_SUCCESS the phy has been removed from the port. Any
 
1287
 * other status is a failure to add the phy to the port.
 
1288
 */
 
1289
enum sci_status sci_port_remove_phy(struct isci_port *iport,
 
1290
                                         struct isci_phy *iphy)
 
1291
{
 
1292
        enum sci_status status;
 
1293
        enum sci_port_states state;
 
1294
 
 
1295
        state = iport->sm.current_state_id;
 
1296
 
 
1297
        switch (state) {
 
1298
        case SCI_PORT_STOPPED:
 
1299
                return sci_port_clear_phy(iport, iphy);
 
1300
        case SCI_PORT_SUB_OPERATIONAL:
 
1301
                status = sci_port_clear_phy(iport, iphy);
 
1302
                if (status != SCI_SUCCESS)
 
1303
                        return status;
 
1304
 
 
1305
                sci_port_deactivate_phy(iport, iphy, true);
 
1306
                iport->not_ready_reason = SCIC_PORT_NOT_READY_RECONFIGURING;
 
1307
                port_state_machine_change(iport,
 
1308
                                          SCI_PORT_SUB_CONFIGURING);
 
1309
                return SCI_SUCCESS;
 
1310
        case SCI_PORT_SUB_CONFIGURING:
 
1311
                status = sci_port_clear_phy(iport, iphy);
 
1312
 
 
1313
                if (status != SCI_SUCCESS)
 
1314
                        return status;
 
1315
                sci_port_deactivate_phy(iport, iphy, true);
 
1316
 
 
1317
                /* Re-enter the configuring state since this may be the last phy in
 
1318
                 * the port
 
1319
                 */
 
1320
                port_state_machine_change(iport,
 
1321
                                          SCI_PORT_SUB_CONFIGURING);
 
1322
                return SCI_SUCCESS;
 
1323
        default:
 
1324
                dev_warn(sciport_to_dev(iport),
 
1325
                         "%s: in wrong state: %d\n", __func__, state);
 
1326
                return SCI_FAILURE_INVALID_STATE;
 
1327
        }
 
1328
}
 
1329
 
 
1330
enum sci_status sci_port_link_up(struct isci_port *iport,
 
1331
                                      struct isci_phy *iphy)
 
1332
{
 
1333
        enum sci_port_states state;
 
1334
 
 
1335
        state = iport->sm.current_state_id;
 
1336
        switch (state) {
 
1337
        case SCI_PORT_SUB_WAITING:
 
1338
                /* Since this is the first phy going link up for the port we
 
1339
                 * can just enable it and continue
 
1340
                 */
 
1341
                sci_port_activate_phy(iport, iphy, true);
 
1342
 
 
1343
                port_state_machine_change(iport,
 
1344
                                          SCI_PORT_SUB_OPERATIONAL);
 
1345
                return SCI_SUCCESS;
 
1346
        case SCI_PORT_SUB_OPERATIONAL:
 
1347
                sci_port_general_link_up_handler(iport, iphy, true);
 
1348
                return SCI_SUCCESS;
 
1349
        case SCI_PORT_RESETTING:
 
1350
                /* TODO We should  make  sure  that  the phy  that  has gone
 
1351
                 * link up is the same one on which we sent the reset.  It is
 
1352
                 * possible that the phy on which we sent  the reset is not the
 
1353
                 * one that has  gone  link up  and we  want to make sure that
 
1354
                 * phy being reset  comes  back.  Consider the case where a
 
1355
                 * reset is sent but before the hardware processes the reset it
 
1356
                 * get a link up on  the  port because of a hot plug event.
 
1357
                 * because  of  the reset request this phy will go link down
 
1358
                 * almost immediately.
 
1359
                 */
 
1360
 
 
1361
                /* In the resetting state we don't notify the user regarding
 
1362
                 * link up and link down notifications.
 
1363
                 */
 
1364
                sci_port_general_link_up_handler(iport, iphy, false);
 
1365
                return SCI_SUCCESS;
 
1366
        default:
 
1367
                dev_warn(sciport_to_dev(iport),
 
1368
                         "%s: in wrong state: %d\n", __func__, state);
 
1369
                return SCI_FAILURE_INVALID_STATE;
 
1370
        }
 
1371
}
 
1372
 
 
1373
enum sci_status sci_port_link_down(struct isci_port *iport,
 
1374
                                        struct isci_phy *iphy)
 
1375
{
 
1376
        enum sci_port_states state;
 
1377
 
 
1378
        state = iport->sm.current_state_id;
 
1379
        switch (state) {
 
1380
        case SCI_PORT_SUB_OPERATIONAL:
 
1381
                sci_port_deactivate_phy(iport, iphy, true);
 
1382
 
 
1383
                /* If there are no active phys left in the port, then
 
1384
                 * transition the port to the WAITING state until such time
 
1385
                 * as a phy goes link up
 
1386
                 */
 
1387
                if (iport->active_phy_mask == 0)
 
1388
                        port_state_machine_change(iport,
 
1389
                                                  SCI_PORT_SUB_WAITING);
 
1390
                return SCI_SUCCESS;
 
1391
        case SCI_PORT_RESETTING:
 
1392
                /* In the resetting state we don't notify the user regarding
 
1393
                 * link up and link down notifications. */
 
1394
                sci_port_deactivate_phy(iport, iphy, false);
 
1395
                return SCI_SUCCESS;
 
1396
        default:
 
1397
                dev_warn(sciport_to_dev(iport),
 
1398
                         "%s: in wrong state: %d\n", __func__, state);
 
1399
                return SCI_FAILURE_INVALID_STATE;
 
1400
        }
 
1401
}
 
1402
 
 
1403
enum sci_status sci_port_start_io(struct isci_port *iport,
 
1404
                                  struct isci_remote_device *idev,
 
1405
                                  struct isci_request *ireq)
 
1406
{
 
1407
        enum sci_port_states state;
 
1408
 
 
1409
        state = iport->sm.current_state_id;
 
1410
        switch (state) {
 
1411
        case SCI_PORT_SUB_WAITING:
 
1412
                return SCI_FAILURE_INVALID_STATE;
 
1413
        case SCI_PORT_SUB_OPERATIONAL:
 
1414
                iport->started_request_count++;
 
1415
                return SCI_SUCCESS;
 
1416
        default:
 
1417
                dev_warn(sciport_to_dev(iport),
 
1418
                         "%s: in wrong state: %d\n", __func__, state);
 
1419
                return SCI_FAILURE_INVALID_STATE;
 
1420
        }
 
1421
}
 
1422
 
 
1423
enum sci_status sci_port_complete_io(struct isci_port *iport,
 
1424
                                     struct isci_remote_device *idev,
 
1425
                                     struct isci_request *ireq)
 
1426
{
 
1427
        enum sci_port_states state;
 
1428
 
 
1429
        state = iport->sm.current_state_id;
 
1430
        switch (state) {
 
1431
        case SCI_PORT_STOPPED:
 
1432
                dev_warn(sciport_to_dev(iport),
 
1433
                         "%s: in wrong state: %d\n", __func__, state);
 
1434
                return SCI_FAILURE_INVALID_STATE;
 
1435
        case SCI_PORT_STOPPING:
 
1436
                sci_port_decrement_request_count(iport);
 
1437
 
 
1438
                if (iport->started_request_count == 0)
 
1439
                        port_state_machine_change(iport,
 
1440
                                                  SCI_PORT_STOPPED);
 
1441
                break;
 
1442
        case SCI_PORT_READY:
 
1443
        case SCI_PORT_RESETTING:
 
1444
        case SCI_PORT_FAILED:
 
1445
        case SCI_PORT_SUB_WAITING:
 
1446
        case SCI_PORT_SUB_OPERATIONAL:
 
1447
                sci_port_decrement_request_count(iport);
 
1448
                break;
 
1449
        case SCI_PORT_SUB_CONFIGURING:
 
1450
                sci_port_decrement_request_count(iport);
 
1451
                if (iport->started_request_count == 0) {
 
1452
                        port_state_machine_change(iport,
 
1453
                                                  SCI_PORT_SUB_OPERATIONAL);
 
1454
                }
 
1455
                break;
 
1456
        }
 
1457
        return SCI_SUCCESS;
 
1458
}
 
1459
 
 
1460
static void sci_port_enable_port_task_scheduler(struct isci_port *iport)
 
1461
{
 
1462
        u32 pts_control_value;
 
1463
 
 
1464
         /* enable the port task scheduler in a suspended state */
 
1465
        pts_control_value = readl(&iport->port_task_scheduler_registers->control);
 
1466
        pts_control_value |= SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND);
 
1467
        writel(pts_control_value, &iport->port_task_scheduler_registers->control);
 
1468
}
 
1469
 
 
1470
static void sci_port_disable_port_task_scheduler(struct isci_port *iport)
 
1471
{
 
1472
        u32 pts_control_value;
 
1473
 
 
1474
        pts_control_value = readl(&iport->port_task_scheduler_registers->control);
 
1475
        pts_control_value &=
 
1476
                ~(SCU_PTSxCR_GEN_BIT(ENABLE) | SCU_PTSxCR_GEN_BIT(SUSPEND));
 
1477
        writel(pts_control_value, &iport->port_task_scheduler_registers->control);
 
1478
}
 
1479
 
 
1480
static void sci_port_post_dummy_remote_node(struct isci_port *iport)
 
1481
{
 
1482
        struct isci_host *ihost = iport->owning_controller;
 
1483
        u8 phys_index = iport->physical_port_index;
 
1484
        union scu_remote_node_context *rnc;
 
1485
        u16 rni = iport->reserved_rni;
 
1486
        u32 command;
 
1487
 
 
1488
        rnc = &ihost->remote_node_context_table[rni];
 
1489
        rnc->ssp.is_valid = true;
 
1490
 
 
1491
        command = SCU_CONTEXT_COMMAND_POST_RNC_32 |
 
1492
                  phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
 
1493
 
 
1494
        sci_controller_post_request(ihost, command);
 
1495
 
 
1496
        /* ensure hardware has seen the post rnc command and give it
 
1497
         * ample time to act before sending the suspend
 
1498
         */
 
1499
        readl(&ihost->smu_registers->interrupt_status); /* flush */
 
1500
        udelay(10);
 
1501
 
 
1502
        command = SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX |
 
1503
                  phys_index << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT | rni;
 
1504
 
 
1505
        sci_controller_post_request(ihost, command);
 
1506
}
 
1507
 
 
1508
static void sci_port_stopped_state_enter(struct sci_base_state_machine *sm)
 
1509
{
 
1510
        struct isci_port *iport = container_of(sm, typeof(*iport), sm);
 
1511
 
 
1512
        if (iport->sm.previous_state_id == SCI_PORT_STOPPING) {
 
1513
                /*
 
1514
                 * If we enter this state becasuse of a request to stop
 
1515
                 * the port then we want to disable the hardwares port
 
1516
                 * task scheduler. */
 
1517
                sci_port_disable_port_task_scheduler(iport);
 
1518
        }
 
1519
}
 
1520
 
 
1521
static void sci_port_stopped_state_exit(struct sci_base_state_machine *sm)
 
1522
{
 
1523
        struct isci_port *iport = container_of(sm, typeof(*iport), sm);
 
1524
 
 
1525
        /* Enable and suspend the port task scheduler */
 
1526
        sci_port_enable_port_task_scheduler(iport);
 
1527
}
 
1528
 
 
1529
static void sci_port_ready_state_enter(struct sci_base_state_machine *sm)
 
1530
{
 
1531
        struct isci_port *iport = container_of(sm, typeof(*iport), sm);
 
1532
        struct isci_host *ihost = iport->owning_controller;
 
1533
        u32 prev_state;
 
1534
 
 
1535
        prev_state = iport->sm.previous_state_id;
 
1536
        if (prev_state  == SCI_PORT_RESETTING)
 
1537
                isci_port_hard_reset_complete(iport, SCI_SUCCESS);
 
1538
        else
 
1539
                isci_port_not_ready(ihost, iport);
 
1540
 
 
1541
        /* Post and suspend the dummy remote node context for this port. */
 
1542
        sci_port_post_dummy_remote_node(iport);
 
1543
 
 
1544
        /* Start the ready substate machine */
 
1545
        port_state_machine_change(iport,
 
1546
                                  SCI_PORT_SUB_WAITING);
 
1547
}
 
1548
 
 
1549
static void sci_port_resetting_state_exit(struct sci_base_state_machine *sm)
 
1550
{
 
1551
        struct isci_port *iport = container_of(sm, typeof(*iport), sm);
 
1552
 
 
1553
        sci_del_timer(&iport->timer);
 
1554
}
 
1555
 
 
1556
static void sci_port_stopping_state_exit(struct sci_base_state_machine *sm)
 
1557
{
 
1558
        struct isci_port *iport = container_of(sm, typeof(*iport), sm);
 
1559
 
 
1560
        sci_del_timer(&iport->timer);
 
1561
 
 
1562
        sci_port_destroy_dummy_resources(iport);
 
1563
}
 
1564
 
 
1565
static void sci_port_failed_state_enter(struct sci_base_state_machine *sm)
 
1566
{
 
1567
        struct isci_port *iport = container_of(sm, typeof(*iport), sm);
 
1568
 
 
1569
        isci_port_hard_reset_complete(iport, SCI_FAILURE_TIMEOUT);
 
1570
}
 
1571
 
 
1572
/* --------------------------------------------------------------------------- */
 
1573
 
 
1574
static const struct sci_base_state sci_port_state_table[] = {
 
1575
        [SCI_PORT_STOPPED] = {
 
1576
                .enter_state = sci_port_stopped_state_enter,
 
1577
                .exit_state  = sci_port_stopped_state_exit
 
1578
        },
 
1579
        [SCI_PORT_STOPPING] = {
 
1580
                .exit_state  = sci_port_stopping_state_exit
 
1581
        },
 
1582
        [SCI_PORT_READY] = {
 
1583
                .enter_state = sci_port_ready_state_enter,
 
1584
        },
 
1585
        [SCI_PORT_SUB_WAITING] = {
 
1586
                .enter_state = sci_port_ready_substate_waiting_enter,
 
1587
        },
 
1588
        [SCI_PORT_SUB_OPERATIONAL] = {
 
1589
                .enter_state = sci_port_ready_substate_operational_enter,
 
1590
                .exit_state  = sci_port_ready_substate_operational_exit
 
1591
        },
 
1592
        [SCI_PORT_SUB_CONFIGURING] = {
 
1593
                .enter_state = sci_port_ready_substate_configuring_enter,
 
1594
                .exit_state  = sci_port_ready_substate_configuring_exit
 
1595
        },
 
1596
        [SCI_PORT_RESETTING] = {
 
1597
                .exit_state  = sci_port_resetting_state_exit
 
1598
        },
 
1599
        [SCI_PORT_FAILED] = {
 
1600
                .enter_state = sci_port_failed_state_enter,
 
1601
        }
 
1602
};
 
1603
 
 
1604
void sci_port_construct(struct isci_port *iport, u8 index,
 
1605
                             struct isci_host *ihost)
 
1606
{
 
1607
        sci_init_sm(&iport->sm, sci_port_state_table, SCI_PORT_STOPPED);
 
1608
 
 
1609
        iport->logical_port_index  = SCIC_SDS_DUMMY_PORT;
 
1610
        iport->physical_port_index = index;
 
1611
        iport->active_phy_mask     = 0;
 
1612
        iport->last_active_phy     = 0;
 
1613
        iport->ready_exit          = false;
 
1614
 
 
1615
        iport->owning_controller = ihost;
 
1616
 
 
1617
        iport->started_request_count = 0;
 
1618
        iport->assigned_device_count = 0;
 
1619
 
 
1620
        iport->reserved_rni = SCU_DUMMY_INDEX;
 
1621
        iport->reserved_tag = SCI_CONTROLLER_INVALID_IO_TAG;
 
1622
 
 
1623
        sci_init_timer(&iport->timer, port_timeout);
 
1624
 
 
1625
        iport->port_task_scheduler_registers = NULL;
 
1626
 
 
1627
        for (index = 0; index < SCI_MAX_PHYS; index++)
 
1628
                iport->phy_table[index] = NULL;
 
1629
}
 
1630
 
 
1631
void isci_port_init(struct isci_port *iport, struct isci_host *ihost, int index)
 
1632
{
 
1633
        INIT_LIST_HEAD(&iport->remote_dev_list);
 
1634
        INIT_LIST_HEAD(&iport->domain_dev_list);
 
1635
        spin_lock_init(&iport->state_lock);
 
1636
        init_completion(&iport->start_complete);
 
1637
        iport->isci_host = ihost;
 
1638
        isci_port_change_state(iport, isci_freed);
 
1639
}
 
1640
 
 
1641
/**
 
1642
 * isci_port_get_state() - This function gets the status of the port object.
 
1643
 * @isci_port: This parameter points to the isci_port object
 
1644
 *
 
1645
 * status of the object as a isci_status enum.
 
1646
 */
 
1647
enum isci_status isci_port_get_state(
 
1648
        struct isci_port *isci_port)
 
1649
{
 
1650
        return isci_port->status;
 
1651
}
 
1652
 
 
1653
void sci_port_broadcast_change_received(struct isci_port *iport, struct isci_phy *iphy)
 
1654
{
 
1655
        struct isci_host *ihost = iport->owning_controller;
 
1656
 
 
1657
        /* notify the user. */
 
1658
        isci_port_bc_change_received(ihost, iport, iphy);
 
1659
}
 
1660
 
 
1661
int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport,
 
1662
                                 struct isci_phy *iphy)
 
1663
{
 
1664
        unsigned long flags;
 
1665
        enum sci_status status;
 
1666
        int ret = TMF_RESP_FUNC_COMPLETE;
 
1667
 
 
1668
        dev_dbg(&ihost->pdev->dev, "%s: iport = %p\n",
 
1669
                __func__, iport);
 
1670
 
 
1671
        init_completion(&iport->hard_reset_complete);
 
1672
 
 
1673
        spin_lock_irqsave(&ihost->scic_lock, flags);
 
1674
 
 
1675
        #define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT
 
1676
        status = sci_port_hard_reset(iport, ISCI_PORT_RESET_TIMEOUT);
 
1677
 
 
1678
        spin_unlock_irqrestore(&ihost->scic_lock, flags);
 
1679
 
 
1680
        if (status == SCI_SUCCESS) {
 
1681
                wait_for_completion(&iport->hard_reset_complete);
 
1682
 
 
1683
                dev_dbg(&ihost->pdev->dev,
 
1684
                        "%s: iport = %p; hard reset completion\n",
 
1685
                        __func__, iport);
 
1686
 
 
1687
                if (iport->hard_reset_status != SCI_SUCCESS) {
 
1688
                        ret = TMF_RESP_FUNC_FAILED;
 
1689
 
 
1690
                        dev_err(&ihost->pdev->dev,
 
1691
                                "%s: iport = %p; hard reset failed (0x%x)\n",
 
1692
                                __func__, iport, iport->hard_reset_status);
 
1693
                }
 
1694
        } else {
 
1695
                ret = TMF_RESP_FUNC_FAILED;
 
1696
 
 
1697
                dev_err(&ihost->pdev->dev,
 
1698
                        "%s: iport = %p; sci_port_hard_reset call"
 
1699
                        " failed 0x%x\n",
 
1700
                        __func__, iport, status);
 
1701
 
 
1702
        }
 
1703
 
 
1704
        /* If the hard reset for the port has failed, consider this
 
1705
         * the same as link failures on all phys in the port.
 
1706
         */
 
1707
        if (ret != TMF_RESP_FUNC_COMPLETE) {
 
1708
 
 
1709
                dev_err(&ihost->pdev->dev,
 
1710
                        "%s: iport = %p; hard reset failed "
 
1711
                        "(0x%x) - driving explicit link fail for all phys\n",
 
1712
                        __func__, iport, iport->hard_reset_status);
 
1713
        }
 
1714
        return ret;
 
1715
}
 
1716
 
 
1717
/**
 
1718
 * isci_port_deformed() - This function is called by libsas when a port becomes
 
1719
 *    inactive.
 
1720
 * @phy: This parameter specifies the libsas phy with the inactive port.
 
1721
 *
 
1722
 */
 
1723
void isci_port_deformed(struct asd_sas_phy *phy)
 
1724
{
 
1725
        pr_debug("%s: sas_phy = %p\n", __func__, phy);
 
1726
}
 
1727
 
 
1728
/**
 
1729
 * isci_port_formed() - This function is called by libsas when a port becomes
 
1730
 *    active.
 
1731
 * @phy: This parameter specifies the libsas phy with the active port.
 
1732
 *
 
1733
 */
 
1734
void isci_port_formed(struct asd_sas_phy *phy)
 
1735
{
 
1736
        pr_debug("%s: sas_phy = %p, sas_port = %p\n", __func__, phy, phy->port);
 
1737
}