blob: 8b387b32fd622b981a19e951eca1b3fd30c783bf [file] [log] [blame]
Sebastian Ottf30664e2012-08-28 16:50:38 +02001#ifndef SCM_BLK_H
2#define SCM_BLK_H
3
4#include <linux/interrupt.h>
5#include <linux/spinlock.h>
6#include <linux/blkdev.h>
7#include <linux/genhd.h>
8#include <linux/list.h>
9
10#include <asm/debug.h>
11#include <asm/eadm.h>
12
13#define SCM_NR_PARTS 8
14#define SCM_QUEUE_DELAY 5
15
16struct scm_blk_dev {
17 struct tasklet_struct tasklet;
18 struct request_queue *rq;
19 struct gendisk *gendisk;
20 struct scm_device *scmdev;
21 spinlock_t rq_lock; /* guard the request queue */
22 spinlock_t lock; /* guard the rest of the blockdev */
23 atomic_t queued_reqs;
Sebastian Ott4fa3c012013-02-28 12:07:48 +010024 enum {SCM_OPER, SCM_WR_PROHIBIT} state;
Sebastian Ottf30664e2012-08-28 16:50:38 +020025 struct list_head finished_requests;
Sebastian Ott0d804b22012-08-28 16:51:19 +020026#ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE
27 struct list_head cluster_list;
28#endif
Sebastian Ottf30664e2012-08-28 16:50:38 +020029};
30
31struct scm_request {
32 struct scm_blk_dev *bdev;
33 struct request *request;
34 struct aidaw *aidaw;
35 struct aob *aob;
36 struct list_head list;
37 u8 retries;
38 int error;
Sebastian Ott0d804b22012-08-28 16:51:19 +020039#ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE
40 struct {
41 enum {CLUSTER_NONE, CLUSTER_READ, CLUSTER_WRITE} state;
42 struct list_head list;
43 void **buf;
44 } cluster;
45#endif
Sebastian Ottf30664e2012-08-28 16:50:38 +020046};
47
48#define to_aobrq(rq) container_of((void *) rq, struct aob_rq_header, data)
49
50int scm_blk_dev_setup(struct scm_blk_dev *, struct scm_device *);
51void scm_blk_dev_cleanup(struct scm_blk_dev *);
Sebastian Ott4fa3c012013-02-28 12:07:48 +010052void scm_blk_set_available(struct scm_blk_dev *);
Sebastian Ottf30664e2012-08-28 16:50:38 +020053void scm_blk_irq(struct scm_device *, void *, int);
54
Sebastian Ott0d804b22012-08-28 16:51:19 +020055void scm_request_finish(struct scm_request *);
56void scm_request_requeue(struct scm_request *);
57
Sebastian Ottf30664e2012-08-28 16:50:38 +020058int scm_drv_init(void);
59void scm_drv_cleanup(void);
60
Sebastian Ott0d804b22012-08-28 16:51:19 +020061#ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE
62void __scm_free_rq_cluster(struct scm_request *);
63int __scm_alloc_rq_cluster(struct scm_request *);
64void scm_request_cluster_init(struct scm_request *);
65bool scm_reserve_cluster(struct scm_request *);
66void scm_release_cluster(struct scm_request *);
67void scm_blk_dev_cluster_setup(struct scm_blk_dev *);
68bool scm_need_cluster_request(struct scm_request *);
69void scm_initiate_cluster_request(struct scm_request *);
70void scm_cluster_request_irq(struct scm_request *);
71bool scm_test_cluster_request(struct scm_request *);
72bool scm_cluster_size_valid(void);
Sebastian Ott58fece72013-01-28 19:34:26 +010073#else /* CONFIG_SCM_BLOCK_CLUSTER_WRITE */
74static inline void __scm_free_rq_cluster(struct scm_request *scmrq) {}
75static inline int __scm_alloc_rq_cluster(struct scm_request *scmrq)
76{
77 return 0;
78}
79static inline void scm_request_cluster_init(struct scm_request *scmrq) {}
80static inline bool scm_reserve_cluster(struct scm_request *scmrq)
81{
82 return true;
83}
84static inline void scm_release_cluster(struct scm_request *scmrq) {}
85static inline void scm_blk_dev_cluster_setup(struct scm_blk_dev *bdev) {}
86static inline bool scm_need_cluster_request(struct scm_request *scmrq)
87{
88 return false;
89}
90static inline void scm_initiate_cluster_request(struct scm_request *scmrq) {}
91static inline void scm_cluster_request_irq(struct scm_request *scmrq) {}
92static inline bool scm_test_cluster_request(struct scm_request *scmrq)
93{
94 return false;
95}
96static inline bool scm_cluster_size_valid(void)
97{
98 return true;
99}
100#endif /* CONFIG_SCM_BLOCK_CLUSTER_WRITE */
Sebastian Ottf30664e2012-08-28 16:50:38 +0200101
102extern debug_info_t *scm_debug;
103
104#define SCM_LOG(imp, txt) do { \
105 debug_text_event(scm_debug, imp, txt); \
106 } while (0)
107
108static inline void SCM_LOG_HEX(int level, void *data, int length)
109{
110 if (level > scm_debug->level)
111 return;
112 while (length > 0) {
113 debug_event(scm_debug, level, data, length);
114 length -= scm_debug->buf_size;
115 data += scm_debug->buf_size;
116 }
117}
118
119static inline void SCM_LOG_STATE(int level, struct scm_device *scmdev)
120{
121 struct {
122 u64 address;
123 u8 oper_state;
124 u8 rank;
125 } __packed data = {
126 .address = scmdev->address,
127 .oper_state = scmdev->attrs.oper_state,
128 .rank = scmdev->attrs.rank,
129 };
130
131 SCM_LOG_HEX(level, &data, sizeof(data));
132}
133
134#endif /* SCM_BLK_H */