Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 359533
b: refs/heads/master
c: 8722ff8
h: refs/heads/master
i:
  359531: c8b44e7
v: v3
  • Loading branch information
josh.h.morris@us.ibm.com authored and Jens Axboe committed Feb 5, 2013
1 parent b3381d7 commit 59f78ec
Show file tree
Hide file tree
Showing 13 changed files with 3,515 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 478c030eecbec927d62561c5f48a4515ea0fa21a
refs/heads/master: 8722ff8cdbfac9c1b20e67bb067b455c48cb8e93
6 changes: 6 additions & 0 deletions trunk/MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -6306,6 +6306,12 @@ S: Maintained
F: Documentation/blockdev/ramdisk.txt
F: drivers/block/brd.c

RAMSAM DRIVER (IBM RamSan 70/80 PCI SSD Flash Card)
M: Joshua Morris <josh.h.morris@us.ibm.com>
M: Philip Kelleher <pjk1939@linux.vnet.ibm.com>
S: Maintained
F: drivers/block/rsxx/

RANDOM NUMBER DRIVER
M: Theodore Ts'o" <tytso@mit.edu>
S: Maintained
Expand Down
10 changes: 10 additions & 0 deletions trunk/drivers/block/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -544,4 +544,14 @@ config BLK_DEV_RBD

If unsure, say N.

config BLK_DEV_RSXX
tristate "RamSam PCIe Flash SSD Device Driver"
depends on PCI
help
Device driver for IBM's high speed PCIe SSD
storage devices: RamSan-70 and RamSan-80.

To compile this driver as a module, choose M here: the
module will be called rsxx.

endif # BLK_DEV
2 changes: 2 additions & 0 deletions trunk/drivers/block/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ obj-$(CONFIG_BLK_DEV_DRBD) += drbd/
obj-$(CONFIG_BLK_DEV_RBD) += rbd.o
obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx/

obj-$(CONFIG_BLK_DEV_RSXX) += rsxx/

swim_mod-y := swim.o swim_asm.o
2 changes: 2 additions & 0 deletions trunk/drivers/block/rsxx/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
obj-$(CONFIG_BLK_DEV_RSXX) += rsxx.o
rsxx-y := config.o core.o cregs.o dev.o dma.o
213 changes: 213 additions & 0 deletions trunk/drivers/block/rsxx/config.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
/*
* Filename: config.c
*
*
* Authors: Joshua Morris <josh.h.morris@us.ibm.com>
* Philip Kelleher <pjk1939@linux.vnet.ibm.com>
*
* (C) Copyright 2013 IBM Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include <linux/types.h>
#include <linux/crc32.h>
#include <linux/swab.h>

#include "rsxx_priv.h"
#include "rsxx_cfg.h"

static void initialize_config(void *config)
{
struct rsxx_card_cfg *cfg = (struct rsxx_card_cfg *) config;

cfg->hdr.version = RSXX_CFG_VERSION;

cfg->data.block_size = RSXX_HW_BLK_SIZE;
cfg->data.stripe_size = RSXX_HW_BLK_SIZE;
cfg->data.vendor_id = RSXX_VENDOR_ID_TMS_IBM;
cfg->data.cache_order = (-1);
cfg->data.intr_coal.mode = RSXX_INTR_COAL_DISABLED;
cfg->data.intr_coal.count = 0;
cfg->data.intr_coal.latency = 0;
}

static u32 config_data_crc32(struct rsxx_card_cfg *cfg)
{
/*
* Return the compliment of the CRC to ensure compatibility
* (i.e. this is how early rsxx drivers did it.)
*/

return ~crc32(~0, &cfg->data, sizeof(cfg->data));
}


/*----------------- Config Byte Swap Functions -------------------*/
static void config_hdr_be_to_cpu(struct card_cfg_hdr *hdr)
{
hdr->version = be32_to_cpu((__force __be32) hdr->version);
hdr->crc = be32_to_cpu((__force __be32) hdr->crc);
}

static void config_hdr_cpu_to_be(struct card_cfg_hdr *hdr)
{
hdr->version = (__force u32) cpu_to_be32(hdr->version);
hdr->crc = (__force u32) cpu_to_be32(hdr->crc);
}

static void config_data_swab(struct rsxx_card_cfg *cfg)
{
u32 *data = (u32 *) &cfg->data;
int i;

for (i = 0; i < (sizeof(cfg->data) / 4); i++)
data[i] = swab32(data[i]);
}

static void config_data_le_to_cpu(struct rsxx_card_cfg *cfg)
{
u32 *data = (u32 *) &cfg->data;
int i;

for (i = 0; i < (sizeof(cfg->data) / 4); i++)
data[i] = le32_to_cpu((__force __le32) data[i]);
}

static void config_data_cpu_to_le(struct rsxx_card_cfg *cfg)
{
u32 *data = (u32 *) &cfg->data;
int i;

for (i = 0; i < (sizeof(cfg->data) / 4); i++)
data[i] = (__force u32) cpu_to_le32(data[i]);
}


/*----------------- Config Operations ------------------*/
int rsxx_save_config(struct rsxx_cardinfo *card)
{
struct rsxx_card_cfg cfg;
int st;

memcpy(&cfg, &card->config, sizeof(cfg));

if (unlikely(cfg.hdr.version != RSXX_CFG_VERSION)) {
dev_err(CARD_TO_DEV(card),
"Cannot save config with invalid version %d\n",
cfg.hdr.version);
return -EINVAL;
}

/* Convert data to little endian for the CRC calculation. */
config_data_cpu_to_le(&cfg);

cfg.hdr.crc = config_data_crc32(&cfg);

/*
* Swap the data from little endian to big endian so it can be
* stored.
*/
config_data_swab(&cfg);
config_hdr_cpu_to_be(&cfg.hdr);

st = rsxx_creg_write(card, CREG_ADD_CONFIG, sizeof(cfg), &cfg, 1);
if (st)
return st;

return 0;
}

int rsxx_load_config(struct rsxx_cardinfo *card)
{
int st;
u32 crc;

st = rsxx_creg_read(card, CREG_ADD_CONFIG, sizeof(card->config),
&card->config, 1);
if (st) {
dev_err(CARD_TO_DEV(card),
"Failed reading card config.\n");
return st;
}

config_hdr_be_to_cpu(&card->config.hdr);

if (card->config.hdr.version == RSXX_CFG_VERSION) {
/*
* We calculate the CRC with the data in little endian, because
* early drivers did not take big endian CPUs into account.
* The data is always stored in big endian, so we need to byte
* swap it before calculating the CRC.
*/

config_data_swab(&card->config);

/* Check the CRC */
crc = config_data_crc32(&card->config);
if (crc != card->config.hdr.crc) {
dev_err(CARD_TO_DEV(card),
"Config corruption detected!\n");
dev_info(CARD_TO_DEV(card),
"CRC (sb x%08x is x%08x)\n",
card->config.hdr.crc, crc);
return -EIO;
}

/* Convert the data to CPU byteorder */
config_data_le_to_cpu(&card->config);

} else if (card->config.hdr.version != 0) {
dev_err(CARD_TO_DEV(card),
"Invalid config version %d.\n",
card->config.hdr.version);
/*
* Config version changes require special handling from the
* user
*/
return -EINVAL;
} else {
dev_info(CARD_TO_DEV(card),
"Initializing card configuration.\n");
initialize_config(card);
st = rsxx_save_config(card);
if (st)
return st;
}

card->config_valid = 1;

dev_dbg(CARD_TO_DEV(card), "version: x%08x\n",
card->config.hdr.version);
dev_dbg(CARD_TO_DEV(card), "crc: x%08x\n",
card->config.hdr.crc);
dev_dbg(CARD_TO_DEV(card), "block_size: x%08x\n",
card->config.data.block_size);
dev_dbg(CARD_TO_DEV(card), "stripe_size: x%08x\n",
card->config.data.stripe_size);
dev_dbg(CARD_TO_DEV(card), "vendor_id: x%08x\n",
card->config.data.vendor_id);
dev_dbg(CARD_TO_DEV(card), "cache_order: x%08x\n",
card->config.data.cache_order);
dev_dbg(CARD_TO_DEV(card), "mode: x%08x\n",
card->config.data.intr_coal.mode);
dev_dbg(CARD_TO_DEV(card), "count: x%08x\n",
card->config.data.intr_coal.count);
dev_dbg(CARD_TO_DEV(card), "latency: x%08x\n",
card->config.data.intr_coal.latency);

return 0;
}

Loading

0 comments on commit 59f78ec

Please sign in to comment.