Skip to content

Commit a941b78

Browse files
nipung87Alex Williamson
authored andcommitted
cdx: add support for bus mastering
Introduce cdx_set_master() and cdx_clear_master() APIs to support enable and disable of bus mastering. Drivers need to use these APIs to enable/disable DMAs from the CDX devices. Signed-off-by: Nipun Gupta <nipun.gupta@amd.com> Reviewed-by: Pieter Jansen van Vuuren <pieter.jansen-van-vuuren@amd.com> Link: https://lore.kernel.org/r/20230915045423.31630-1-nipun.gupta@amd.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
1 parent a1e16a3 commit a941b78

5 files changed

Lines changed: 125 additions & 0 deletions

File tree

drivers/cdx/cdx.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,38 @@ cdx_match_id(const struct cdx_device_id *ids, struct cdx_device *dev)
182182
return NULL;
183183
}
184184

185+
int cdx_set_master(struct cdx_device *cdx_dev)
186+
{
187+
struct cdx_controller *cdx = cdx_dev->cdx;
188+
struct cdx_device_config dev_config;
189+
int ret = -EOPNOTSUPP;
190+
191+
dev_config.type = CDX_DEV_BUS_MASTER_CONF;
192+
dev_config.bus_master_enable = true;
193+
if (cdx->ops->dev_configure)
194+
ret = cdx->ops->dev_configure(cdx, cdx_dev->bus_num,
195+
cdx_dev->dev_num, &dev_config);
196+
197+
return ret;
198+
}
199+
EXPORT_SYMBOL_GPL(cdx_set_master);
200+
201+
int cdx_clear_master(struct cdx_device *cdx_dev)
202+
{
203+
struct cdx_controller *cdx = cdx_dev->cdx;
204+
struct cdx_device_config dev_config;
205+
int ret = -EOPNOTSUPP;
206+
207+
dev_config.type = CDX_DEV_BUS_MASTER_CONF;
208+
dev_config.bus_master_enable = false;
209+
if (cdx->ops->dev_configure)
210+
ret = cdx->ops->dev_configure(cdx, cdx_dev->bus_num,
211+
cdx_dev->dev_num, &dev_config);
212+
213+
return ret;
214+
}
215+
EXPORT_SYMBOL_GPL(cdx_clear_master);
216+
185217
/**
186218
* cdx_bus_match - device to driver matching callback
187219
* @dev: the cdx device to match against

drivers/cdx/controller/cdx_controller.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ static int cdx_configure_device(struct cdx_controller *cdx,
5656
case CDX_DEV_RESET_CONF:
5757
ret = cdx_mcdi_reset_device(cdx->priv, bus_num, dev_num);
5858
break;
59+
case CDX_DEV_BUS_MASTER_CONF:
60+
ret = cdx_mcdi_bus_master_enable(cdx->priv, bus_num, dev_num,
61+
dev_config->bus_master_enable);
62+
break;
5963
default:
6064
ret = -EINVAL;
6165
}

drivers/cdx/controller/mcdi_functions.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,61 @@ int cdx_mcdi_reset_device(struct cdx_mcdi *cdx, u8 bus_num, u8 dev_num)
137137

138138
return ret;
139139
}
140+
141+
static int cdx_mcdi_ctrl_flag_get(struct cdx_mcdi *cdx, u8 bus_num,
142+
u8 dev_num, u32 *flags)
143+
{
144+
MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_CONTROL_GET_IN_LEN);
145+
MCDI_DECLARE_BUF(outbuf, MC_CMD_CDX_DEVICE_CONTROL_GET_OUT_LEN);
146+
size_t outlen;
147+
int ret;
148+
149+
MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_GET_IN_BUS, bus_num);
150+
MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_GET_IN_DEVICE, dev_num);
151+
ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_DEVICE_CONTROL_GET, inbuf,
152+
sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
153+
if (ret)
154+
return ret;
155+
156+
if (outlen != MC_CMD_CDX_DEVICE_CONTROL_GET_OUT_LEN)
157+
return -EIO;
158+
159+
*flags = MCDI_DWORD(outbuf, CDX_DEVICE_CONTROL_GET_OUT_FLAGS);
160+
161+
return 0;
162+
}
163+
164+
static int cdx_mcdi_ctrl_flag_set(struct cdx_mcdi *cdx, u8 bus_num,
165+
u8 dev_num, bool enable, int bit_pos)
166+
{
167+
MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_CONTROL_SET_IN_LEN);
168+
u32 flags;
169+
int ret;
170+
171+
/*
172+
* Get flags and then set/reset bit at bit_pos according to
173+
* the input params.
174+
*/
175+
ret = cdx_mcdi_ctrl_flag_get(cdx, bus_num, dev_num, &flags);
176+
if (ret)
177+
return ret;
178+
179+
flags = flags & (u32)(~(BIT(bit_pos)));
180+
if (enable)
181+
flags |= (1 << bit_pos);
182+
183+
MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_SET_IN_BUS, bus_num);
184+
MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_SET_IN_DEVICE, dev_num);
185+
MCDI_SET_DWORD(inbuf, CDX_DEVICE_CONTROL_SET_IN_FLAGS, flags);
186+
ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_DEVICE_CONTROL_SET, inbuf,
187+
sizeof(inbuf), NULL, 0, NULL);
188+
189+
return ret;
190+
}
191+
192+
int cdx_mcdi_bus_master_enable(struct cdx_mcdi *cdx, u8 bus_num,
193+
u8 dev_num, bool enable)
194+
{
195+
return cdx_mcdi_ctrl_flag_set(cdx, bus_num, dev_num, enable,
196+
MC_CMD_CDX_DEVICE_CONTROL_SET_IN_BUS_MASTER_ENABLE_LBN);
197+
}

drivers/cdx/controller/mcdi_functions.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,17 @@ int cdx_mcdi_get_dev_config(struct cdx_mcdi *cdx,
5858
int cdx_mcdi_reset_device(struct cdx_mcdi *cdx,
5959
u8 bus_num, u8 dev_num);
6060

61+
/**
62+
* cdx_mcdi_bus_master_enable - Set/Reset bus mastering for cdx device
63+
* represented by bus_num:dev_num
64+
* @cdx: pointer to MCDI interface.
65+
* @bus_num: Bus number.
66+
* @dev_num: Device number.
67+
* @enable: Enable bus mastering if set, disable otherwise.
68+
*
69+
* Return: 0 on success, <0 on failure
70+
*/
71+
int cdx_mcdi_bus_master_enable(struct cdx_mcdi *cdx, u8 bus_num,
72+
u8 dev_num, bool enable);
73+
6174
#endif /* CDX_MCDI_FUNCTIONS_H */

include/linux/cdx/cdx_bus.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@
2121
struct cdx_controller;
2222

2323
enum {
24+
CDX_DEV_BUS_MASTER_CONF,
2425
CDX_DEV_RESET_CONF,
2526
};
2627

2728
struct cdx_device_config {
2829
u8 type;
30+
bool bus_master_enable;
2931
};
3032

3133
typedef int (*cdx_scan_cb)(struct cdx_controller *cdx);
@@ -170,4 +172,20 @@ extern struct bus_type cdx_bus_type;
170172
*/
171173
int cdx_dev_reset(struct device *dev);
172174

175+
/**
176+
* cdx_set_master - enables bus-mastering for CDX device
177+
* @cdx_dev: the CDX device to enable
178+
*
179+
* Return: 0 for success, -errno on failure
180+
*/
181+
int cdx_set_master(struct cdx_device *cdx_dev);
182+
183+
/**
184+
* cdx_clear_master - disables bus-mastering for CDX device
185+
* @cdx_dev: the CDX device to disable
186+
*
187+
* Return: 0 for success, -errno on failure
188+
*/
189+
int cdx_clear_master(struct cdx_device *cdx_dev);
190+
173191
#endif /* _CDX_BUS_H_ */

0 commit comments

Comments
 (0)