~ubuntu-branches/ubuntu/karmic/linux-ec2/karmic

« back to all changes in this revision

Viewing changes to drivers/scsi/mpt2sas/mpt2sas_scsih.c

  • Committer: Bazaar Package Importer
  • Author(s): Tim Gardner, Tim Gardner, Upstream Kernel Changes
  • Date: 2009-09-28 22:15:20 UTC
  • Revision ID: james.westby@ubuntu.com-20090928221520-hih5h5376lcnjgnf
Tags: 2.6.31-300.4
[ Tim Gardner ]

* [Config] Disable Lenovo laptop config
* Rebase against master Ubuntu-2.6.31-11.37

[ Upstream Kernel Changes ]

* n_tty: honor opost flag for echoes
* n_tty: move echoctl check and clean up logic
  - LP: #438310

Show diffs side-by-side

added added

removed removed

Lines of Context:
103
103
};
104
104
 
105
105
 
106
 
#define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF)
107
106
/**
108
107
 * struct fw_event_work - firmware event struct
109
108
 * @list: link list framework
1502
1501
                        break;
1503
1502
                case MPI2_RAID_VOL_TYPE_RAID1E:
1504
1503
                        qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
1505
 
                        r_level = "RAID1E";
 
1504
                        if (ioc->manu_pg10.OEMIdentifier &&
 
1505
                            (ioc->manu_pg10.GenericFlags0 &
 
1506
                            MFG10_GF0_R10_DISPLAY) &&
 
1507
                            !(raid_device->num_pds % 2))
 
1508
                                r_level = "RAID10";
 
1509
                        else
 
1510
                                r_level = "RAID1E";
1506
1511
                        break;
1507
1512
                case MPI2_RAID_VOL_TYPE_RAID1:
1508
1513
                        qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
1786
1791
        u32 ioc_state;
1787
1792
        unsigned long timeleft;
1788
1793
        u8 VF_ID = 0;
1789
 
        unsigned long flags;
1790
 
 
1791
 
        spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
1792
 
        if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED ||
1793
 
            ioc->shost_recovery) {
1794
 
                spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
1794
 
 
1795
        if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) {
 
1796
                printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n",
 
1797
                    __func__, ioc->name);
 
1798
                return;
 
1799
        }
 
1800
 
 
1801
        if (ioc->shost_recovery) {
1795
1802
                printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
1796
1803
                    __func__, ioc->name);
1797
1804
                return;
1798
1805
        }
1799
 
        spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
1800
1806
 
1801
1807
        ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
1802
1808
        if (ioc_state & MPI2_DOORBELL_USED) {
2222
2228
                            MPT2SAS_INFO_FMT "SDEV_RUNNING: "
2223
2229
                            "handle(0x%04x)\n", ioc->name, handle));
2224
2230
                        sas_device_priv_data->block = 0;
2225
 
                        scsi_device_set_state(sdev, SDEV_RUNNING);
 
2231
                        scsi_internal_device_unblock(sdev);
2226
2232
                }
2227
2233
        }
2228
2234
}
2251
2257
                            MPT2SAS_INFO_FMT "SDEV_BLOCK: "
2252
2258
                            "handle(0x%04x)\n", ioc->name, handle));
2253
2259
                        sas_device_priv_data->block = 1;
2254
 
                        scsi_device_set_state(sdev, SDEV_BLOCK);
 
2260
                        scsi_internal_device_block(sdev);
2255
2261
                }
2256
2262
        }
2257
2263
}
2327
2333
        u16 handle;
2328
2334
        u16 reason_code;
2329
2335
        u8 phy_number;
 
2336
        u8 link_rate;
2330
2337
 
2331
2338
        for (i = 0; i < event_data->NumEntries; i++) {
2332
2339
                handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
2337
2344
                    MPI2_EVENT_SAS_TOPO_RC_MASK;
2338
2345
                if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
2339
2346
                        _scsih_block_io_device(ioc, handle);
 
2347
                if (reason_code == MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED) {
 
2348
                        link_rate = event_data->PHY[i].LinkRate >> 4;
 
2349
                        if (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)
 
2350
                                _scsih_ublock_io_device(ioc, handle);
 
2351
                }
2340
2352
        }
2341
2353
}
2342
2354
 
2405
2417
}
2406
2418
 
2407
2419
/**
2408
 
 * _scsih_queue_rescan - queue a topology rescan from user context
2409
 
 * @ioc: per adapter object
2410
 
 *
2411
 
 * Return nothing.
2412
 
 */
2413
 
static void
2414
 
_scsih_queue_rescan(struct MPT2SAS_ADAPTER *ioc)
2415
 
{
2416
 
        struct fw_event_work *fw_event;
2417
 
 
2418
 
        if (ioc->wait_for_port_enable_to_complete)
2419
 
                return;
2420
 
        fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
2421
 
        if (!fw_event)
2422
 
                return;
2423
 
        fw_event->event = MPT2SAS_RESCAN_AFTER_HOST_RESET;
2424
 
        fw_event->ioc = ioc;
2425
 
        _scsih_fw_event_add(ioc, fw_event);
2426
 
}
2427
 
 
2428
 
/**
2429
2420
 * _scsih_flush_running_cmds - completing outstanding commands.
2430
2421
 * @ioc: per adapter object
2431
2422
 *
2456
2447
}
2457
2448
 
2458
2449
/**
2459
 
 * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
2460
 
 * @ioc: per adapter object
2461
 
 * @reset_phase: phase
2462
 
 *
2463
 
 * The handler for doing any required cleanup or initialization.
2464
 
 *
2465
 
 * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
2466
 
 * MPT2_IOC_DONE_RESET
2467
 
 *
2468
 
 * Return nothing.
2469
 
 */
2470
 
void
2471
 
mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
2472
 
{
2473
 
        switch (reset_phase) {
2474
 
        case MPT2_IOC_PRE_RESET:
2475
 
                dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
2476
 
                    "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
2477
 
                _scsih_fw_event_off(ioc);
2478
 
                break;
2479
 
        case MPT2_IOC_AFTER_RESET:
2480
 
                dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
2481
 
                    "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
2482
 
                if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
2483
 
                        ioc->tm_cmds.status |= MPT2_CMD_RESET;
2484
 
                        mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
2485
 
                        complete(&ioc->tm_cmds.done);
2486
 
                }
2487
 
                _scsih_fw_event_on(ioc);
2488
 
                _scsih_flush_running_cmds(ioc);
2489
 
                break;
2490
 
        case MPT2_IOC_DONE_RESET:
2491
 
                dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
2492
 
                    "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
2493
 
                _scsih_queue_rescan(ioc);
2494
 
                break;
2495
 
        }
2496
 
}
2497
 
 
2498
 
/**
2499
2450
 * _scsih_setup_eedp - setup MPI request for EEDP transfer
2500
2451
 * @scmd: pointer to scsi command object
2501
2452
 * @mpi_request: pointer to the SCSI_IO reqest message frame
2615
2566
        Mpi2SCSIIORequest_t *mpi_request;
2616
2567
        u32 mpi_control;
2617
2568
        u16 smid;
2618
 
        unsigned long flags;
2619
2569
 
2620
2570
        scmd->scsi_done = done;
2621
2571
        sas_device_priv_data = scmd->device->hostdata;
2634
2584
        }
2635
2585
 
2636
2586
        /* see if we are busy with task managment stuff */
2637
 
        spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
2638
 
        if (sas_target_priv_data->tm_busy ||
2639
 
            ioc->shost_recovery || ioc->ioc_link_reset_in_progress) {
2640
 
                spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
2587
        if (sas_target_priv_data->tm_busy)
 
2588
                return SCSI_MLQUEUE_DEVICE_BUSY;
 
2589
        else if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
2641
2590
                return SCSI_MLQUEUE_HOST_BUSY;
2642
 
        }
2643
 
        spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
2644
2591
 
2645
2592
        if (scmd->sc_data_direction == DMA_FROM_DEVICE)
2646
2593
                mpi_control = MPI2_SCSIIO_CONTROL_READ;
3436
3383
        if (!handle)
3437
3384
                return -1;
3438
3385
 
 
3386
        if (ioc->shost_recovery)
 
3387
                return -1;
 
3388
 
3439
3389
        if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
3440
3390
            MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
3441
3391
                printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
3572
3522
        struct _sas_node *sas_expander;
3573
3523
        unsigned long flags;
3574
3524
 
 
3525
        if (ioc->shost_recovery)
 
3526
                return;
 
3527
 
3575
3528
        spin_lock_irqsave(&ioc->sas_node_lock, flags);
3576
3529
        sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, handle);
3577
3530
        spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
3743
3696
                mutex_unlock(&ioc->tm_cmds.mutex);
3744
3697
                dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset "
3745
3698
                    "done: handle(0x%04x)\n", ioc->name, device_handle));
 
3699
                if (ioc->shost_recovery)
 
3700
                        goto out;
3746
3701
        }
3747
3702
 
3748
3703
        /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */
3765
3720
            le32_to_cpu(mpi_reply.IOCLogInfo)));
3766
3721
 
3767
3722
 out:
 
3723
 
 
3724
        _scsih_ublock_io_device(ioc, handle);
 
3725
 
3768
3726
        mpt2sas_transport_port_remove(ioc, sas_device->sas_address,
3769
3727
            sas_device->parent_handle);
3770
3728
 
3908
3866
                            "expander event\n", ioc->name));
3909
3867
                        return;
3910
3868
                }
 
3869
                if (ioc->shost_recovery)
 
3870
                        return;
3911
3871
                if (event_data->PHY[i].PhyStatus &
3912
3872
                    MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT)
3913
3873
                        continue;
3942
3902
                                                   link_rate_);
3943
3903
                                }
3944
3904
                        }
3945
 
                        if (reason_code == MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED) {
3946
 
                                if (link_rate_ >= MPI2_SAS_NEG_LINK_RATE_1_5)
3947
 
                                        _scsih_ublock_io_device(ioc, handle);
3948
 
                        }
3949
3905
                        if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED) {
3950
3906
                                if (link_rate_ < MPI2_SAS_NEG_LINK_RATE_1_5)
3951
3907
                                        break;
5156
5112
_scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc)
5157
5113
{
5158
5114
        struct _sas_device *sas_device, *sas_device_next;
5159
 
        struct _sas_node *sas_expander, *sas_expander_next;
 
5115
        struct _sas_node *sas_expander;
5160
5116
        struct _raid_device *raid_device, *raid_device_next;
5161
 
        unsigned long flags;
5162
 
 
5163
 
        _scsih_search_responding_sas_devices(ioc);
5164
 
        _scsih_search_responding_raid_devices(ioc);
5165
 
        _scsih_search_responding_expanders(ioc);
5166
 
 
5167
 
        spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
5168
 
        ioc->shost_recovery = 0;
5169
 
        if (ioc->shost->shost_state == SHOST_RECOVERY) {
5170
 
                printk(MPT2SAS_INFO_FMT "putting controller into "
5171
 
                    "SHOST_RUNNING\n", ioc->name);
5172
 
                scsi_host_set_state(ioc->shost, SHOST_RUNNING);
5173
 
        }
5174
 
        spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 
5117
 
5175
5118
 
5176
5119
        list_for_each_entry_safe(sas_device, sas_device_next,
5177
5120
            &ioc->sas_device_list, list) {
5207
5150
                _scsih_raid_device_remove(ioc, raid_device);
5208
5151
        }
5209
5152
 
5210
 
        list_for_each_entry_safe(sas_expander, sas_expander_next,
5211
 
            &ioc->sas_expander_list, list) {
 
5153
 retry_expander_search:
 
5154
        sas_expander = NULL;
 
5155
        list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
5212
5156
                if (sas_expander->responding) {
5213
5157
                        sas_expander->responding = 0;
5214
5158
                        continue;
5215
5159
                }
5216
 
                printk("\tremoving expander: handle(0x%04x), "
5217
 
                    " sas_addr(0x%016llx)\n", sas_expander->handle,
5218
 
                    (unsigned long long)sas_expander->sas_address);
5219
5160
                _scsih_expander_remove(ioc, sas_expander->handle);
 
5161
                goto retry_expander_search;
 
5162
        }
 
5163
}
 
5164
 
 
5165
/**
 
5166
 * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
 
5167
 * @ioc: per adapter object
 
5168
 * @reset_phase: phase
 
5169
 *
 
5170
 * The handler for doing any required cleanup or initialization.
 
5171
 *
 
5172
 * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
 
5173
 * MPT2_IOC_DONE_RESET
 
5174
 *
 
5175
 * Return nothing.
 
5176
 */
 
5177
void
 
5178
mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
 
5179
{
 
5180
        switch (reset_phase) {
 
5181
        case MPT2_IOC_PRE_RESET:
 
5182
                dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
 
5183
                    "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
 
5184
                _scsih_fw_event_off(ioc);
 
5185
                break;
 
5186
        case MPT2_IOC_AFTER_RESET:
 
5187
                dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
 
5188
                    "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
 
5189
                if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
 
5190
                        ioc->tm_cmds.status |= MPT2_CMD_RESET;
 
5191
                        mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
 
5192
                        complete(&ioc->tm_cmds.done);
 
5193
                }
 
5194
                _scsih_fw_event_on(ioc);
 
5195
                _scsih_flush_running_cmds(ioc);
 
5196
                break;
 
5197
        case MPT2_IOC_DONE_RESET:
 
5198
                dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
 
5199
                    "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
 
5200
                _scsih_sas_host_refresh(ioc, 0);
 
5201
                _scsih_search_responding_sas_devices(ioc);
 
5202
                _scsih_search_responding_raid_devices(ioc);
 
5203
                _scsih_search_responding_expanders(ioc);
 
5204
                break;
 
5205
        case MPT2_IOC_RUNNING:
 
5206
                dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
 
5207
                    "MPT2_IOC_RUNNING\n", ioc->name, __func__));
 
5208
                _scsih_remove_unresponding_devices(ioc);
 
5209
                break;
5220
5210
        }
5221
5211
}
5222
5212
 
5236
5226
        unsigned long flags;
5237
5227
        struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
5238
5228
 
5239
 
        /* This is invoked by calling _scsih_queue_rescan(). */
5240
 
        if (fw_event->event == MPT2SAS_RESCAN_AFTER_HOST_RESET) {
5241
 
                _scsih_fw_event_free(ioc, fw_event);
5242
 
                _scsih_sas_host_refresh(ioc, 1);
5243
 
                _scsih_remove_unresponding_devices(ioc);
5244
 
                return;
5245
 
        }
5246
 
 
5247
5229
        /* the queue is being flushed so ignore this event */
5248
5230
        spin_lock_irqsave(&ioc->fw_event_lock, flags);
5249
5231
        if (ioc->fw_events_off || ioc->remove_host) {
5253
5235
        }
5254
5236
        spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
5255
5237
 
5256
 
        spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
5257
5238
        if (ioc->shost_recovery) {
5258
 
                spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
5259
5239
                _scsih_fw_event_requeue(ioc, fw_event, 1000);
5260
5240
                return;
5261
5241
        }
5262
 
        spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
5263
5242
 
5264
5243
        switch (fw_event->event) {
5265
5244
        case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
5461
5440
                        if (!sas_device)
5462
5441
                                continue;
5463
5442
                        _scsih_remove_device(ioc, sas_device->handle);
 
5443
                        if (ioc->shost_recovery)
 
5444
                                return;
5464
5445
                        goto retry_device_search;
5465
5446
                }
5466
5447
        }
5482
5463
                        if (!expander_sibling)
5483
5464
                                continue;
5484
5465
                        _scsih_expander_remove(ioc, expander_sibling->handle);
 
5466
                        if (ioc->shost_recovery)
 
5467
                                return;
5485
5468
                        goto retry_expander_search;
5486
5469
                }
5487
5470
        }