blob: 778384237b8c846c3f5fd5957118aa6715182132 [file] [log] [blame]
Uma Krishnan76ebe012018-03-26 11:30:51 -05001/*
2 * CXL Flash Device Driver
3 *
4 * Written by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>, IBM Corporation
5 * Uma Krishnan <ukrishn@linux.vnet.ibm.com>, IBM Corporation
6 *
7 * Copyright (C) 2018 IBM Corporation
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15#include <misc/ocxl.h>
16
17#include "backend.h"
Uma Krishnan48e077d2018-03-26 11:31:01 -050018#include "ocxl_hw.h"
19
20/**
21 * ocxlflash_destroy_afu() - destroy the AFU structure
22 * @afu_cookie: AFU to be freed.
23 */
24static void ocxlflash_destroy_afu(void *afu_cookie)
25{
26 struct ocxl_hw_afu *afu = afu_cookie;
27
28 if (!afu)
29 return;
30
31 kfree(afu);
32}
33
34/**
Uma Krishnane9dfced2018-03-26 11:31:09 -050035 * ocxlflash_config_fn() - configure the host function
36 * @pdev: PCI device associated with the host.
37 * @afu: AFU associated with the host.
38 *
39 * Return: 0 on success, -errno on failure
40 */
41static int ocxlflash_config_fn(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
42{
43 struct ocxl_fn_config *fcfg = &afu->fcfg;
44 struct device *dev = &pdev->dev;
Uma Krishnan2e222772018-03-26 11:31:21 -050045 u16 base, enabled, supported;
Uma Krishnane9dfced2018-03-26 11:31:09 -050046 int rc = 0;
47
48 /* Read DVSEC config of the function */
49 rc = ocxl_config_read_function(pdev, fcfg);
50 if (unlikely(rc)) {
51 dev_err(dev, "%s: ocxl_config_read_function failed rc=%d\n",
52 __func__, rc);
53 goto out;
54 }
55
56 /* Check if function has AFUs defined, only 1 per function supported */
57 if (fcfg->max_afu_index >= 0) {
58 afu->is_present = true;
59 if (fcfg->max_afu_index != 0)
60 dev_warn(dev, "%s: Unexpected AFU index value %d\n",
61 __func__, fcfg->max_afu_index);
62 }
Uma Krishnan2e222772018-03-26 11:31:21 -050063
64 rc = ocxl_config_get_actag_info(pdev, &base, &enabled, &supported);
65 if (unlikely(rc)) {
66 dev_err(dev, "%s: ocxl_config_get_actag_info failed rc=%d\n",
67 __func__, rc);
68 goto out;
69 }
70
71 afu->fn_actag_base = base;
72 afu->fn_actag_enabled = enabled;
73
74 ocxl_config_set_actag(pdev, fcfg->dvsec_function_pos, base, enabled);
75 dev_dbg(dev, "%s: Function acTag range base=%u enabled=%u\n",
76 __func__, base, enabled);
Uma Krishnane9dfced2018-03-26 11:31:09 -050077out:
78 return rc;
79}
80
81/**
Uma Krishnan48e077d2018-03-26 11:31:01 -050082 * ocxlflash_create_afu() - create the AFU for OCXL
83 * @pdev: PCI device associated with the host.
84 *
85 * Return: AFU on success, NULL on failure
86 */
87static void *ocxlflash_create_afu(struct pci_dev *pdev)
88{
89 struct device *dev = &pdev->dev;
90 struct ocxl_hw_afu *afu;
Uma Krishnane9dfced2018-03-26 11:31:09 -050091 int rc;
Uma Krishnan48e077d2018-03-26 11:31:01 -050092
93 afu = kzalloc(sizeof(*afu), GFP_KERNEL);
94 if (unlikely(!afu)) {
95 dev_err(dev, "%s: HW AFU allocation failed\n", __func__);
96 goto out;
97 }
98
99 afu->pdev = pdev;
100 afu->dev = dev;
Uma Krishnane9dfced2018-03-26 11:31:09 -0500101
102 rc = ocxlflash_config_fn(pdev, afu);
103 if (unlikely(rc)) {
104 dev_err(dev, "%s: Function configuration failed rc=%d\n",
105 __func__, rc);
106 goto err1;
107 }
Uma Krishnan48e077d2018-03-26 11:31:01 -0500108out:
109 return afu;
Uma Krishnane9dfced2018-03-26 11:31:09 -0500110err1:
111 kfree(afu);
112 afu = NULL;
113 goto out;
Uma Krishnan48e077d2018-03-26 11:31:01 -0500114}
Uma Krishnan76ebe012018-03-26 11:30:51 -0500115
116/* Backend ops to ocxlflash services */
117const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
118 .module = THIS_MODULE,
Uma Krishnan48e077d2018-03-26 11:31:01 -0500119 .create_afu = ocxlflash_create_afu,
120 .destroy_afu = ocxlflash_destroy_afu,
Uma Krishnan76ebe012018-03-26 11:30:51 -0500121};