linux/drivers/scsi/aic94xx/aic94xx_scb.c
<<
>>
Prefs
   1/*
   2 * Aic94xx SAS/SATA driver SCB management.
   3 *
   4 * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
   5 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
   6 *
   7 * This file is licensed under GPLv2.
   8 *
   9 * This file is part of the aic94xx driver.
  10 *
  11 * The aic94xx driver is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; version 2 of the
  14 * License.
  15 *
  16 * The aic94xx driver is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19 * General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with the aic94xx driver; if not, write to the Free Software
  23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  24 *
  25 */
  26
  27#include <scsi/scsi_host.h>
  28
  29#include "aic94xx.h"
  30#include "aic94xx_reg.h"
  31#include "aic94xx_hwi.h"
  32#include "aic94xx_seq.h"
  33
  34#include "aic94xx_dump.h"
  35
  36/* ---------- EMPTY SCB ---------- */
  37
  38#define DL_PHY_MASK      7
  39#define BYTES_DMAED      0
  40#define PRIMITIVE_RECVD  0x08
  41#define PHY_EVENT        0x10
  42#define LINK_RESET_ERROR 0x18
  43#define TIMER_EVENT      0x20
  44#define REQ_TASK_ABORT   0xF0
  45#define REQ_DEVICE_RESET 0xF1
  46#define SIGNAL_NCQ_ERROR 0xF2
  47#define CLEAR_NCQ_ERROR  0xF3
  48
  49#define PHY_EVENTS_STATUS (CURRENT_LOSS_OF_SIGNAL | CURRENT_OOB_DONE   \
  50                           | CURRENT_SPINUP_HOLD | CURRENT_GTO_TIMEOUT \
  51                           | CURRENT_OOB_ERROR)
  52
  53static void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
  54{
  55        struct sas_phy *sas_phy = phy->sas_phy.phy;
  56
  57        switch (oob_mode & 7) {
  58        case PHY_SPEED_60:
  59                /* FIXME: sas transport class doesn't have this */
  60                phy->sas_phy.linkrate = SAS_LINK_RATE_6_0_GBPS;
  61                phy->sas_phy.phy->negotiated_linkrate = SAS_LINK_RATE_6_0_GBPS;
  62                break;
  63        case PHY_SPEED_30:
  64                phy->sas_phy.linkrate = SAS_LINK_RATE_3_0_GBPS;
  65                phy->sas_phy.phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
  66                break;
  67        case PHY_SPEED_15:
  68                phy->sas_phy.linkrate = SAS_LINK_RATE_1_5_GBPS;
  69                phy->sas_phy.phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
  70                break;
  71        }
  72        sas_phy->negotiated_linkrate = phy->sas_phy.linkrate;
  73        sas_phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
  74        sas_phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
  75        sas_phy->maximum_linkrate = phy->phy_desc->max_sas_lrate;
  76        sas_phy->minimum_linkrate = phy->phy_desc->min_sas_lrate;
  77
  78        if (oob_mode & SAS_MODE)
  79                phy->sas_phy.oob_mode = SAS_OOB_MODE;
  80        else if (oob_mode & SATA_MODE)
  81                phy->sas_phy.oob_mode = SATA_OOB_MODE;
  82}
  83
  84static void asd_phy_event_tasklet(struct asd_ascb *ascb,
  85                                         struct done_list_struct *dl)
  86{
  87        struct asd_ha_struct *asd_ha = ascb->ha;
  88        struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
  89        int phy_id = dl->status_block[0] & DL_PHY_MASK;
  90        struct asd_phy *phy = &asd_ha->phys[phy_id];
  91
  92        u8 oob_status = dl->status_block[1] & PHY_EVENTS_STATUS;
  93        u8 oob_mode   = dl->status_block[2];
  94
  95        switch (oob_status) {
  96        case CURRENT_LOSS_OF_SIGNAL:
  97                /* directly attached device was removed */
  98                ASD_DPRINTK("phy%d: device unplugged\n", phy_id);
  99                asd_turn_led(asd_ha, phy_id, 0);
 100                sas_phy_disconnected(&phy->sas_phy);
 101                sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
 102                break;
 103        case CURRENT_OOB_DONE:
 104                /* hot plugged device */
 105                asd_turn_led(asd_ha, phy_id, 1);
 106                get_lrate_mode(phy, oob_mode);
 107                ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n",
 108                            phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto);
 109                sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
 110                break;
 111        case CURRENT_SPINUP_HOLD:
 112                /* hot plug SATA, no COMWAKE sent */
 113                asd_turn_led(asd_ha, phy_id, 1);
 114                sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD);
 115                break;
 116        case CURRENT_GTO_TIMEOUT:
 117        case CURRENT_OOB_ERROR:
 118                ASD_DPRINTK("phy%d error while OOB: oob status:0x%x\n", phy_id,
 119                            dl->status_block[1]);
 120                asd_turn_led(asd_ha, phy_id, 0);
 121                sas_phy_disconnected(&phy->sas_phy);
 122                sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR);
 123                break;
 124        }
 125}
 126
 127/* If phys are enabled sparsely, this will do the right thing. */
 128static unsigned ord_phy(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
 129{
 130        u8 enabled_mask = asd_ha->hw_prof.enabled_phys;
 131        int i, k = 0;
 132
 133        for_each_phy(enabled_mask, enabled_mask, i) {
 134                if (&asd_ha->phys[i] == phy)
 135                        return k;
 136                k++;
 137        }
 138        return 0;
 139}
 140
 141/**
 142 * asd_get_attached_sas_addr -- extract/generate attached SAS address
 143 * phy: pointer to asd_phy
 144 * sas_addr: pointer to buffer where the SAS address is to be written
 145 *
 146 * This function extracts the SAS address from an IDENTIFY frame
 147 * received.  If OOB is SATA, then a SAS address is generated from the
 148 * HA tables.
 149 *
 150 * LOCKING: the frame_rcvd_lock needs to be held since this parses the frame
 151 * buffer.
 152 */
 153static void asd_get_attached_sas_addr(struct asd_phy *phy, u8 *sas_addr)
 154{
 155        if (phy->sas_phy.frame_rcvd[0] == 0x34
 156            && phy->sas_phy.oob_mode == SATA_OOB_MODE) {
 157                struct asd_ha_struct *asd_ha = phy->sas_phy.ha->lldd_ha;
 158                /* FIS device-to-host */
 159                u64 addr = be64_to_cpu(*(__be64 *)phy->phy_desc->sas_addr);
 160
 161                addr += asd_ha->hw_prof.sata_name_base + ord_phy(asd_ha, phy);
 162                *(__be64 *)sas_addr = cpu_to_be64(addr);
 163        } else {
 164                struct sas_identify_frame *idframe =
 165                        (void *) phy->sas_phy.frame_rcvd;
 166                memcpy(sas_addr, idframe->sas_addr, SAS_ADDR_SIZE);
 167        }
 168}
 169
 170static void asd_form_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
 171{
 172        int i;
 173        struct asd_port *free_port = NULL;
 174        struct asd_port *port;
 175        struct asd_sas_phy *sas_phy = &phy->sas_phy;
 176        unsigned long flags;
 177
 178        spin_lock_irqsave(&asd_ha->asd_ports_lock, flags);
 179        if (!phy->asd_port) {
 180                for (i = 0; i < ASD_MAX_PHYS; i++) {
 181                        port = &asd_ha->asd_ports[i];
 182
 183                        /* Check for wide port */
 184                        if (port->num_phys > 0 &&
 185                            memcmp(port->sas_addr, sas_phy->sas_addr,
 186                                   SAS_ADDR_SIZE) == 0 &&
 187                            memcmp(port->attached_sas_addr,
 188                                   sas_phy->attached_sas_addr,
 189                                   SAS_ADDR_SIZE) == 0) {
 190                                break;
 191                        }
 192
 193                        /* Find a free port */
 194                        if (port->num_phys == 0 && free_port == NULL) {
 195                                free_port = port;
 196                        }
 197                }
 198
 199                /* Use a free port if this doesn't form a wide port */
 200                if (i >= ASD_MAX_PHYS) {
 201                        port = free_port;
 202                        BUG_ON(!port);
 203                        memcpy(port->sas_addr, sas_phy->sas_addr,
 204                               SAS_ADDR_SIZE);
 205                        memcpy(port->attached_sas_addr,
 206                               sas_phy->attached_sas_addr,
 207                               SAS_ADDR_SIZE);
 208                }
 209                port->num_phys++;
 210                port->phy_mask |= (1U << sas_phy->id);
 211                phy->asd_port = port;
 212        }
 213        ASD_DPRINTK("%s: updating phy_mask 0x%x for phy%d\n",
 214                    __func__, phy->asd_port->phy_mask, sas_phy->id);
 215        asd_update_port_links(asd_ha, phy);
 216        spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags);
 217}
 218
 219static void asd_deform_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
 220{
 221        struct asd_port *port = phy->asd_port;
 222        struct asd_sas_phy *sas_phy = &phy->sas_phy;
 223        unsigned long flags;
 224
 225        spin_lock_irqsave(&asd_ha->asd_ports_lock, flags);
 226        if (port) {
 227                port->num_phys--;
 228                port->phy_mask &= ~(1U << sas_phy->id);
 229                phy->asd_port = NULL;
 230        }
 231        spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags);
 232}
 233
 234static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
 235                                    struct done_list_struct *dl,
 236                                    int edb_id, int phy_id)
 237{
 238        unsigned long flags;
 239        int edb_el = edb_id + ascb->edb_index;
 240        struct asd_dma_tok *edb = ascb->ha->seq.edb_arr[edb_el];
 241        struct asd_phy *phy = &ascb->ha->phys[phy_id];
 242        struct sas_ha_struct *sas_ha = phy->sas_phy.ha;
 243        u16 size = ((dl->status_block[3] & 7) << 8) | dl->status_block[2];
 244
 245        size = min(size, (u16) sizeof(phy->frame_rcvd));
 246
 247        spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);
 248        memcpy(phy->sas_phy.frame_rcvd, edb->vaddr, size);
 249        phy->sas_phy.frame_rcvd_size = size;
 250        asd_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
 251        spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
 252        asd_dump_frame_rcvd(phy, dl);
 253        asd_form_port(ascb->ha, phy);
 254        sas_ha->notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED);
 255}
 256
 257static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
 258                                       struct done_list_struct *dl,
 259                                       int phy_id)
 260{
 261        struct asd_ha_struct *asd_ha = ascb->ha;
 262        struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
 263        struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
 264        struct asd_phy *phy = &asd_ha->phys[phy_id];
 265        u8 lr_error = dl->status_block[1];
 266        u8 retries_left = dl->status_block[2];
 267
 268        switch (lr_error) {
 269        case 0:
 270                ASD_DPRINTK("phy%d: Receive ID timer expired\n", phy_id);
 271                break;
 272        case 1:
 273                ASD_DPRINTK("phy%d: Loss of signal\n", phy_id);
 274                break;
 275        case 2:
 276                ASD_DPRINTK("phy%d: Loss of dword sync\n", phy_id);
 277                break;
 278        case 3:
 279                ASD_DPRINTK("phy%d: Receive FIS timeout\n", phy_id);
 280                break;
 281        default:
 282                ASD_DPRINTK("phy%d: unknown link reset error code: 0x%x\n",
 283                            phy_id, lr_error);
 284                break;
 285        }
 286
 287        asd_turn_led(asd_ha, phy_id, 0);
 288        sas_phy_disconnected(sas_phy);
 289        asd_deform_port(asd_ha, phy);
 290        sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
 291
 292        if (retries_left == 0) {
 293                int num = 1;
 294                struct asd_ascb *cp = asd_ascb_alloc_list(ascb->ha, &num,
 295                                                          GFP_ATOMIC);
 296                if (!cp) {
 297                        asd_printk("%s: out of memory\n", __func__);
 298                        goto out;
 299                }
 300                ASD_DPRINTK("phy%d: retries:0 performing link reset seq\n",
 301                            phy_id);
 302                asd_build_control_phy(cp, phy_id, ENABLE_PHY);
 303                if (asd_post_ascb_list(ascb->ha, cp, 1) != 0)
 304                        asd_ascb_free(cp);
 305        }
 306out:
 307        ;
 308}
 309
 310static void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb,
 311                                       struct done_list_struct *dl,
 312                                       int phy_id)
 313{
 314        unsigned long flags;
 315        struct sas_ha_struct *sas_ha = &ascb->ha->sas_ha;
 316        struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
 317        struct asd_ha_struct *asd_ha = ascb->ha;
 318        struct asd_phy *phy = &asd_ha->phys[phy_id];
 319        u8  reg  = dl->status_block[1];
 320        u32 cont = dl->status_block[2] << ((reg & 3)*8);
 321
 322        reg &= ~3;
 323        switch (reg) {
 324        case LmPRMSTAT0BYTE0:
 325                switch (cont) {
 326                case LmBROADCH:
 327                case LmBROADRVCH0:
 328                case LmBROADRVCH1:
 329                case LmBROADSES:
 330                        ASD_DPRINTK("phy%d: BROADCAST change received:%d\n",
 331                                    phy_id, cont);
 332                        spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
 333                        sas_phy->sas_prim = ffs(cont);
 334                        spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
 335                        sas_ha->notify_port_event(sas_phy,PORTE_BROADCAST_RCVD);
 336                        break;
 337
 338                case LmUNKNOWNP:
 339                        ASD_DPRINTK("phy%d: unknown BREAK\n", phy_id);
 340                        break;
 341
 342                default:
 343                        ASD_DPRINTK("phy%d: primitive reg:0x%x, cont:0x%04x\n",
 344                                    phy_id, reg, cont);
 345                        break;
 346                }
 347                break;
 348        case LmPRMSTAT1BYTE0:
 349                switch (cont) {
 350                case LmHARDRST:
 351                        ASD_DPRINTK("phy%d: HARD_RESET primitive rcvd\n",
 352                                    phy_id);
 353                        /* The sequencer disables all phys on that port.
 354                         * We have to re-enable the phys ourselves. */
 355                        asd_deform_port(asd_ha, phy);
 356                        sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET);
 357                        break;
 358
 359                default:
 360                        ASD_DPRINTK("phy%d: primitive reg:0x%x, cont:0x%04x\n",
 361                                    phy_id, reg, cont);
 362                        break;
 363                }
 364                break;
 365        default:
 366                ASD_DPRINTK("unknown primitive register:0x%x\n",
 367                            dl->status_block[1]);
 368                break;
 369        }
 370}
 371
 372/**
 373 * asd_invalidate_edb -- invalidate an EDB and if necessary post the ESCB
 374 * @ascb: pointer to Empty SCB
 375 * @edb_id: index [0,6] to the empty data buffer which is to be invalidated
 376 *
 377 * After an EDB has been invalidated, if all EDBs in this ESCB have been
 378 * invalidated, the ESCB is posted back to the sequencer.
 379 * Context is tasklet/IRQ.
 380 */
 381void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id)
 382{
 383        struct asd_seq_data *seq = &ascb->ha->seq;
 384        struct empty_scb *escb = &ascb->scb->escb;
 385        struct sg_el     *eb   = &escb->eb[edb_id];
 386        struct asd_dma_tok *edb = seq->edb_arr[ascb->edb_index + edb_id];
 387
 388        memset(edb->vaddr, 0, ASD_EDB_SIZE);
 389        eb->flags |= ELEMENT_NOT_VALID;
 390        escb->num_valid--;
 391
 392        if (escb->num_valid == 0) {
 393                int i;
 394                /* ASD_DPRINTK("reposting escb: vaddr: 0x%p, "
 395                            "dma_handle: 0x%08llx, next: 0x%08llx, "
 396                            "index:%d, opcode:0x%02x\n",
 397                            ascb->dma_scb.vaddr,
 398                            (u64)ascb->dma_scb.dma_handle,
 399                            le64_to_cpu(ascb->scb->header.next_scb),
 400                            le16_to_cpu(ascb->scb->header.index),
 401                            ascb->scb->header.opcode);
 402                */
 403                escb->num_valid = ASD_EDBS_PER_SCB;
 404                for (i = 0; i < ASD_EDBS_PER_SCB; i++)
 405                        escb->eb[i].flags = 0;
 406                if (!list_empty(&ascb->list))
 407                        list_del_init(&ascb->list);
 408                i = asd_post_escb_list(ascb->ha, ascb, 1);
 409                if (i)
 410                        asd_printk("couldn't post escb, err:%d\n", i);
 411        }
 412}
 413
 414static void escb_tasklet_complete(struct asd_ascb *ascb,
 415                                  struct done_list_struct *dl)
 416{
 417        struct asd_ha_struct *asd_ha = ascb->ha;
 418        struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
 419        int edb = (dl->opcode & DL_PHY_MASK) - 1; /* [0xc1,0xc7] -> [0,6] */
 420        u8  sb_opcode = dl->status_block[0];
 421        int phy_id = sb_opcode & DL_PHY_MASK;
 422        struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
 423        struct asd_phy *phy = &asd_ha->phys[phy_id];
 424
 425        if (edb > 6 || edb < 0) {
 426                ASD_DPRINTK("edb is 0x%x! dl->opcode is 0x%x\n",
 427                            edb, dl->opcode);
 428                ASD_DPRINTK("sb_opcode : 0x%x, phy_id: 0x%x\n",
 429                            sb_opcode, phy_id);
 430                ASD_DPRINTK("escb: vaddr: 0x%p, "
 431                            "dma_handle: 0x%llx, next: 0x%llx, "
 432                            "index:%d, opcode:0x%02x\n",
 433                            ascb->dma_scb.vaddr,
 434                            (unsigned long long)ascb->dma_scb.dma_handle,
 435                            (unsigned long long)
 436                            le64_to_cpu(ascb->scb->header.next_scb),
 437                            le16_to_cpu(ascb->scb->header.index),
 438                            ascb->scb->header.opcode);
 439        }
 440
 441        /* Catch these before we mask off the sb_opcode bits */
 442        switch (sb_opcode) {
 443        case REQ_TASK_ABORT: {
 444                struct asd_ascb *a, *b;
 445                u16 tc_abort;
 446                struct domain_device *failed_dev = NULL;
 447
 448                ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n",
 449                            __func__, dl->status_block[3]);
 450
 451                /*
 452                 * Find the task that caused the abort and abort it first.
 453                 * The sequencer won't put anything on the done list until
 454                 * that happens.
 455                 */
 456                tc_abort = *((u16*)(&dl->status_block[1]));
 457                tc_abort = le16_to_cpu(tc_abort);
 458
 459                list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
 460                        struct sas_task *task = a->uldd_task;
 461
 462                        if (a->tc_index != tc_abort)
 463                                continue;
 464
 465                        if (task) {
 466                                failed_dev = task->dev;
 467                                sas_task_abort(task);
 468                        } else {
 469                                ASD_DPRINTK("R_T_A for non TASK scb 0x%x\n",
 470                                            a->scb->header.opcode);
 471                        }
 472                        break;
 473                }
 474
 475                if (!failed_dev) {
 476                        ASD_DPRINTK("%s: Can't find task (tc=%d) to abort!\n",
 477                                    __func__, tc_abort);
 478                        goto out;
 479                }
 480
 481                /*
 482                 * Now abort everything else for that device (hba?) so
 483                 * that the EH will wake up and do something.
 484                 */
 485                list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
 486                        struct sas_task *task = a->uldd_task;
 487
 488                        if (task &&
 489                            task->dev == failed_dev &&
 490                            a->tc_index != tc_abort)
 491                                sas_task_abort(task);
 492                }
 493
 494                goto out;
 495        }
 496        case REQ_DEVICE_RESET: {
 497                struct asd_ascb *a;
 498                u16 conn_handle;
 499                unsigned long flags;
 500                struct sas_task *last_dev_task = NULL;
 501
 502                conn_handle = *((u16*)(&dl->status_block[1]));
 503                conn_handle = le16_to_cpu(conn_handle);
 504
 505                ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __func__,
 506                            dl->status_block[3]);
 507
 508                /* Find the last pending task for the device... */
 509                list_for_each_entry(a, &asd_ha->seq.pend_q, list) {
 510                        u16 x;
 511                        struct domain_device *dev;
 512                        struct sas_task *task = a->uldd_task;
 513
 514                        if (!task)
 515                                continue;
 516                        dev = task->dev;
 517
 518                        x = (unsigned long)dev->lldd_dev;
 519                        if (x == conn_handle)
 520                                last_dev_task = task;
 521                }
 522
 523                if (!last_dev_task) {
 524                        ASD_DPRINTK("%s: Device reset for idle device %d?\n",
 525                                    __func__, conn_handle);
 526                        goto out;
 527                }
 528
 529                /* ...and set the reset flag */
 530                spin_lock_irqsave(&last_dev_task->task_state_lock, flags);
 531                last_dev_task->task_state_flags |= SAS_TASK_NEED_DEV_RESET;
 532                spin_unlock_irqrestore(&last_dev_task->task_state_lock, flags);
 533
 534                /* Kill all pending tasks for the device */
 535                list_for_each_entry(a, &asd_ha->seq.pend_q, list) {
 536                        u16 x;
 537                        struct domain_device *dev;
 538                        struct sas_task *task = a->uldd_task;
 539
 540                        if (!task)
 541                                continue;
 542                        dev = task->dev;
 543
 544                        x = (unsigned long)dev->lldd_dev;
 545                        if (x == conn_handle)
 546                                sas_task_abort(task);
 547                }
 548
 549                goto out;
 550        }
 551        case SIGNAL_NCQ_ERROR:
 552                ASD_DPRINTK("%s: SIGNAL_NCQ_ERROR\n", __func__);
 553                goto out;
 554        case CLEAR_NCQ_ERROR:
 555                ASD_DPRINTK("%s: CLEAR_NCQ_ERROR\n", __func__);
 556                goto out;
 557        }
 558
 559        sb_opcode &= ~DL_PHY_MASK;
 560
 561        switch (sb_opcode) {
 562        case BYTES_DMAED:
 563                ASD_DPRINTK("%s: phy%d: BYTES_DMAED\n", __func__, phy_id);
 564                asd_bytes_dmaed_tasklet(ascb, dl, edb, phy_id);
 565                break;
 566        case PRIMITIVE_RECVD:
 567                ASD_DPRINTK("%s: phy%d: PRIMITIVE_RECVD\n", __func__,
 568                            phy_id);
 569                asd_primitive_rcvd_tasklet(ascb, dl, phy_id);
 570                break;
 571        case PHY_EVENT:
 572                ASD_DPRINTK("%s: phy%d: PHY_EVENT\n", __func__, phy_id);
 573                asd_phy_event_tasklet(ascb, dl);
 574                break;
 575        case LINK_RESET_ERROR:
 576                ASD_DPRINTK("%s: phy%d: LINK_RESET_ERROR\n", __func__,
 577                            phy_id);
 578                asd_link_reset_err_tasklet(ascb, dl, phy_id);
 579                break;
 580        case TIMER_EVENT:
 581                ASD_DPRINTK("%s: phy%d: TIMER_EVENT, lost dw sync\n",
 582                            __func__, phy_id);
 583                asd_turn_led(asd_ha, phy_id, 0);
 584                /* the device is gone */
 585                sas_phy_disconnected(sas_phy);
 586                asd_deform_port(asd_ha, phy);
 587                sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT);
 588                break;
 589        default:
 590                ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __func__,
 591                            phy_id, sb_opcode);
 592                ASD_DPRINTK("edb is 0x%x! dl->opcode is 0x%x\n",
 593                            edb, dl->opcode);
 594                ASD_DPRINTK("sb_opcode : 0x%x, phy_id: 0x%x\n",
 595                            sb_opcode, phy_id);
 596                ASD_DPRINTK("escb: vaddr: 0x%p, "
 597                            "dma_handle: 0x%llx, next: 0x%llx, "
 598                            "index:%d, opcode:0x%02x\n",
 599                            ascb->dma_scb.vaddr,
 600                            (unsigned long long)ascb->dma_scb.dma_handle,
 601                            (unsigned long long)
 602                            le64_to_cpu(ascb->scb->header.next_scb),
 603                            le16_to_cpu(ascb->scb->header.index),
 604                            ascb->scb->header.opcode);
 605
 606                break;
 607        }
 608out:
 609        asd_invalidate_edb(ascb, edb);
 610}
 611
 612int asd_init_post_escbs(struct asd_ha_struct *asd_ha)
 613{
 614        struct asd_seq_data *seq = &asd_ha->seq;
 615        int i;
 616
 617        for (i = 0; i < seq->num_escbs; i++)
 618                seq->escb_arr[i]->tasklet_complete = escb_tasklet_complete;
 619
 620        ASD_DPRINTK("posting %d escbs\n", i);
 621        return asd_post_escb_list(asd_ha, seq->escb_arr[0], seq->num_escbs);
 622}
 623
 624/* ---------- CONTROL PHY ---------- */
 625
 626#define CONTROL_PHY_STATUS (CURRENT_DEVICE_PRESENT | CURRENT_OOB_DONE   \
 627                            | CURRENT_SPINUP_HOLD | CURRENT_GTO_TIMEOUT \
 628                            | CURRENT_OOB_ERROR)
 629
 630/**
 631 * control_phy_tasklet_complete -- tasklet complete for CONTROL PHY ascb
 632 * @ascb: pointer to an ascb
 633 * @dl: pointer to the done list entry
 634 *
 635 * This function completes a CONTROL PHY scb and frees the ascb.
 636 * A note on LEDs:
 637 *  - an LED blinks if there is IO though it,
 638 *  - if a device is connected to the LED, it is lit,
 639 *  - if no device is connected to the LED, is is dimmed (off).
 640 */
 641static void control_phy_tasklet_complete(struct asd_ascb *ascb,
 642                                         struct done_list_struct *dl)
 643{
 644        struct asd_ha_struct *asd_ha = ascb->ha;
 645        struct scb *scb = ascb->scb;
 646        struct control_phy *control_phy = &scb->control_phy;
 647        u8 phy_id = control_phy->phy_id;
 648        struct asd_phy *phy = &ascb->ha->phys[phy_id];
 649
 650        u8 status     = dl->status_block[0];
 651        u8 oob_status = dl->status_block[1];
 652        u8 oob_mode   = dl->status_block[2];
 653        /* u8 oob_signals= dl->status_block[3]; */
 654
 655        if (status != 0) {
 656                ASD_DPRINTK("%s: phy%d status block opcode:0x%x\n",
 657                            __func__, phy_id, status);
 658                goto out;
 659        }
 660
 661        switch (control_phy->sub_func) {
 662        case DISABLE_PHY:
 663                asd_ha->hw_prof.enabled_phys &= ~(1 << phy_id);
 664                asd_turn_led(asd_ha, phy_id, 0);
 665                asd_control_led(asd_ha, phy_id, 0);
 666                ASD_DPRINTK("%s: disable phy%d\n", __func__, phy_id);
 667                break;
 668
 669        case ENABLE_PHY:
 670                asd_control_led(asd_ha, phy_id, 1);
 671                if (oob_status & CURRENT_OOB_DONE) {
 672                        asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
 673                        get_lrate_mode(phy, oob_mode);
 674                        asd_turn_led(asd_ha, phy_id, 1);
 675                        ASD_DPRINTK("%s: phy%d, lrate:0x%x, proto:0x%x\n",
 676                                    __func__, phy_id,phy->sas_phy.linkrate,
 677                                    phy->sas_phy.iproto);
 678                } else if (oob_status & CURRENT_SPINUP_HOLD) {
 679                        asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
 680                        asd_turn_led(asd_ha, phy_id, 1);
 681                        ASD_DPRINTK("%s: phy%d, spinup hold\n", __func__,
 682                                    phy_id);
 683                } else if (oob_status & CURRENT_ERR_MASK) {
 684                        asd_turn_led(asd_ha, phy_id, 0);
 685                        ASD_DPRINTK("%s: phy%d: error: oob status:0x%02x\n",
 686                                    __func__, phy_id, oob_status);
 687                } else if (oob_status & (CURRENT_HOT_PLUG_CNCT
 688                                         | CURRENT_DEVICE_PRESENT))  {
 689                        asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
 690                        asd_turn_led(asd_ha, phy_id, 1);
 691                        ASD_DPRINTK("%s: phy%d: hot plug or device present\n",
 692                                    __func__, phy_id);
 693                } else {
 694                        asd_ha->hw_prof.enabled_phys |= (1 << phy_id);
 695                        asd_turn_led(asd_ha, phy_id, 0);
 696                        ASD_DPRINTK("%s: phy%d: no device present: "
 697                                    "oob_status:0x%x\n",
 698                                    __func__, phy_id, oob_status);
 699                }
 700                break;
 701        case RELEASE_SPINUP_HOLD:
 702        case PHY_NO_OP:
 703        case EXECUTE_HARD_RESET:
 704                ASD_DPRINTK("%s: phy%d: sub_func:0x%x\n", __func__,
 705                            phy_id, control_phy->sub_func);
 706                /* XXX finish */
 707                break;
 708        default:
 709                ASD_DPRINTK("%s: phy%d: sub_func:0x%x?\n", __func__,
 710                            phy_id, control_phy->sub_func);
 711                break;
 712        }
 713out:
 714        asd_ascb_free(ascb);
 715}
 716
 717static void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd)
 718{
 719        /* disable all speeds, then enable defaults */
 720        *speed_mask = SAS_SPEED_60_DIS | SAS_SPEED_30_DIS | SAS_SPEED_15_DIS
 721                | SATA_SPEED_30_DIS | SATA_SPEED_15_DIS;
 722
 723        switch (pd->max_sas_lrate) {
 724        case SAS_LINK_RATE_6_0_GBPS:
 725                *speed_mask &= ~SAS_SPEED_60_DIS;
 726        default:
 727        case SAS_LINK_RATE_3_0_GBPS:
 728                *speed_mask &= ~SAS_SPEED_30_DIS;
 729        case SAS_LINK_RATE_1_5_GBPS:
 730                *speed_mask &= ~SAS_SPEED_15_DIS;
 731        }
 732
 733        switch (pd->min_sas_lrate) {
 734        case SAS_LINK_RATE_6_0_GBPS:
 735                *speed_mask |= SAS_SPEED_30_DIS;
 736        case SAS_LINK_RATE_3_0_GBPS:
 737                *speed_mask |= SAS_SPEED_15_DIS;
 738        default:
 739        case SAS_LINK_RATE_1_5_GBPS:
 740                /* nothing to do */
 741                ;
 742        }
 743
 744        switch (pd->max_sata_lrate) {
 745        case SAS_LINK_RATE_3_0_GBPS:
 746                *speed_mask &= ~SATA_SPEED_30_DIS;
 747        default:
 748        case SAS_LINK_RATE_1_5_GBPS:
 749                *speed_mask &= ~SATA_SPEED_15_DIS;
 750        }
 751
 752        switch (pd->min_sata_lrate) {
 753        case SAS_LINK_RATE_3_0_GBPS:
 754                *speed_mask |= SATA_SPEED_15_DIS;
 755        default:
 756        case SAS_LINK_RATE_1_5_GBPS:
 757                /* nothing to do */
 758                ;
 759        }
 760}
 761
 762/**
 763 * asd_build_control_phy -- build a CONTROL PHY SCB
 764 * @ascb: pointer to an ascb
 765 * @phy_id: phy id to control, integer
 766 * @subfunc: subfunction, what to actually to do the phy
 767 *
 768 * This function builds a CONTROL PHY scb.  No allocation of any kind
 769 * is performed. @ascb is allocated with the list function.
 770 * The caller can override the ascb->tasklet_complete to point
 771 * to its own callback function.  It must call asd_ascb_free()
 772 * at its tasklet complete function.
 773 * See the default implementation.
 774 */
 775void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc)
 776{
 777        struct asd_phy *phy = &ascb->ha->phys[phy_id];
 778        struct scb *scb = ascb->scb;
 779        struct control_phy *control_phy = &scb->control_phy;
 780
 781        scb->header.opcode = CONTROL_PHY;
 782        control_phy->phy_id = (u8) phy_id;
 783        control_phy->sub_func = subfunc;
 784
 785        switch (subfunc) {
 786        case EXECUTE_HARD_RESET:  /* 0x81 */
 787        case ENABLE_PHY:          /* 0x01 */
 788                /* decide hot plug delay */
 789                control_phy->hot_plug_delay = HOTPLUG_DELAY_TIMEOUT;
 790
 791                /* decide speed mask */
 792                set_speed_mask(&control_phy->speed_mask, phy->phy_desc);
 793
 794                /* initiator port settings are in the hi nibble */
 795                if (phy->sas_phy.role == PHY_ROLE_INITIATOR)
 796                        control_phy->port_type = SAS_PROTOCOL_ALL << 4;
 797                else if (phy->sas_phy.role == PHY_ROLE_TARGET)
 798                        control_phy->port_type = SAS_PROTOCOL_ALL;
 799                else
 800                        control_phy->port_type =
 801                                (SAS_PROTOCOL_ALL << 4) | SAS_PROTOCOL_ALL;
 802
 803                /* link reset retries, this should be nominal */
 804                control_phy->link_reset_retries = 10;
 805
 806        case RELEASE_SPINUP_HOLD: /* 0x02 */
 807                /* decide the func_mask */
 808                control_phy->func_mask = FUNCTION_MASK_DEFAULT;
 809                if (phy->phy_desc->flags & ASD_SATA_SPINUP_HOLD)
 810                        control_phy->func_mask &= ~SPINUP_HOLD_DIS;
 811                else
 812                        control_phy->func_mask |= SPINUP_HOLD_DIS;
 813        }
 814
 815        control_phy->conn_handle = cpu_to_le16(0xFFFF);
 816
 817        ascb->tasklet_complete = control_phy_tasklet_complete;
 818}
 819
 820/* ---------- INITIATE LINK ADM TASK ---------- */
 821
 822#if 0
 823
 824static void link_adm_tasklet_complete(struct asd_ascb *ascb,
 825                                      struct done_list_struct *dl)
 826{
 827        u8 opcode = dl->opcode;
 828        struct initiate_link_adm *link_adm = &ascb->scb->link_adm;
 829        u8 phy_id = link_adm->phy_id;
 830
 831        if (opcode != TC_NO_ERROR) {
 832                asd_printk("phy%d: link adm task 0x%x completed with error "
 833                           "0x%x\n", phy_id, link_adm->sub_func, opcode);
 834        }
 835        ASD_DPRINTK("phy%d: link adm task 0x%x: 0x%x\n",
 836                    phy_id, link_adm->sub_func, opcode);
 837
 838        asd_ascb_free(ascb);
 839}
 840
 841void asd_build_initiate_link_adm_task(struct asd_ascb *ascb, int phy_id,
 842                                      u8 subfunc)
 843{
 844        struct scb *scb = ascb->scb;
 845        struct initiate_link_adm *link_adm = &scb->link_adm;
 846
 847        scb->header.opcode = INITIATE_LINK_ADM_TASK;
 848
 849        link_adm->phy_id = phy_id;
 850        link_adm->sub_func = subfunc;
 851        link_adm->conn_handle = cpu_to_le16(0xFFFF);
 852
 853        ascb->tasklet_complete = link_adm_tasklet_complete;
 854}
 855
 856#endif  /*  0  */
 857
 858/* ---------- SCB timer ---------- */
 859
 860/**
 861 * asd_ascb_timedout -- called when a pending SCB's timer has expired
 862 * @data: unsigned long, a pointer to the ascb in question
 863 *
 864 * This is the default timeout function which does the most necessary.
 865 * Upper layers can implement their own timeout function, say to free
 866 * resources they have with this SCB, and then call this one at the
 867 * end of their timeout function.  To do this, one should initialize
 868 * the ascb->timer.{function, data, expires} prior to calling the post
 869 * funcion.  The timer is started by the post function.
 870 */
 871void asd_ascb_timedout(unsigned long data)
 872{
 873        struct asd_ascb *ascb = (void *) data;
 874        struct asd_seq_data *seq = &ascb->ha->seq;
 875        unsigned long flags;
 876
 877        ASD_DPRINTK("scb:0x%x timed out\n", ascb->scb->header.opcode);
 878
 879        spin_lock_irqsave(&seq->pend_q_lock, flags);
 880        seq->pending--;
 881        list_del_init(&ascb->list);
 882        spin_unlock_irqrestore(&seq->pend_q_lock, flags);
 883
 884        asd_ascb_free(ascb);
 885}
 886
 887/* ---------- CONTROL PHY ---------- */
 888
 889/* Given the spec value, return a driver value. */
 890static const int phy_func_table[] = {
 891        [PHY_FUNC_NOP]        = PHY_NO_OP,
 892        [PHY_FUNC_LINK_RESET] = ENABLE_PHY,
 893        [PHY_FUNC_HARD_RESET] = EXECUTE_HARD_RESET,
 894        [PHY_FUNC_DISABLE]    = DISABLE_PHY,
 895        [PHY_FUNC_RELEASE_SPINUP_HOLD] = RELEASE_SPINUP_HOLD,
 896};
 897
 898int asd_control_phy(struct asd_sas_phy *phy, enum phy_func func, void *arg)
 899{
 900        struct asd_ha_struct *asd_ha = phy->ha->lldd_ha;
 901        struct asd_phy_desc *pd = asd_ha->phys[phy->id].phy_desc;
 902        struct asd_ascb *ascb;
 903        struct sas_phy_linkrates *rates;
 904        int res = 1;
 905
 906        switch (func) {
 907        case PHY_FUNC_CLEAR_ERROR_LOG:
 908                return -ENOSYS;
 909        case PHY_FUNC_SET_LINK_RATE:
 910                rates = arg;
 911                if (rates->minimum_linkrate) {
 912                        pd->min_sas_lrate = rates->minimum_linkrate;
 913                        pd->min_sata_lrate = rates->minimum_linkrate;
 914                }
 915                if (rates->maximum_linkrate) {
 916                        pd->max_sas_lrate = rates->maximum_linkrate;
 917                        pd->max_sata_lrate = rates->maximum_linkrate;
 918                }
 919                func = PHY_FUNC_LINK_RESET;
 920                break;
 921        default:
 922                break;
 923        }
 924
 925        ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL);
 926        if (!ascb)
 927                return -ENOMEM;
 928
 929        asd_build_control_phy(ascb, phy->id, phy_func_table[func]);
 930        res = asd_post_ascb_list(asd_ha, ascb , 1);
 931        if (res)
 932                asd_ascb_free(ascb);
 933
 934        return res;
 935}
 936
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.