u64 aidaw = msb->data_addr;
unsigned long flags;
- if ((msb->flags & MSB_FLAG_IDA) && aidaw)
+ if ((msb->flags & MSB_FLAG_IDA) && aidaw &&
+ IS_ALIGNED(aidaw, PAGE_SIZE))
mempool_free(virt_to_page(aidaw), aidaw_pool);
spin_lock_irqsave(&list_lock, flags);
return rq_data_dir(req) != WRITE || bdev->state != SCM_WR_PROHIBIT;
}
-struct aidaw *scm_aidaw_alloc(void)
+static inline struct aidaw *scm_aidaw_alloc(void)
{
struct page *page = mempool_alloc(aidaw_pool, GFP_ATOMIC);
return page ? page_address(page) : NULL;
}
+static inline unsigned long scm_aidaw_bytes(struct aidaw *aidaw)
+{
+ unsigned long _aidaw = (unsigned long) aidaw;
+ unsigned long bytes = ALIGN(_aidaw, PAGE_SIZE) - _aidaw;
+
+ return (bytes / sizeof(*aidaw)) * PAGE_SIZE;
+}
+
+struct aidaw *scm_aidaw_fetch(struct scm_request *scmrq, unsigned int bytes)
+{
+ struct aidaw *aidaw;
+
+ if (scm_aidaw_bytes(scmrq->next_aidaw) >= bytes)
+ return scmrq->next_aidaw;
+
+ aidaw = scm_aidaw_alloc();
+ if (aidaw)
+ memset(aidaw, 0, PAGE_SIZE);
+ return aidaw;
+}
+
static int scm_request_prepare(struct scm_request *scmrq)
{
struct scm_blk_dev *bdev = scmrq->bdev;
struct scm_device *scmdev = bdev->gendisk->private_data;
- struct aidaw *aidaw = scm_aidaw_alloc();
struct msb *msb = &scmrq->aob->msb[0];
struct req_iterator iter;
+ struct aidaw *aidaw;
struct bio_vec bv;
+ aidaw = scm_aidaw_fetch(scmrq, blk_rq_bytes(scmrq->request));
if (!aidaw)
return -ENOMEM;
- memset(aidaw, 0, PAGE_SIZE);
msb->bs = MSB_BS_4K;
scmrq->aob->request.msb_count = 1;
msb->scm_addr = scmdev->address +
scmrq->bdev = bdev;
scmrq->retries = 4;
scmrq->error = 0;
+ /* We don't use all msbs - place aidaws at the end of the aob page. */
+ scmrq->next_aidaw = (void *) &aob->msb[1];
scm_request_cluster_init(scmrq);
}
struct scm_request {
struct scm_blk_dev *bdev;
+ struct aidaw *next_aidaw;
struct request *request;
struct aob *aob;
struct list_head list;
void scm_request_finish(struct scm_request *);
void scm_request_requeue(struct scm_request *);
-struct aidaw *scm_aidaw_alloc(void);
+struct aidaw *scm_aidaw_fetch(struct scm_request *scmrq, unsigned int bytes);
int scm_drv_init(void);
void scm_drv_cleanup(void);
scmrq->cluster.state = CLUSTER_READ;
/* fall through */
case CLUSTER_READ:
- aidaw = scm_aidaw_alloc();
- if (!aidaw)
- return -ENOMEM;
-
- memset(aidaw, 0, PAGE_SIZE);
- scmrq->aob->request.msb_count = 1;
msb->bs = MSB_BS_4K;
msb->oc = MSB_OC_READ;
msb->flags = MSB_FLAG_IDA;
- msb->data_addr = (u64) aidaw;
msb->blk_count = write_cluster_size;
addr = scmdev->address + ((u64) blk_rq_pos(req) << 9);
CLUSTER_SIZE))
msb->blk_count = 2 * write_cluster_size;
+ aidaw = scm_aidaw_fetch(scmrq, msb->blk_count * PAGE_SIZE);
+ if (!aidaw)
+ return -ENOMEM;
+
+ scmrq->aob->request.msb_count = 1;
+ msb->data_addr = (u64) aidaw;
for (i = 0; i < msb->blk_count; i++) {
aidaw->data_addr = (u64) scmrq->cluster.buf[i];
aidaw++;