diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 16:44:18 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 16:44:18 -0700 |
commit | ec7ae517537ae5c7b0b2cd7f562dfa3e7a05b954 (patch) | |
tree | e6b0c64a51a7c0aa0efd09d4f7a80872e3b1657a /drivers/scsi/libsas/sas_host_smp.c | |
parent | 97d2eb13a019ec09cc1a7ea2d3705c0b117b3c0d (diff) | |
parent | 590134fa78fbdbe5fea78c7ae0b2c3364bc9572f (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (204 commits)
[SCSI] qla4xxx: export address/port of connection (fix udev disk names)
[SCSI] ipr: Fix BUG on adapter dump timeout
[SCSI] megaraid_sas: Fix instance access in megasas_reset_timer
[SCSI] hpsa: change confusing message to be more clear
[SCSI] iscsi class: fix vlan configuration
[SCSI] qla4xxx: fix data alignment and use nl helpers
[SCSI] iscsi class: fix link local mispelling
[SCSI] iscsi class: Replace iscsi_get_next_target_id with IDA
[SCSI] aacraid: use lower snprintf() limit
[SCSI] lpfc 8.3.27: Change driver version to 8.3.27
[SCSI] lpfc 8.3.27: T10 additions for SLI4
[SCSI] lpfc 8.3.27: Fix queue allocation failure recovery
[SCSI] lpfc 8.3.27: Change algorithm for getting physical port name
[SCSI] lpfc 8.3.27: Changed worst case mailbox timeout
[SCSI] lpfc 8.3.27: Miscellanous logic and interface fixes
[SCSI] megaraid_sas: Changelog and version update
[SCSI] megaraid_sas: Add driver workaround for PERC5/1068 kdump kernel panic
[SCSI] megaraid_sas: Add multiple MSI-X vector/multiple reply queue support
[SCSI] megaraid_sas: Add support for MegaRAID 9360/9380 12GB/s controllers
[SCSI] megaraid_sas: Clear FUSION_IN_RESET before enabling interrupts
...
Diffstat (limited to 'drivers/scsi/libsas/sas_host_smp.c')
-rw-r--r-- | drivers/scsi/libsas/sas_host_smp.c | 103 |
1 files changed, 101 insertions, 2 deletions
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c index 04ad8dd1a74..e1aa17840c5 100644 --- a/drivers/scsi/libsas/sas_host_smp.c +++ b/drivers/scsi/libsas/sas_host_smp.c @@ -51,6 +51,91 @@ static void sas_host_smp_discover(struct sas_ha_struct *sas_ha, u8 *resp_data, resp_data[15] = rphy->identify.target_port_protocols; } +/** + * to_sas_gpio_gp_bit - given the gpio frame data find the byte/bit position of 'od' + * @od: od bit to find + * @data: incoming bitstream (from frame) + * @index: requested data register index (from frame) + * @count: total number of registers in the bitstream (from frame) + * @bit: bit position of 'od' in the returned byte + * + * returns NULL if 'od' is not in 'data' + * + * From SFF-8485 v0.7: + * "In GPIO_TX[1], bit 0 of byte 3 contains the first bit (i.e., OD0.0) + * and bit 7 of byte 0 contains the 32nd bit (i.e., OD10.1). + * + * In GPIO_TX[2], bit 0 of byte 3 contains the 33rd bit (i.e., OD10.2) + * and bit 7 of byte 0 contains the 64th bit (i.e., OD21.0)." + * + * The general-purpose (raw-bitstream) RX registers have the same layout + * although 'od' is renamed 'id' for 'input data'. + * + * SFF-8489 defines the behavior of the LEDs in response to the 'od' values. + */ +static u8 *to_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count, u8 *bit) +{ + unsigned int reg; + u8 byte; + + /* gp registers start at index 1 */ + if (index == 0) + return NULL; + + index--; /* make index 0-based */ + if (od < index * 32) + return NULL; + + od -= index * 32; + reg = od >> 5; + + if (reg >= count) + return NULL; + + od &= (1 << 5) - 1; + byte = 3 - (od >> 3); + *bit = od & ((1 << 3) - 1); + + return &data[reg * 4 + byte]; +} + +int try_test_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count) +{ + u8 *byte; + u8 bit; + + byte = to_sas_gpio_gp_bit(od, data, index, count, &bit); + if (!byte) + return -1; + + return (*byte >> bit) & 1; +} +EXPORT_SYMBOL(try_test_sas_gpio_gp_bit); + +static int sas_host_smp_write_gpio(struct sas_ha_struct *sas_ha, u8 *resp_data, + u8 reg_type, u8 reg_index, u8 reg_count, + u8 *req_data) +{ + struct sas_internal *i = to_sas_internal(sas_ha->core.shost->transportt); + int written; + + if (i->dft->lldd_write_gpio == NULL) { + resp_data[2] = SMP_RESP_FUNC_UNK; + return 0; + } + + written = i->dft->lldd_write_gpio(sas_ha, reg_type, reg_index, + reg_count, req_data); + + if (written < 0) { + resp_data[2] = SMP_RESP_FUNC_FAILED; + written = 0; + } else + resp_data[2] = SMP_RESP_FUNC_ACC; + + return written; +} + static void sas_report_phy_sata(struct sas_ha_struct *sas_ha, u8 *resp_data, u8 phy_id) { @@ -230,9 +315,23 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, /* Can't implement; hosts have no routes */ break; - case SMP_WRITE_GPIO_REG: - /* FIXME: need GPIO support in the transport class */ + case SMP_WRITE_GPIO_REG: { + /* SFF-8485 v0.7 */ + const int base_frame_size = 11; + int to_write = req_data[4]; + + if (blk_rq_bytes(req) < base_frame_size + to_write * 4 || + req->resid_len < base_frame_size + to_write * 4) { + resp_data[2] = SMP_RESP_INV_FRM_LEN; + break; + } + + to_write = sas_host_smp_write_gpio(sas_ha, resp_data, req_data[2], + req_data[3], to_write, &req_data[8]); + req->resid_len -= base_frame_size + to_write * 4; + rsp->resid_len -= 8; break; + } case SMP_CONF_ROUTE_INFO: /* Can't implement; hosts have no routes */ |