diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2012-08-28 18:50:38 +0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-09-26 17:45:01 +0400 |
commit | f30664e2c85c7804f07c636bbe99f35e0b2d4c76 (patch) | |
tree | 17b6c655cd9f7eddc8980e05c7f378ff774cac0d /drivers/s390/block/scm_blk.h | |
parent | 2e73c2cf78f797f3ff299ca39b210bceb40ab804 (diff) | |
download | linux-f30664e2c85c7804f07c636bbe99f35e0b2d4c76.tar.xz |
s390: add scm block driver
Block device driver for Storage Class Memory (SCM). This driver
provides a block device interface for each available SCM increment.
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/block/scm_blk.h')
-rw-r--r-- | drivers/s390/block/scm_blk.h | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/drivers/s390/block/scm_blk.h b/drivers/s390/block/scm_blk.h new file mode 100644 index 000000000000..5aba5612588f --- /dev/null +++ b/drivers/s390/block/scm_blk.h @@ -0,0 +1,79 @@ +#ifndef SCM_BLK_H +#define SCM_BLK_H + +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/blkdev.h> +#include <linux/genhd.h> +#include <linux/list.h> + +#include <asm/debug.h> +#include <asm/eadm.h> + +#define SCM_NR_PARTS 8 +#define SCM_QUEUE_DELAY 5 + +struct scm_blk_dev { + struct tasklet_struct tasklet; + struct request_queue *rq; + struct gendisk *gendisk; + struct scm_device *scmdev; + spinlock_t rq_lock; /* guard the request queue */ + spinlock_t lock; /* guard the rest of the blockdev */ + atomic_t queued_reqs; + struct list_head finished_requests; +}; + +struct scm_request { + struct scm_blk_dev *bdev; + struct request *request; + struct aidaw *aidaw; + struct aob *aob; + struct list_head list; + u8 retries; + int error; +}; + +#define to_aobrq(rq) container_of((void *) rq, struct aob_rq_header, data) + +int scm_blk_dev_setup(struct scm_blk_dev *, struct scm_device *); +void scm_blk_dev_cleanup(struct scm_blk_dev *); +void scm_blk_irq(struct scm_device *, void *, int); + +int scm_drv_init(void); +void scm_drv_cleanup(void); + + +extern debug_info_t *scm_debug; + +#define SCM_LOG(imp, txt) do { \ + debug_text_event(scm_debug, imp, txt); \ + } while (0) + +static inline void SCM_LOG_HEX(int level, void *data, int length) +{ + if (level > scm_debug->level) + return; + while (length > 0) { + debug_event(scm_debug, level, data, length); + length -= scm_debug->buf_size; + data += scm_debug->buf_size; + } +} + +static inline void SCM_LOG_STATE(int level, struct scm_device *scmdev) +{ + struct { + u64 address; + u8 oper_state; + u8 rank; + } __packed data = { + .address = scmdev->address, + .oper_state = scmdev->attrs.oper_state, + .rank = scmdev->attrs.rank, + }; + + SCM_LOG_HEX(level, &data, sizeof(data)); +} + +#endif /* SCM_BLK_H */ |