Skip to content

Commit faae6e3

Browse files
amboarcminyard
authored andcommitted
ipmi: kcs_bmc: Split headers into device and client
Strengthen the distinction between code that abstracts the implementation of the KCS behaviours (device drivers) and code that exploits KCS behaviours (clients). Neither needs to know about the APIs required by the other, so provide separate headers. Signed-off-by: Andrew Jeffery <[email protected]> Message-Id: <[email protected]> Reviewed-by: Zev Weiss <[email protected]> Signed-off-by: Corey Minyard <[email protected]>
1 parent d709697 commit faae6e3

File tree

7 files changed

+117
-52
lines changed

7 files changed

+117
-52
lines changed

drivers/char/ipmi/kcs_bmc.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,52 @@
11
// SPDX-License-Identifier: GPL-2.0
22
/*
33
* Copyright (c) 2015-2018, Intel Corporation.
4+
* Copyright (c) 2021, IBM Corp.
45
*/
56

67
#include <linux/module.h>
78

89
#include "kcs_bmc.h"
910

11+
/* Implement both the device and client interfaces here */
12+
#include "kcs_bmc_device.h"
13+
#include "kcs_bmc_client.h"
14+
15+
/* Consumer data access */
16+
1017
u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc)
1118
{
12-
return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr);
19+
return kcs_bmc->ops->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr);
1320
}
1421
EXPORT_SYMBOL(kcs_bmc_read_data);
1522

1623
void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data)
1724
{
18-
kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data);
25+
kcs_bmc->ops->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data);
1926
}
2027
EXPORT_SYMBOL(kcs_bmc_write_data);
2128

2229
u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc)
2330
{
24-
return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.str);
31+
return kcs_bmc->ops->io_inputb(kcs_bmc, kcs_bmc->ioreg.str);
2532
}
2633
EXPORT_SYMBOL(kcs_bmc_read_status);
2734

2835
void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data)
2936
{
30-
kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data);
37+
kcs_bmc->ops->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data);
3138
}
3239
EXPORT_SYMBOL(kcs_bmc_write_status);
3340

3441
void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val)
3542
{
36-
kcs_bmc->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val);
43+
kcs_bmc->ops->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val);
3744
}
3845
EXPORT_SYMBOL(kcs_bmc_update_status);
3946

40-
int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc);
41-
int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc)
47+
irqreturn_t kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc)
4248
{
43-
return kcs_bmc_ipmi_event(kcs_bmc);
49+
return kcs_bmc->client.ops->event(&kcs_bmc->client);
4450
}
4551
EXPORT_SYMBOL(kcs_bmc_handle_event);
4652

@@ -62,4 +68,5 @@ EXPORT_SYMBOL(kcs_bmc_remove_device);
6268

6369
MODULE_LICENSE("GPL v2");
6470
MODULE_AUTHOR("Haiyue Wang <[email protected]>");
71+
MODULE_AUTHOR("Andrew Jeffery <[email protected]>");
6572
MODULE_DESCRIPTION("KCS BMC to handle the IPMI request from system software");

drivers/char/ipmi/kcs_bmc.h

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88

99
#include <linux/miscdevice.h>
1010

11+
#include "kcs_bmc_client.h"
12+
13+
#define KCS_BMC_STR_OBF BIT(0)
14+
#define KCS_BMC_STR_IBF BIT(1)
15+
#define KCS_BMC_STR_CMD_DAT BIT(3)
16+
1117
/* Different phases of the KCS BMC module.
1218
* KCS_PHASE_IDLE:
1319
* BMC should not be expecting nor sending any data.
@@ -66,19 +72,21 @@ struct kcs_ioreg {
6672
u32 str;
6773
};
6874

75+
struct kcs_bmc_device_ops;
76+
6977
struct kcs_bmc {
7078
struct device *dev;
7179

80+
const struct kcs_bmc_device_ops *ops;
81+
82+
struct kcs_bmc_client client;
83+
7284
spinlock_t lock;
7385

7486
u32 channel;
7587
int running;
7688

77-
/* Setup by BMC KCS controller driver */
7889
struct kcs_ioreg ioreg;
79-
u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg);
80-
void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b);
81-
void (*io_updateb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val);
8290

8391
enum kcs_phases phase;
8492
enum kcs_errors error;
@@ -97,15 +105,4 @@ struct kcs_bmc {
97105

98106
struct miscdevice miscdev;
99107
};
100-
101-
int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc);
102-
int kcs_bmc_add_device(struct kcs_bmc *kcs_bmc);
103-
void kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc);
104-
105-
u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc);
106-
void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data);
107-
u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc);
108-
void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data);
109-
void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val);
110-
111108
#endif /* __KCS_BMC_H__ */

drivers/char/ipmi/kcs_bmc_aspeed.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#include <linux/slab.h>
2222
#include <linux/timer.h>
2323

24-
#include "kcs_bmc.h"
24+
#include "kcs_bmc_device.h"
2525

2626

2727
#define DEVICE_NAME "ast-kcs-bmc"
@@ -220,14 +220,17 @@ static void aspeed_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable)
220220
}
221221
}
222222

223+
static const struct kcs_bmc_device_ops aspeed_kcs_ops = {
224+
.io_inputb = aspeed_kcs_inb,
225+
.io_outputb = aspeed_kcs_outb,
226+
.io_updateb = aspeed_kcs_updateb,
227+
};
228+
223229
static irqreturn_t aspeed_kcs_irq(int irq, void *arg)
224230
{
225231
struct kcs_bmc *kcs_bmc = arg;
226232

227-
if (!kcs_bmc_handle_event(kcs_bmc))
228-
return IRQ_HANDLED;
229-
230-
return IRQ_NONE;
233+
return kcs_bmc_handle_event(kcs_bmc);
231234
}
232235

233236
static int aspeed_kcs_config_irq(struct kcs_bmc *kcs_bmc,
@@ -364,9 +367,7 @@ static int aspeed_kcs_probe(struct platform_device *pdev)
364367
kcs_bmc->dev = &pdev->dev;
365368
kcs_bmc->channel = channel;
366369
kcs_bmc->ioreg = ast_kcs_bmc_ioregs[channel - 1];
367-
kcs_bmc->io_inputb = aspeed_kcs_inb;
368-
kcs_bmc->io_outputb = aspeed_kcs_outb;
369-
kcs_bmc->io_updateb = aspeed_kcs_updateb;
370+
kcs_bmc->ops = &aspeed_kcs_ops;
370371

371372
priv->map = syscon_node_to_regmap(pdev->dev.parent->of_node);
372373
if (IS_ERR(priv->map)) {

drivers/char/ipmi/kcs_bmc_cdev_ipmi.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222

2323
#define KCS_ZERO_DATA 0
2424

25-
2625
/* IPMI 2.0 - Table 9-1, KCS Interface Status Register Bits */
2726
#define KCS_STATUS_STATE(state) (state << 6)
2827
#define KCS_STATUS_STATE_MASK GENMASK(7, 6)
@@ -179,12 +178,19 @@ static void kcs_bmc_ipmi_handle_cmd(struct kcs_bmc *kcs_bmc)
179178
}
180179
}
181180

182-
int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc);
183-
int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc)
181+
static inline struct kcs_bmc *client_to_kcs_bmc(struct kcs_bmc_client *client)
182+
{
183+
return container_of(client, struct kcs_bmc, client);
184+
}
185+
186+
static irqreturn_t kcs_bmc_ipmi_event(struct kcs_bmc_client *client)
184187
{
188+
struct kcs_bmc *kcs_bmc;
185189
unsigned long flags;
186-
int ret = -ENODATA;
187190
u8 status;
191+
int ret;
192+
193+
kcs_bmc = client_to_kcs_bmc(client);
188194

189195
spin_lock_irqsave(&kcs_bmc->lock, flags);
190196

@@ -197,23 +203,28 @@ int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc)
197203
else
198204
kcs_bmc_ipmi_handle_data(kcs_bmc);
199205

200-
ret = 0;
206+
ret = IRQ_HANDLED;
207+
} else {
208+
ret = IRQ_NONE;
201209
}
202210

203211
spin_unlock_irqrestore(&kcs_bmc->lock, flags);
204212

205213
return ret;
206214
}
207-
EXPORT_SYMBOL(kcs_bmc_ipmi_event);
208215

209-
static inline struct kcs_bmc *to_kcs_bmc(struct file *filp)
216+
static const struct kcs_bmc_client_ops kcs_bmc_ipmi_client_ops = {
217+
.event = kcs_bmc_ipmi_event,
218+
};
219+
220+
static inline struct kcs_bmc *file_to_kcs_bmc(struct file *filp)
210221
{
211222
return container_of(filp->private_data, struct kcs_bmc, miscdev);
212223
}
213224

214225
static int kcs_bmc_ipmi_open(struct inode *inode, struct file *filp)
215226
{
216-
struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp);
227+
struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp);
217228
int ret = 0;
218229

219230
spin_lock_irq(&kcs_bmc->lock);
@@ -228,7 +239,7 @@ static int kcs_bmc_ipmi_open(struct inode *inode, struct file *filp)
228239

229240
static __poll_t kcs_bmc_ipmi_poll(struct file *filp, poll_table *wait)
230241
{
231-
struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp);
242+
struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp);
232243
__poll_t mask = 0;
233244

234245
poll_wait(filp, &kcs_bmc->queue, wait);
@@ -244,7 +255,7 @@ static __poll_t kcs_bmc_ipmi_poll(struct file *filp, poll_table *wait)
244255
static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf,
245256
size_t count, loff_t *ppos)
246257
{
247-
struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp);
258+
struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp);
248259
bool data_avail;
249260
size_t data_len;
250261
ssize_t ret;
@@ -306,7 +317,7 @@ static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf,
306317
static ssize_t kcs_bmc_ipmi_write(struct file *filp, const char __user *buf,
307318
size_t count, loff_t *ppos)
308319
{
309-
struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp);
320+
struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp);
310321
ssize_t ret;
311322

312323
/* a minimum response size '3' : netfn + cmd + ccode */
@@ -342,7 +353,7 @@ static ssize_t kcs_bmc_ipmi_write(struct file *filp, const char __user *buf,
342353
static long kcs_bmc_ipmi_ioctl(struct file *filp, unsigned int cmd,
343354
unsigned long arg)
344355
{
345-
struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp);
356+
struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp);
346357
long ret = 0;
347358

348359
spin_lock_irq(&kcs_bmc->lock);
@@ -372,7 +383,7 @@ static long kcs_bmc_ipmi_ioctl(struct file *filp, unsigned int cmd,
372383

373384
static int kcs_bmc_ipmi_release(struct inode *inode, struct file *filp)
374385
{
375-
struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp);
386+
struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp);
376387

377388
spin_lock_irq(&kcs_bmc->lock);
378389
kcs_bmc->running = 0;
@@ -401,6 +412,8 @@ int kcs_bmc_ipmi_add_device(struct kcs_bmc *kcs_bmc)
401412
mutex_init(&kcs_bmc->mutex);
402413
init_waitqueue_head(&kcs_bmc->queue);
403414

415+
kcs_bmc->client.dev = kcs_bmc;
416+
kcs_bmc->client.ops = &kcs_bmc_ipmi_client_ops;
404417
kcs_bmc->data_in = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL);
405418
kcs_bmc->data_out = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL);
406419
kcs_bmc->kbuffer = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL);

drivers/char/ipmi/kcs_bmc_client.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (c) 2021, IBM Corp. */
3+
4+
#ifndef __KCS_BMC_CONSUMER_H__
5+
#define __KCS_BMC_CONSUMER_H__
6+
7+
#include <linux/irqreturn.h>
8+
9+
struct kcs_bmc;
10+
struct kcs_bmc_client_ops;
11+
12+
struct kcs_bmc_client {
13+
const struct kcs_bmc_client_ops *ops;
14+
15+
struct kcs_bmc *dev;
16+
};
17+
18+
struct kcs_bmc_client_ops {
19+
irqreturn_t (*event)(struct kcs_bmc_client *client);
20+
};
21+
22+
u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc);
23+
void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data);
24+
u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc);
25+
void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data);
26+
void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val);
27+
#endif

drivers/char/ipmi/kcs_bmc_device.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (c) 2021, IBM Corp. */
3+
4+
#ifndef __KCS_BMC_DEVICE_H__
5+
#define __KCS_BMC_DEVICE_H__
6+
7+
#include "kcs_bmc.h"
8+
9+
struct kcs_bmc_device_ops {
10+
u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg);
11+
void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b);
12+
void (*io_updateb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 b);
13+
};
14+
15+
irqreturn_t kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc);
16+
int kcs_bmc_add_device(struct kcs_bmc *kcs_bmc);
17+
void kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc);
18+
19+
#endif

drivers/char/ipmi/kcs_bmc_npcm7xx.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include <linux/regmap.h>
1818
#include <linux/slab.h>
1919

20-
#include "kcs_bmc.h"
20+
#include "kcs_bmc_device.h"
2121

2222
#define DEVICE_NAME "npcm-kcs-bmc"
2323
#define KCS_CHANNEL_MAX 3
@@ -128,10 +128,7 @@ static irqreturn_t npcm7xx_kcs_irq(int irq, void *arg)
128128
{
129129
struct kcs_bmc *kcs_bmc = arg;
130130

131-
if (!kcs_bmc_handle_event(kcs_bmc))
132-
return IRQ_HANDLED;
133-
134-
return IRQ_NONE;
131+
return kcs_bmc_handle_event(kcs_bmc);
135132
}
136133

137134
static int npcm7xx_kcs_config_irq(struct kcs_bmc *kcs_bmc,
@@ -148,6 +145,12 @@ static int npcm7xx_kcs_config_irq(struct kcs_bmc *kcs_bmc,
148145
dev_name(dev), kcs_bmc);
149146
}
150147

148+
static const struct kcs_bmc_device_ops npcm7xx_kcs_ops = {
149+
.io_inputb = npcm7xx_kcs_inb,
150+
.io_outputb = npcm7xx_kcs_outb,
151+
.io_updateb = npcm7xx_kcs_updateb,
152+
};
153+
151154
static int npcm7xx_kcs_probe(struct platform_device *pdev)
152155
{
153156
struct device *dev = &pdev->dev;
@@ -179,9 +182,7 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev)
179182
kcs_bmc->ioreg.idr = priv->reg->dib;
180183
kcs_bmc->ioreg.odr = priv->reg->dob;
181184
kcs_bmc->ioreg.str = priv->reg->sts;
182-
kcs_bmc->io_inputb = npcm7xx_kcs_inb;
183-
kcs_bmc->io_outputb = npcm7xx_kcs_outb;
184-
kcs_bmc->io_updateb = npcm7xx_kcs_updateb;
185+
kcs_bmc->ops = &npcm7xx_kcs_ops;
185186

186187
platform_set_drvdata(pdev, priv);
187188

0 commit comments

Comments
 (0)