Commit | Line | Data |
---|---|---|
800f879a AT |
1 | /* |
2 | * Copyright 2010-2017 Intel Corporation. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License, version 2, | |
6 | * as published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
11 | * General Public License for more details. | |
12 | * | |
13 | * Disclaimer: The codes contained in these modules may be specific to | |
14 | * the Intel Software Development Platform codenamed Knights Ferry, | |
15 | * and the Intel product codenamed Knights Corner, and are not backward | |
16 | * compatible with other Intel products. Additionally, Intel will NOT | |
17 | * support the codes or instruction set in future products. | |
18 | * | |
19 | * Intel offers no warranty of any kind regarding the code. This code is | |
20 | * licensed on an "AS IS" basis and Intel is not obligated to provide | |
21 | * any support, assistance, installation, training, or other services | |
22 | * of any kind. Intel is also not obligated to provide any updates, | |
23 | * enhancements or extensions. Intel specifically disclaims any warranty | |
24 | * of merchantability, non-infringement, fitness for any particular | |
25 | * purpose, and any other warranty. | |
26 | * | |
27 | * Further, Intel disclaims all liability of any kind, including but | |
28 | * not limited to liability for infringement of any proprietary rights, | |
29 | * relating to the use of the code, even if Intel is notified of the | |
30 | * possibility of such liability. Except as expressly stated in an Intel | |
31 | * license agreement provided with this code and agreed upon with Intel, | |
32 | * no license, express or implied, by estoppel or otherwise, to any | |
33 | * intellectual property rights is granted herein. | |
34 | */ | |
35 | ||
36 | /* contains code to handle MIC IO control codes */ | |
37 | ||
38 | #include "mic_common.h" | |
39 | ||
40 | static int do_send_flash_cmd(mic_ctx_t *mic_ctx, struct ctrlioctl_flashcmd *args); | |
41 | static int get_card_mem(mic_ctx_t *mic_ctx, struct ctrlioctl_cardmemcpy *args); | |
42 | ||
43 | /* | |
44 | DESCRIPTION:: Gets the opcode from the input buffer and call appropriate method | |
45 | PARAMETERS:: | |
46 | [in]mic_ctx_t *mic_ctx - pointer to the mic private context | |
47 | [in]void *in_buffer - input buffer containing opcode + ioctl arguments, | |
48 | RETURN_VALUE:: 0 if successful, non-zero if failure | |
49 | */ | |
50 | int | |
51 | adapter_do_ioctl(uint32_t cmd, uint64_t arg) | |
52 | { | |
53 | int status = 0; | |
54 | mic_ctx_t *mic_ctx = NULL; | |
55 | ||
56 | void __user *argp = (void __user *)arg; | |
57 | switch (cmd) { | |
58 | ||
59 | case IOCTL_FLASHCMD: | |
60 | { | |
61 | struct ctrlioctl_flashcmd args = {0}; | |
62 | ||
63 | if (copy_from_user(&args, argp, sizeof(struct ctrlioctl_flashcmd))) { | |
64 | return -EFAULT; | |
65 | } | |
66 | ||
67 | if (args.brdnum >= (uint32_t)mic_data.dd_numdevs) { | |
68 | printk(KERN_ERR "IOCTL error: given board num is invalid\n"); | |
69 | return -EINVAL; | |
70 | } | |
71 | ||
72 | mic_ctx = get_per_dev_ctx(args.brdnum); | |
73 | if (!mic_ctx) { | |
74 | printk(KERN_ERR "IOCTL error: null mic context\n"); | |
75 | return -ENODEV; | |
76 | } | |
77 | ||
78 | /* Make sure we are running in flash mode */ | |
79 | if (mic_ctx->mode != MODE_FLASH || mic_ctx->state != MIC_ONLINE) { | |
80 | printk(KERN_ERR "%s Card is not online in flash mode or online state\n", __func__); | |
81 | return -EPERM; | |
82 | } | |
83 | ||
84 | if (mic_ctx->bi_family != FAMILY_KNC) { | |
85 | printk(KERN_ERR "%s IOCTL_FLASHCMD not supported for non KNC family cards\n", __func__); | |
86 | return -EPERM; | |
87 | } | |
88 | ||
89 | status = do_send_flash_cmd(mic_ctx, &args); | |
90 | if (status) { | |
91 | printk(KERN_ERR "IOCTL error: failed to complete IOCTL for bdnum %d\n", args.brdnum); | |
92 | return status; | |
93 | } | |
94 | ||
95 | if (copy_to_user(argp, &args, sizeof(struct ctrlioctl_flashcmd))) { | |
96 | return -EFAULT; | |
97 | } | |
98 | ||
99 | break; | |
100 | } | |
101 | ||
102 | case IOCTL_CARDMEMCPY: | |
103 | { | |
104 | struct ctrlioctl_cardmemcpy args = {0}; | |
105 | ||
106 | if (copy_from_user(&args, argp, sizeof(struct ctrlioctl_cardmemcpy))) { | |
107 | return -EFAULT; | |
108 | } | |
109 | ||
110 | if (args.brdnum >= (uint32_t)mic_data.dd_numdevs) { | |
111 | printk(KERN_ERR "IOCTL error: given board num is invalid\n"); | |
112 | return -EINVAL; | |
113 | } | |
114 | mic_ctx = get_per_dev_ctx(args.brdnum); | |
115 | if (!mic_ctx) { | |
116 | printk(KERN_ERR "IOCTL error: null mic context\n"); | |
117 | return -ENODEV; | |
118 | } | |
119 | ||
120 | if(mic_ctx->state != MIC_ONLINE || mic_ctx->mode != MODE_LINUX) { | |
121 | status = -EPERM; | |
122 | printk("Error ! Card not in linux mode or online state!\n"); | |
123 | return status; | |
124 | } | |
125 | ||
126 | status = get_card_mem(mic_ctx, &args); | |
127 | if (status) { | |
128 | printk(KERN_ERR "IOCTL error: failed to complete IOCTL for bdnum %d\n", args.brdnum); | |
129 | return status; | |
130 | } | |
131 | ||
132 | ; | |
133 | break; | |
134 | } | |
135 | ||
136 | default: | |
137 | printk("Invalid IOCTL\n"); | |
138 | status = -EINVAL; | |
139 | break; | |
140 | } | |
141 | ||
142 | return status; | |
143 | } | |
144 | ||
145 | int | |
146 | do_send_flash_cmd(mic_ctx_t *mic_ctx, struct ctrlioctl_flashcmd *args) | |
147 | { | |
148 | int status = 0; | |
149 | ||
150 | if(!capable(CAP_SYS_ADMIN)) { | |
151 | printk(KERN_ERR "Cannot execute unless sysadmin\n"); | |
152 | return -EACCES; | |
153 | } | |
154 | ||
155 | pr_debug("%s\n IN:: brdnum = %d, type = %x, data = %p, len = %x\n", | |
156 | __func__, args->brdnum, args->type, args->data, args->len); | |
157 | ||
158 | status = send_flash_cmd(mic_ctx, args->type, args->data, args->len); | |
159 | ||
160 | return status; | |
161 | } | |
162 | ||
163 | ||
164 | int | |
165 | get_card_mem(mic_ctx_t *mic_ctx, struct ctrlioctl_cardmemcpy *args) | |
166 | { | |
167 | int32_t status = 0; | |
168 | ||
169 | if(!capable(CAP_SYS_ADMIN)) { | |
170 | printk(KERN_ERR "Cannot execute unless sysadmin\n"); | |
171 | return -EACCES; | |
172 | } | |
173 | ||
174 | if (args->dest == NULL) { | |
175 | status = EINVAL; | |
176 | goto exit; | |
177 | } | |
178 | pr_debug("%s\n IN:: brdnum = %d, start = %qx, size = %qx, dest = %p\n", | |
179 | __func__, args->brdnum, args->start, args->size, args->dest); | |
180 | ||
181 | status = get_cardside_mem(mic_ctx, args->start, args->size, args->dest); | |
182 | ||
183 | exit: | |
184 | return status; | |
185 | ||
186 | } |