diff options
author | Kashyap, Desai <kashyap.desai@lsi.com> | 2009-12-16 08:24:42 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-02-08 19:19:41 -0500 |
commit | f7c95ef02b564d9984c0655c9659791b1dd5d7ad (patch) | |
tree | 40d9c4457ad24d639578c5734016dfaec4fdc69b /drivers/scsi/mpt2sas/mpt2sas_scsih.c | |
parent | 22c88425e03e8476176375ab0457c88ff3a5b68c (diff) |
[SCSI] mpt2sas: Added raid transport support
Adding support for raid transport layer. This will provide sysfs attributes
containing raid level, state, and resync rate.
MPT2SAS module will select RAID_ATTRS.
Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
Reviewed-by: Eric Moore <eric.moore@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_scsih.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 190 |
1 files changed, 186 insertions, 4 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index cd551768bfbf..ca984cbc8e2f 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <linux/delay.h> | 52 | #include <linux/delay.h> |
53 | #include <linux/pci.h> | 53 | #include <linux/pci.h> |
54 | #include <linux/interrupt.h> | 54 | #include <linux/interrupt.h> |
55 | #include <linux/raid_class.h> | ||
55 | 56 | ||
56 | #include "mpt2sas_base.h" | 57 | #include "mpt2sas_base.h" |
57 | 58 | ||
@@ -133,6 +134,9 @@ struct fw_event_work { | |||
133 | void *event_data; | 134 | void *event_data; |
134 | }; | 135 | }; |
135 | 136 | ||
137 | /* raid transport support */ | ||
138 | static struct raid_template *mpt2sas_raid_template; | ||
139 | |||
136 | /** | 140 | /** |
137 | * struct _scsi_io_transfer - scsi io transfer | 141 | * struct _scsi_io_transfer - scsi io transfer |
138 | * @handle: sas device handle (assigned by firmware) | 142 | * @handle: sas device handle (assigned by firmware) |
@@ -1419,6 +1423,140 @@ _scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc, | |||
1419 | } | 1423 | } |
1420 | 1424 | ||
1421 | /** | 1425 | /** |
1426 | * _scsih_is_raid - return boolean indicating device is raid volume | ||
1427 | * @dev the device struct object | ||
1428 | */ | ||
1429 | static int | ||
1430 | _scsih_is_raid(struct device *dev) | ||
1431 | { | ||
1432 | struct scsi_device *sdev = to_scsi_device(dev); | ||
1433 | |||
1434 | return (sdev->channel == RAID_CHANNEL) ? 1 : 0; | ||
1435 | } | ||
1436 | |||
1437 | /** | ||
1438 | * _scsih_get_resync - get raid volume resync percent complete | ||
1439 | * @dev the device struct object | ||
1440 | */ | ||
1441 | static void | ||
1442 | _scsih_get_resync(struct device *dev) | ||
1443 | { | ||
1444 | struct scsi_device *sdev = to_scsi_device(dev); | ||
1445 | struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host); | ||
1446 | static struct _raid_device *raid_device; | ||
1447 | unsigned long flags; | ||
1448 | Mpi2RaidVolPage0_t vol_pg0; | ||
1449 | Mpi2ConfigReply_t mpi_reply; | ||
1450 | u32 volume_status_flags; | ||
1451 | u8 percent_complete = 0; | ||
1452 | |||
1453 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
1454 | raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id, | ||
1455 | sdev->channel); | ||
1456 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
1457 | |||
1458 | if (!raid_device) | ||
1459 | goto out; | ||
1460 | |||
1461 | if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0, | ||
1462 | MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, | ||
1463 | sizeof(Mpi2RaidVolPage0_t))) { | ||
1464 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
1465 | ioc->name, __FILE__, __LINE__, __func__); | ||
1466 | goto out; | ||
1467 | } | ||
1468 | |||
1469 | volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags); | ||
1470 | if (volume_status_flags & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) | ||
1471 | percent_complete = raid_device->percent_complete; | ||
1472 | out: | ||
1473 | raid_set_resync(mpt2sas_raid_template, dev, percent_complete); | ||
1474 | } | ||
1475 | |||
1476 | /** | ||
1477 | * _scsih_get_state - get raid volume level | ||
1478 | * @dev the device struct object | ||
1479 | */ | ||
1480 | static void | ||
1481 | _scsih_get_state(struct device *dev) | ||
1482 | { | ||
1483 | struct scsi_device *sdev = to_scsi_device(dev); | ||
1484 | struct MPT2SAS_ADAPTER *ioc = shost_priv(sdev->host); | ||
1485 | static struct _raid_device *raid_device; | ||
1486 | unsigned long flags; | ||
1487 | Mpi2RaidVolPage0_t vol_pg0; | ||
1488 | Mpi2ConfigReply_t mpi_reply; | ||
1489 | u32 volstate; | ||
1490 | enum raid_state state = RAID_STATE_UNKNOWN; | ||
1491 | |||
1492 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
1493 | raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id, | ||
1494 | sdev->channel); | ||
1495 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
1496 | |||
1497 | if (!raid_device) | ||
1498 | goto out; | ||
1499 | |||
1500 | if (mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0, | ||
1501 | MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, | ||
1502 | sizeof(Mpi2RaidVolPage0_t))) { | ||
1503 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | ||
1504 | ioc->name, __FILE__, __LINE__, __func__); | ||
1505 | goto out; | ||
1506 | } | ||
1507 | |||
1508 | volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags); | ||
1509 | if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) { | ||
1510 | state = RAID_STATE_RESYNCING; | ||
1511 | goto out; | ||
1512 | } | ||
1513 | |||
1514 | switch (vol_pg0.VolumeState) { | ||
1515 | case MPI2_RAID_VOL_STATE_OPTIMAL: | ||
1516 | case MPI2_RAID_VOL_STATE_ONLINE: | ||
1517 | state = RAID_STATE_ACTIVE; | ||
1518 | break; | ||
1519 | case MPI2_RAID_VOL_STATE_DEGRADED: | ||
1520 | state = RAID_STATE_DEGRADED; | ||
1521 | break; | ||
1522 | case MPI2_RAID_VOL_STATE_FAILED: | ||
1523 | case MPI2_RAID_VOL_STATE_MISSING: | ||
1524 | state = RAID_STATE_OFFLINE; | ||
1525 | break; | ||
1526 | } | ||
1527 | out: | ||
1528 | raid_set_state(mpt2sas_raid_template, dev, state); | ||
1529 | } | ||
1530 | |||
1531 | /** | ||
1532 | * _scsih_set_level - set raid level | ||
1533 | * @sdev: scsi device struct | ||
1534 | * @raid_device: raid_device object | ||
1535 | */ | ||
1536 | static void | ||
1537 | _scsih_set_level(struct scsi_device *sdev, struct _raid_device *raid_device) | ||
1538 | { | ||
1539 | enum raid_level level = RAID_LEVEL_UNKNOWN; | ||
1540 | |||
1541 | switch (raid_device->volume_type) { | ||
1542 | case MPI2_RAID_VOL_TYPE_RAID0: | ||
1543 | level = RAID_LEVEL_0; | ||
1544 | break; | ||
1545 | case MPI2_RAID_VOL_TYPE_RAID10: | ||
1546 | level = RAID_LEVEL_10; | ||
1547 | break; | ||
1548 | case MPI2_RAID_VOL_TYPE_RAID1E: | ||
1549 | level = RAID_LEVEL_1E; | ||
1550 | break; | ||
1551 | case MPI2_RAID_VOL_TYPE_RAID1: | ||
1552 | level = RAID_LEVEL_1; | ||
1553 | break; | ||
1554 | } | ||
1555 | |||
1556 | raid_set_level(mpt2sas_raid_template, &sdev->sdev_gendev, level); | ||
1557 | } | ||
1558 | |||
1559 | /** | ||
1422 | * _scsih_get_volume_capabilities - volume capabilities | 1560 | * _scsih_get_volume_capabilities - volume capabilities |
1423 | * @ioc: per adapter object | 1561 | * @ioc: per adapter object |
1424 | * @sas_device: the raid_device object | 1562 | * @sas_device: the raid_device object |
@@ -1574,6 +1712,8 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
1574 | (unsigned long long)raid_device->wwid, | 1712 | (unsigned long long)raid_device->wwid, |
1575 | raid_device->num_pds, ds); | 1713 | raid_device->num_pds, ds); |
1576 | _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); | 1714 | _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); |
1715 | /* raid transport support */ | ||
1716 | _scsih_set_level(sdev, raid_device); | ||
1577 | return 0; | 1717 | return 0; |
1578 | } | 1718 | } |
1579 | 1719 | ||
@@ -5170,11 +5310,33 @@ static void | |||
5170 | _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, | 5310 | _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, |
5171 | struct fw_event_work *fw_event) | 5311 | struct fw_event_work *fw_event) |
5172 | { | 5312 | { |
5313 | Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data; | ||
5314 | static struct _raid_device *raid_device; | ||
5315 | unsigned long flags; | ||
5316 | u16 handle; | ||
5317 | |||
5173 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 5318 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
5174 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 5319 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) |
5175 | _scsih_sas_ir_operation_status_event_debug(ioc, | 5320 | _scsih_sas_ir_operation_status_event_debug(ioc, |
5176 | fw_event->event_data); | 5321 | event_data); |
5177 | #endif | 5322 | #endif |
5323 | |||
5324 | /* code added for raid transport support */ | ||
5325 | if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) { | ||
5326 | |||
5327 | handle = le16_to_cpu(event_data->VolDevHandle); | ||
5328 | |||
5329 | spin_lock_irqsave(&ioc->raid_device_lock, flags); | ||
5330 | raid_device = _scsih_raid_device_find_by_handle(ioc, handle); | ||
5331 | spin_unlock_irqrestore(&ioc->raid_device_lock, flags); | ||
5332 | |||
5333 | if (!raid_device) | ||
5334 | return; | ||
5335 | |||
5336 | if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) | ||
5337 | raid_device->percent_complete = | ||
5338 | event_data->PercentComplete; | ||
5339 | } | ||
5178 | } | 5340 | } |
5179 | 5341 | ||
5180 | /** | 5342 | /** |
@@ -6390,6 +6552,13 @@ static struct pci_driver scsih_driver = { | |||
6390 | #endif | 6552 | #endif |
6391 | }; | 6553 | }; |
6392 | 6554 | ||
6555 | /* raid transport support */ | ||
6556 | static struct raid_function_template mpt2sas_raid_functions = { | ||
6557 | .cookie = &scsih_driver_template, | ||
6558 | .is_raid = _scsih_is_raid, | ||
6559 | .get_resync = _scsih_get_resync, | ||
6560 | .get_state = _scsih_get_state, | ||
6561 | }; | ||
6393 | 6562 | ||
6394 | /** | 6563 | /** |
6395 | * _scsih_init - main entry point for this driver. | 6564 | * _scsih_init - main entry point for this driver. |
@@ -6409,6 +6578,12 @@ _scsih_init(void) | |||
6409 | sas_attach_transport(&mpt2sas_transport_functions); | 6578 | sas_attach_transport(&mpt2sas_transport_functions); |
6410 | if (!mpt2sas_transport_template) | 6579 | if (!mpt2sas_transport_template) |
6411 | return -ENODEV; | 6580 | return -ENODEV; |
6581 | /* raid transport support */ | ||
6582 | mpt2sas_raid_template = raid_class_attach(&mpt2sas_raid_functions); | ||
6583 | if (!mpt2sas_raid_template) { | ||
6584 | sas_release_transport(mpt2sas_transport_template); | ||
6585 | return -ENODEV; | ||
6586 | } | ||
6412 | 6587 | ||
6413 | mpt2sas_base_initialize_callback_handler(); | 6588 | mpt2sas_base_initialize_callback_handler(); |
6414 | 6589 | ||
@@ -6443,8 +6618,11 @@ _scsih_init(void) | |||
6443 | mpt2sas_ctl_init(); | 6618 | mpt2sas_ctl_init(); |
6444 | 6619 | ||
6445 | error = pci_register_driver(&scsih_driver); | 6620 | error = pci_register_driver(&scsih_driver); |
6446 | if (error) | 6621 | if (error) { |
6622 | /* raid transport support */ | ||
6623 | raid_class_release(mpt2sas_raid_template); | ||
6447 | sas_release_transport(mpt2sas_transport_template); | 6624 | sas_release_transport(mpt2sas_transport_template); |
6625 | } | ||
6448 | 6626 | ||
6449 | return error; | 6627 | return error; |
6450 | } | 6628 | } |
@@ -6462,7 +6640,8 @@ _scsih_exit(void) | |||
6462 | 6640 | ||
6463 | pci_unregister_driver(&scsih_driver); | 6641 | pci_unregister_driver(&scsih_driver); |
6464 | 6642 | ||
6465 | sas_release_transport(mpt2sas_transport_template); | 6643 | mpt2sas_ctl_exit(); |
6644 | |||
6466 | mpt2sas_base_release_callback_handler(scsi_io_cb_idx); | 6645 | mpt2sas_base_release_callback_handler(scsi_io_cb_idx); |
6467 | mpt2sas_base_release_callback_handler(tm_cb_idx); | 6646 | mpt2sas_base_release_callback_handler(tm_cb_idx); |
6468 | mpt2sas_base_release_callback_handler(base_cb_idx); | 6647 | mpt2sas_base_release_callback_handler(base_cb_idx); |
@@ -6474,7 +6653,10 @@ _scsih_exit(void) | |||
6474 | mpt2sas_base_release_callback_handler(tm_tr_cb_idx); | 6653 | mpt2sas_base_release_callback_handler(tm_tr_cb_idx); |
6475 | mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx); | 6654 | mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx); |
6476 | 6655 | ||
6477 | mpt2sas_ctl_exit(); | 6656 | /* raid transport support */ |
6657 | raid_class_release(mpt2sas_raid_template); | ||
6658 | sas_release_transport(mpt2sas_transport_template); | ||
6659 | |||
6478 | } | 6660 | } |
6479 | 6661 | ||
6480 | module_init(_scsih_init); | 6662 | module_init(_scsih_init); |