Skip to content

Commit d4e7ac6

Browse files
amboarcminyard
authored andcommitted
ipmi: kcs_bmc: Strip private client data from struct kcs_bmc
Move all client-private data out of `struct kcs_bmc` into the KCS client implementation. With this change the KCS BMC core code now only concerns itself with abstract `struct kcs_bmc` and `struct kcs_bmc_client` types, achieving expected separation of concerns. Further, the change clears the path for implementation of alternative userspace interfaces. The chardev data-structures are rearranged in the same manner applied to the KCS device driver data-structures in an earlier patch - `struct kcs_bmc_client` is embedded in the client's private data and we exploit container_of() to translate as required. Finally, now that it is free of client data, `struct kcs_bmc` is renamed to `struct kcs_bmc_device` to contrast `struct kcs_bmc_client`. Signed-off-by: Andrew Jeffery <[email protected]> Reviewed-by: Zev Weiss <[email protected]> Message-Id: <[email protected]> Signed-off-by: Corey Minyard <[email protected]>
1 parent faae6e3 commit d4e7ac6

File tree

7 files changed

+367
-294
lines changed

7 files changed

+367
-294
lines changed

drivers/char/ipmi/kcs_bmc.c

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Copyright (c) 2021, IBM Corp.
55
*/
66

7+
#include <linux/device.h>
78
#include <linux/module.h>
89

910
#include "kcs_bmc.h"
@@ -14,51 +15,98 @@
1415

1516
/* Consumer data access */
1617

17-
u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc)
18+
u8 kcs_bmc_read_data(struct kcs_bmc_device *kcs_bmc)
1819
{
1920
return kcs_bmc->ops->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr);
2021
}
2122
EXPORT_SYMBOL(kcs_bmc_read_data);
2223

23-
void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data)
24+
void kcs_bmc_write_data(struct kcs_bmc_device *kcs_bmc, u8 data)
2425
{
2526
kcs_bmc->ops->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data);
2627
}
2728
EXPORT_SYMBOL(kcs_bmc_write_data);
2829

29-
u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc)
30+
u8 kcs_bmc_read_status(struct kcs_bmc_device *kcs_bmc)
3031
{
3132
return kcs_bmc->ops->io_inputb(kcs_bmc, kcs_bmc->ioreg.str);
3233
}
3334
EXPORT_SYMBOL(kcs_bmc_read_status);
3435

35-
void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data)
36+
void kcs_bmc_write_status(struct kcs_bmc_device *kcs_bmc, u8 data)
3637
{
3738
kcs_bmc->ops->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data);
3839
}
3940
EXPORT_SYMBOL(kcs_bmc_write_status);
4041

41-
void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val)
42+
void kcs_bmc_update_status(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 val)
4243
{
4344
kcs_bmc->ops->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val);
4445
}
4546
EXPORT_SYMBOL(kcs_bmc_update_status);
4647

47-
irqreturn_t kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc)
48+
irqreturn_t kcs_bmc_handle_event(struct kcs_bmc_device *kcs_bmc)
4849
{
49-
return kcs_bmc->client.ops->event(&kcs_bmc->client);
50+
struct kcs_bmc_client *client;
51+
irqreturn_t rc;
52+
53+
spin_lock(&kcs_bmc->lock);
54+
client = kcs_bmc->client;
55+
if (client) {
56+
rc = client->ops->event(client);
57+
} else {
58+
u8 status;
59+
60+
status = kcs_bmc_read_status(kcs_bmc);
61+
if (status & KCS_BMC_STR_IBF) {
62+
/* Ack the event by reading the data */
63+
kcs_bmc_read_data(kcs_bmc);
64+
rc = IRQ_HANDLED;
65+
} else {
66+
rc = IRQ_NONE;
67+
}
68+
}
69+
spin_unlock(&kcs_bmc->lock);
70+
71+
return rc;
5072
}
5173
EXPORT_SYMBOL(kcs_bmc_handle_event);
5274

53-
int kcs_bmc_ipmi_add_device(struct kcs_bmc *kcs_bmc);
54-
int kcs_bmc_add_device(struct kcs_bmc *kcs_bmc)
75+
int kcs_bmc_enable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client)
76+
{
77+
int rc;
78+
79+
spin_lock_irq(&kcs_bmc->lock);
80+
if (kcs_bmc->client) {
81+
rc = -EBUSY;
82+
} else {
83+
kcs_bmc->client = client;
84+
rc = 0;
85+
}
86+
spin_unlock_irq(&kcs_bmc->lock);
87+
88+
return rc;
89+
}
90+
EXPORT_SYMBOL(kcs_bmc_enable_device);
91+
92+
void kcs_bmc_disable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client)
93+
{
94+
spin_lock_irq(&kcs_bmc->lock);
95+
if (client == kcs_bmc->client)
96+
kcs_bmc->client = NULL;
97+
spin_unlock_irq(&kcs_bmc->lock);
98+
}
99+
EXPORT_SYMBOL(kcs_bmc_disable_device);
100+
101+
int kcs_bmc_ipmi_add_device(struct kcs_bmc_device *kcs_bmc);
102+
int kcs_bmc_add_device(struct kcs_bmc_device *kcs_bmc)
55103
{
56104
return kcs_bmc_ipmi_add_device(kcs_bmc);
57105
}
58106
EXPORT_SYMBOL(kcs_bmc_add_device);
59107

60-
int kcs_bmc_ipmi_remove_device(struct kcs_bmc *kcs_bmc);
61-
void kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc)
108+
int kcs_bmc_ipmi_remove_device(struct kcs_bmc_device *kcs_bmc);
109+
void kcs_bmc_remove_device(struct kcs_bmc_device *kcs_bmc)
62110
{
63111
if (kcs_bmc_ipmi_remove_device(kcs_bmc))
64112
pr_warn("Failed to remove device for KCS channel %d\n",

drivers/char/ipmi/kcs_bmc.h

Lines changed: 9 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -6,61 +6,12 @@
66
#ifndef __KCS_BMC_H__
77
#define __KCS_BMC_H__
88

9-
#include <linux/miscdevice.h>
10-
11-
#include "kcs_bmc_client.h"
9+
#include <linux/list.h>
1210

1311
#define KCS_BMC_STR_OBF BIT(0)
1412
#define KCS_BMC_STR_IBF BIT(1)
1513
#define KCS_BMC_STR_CMD_DAT BIT(3)
1614

17-
/* Different phases of the KCS BMC module.
18-
* KCS_PHASE_IDLE:
19-
* BMC should not be expecting nor sending any data.
20-
* KCS_PHASE_WRITE_START:
21-
* BMC is receiving a WRITE_START command from system software.
22-
* KCS_PHASE_WRITE_DATA:
23-
* BMC is receiving a data byte from system software.
24-
* KCS_PHASE_WRITE_END_CMD:
25-
* BMC is waiting a last data byte from system software.
26-
* KCS_PHASE_WRITE_DONE:
27-
* BMC has received the whole request from system software.
28-
* KCS_PHASE_WAIT_READ:
29-
* BMC is waiting the response from the upper IPMI service.
30-
* KCS_PHASE_READ:
31-
* BMC is transferring the response to system software.
32-
* KCS_PHASE_ABORT_ERROR1:
33-
* BMC is waiting error status request from system software.
34-
* KCS_PHASE_ABORT_ERROR2:
35-
* BMC is waiting for idle status afer error from system software.
36-
* KCS_PHASE_ERROR:
37-
* BMC has detected a protocol violation at the interface level.
38-
*/
39-
enum kcs_phases {
40-
KCS_PHASE_IDLE,
41-
42-
KCS_PHASE_WRITE_START,
43-
KCS_PHASE_WRITE_DATA,
44-
KCS_PHASE_WRITE_END_CMD,
45-
KCS_PHASE_WRITE_DONE,
46-
47-
KCS_PHASE_WAIT_READ,
48-
KCS_PHASE_READ,
49-
50-
KCS_PHASE_ABORT_ERROR1,
51-
KCS_PHASE_ABORT_ERROR2,
52-
KCS_PHASE_ERROR
53-
};
54-
55-
/* IPMI 2.0 - Table 9-4, KCS Interface Status Codes */
56-
enum kcs_errors {
57-
KCS_NO_ERROR = 0x00,
58-
KCS_ABORTED_BY_COMMAND = 0x01,
59-
KCS_ILLEGAL_CONTROL_CODE = 0x02,
60-
KCS_LENGTH_ERROR = 0x06,
61-
KCS_UNSPECIFIED_ERROR = 0xFF
62-
};
63-
6415
/* IPMI 2.0 - 9.5, KCS Interface Registers
6516
* @idr: Input Data Register
6617
* @odr: Output Data Register
@@ -73,36 +24,20 @@ struct kcs_ioreg {
7324
};
7425

7526
struct kcs_bmc_device_ops;
27+
struct kcs_bmc_client;
7628

77-
struct kcs_bmc {
78-
struct device *dev;
79-
80-
const struct kcs_bmc_device_ops *ops;
81-
82-
struct kcs_bmc_client client;
83-
84-
spinlock_t lock;
29+
struct kcs_bmc_device {
30+
struct list_head entry;
8531

32+
struct device *dev;
8633
u32 channel;
87-
int running;
8834

8935
struct kcs_ioreg ioreg;
9036

91-
enum kcs_phases phase;
92-
enum kcs_errors error;
93-
94-
wait_queue_head_t queue;
95-
bool data_in_avail;
96-
int data_in_idx;
97-
u8 *data_in;
98-
99-
int data_out_idx;
100-
int data_out_len;
101-
u8 *data_out;
102-
103-
struct mutex mutex;
104-
u8 *kbuffer;
37+
const struct kcs_bmc_device_ops *ops;
10538

106-
struct miscdevice miscdev;
39+
spinlock_t lock;
40+
struct kcs_bmc_client *client;
10741
};
42+
10843
#endif /* __KCS_BMC_H__ */

drivers/char/ipmi/kcs_bmc_aspeed.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
#define LPC_STR4 0x11C
6262

6363
struct aspeed_kcs_bmc {
64-
struct kcs_bmc kcs_bmc;
64+
struct kcs_bmc_device kcs_bmc;
6565

6666
struct regmap *map;
6767
};
@@ -71,12 +71,12 @@ struct aspeed_kcs_of_ops {
7171
int (*get_io_address)(struct platform_device *pdev);
7272
};
7373

74-
static inline struct aspeed_kcs_bmc *to_aspeed_kcs_bmc(struct kcs_bmc *kcs_bmc)
74+
static inline struct aspeed_kcs_bmc *to_aspeed_kcs_bmc(struct kcs_bmc_device *kcs_bmc)
7575
{
7676
return container_of(kcs_bmc, struct aspeed_kcs_bmc, kcs_bmc);
7777
}
7878

79-
static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg)
79+
static u8 aspeed_kcs_inb(struct kcs_bmc_device *kcs_bmc, u32 reg)
8080
{
8181
struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc);
8282
u32 val = 0;
@@ -88,7 +88,7 @@ static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg)
8888
return rc == 0 ? (u8) val : 0;
8989
}
9090

91-
static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data)
91+
static void aspeed_kcs_outb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 data)
9292
{
9393
struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc);
9494
int rc;
@@ -97,7 +97,7 @@ static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data)
9797
WARN(rc != 0, "regmap_write() failed: %d\n", rc);
9898
}
9999

100-
static void aspeed_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val)
100+
static void aspeed_kcs_updateb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, u8 val)
101101
{
102102
struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc);
103103
int rc;
@@ -119,7 +119,7 @@ static void aspeed_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val
119119
* C. KCS4
120120
* D / C : CA4h / CA5h
121121
*/
122-
static void aspeed_kcs_set_address(struct kcs_bmc *kcs_bmc, u16 addr)
122+
static void aspeed_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u16 addr)
123123
{
124124
struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc);
125125

@@ -153,7 +153,7 @@ static void aspeed_kcs_set_address(struct kcs_bmc *kcs_bmc, u16 addr)
153153
}
154154
}
155155

156-
static void aspeed_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable)
156+
static void aspeed_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enable)
157157
{
158158
struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc);
159159

@@ -228,12 +228,12 @@ static const struct kcs_bmc_device_ops aspeed_kcs_ops = {
228228

229229
static irqreturn_t aspeed_kcs_irq(int irq, void *arg)
230230
{
231-
struct kcs_bmc *kcs_bmc = arg;
231+
struct kcs_bmc_device *kcs_bmc = arg;
232232

233233
return kcs_bmc_handle_event(kcs_bmc);
234234
}
235235

236-
static int aspeed_kcs_config_irq(struct kcs_bmc *kcs_bmc,
236+
static int aspeed_kcs_config_irq(struct kcs_bmc_device *kcs_bmc,
237237
struct platform_device *pdev)
238238
{
239239
struct device *dev = &pdev->dev;
@@ -335,8 +335,8 @@ static int aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev)
335335
static int aspeed_kcs_probe(struct platform_device *pdev)
336336
{
337337
const struct aspeed_kcs_of_ops *ops;
338+
struct kcs_bmc_device *kcs_bmc;
338339
struct aspeed_kcs_bmc *priv;
339-
struct kcs_bmc *kcs_bmc;
340340
struct device_node *np;
341341
int rc, channel, addr;
342342

@@ -399,7 +399,7 @@ static int aspeed_kcs_probe(struct platform_device *pdev)
399399
static int aspeed_kcs_remove(struct platform_device *pdev)
400400
{
401401
struct aspeed_kcs_bmc *priv = platform_get_drvdata(pdev);
402-
struct kcs_bmc *kcs_bmc = &priv->kcs_bmc;
402+
struct kcs_bmc_device *kcs_bmc = &priv->kcs_bmc;
403403

404404
kcs_bmc_remove_device(kcs_bmc);
405405

0 commit comments

Comments
 (0)