linux/drivers/scsi/libsas/sas_init.c
<<
>>
Prefs
   1/*
   2 * Serial Attached SCSI (SAS) Transport Layer initialization
   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 program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License as
  11 * published by the Free Software Foundation; either version 2 of the
  12 * License, or (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful, but
  15 * WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  22 * USA
  23 *
  24 */
  25
  26#include <linux/module.h>
  27#include <linux/slab.h>
  28#include <linux/init.h>
  29#include <linux/device.h>
  30#include <linux/spinlock.h>
  31#include <scsi/sas_ata.h>
  32#include <scsi/scsi_host.h>
  33#include <scsi/scsi_device.h>
  34#include <scsi/scsi_transport.h>
  35#include <scsi/scsi_transport_sas.h>
  36
  37#include "sas_internal.h"
  38
  39#include "../scsi_sas_internal.h"
  40
  41static struct kmem_cache *sas_task_cache;
  42
  43struct sas_task *sas_alloc_task(gfp_t flags)
  44{
  45        struct sas_task *task = kmem_cache_zalloc(sas_task_cache, flags);
  46
  47        if (task) {
  48                INIT_LIST_HEAD(&task->list);
  49                spin_lock_init(&task->task_state_lock);
  50                task->task_state_flags = SAS_TASK_STATE_PENDING;
  51        }
  52
  53        return task;
  54}
  55EXPORT_SYMBOL_GPL(sas_alloc_task);
  56
  57struct sas_task *sas_alloc_slow_task(gfp_t flags)
  58{
  59        struct sas_task *task = sas_alloc_task(flags);
  60        struct sas_task_slow *slow = kmalloc(sizeof(*slow), flags);
  61
  62        if (!task || !slow) {
  63                if (task)
  64                        kmem_cache_free(sas_task_cache, task);
  65                kfree(slow);
  66                return NULL;
  67        }
  68
  69        task->slow_task = slow;
  70        init_timer(&slow->timer);
  71        init_completion(&slow->completion);
  72
  73        return task;
  74}
  75EXPORT_SYMBOL_GPL(sas_alloc_slow_task);
  76
  77void sas_free_task(struct sas_task *task)
  78{
  79        if (task) {
  80                BUG_ON(!list_empty(&task->list));
  81                kfree(task->slow_task);
  82                kmem_cache_free(sas_task_cache, task);
  83        }
  84}
  85EXPORT_SYMBOL_GPL(sas_free_task);
  86
  87/*------------ SAS addr hash -----------*/
  88void sas_hash_addr(u8 *hashed, const u8 *sas_addr)
  89{
  90        const u32 poly = 0x00DB2777;
  91        u32     r = 0;
  92        int     i;
  93
  94        for (i = 0; i < 8; i++) {
  95                int b;
  96                for (b = 7; b >= 0; b--) {
  97                        r <<= 1;
  98                        if ((1 << b) & sas_addr[i]) {
  99                                if (!(r & 0x01000000))
 100                                        r ^= poly;
 101                        } else if (r & 0x01000000)
 102                                r ^= poly;
 103                }
 104        }
 105
 106        hashed[0] = (r >> 16) & 0xFF;
 107        hashed[1] = (r >> 8) & 0xFF ;
 108        hashed[2] = r & 0xFF;
 109}
 110
 111
 112/* ---------- HA events ---------- */
 113
 114void sas_hae_reset(struct work_struct *work)
 115{
 116        struct sas_ha_event *ev = to_sas_ha_event(work);
 117        struct sas_ha_struct *ha = ev->ha;
 118
 119        clear_bit(HAE_RESET, &ha->pending);
 120}
 121
 122int sas_register_ha(struct sas_ha_struct *sas_ha)
 123{
 124        int error = 0;
 125
 126        mutex_init(&sas_ha->disco_mutex);
 127        spin_lock_init(&sas_ha->phy_port_lock);
 128        sas_hash_addr(sas_ha->hashed_sas_addr, sas_ha->sas_addr);
 129
 130        if (sas_ha->lldd_queue_size == 0)
 131                sas_ha->lldd_queue_size = 1;
 132        else if (sas_ha->lldd_queue_size == -1)
 133                sas_ha->lldd_queue_size = 128; /* Sanity */
 134
 135        set_bit(SAS_HA_REGISTERED, &sas_ha->state);
 136        spin_lock_init(&sas_ha->lock);
 137        mutex_init(&sas_ha->drain_mutex);
 138        init_waitqueue_head(&sas_ha->eh_wait_q);
 139        INIT_LIST_HEAD(&sas_ha->defer_q);
 140        INIT_LIST_HEAD(&sas_ha->eh_dev_q);
 141
 142        error = sas_register_phys(sas_ha);
 143        if (error) {
 144                printk(KERN_NOTICE "couldn't register sas phys:%d\n", error);
 145                return error;
 146        }
 147
 148        error = sas_register_ports(sas_ha);
 149        if (error) {
 150                printk(KERN_NOTICE "couldn't register sas ports:%d\n", error);
 151                goto Undo_phys;
 152        }
 153
 154        error = sas_init_events(sas_ha);
 155        if (error) {
 156                printk(KERN_NOTICE "couldn't start event thread:%d\n", error);
 157                goto Undo_ports;
 158        }
 159
 160        if (sas_ha->lldd_max_execute_num > 1) {
 161                error = sas_init_queue(sas_ha);
 162                if (error) {
 163                        printk(KERN_NOTICE "couldn't start queue thread:%d, "
 164                               "running in direct mode\n", error);
 165                        sas_ha->lldd_max_execute_num = 1;
 166                }
 167        }
 168
 169        INIT_LIST_HEAD(&sas_ha->eh_done_q);
 170        INIT_LIST_HEAD(&sas_ha->eh_ata_q);
 171
 172        return 0;
 173
 174Undo_ports:
 175        sas_unregister_ports(sas_ha);
 176Undo_phys:
 177
 178        return error;
 179}
 180
 181static void sas_disable_events(struct sas_ha_struct *sas_ha)
 182{
 183        /* Set the state to unregistered to avoid further unchained
 184         * events to be queued, and flush any in-progress drainers
 185         */
 186        mutex_lock(&sas_ha->drain_mutex);
 187        spin_lock_irq(&sas_ha->lock);
 188        clear_bit(SAS_HA_REGISTERED, &sas_ha->state);
 189        spin_unlock_irq(&sas_ha->lock);
 190        __sas_drain_work(sas_ha);
 191        mutex_unlock(&sas_ha->drain_mutex);
 192}
 193
 194int sas_unregister_ha(struct sas_ha_struct *sas_ha)
 195{
 196        sas_disable_events(sas_ha);
 197        sas_unregister_ports(sas_ha);
 198
 199        /* flush unregistration work */
 200        mutex_lock(&sas_ha->drain_mutex);
 201        __sas_drain_work(sas_ha);
 202        mutex_unlock(&sas_ha->drain_mutex);
 203
 204        if (sas_ha->lldd_max_execute_num > 1) {
 205                sas_shutdown_queue(sas_ha);
 206                sas_ha->lldd_max_execute_num = 1;
 207        }
 208
 209        return 0;
 210}
 211
 212static int sas_get_linkerrors(struct sas_phy *phy)
 213{
 214        if (scsi_is_sas_phy_local(phy)) {
 215                struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
 216                struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
 217                struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
 218                struct sas_internal *i =
 219                        to_sas_internal(sas_ha->core.shost->transportt);
 220
 221                return i->dft->lldd_control_phy(asd_phy, PHY_FUNC_GET_EVENTS, NULL);
 222        }
 223
 224        return sas_smp_get_phy_events(phy);
 225}
 226
 227int sas_try_ata_reset(struct asd_sas_phy *asd_phy)
 228{
 229        struct domain_device *dev = NULL;
 230
 231        /* try to route user requested link resets through libata */
 232        if (asd_phy->port)
 233                dev = asd_phy->port->port_dev;
 234
 235        /* validate that dev has been probed */
 236        if (dev)
 237                dev = sas_find_dev_by_rphy(dev->rphy);
 238
 239        if (dev && dev_is_sata(dev)) {
 240                sas_ata_schedule_reset(dev);
 241                sas_ata_wait_eh(dev);
 242                return 0;
 243        }
 244
 245        return -ENODEV;
 246}
 247
 248/**
 249 * transport_sas_phy_reset - reset a phy and permit libata to manage the link
 250 *
 251 * phy reset request via sysfs in host workqueue context so we know we
 252 * can block on eh and safely traverse the domain_device topology
 253 */
 254static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset)
 255{
 256        enum phy_func reset_type;
 257
 258        if (hard_reset)
 259                reset_type = PHY_FUNC_HARD_RESET;
 260        else
 261                reset_type = PHY_FUNC_LINK_RESET;
 262
 263        if (scsi_is_sas_phy_local(phy)) {
 264                struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
 265                struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
 266                struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
 267                struct sas_internal *i =
 268                        to_sas_internal(sas_ha->core.shost->transportt);
 269
 270                if (!hard_reset && sas_try_ata_reset(asd_phy) == 0)
 271                        return 0;
 272                return i->dft->lldd_control_phy(asd_phy, reset_type, NULL);
 273        } else {
 274                struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
 275                struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
 276                struct domain_device *ata_dev = sas_ex_to_ata(ddev, phy->number);
 277
 278                if (ata_dev && !hard_reset) {
 279                        sas_ata_schedule_reset(ata_dev);
 280                        sas_ata_wait_eh(ata_dev);
 281                        return 0;
 282                } else
 283                        return sas_smp_phy_control(ddev, phy->number, reset_type, NULL);
 284        }
 285}
 286
 287static int sas_phy_enable(struct sas_phy *phy, int enable)
 288{
 289        int ret;
 290        enum phy_func cmd;
 291
 292        if (enable)
 293                cmd = PHY_FUNC_LINK_RESET;
 294        else
 295                cmd = PHY_FUNC_DISABLE;
 296
 297        if (scsi_is_sas_phy_local(phy)) {
 298                struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
 299                struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
 300                struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
 301                struct sas_internal *i =
 302                        to_sas_internal(sas_ha->core.shost->transportt);
 303
 304                if (enable)
 305                        ret = transport_sas_phy_reset(phy, 0);
 306                else
 307                        ret = i->dft->lldd_control_phy(asd_phy, cmd, NULL);
 308        } else {
 309                struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
 310                struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
 311
 312                if (enable)
 313                        ret = transport_sas_phy_reset(phy, 0);
 314                else
 315                        ret = sas_smp_phy_control(ddev, phy->number, cmd, NULL);
 316        }
 317        return ret;
 318}
 319
 320int sas_phy_reset(struct sas_phy *phy, int hard_reset)
 321{
 322        int ret;
 323        enum phy_func reset_type;
 324
 325        if (!phy->enabled)
 326                return -ENODEV;
 327
 328        if (hard_reset)
 329                reset_type = PHY_FUNC_HARD_RESET;
 330        else
 331                reset_type = PHY_FUNC_LINK_RESET;
 332
 333        if (scsi_is_sas_phy_local(phy)) {
 334                struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
 335                struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
 336                struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
 337                struct sas_internal *i =
 338                        to_sas_internal(sas_ha->core.shost->transportt);
 339
 340                ret = i->dft->lldd_control_phy(asd_phy, reset_type, NULL);
 341        } else {
 342                struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
 343                struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
 344                ret = sas_smp_phy_control(ddev, phy->number, reset_type, NULL);
 345        }
 346        return ret;
 347}
 348
 349int sas_set_phy_speed(struct sas_phy *phy,
 350                      struct sas_phy_linkrates *rates)
 351{
 352        int ret;
 353
 354        if ((rates->minimum_linkrate &&
 355             rates->minimum_linkrate > phy->maximum_linkrate) ||
 356            (rates->maximum_linkrate &&
 357             rates->maximum_linkrate < phy->minimum_linkrate))
 358                return -EINVAL;
 359
 360        if (rates->minimum_linkrate &&
 361            rates->minimum_linkrate < phy->minimum_linkrate_hw)
 362                rates->minimum_linkrate = phy->minimum_linkrate_hw;
 363
 364        if (rates->maximum_linkrate &&
 365            rates->maximum_linkrate > phy->maximum_linkrate_hw)
 366                rates->maximum_linkrate = phy->maximum_linkrate_hw;
 367
 368        if (scsi_is_sas_phy_local(phy)) {
 369                struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
 370                struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
 371                struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
 372                struct sas_internal *i =
 373                        to_sas_internal(sas_ha->core.shost->transportt);
 374
 375                ret = i->dft->lldd_control_phy(asd_phy, PHY_FUNC_SET_LINK_RATE,
 376                                               rates);
 377        } else {
 378                struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
 379                struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
 380                ret = sas_smp_phy_control(ddev, phy->number,
 381                                          PHY_FUNC_LINK_RESET, rates);
 382
 383        }
 384
 385        return ret;
 386}
 387
 388void sas_prep_resume_ha(struct sas_ha_struct *ha)
 389{
 390        int i;
 391
 392        set_bit(SAS_HA_REGISTERED, &ha->state);
 393
 394        /* clear out any stale link events/data from the suspension path */
 395        for (i = 0; i < ha->num_phys; i++) {
 396                struct asd_sas_phy *phy = ha->sas_phy[i];
 397
 398                memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
 399                phy->port_events_pending = 0;
 400                phy->phy_events_pending = 0;
 401                phy->frame_rcvd_size = 0;
 402        }
 403}
 404EXPORT_SYMBOL(sas_prep_resume_ha);
 405
 406static int phys_suspended(struct sas_ha_struct *ha)
 407{
 408        int i, rc = 0;
 409
 410        for (i = 0; i < ha->num_phys; i++) {
 411                struct asd_sas_phy *phy = ha->sas_phy[i];
 412
 413                if (phy->suspended)
 414                        rc++;
 415        }
 416
 417        return rc;
 418}
 419
 420void sas_resume_ha(struct sas_ha_struct *ha)
 421{
 422        const unsigned long tmo = msecs_to_jiffies(25000);
 423        int i;
 424
 425        /* deform ports on phys that did not resume
 426         * at this point we may be racing the phy coming back (as posted
 427         * by the lldd).  So we post the event and once we are in the
 428         * libsas context check that the phy remains suspended before
 429         * tearing it down.
 430         */
 431        i = phys_suspended(ha);
 432        if (i)
 433                dev_info(ha->dev, "waiting up to 25 seconds for %d phy%s to resume\n",
 434                         i, i > 1 ? "s" : "");
 435        wait_event_timeout(ha->eh_wait_q, phys_suspended(ha) == 0, tmo);
 436        for (i = 0; i < ha->num_phys; i++) {
 437                struct asd_sas_phy *phy = ha->sas_phy[i];
 438
 439                if (phy->suspended) {
 440                        dev_warn(&phy->phy->dev, "resume timeout\n");
 441                        sas_notify_phy_event(phy, PHYE_RESUME_TIMEOUT);
 442                }
 443        }
 444
 445        /* all phys are back up or timed out, turn on i/o so we can
 446         * flush out disks that did not return
 447         */
 448        scsi_unblock_requests(ha->core.shost);
 449        sas_drain_work(ha);
 450}
 451EXPORT_SYMBOL(sas_resume_ha);
 452
 453void sas_suspend_ha(struct sas_ha_struct *ha)
 454{
 455        int i;
 456
 457        sas_disable_events(ha);
 458        scsi_block_requests(ha->core.shost);
 459        for (i = 0; i < ha->num_phys; i++) {
 460                struct asd_sas_port *port = ha->sas_port[i];
 461
 462                sas_discover_event(port, DISCE_SUSPEND);
 463        }
 464
 465        /* flush suspend events while unregistered */
 466        mutex_lock(&ha->drain_mutex);
 467        __sas_drain_work(ha);
 468        mutex_unlock(&ha->drain_mutex);
 469}
 470EXPORT_SYMBOL(sas_suspend_ha);
 471
 472static void sas_phy_release(struct sas_phy *phy)
 473{
 474        kfree(phy->hostdata);
 475        phy->hostdata = NULL;
 476}
 477
 478static void phy_reset_work(struct work_struct *work)
 479{
 480        struct sas_phy_data *d = container_of(work, typeof(*d), reset_work.work);
 481
 482        d->reset_result = transport_sas_phy_reset(d->phy, d->hard_reset);
 483}
 484
 485static void phy_enable_work(struct work_struct *work)
 486{
 487        struct sas_phy_data *d = container_of(work, typeof(*d), enable_work.work);
 488
 489        d->enable_result = sas_phy_enable(d->phy, d->enable);
 490}
 491
 492static int sas_phy_setup(struct sas_phy *phy)
 493{
 494        struct sas_phy_data *d = kzalloc(sizeof(*d), GFP_KERNEL);
 495
 496        if (!d)
 497                return -ENOMEM;
 498
 499        mutex_init(&d->event_lock);
 500        INIT_SAS_WORK(&d->reset_work, phy_reset_work);
 501        INIT_SAS_WORK(&d->enable_work, phy_enable_work);
 502        d->phy = phy;
 503        phy->hostdata = d;
 504
 505        return 0;
 506}
 507
 508static int queue_phy_reset(struct sas_phy *phy, int hard_reset)
 509{
 510        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
 511        struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
 512        struct sas_phy_data *d = phy->hostdata;
 513        int rc;
 514
 515        if (!d)
 516                return -ENOMEM;
 517
 518        /* libsas workqueue coordinates ata-eh reset with discovery */
 519        mutex_lock(&d->event_lock);
 520        d->reset_result = 0;
 521        d->hard_reset = hard_reset;
 522
 523        spin_lock_irq(&ha->lock);
 524        sas_queue_work(ha, &d->reset_work);
 525        spin_unlock_irq(&ha->lock);
 526
 527        rc = sas_drain_work(ha);
 528        if (rc == 0)
 529                rc = d->reset_result;
 530        mutex_unlock(&d->event_lock);
 531
 532        return rc;
 533}
 534
 535static int queue_phy_enable(struct sas_phy *phy, int enable)
 536{
 537        struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
 538        struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
 539        struct sas_phy_data *d = phy->hostdata;
 540        int rc;
 541
 542        if (!d)
 543                return -ENOMEM;
 544
 545        /* libsas workqueue coordinates ata-eh reset with discovery */
 546        mutex_lock(&d->event_lock);
 547        d->enable_result = 0;
 548        d->enable = enable;
 549
 550        spin_lock_irq(&ha->lock);
 551        sas_queue_work(ha, &d->enable_work);
 552        spin_unlock_irq(&ha->lock);
 553
 554        rc = sas_drain_work(ha);
 555        if (rc == 0)
 556                rc = d->enable_result;
 557        mutex_unlock(&d->event_lock);
 558
 559        return rc;
 560}
 561
 562static struct sas_function_template sft = {
 563        .phy_enable = queue_phy_enable,
 564        .phy_reset = queue_phy_reset,
 565        .phy_setup = sas_phy_setup,
 566        .phy_release = sas_phy_release,
 567        .set_phy_speed = sas_set_phy_speed,
 568        .get_linkerrors = sas_get_linkerrors,
 569        .smp_handler = sas_smp_handler,
 570};
 571
 572struct scsi_transport_template *
 573sas_domain_attach_transport(struct sas_domain_function_template *dft)
 574{
 575        struct scsi_transport_template *stt = sas_attach_transport(&sft);
 576        struct sas_internal *i;
 577
 578        if (!stt)
 579                return stt;
 580
 581        i = to_sas_internal(stt);
 582        i->dft = dft;
 583        stt->create_work_queue = 1;
 584        stt->eh_timed_out = sas_scsi_timed_out;
 585        stt->eh_strategy_handler = sas_scsi_recover_host;
 586
 587        return stt;
 588}
 589EXPORT_SYMBOL_GPL(sas_domain_attach_transport);
 590
 591
 592void sas_domain_release_transport(struct scsi_transport_template *stt)
 593{
 594        sas_release_transport(stt);
 595}
 596EXPORT_SYMBOL_GPL(sas_domain_release_transport);
 597
 598/* ---------- SAS Class register/unregister ---------- */
 599
 600static int __init sas_class_init(void)
 601{
 602        sas_task_cache = KMEM_CACHE(sas_task, SLAB_HWCACHE_ALIGN);
 603        if (!sas_task_cache)
 604                return -ENOMEM;
 605
 606        return 0;
 607}
 608
 609static void __exit sas_class_exit(void)
 610{
 611        kmem_cache_destroy(sas_task_cache);
 612}
 613
 614MODULE_AUTHOR("Luben Tuikov <luben_tuikov@adaptec.com>");
 615MODULE_DESCRIPTION("SAS Transport Layer");
 616MODULE_LICENSE("GPL v2");
 617
 618module_init(sas_class_init);
 619module_exit(sas_class_exit);
 620
 621EXPORT_SYMBOL_GPL(sas_register_ha);
 622EXPORT_SYMBOL_GPL(sas_unregister_ha);
 623