s390/cio: Helper functions to read CSSID, IID, and CHID

Add helper functions to expose Channel Subsystem ID (CSSID), MIF Image Id
(IID), Channel ID (CHID) and Channel Path ID (CHPID).
These values are required by the qeth driver's exploitation of network-
address-change-notifications to determine which entries belong to this
interface.

Store the Partition identifier in System log, as this may be used to map
a Linux view to a Hardware view for debugging purpose.

Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Alexandra Winter 2020-09-10 19:23:45 +02:00 committed by David S. Miller
parent 4fea49a79e
commit b983aa1f7d
6 changed files with 108 additions and 9 deletions

View file

@ -240,4 +240,8 @@ u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx);
int ccw_device_pnso(struct ccw_device *cdev,
struct chsc_pnso_area *pnso_area, u8 oc,
struct chsc_pnso_resume_token resume_token, int cnc);
int ccw_device_get_cssid(struct ccw_device *cdev, u8 *cssid);
int ccw_device_get_iid(struct ccw_device *cdev, u8 *iid);
int ccw_device_get_chpid(struct ccw_device *cdev, int chp_idx, u8 *chpid);
int ccw_device_get_chid(struct ccw_device *cdev, int chp_idx, u16 *chid);
#endif /* _S390_CCWDEV_H_ */

View file

@ -1116,7 +1116,7 @@ int chsc_enable_facility(int operation_code)
return ret;
}
int __init chsc_get_cssid(int idx)
int __init chsc_get_cssid_iid(int idx, u8 *cssid, u8 *iid)
{
struct {
struct chsc_header request;
@ -1127,7 +1127,8 @@ int __init chsc_get_cssid(int idx)
u32 reserved2[3];
struct {
u8 cssid;
u32 : 24;
u8 iid;
u32 : 16;
} list[0];
} *sdcal_area;
int ret;
@ -1153,8 +1154,10 @@ int __init chsc_get_cssid(int idx)
}
if ((addr_t) &sdcal_area->list[idx] <
(addr_t) &sdcal_area->response + sdcal_area->response.length)
ret = sdcal_area->list[idx].cssid;
(addr_t) &sdcal_area->response + sdcal_area->response.length) {
*cssid = sdcal_area->list[idx].cssid;
*iid = sdcal_area->list[idx].iid;
}
else
ret = -ENODEV;
exit:

View file

@ -208,7 +208,7 @@ int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token);
int chsc_pnso(struct subchannel_id schid, struct chsc_pnso_area *pnso_area,
u8 oc, struct chsc_pnso_resume_token resume_token, int cnc);
int __init chsc_get_cssid(int idx);
int __init chsc_get_cssid_iid(int idx, u8 *cssid, u8 *iid);
#ifdef CONFIG_SCM_BUS
int scm_update_information(void);

View file

@ -854,7 +854,7 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high)
if (css_general_characteristics.mcss) {
css->global_pgid.pgid_high.ext_cssid.version = 0x80;
css->global_pgid.pgid_high.ext_cssid.cssid =
(css->cssid < 0) ? 0 : css->cssid;
css->id_valid ? css->cssid : 0;
} else {
css->global_pgid.pgid_high.cpu_addr = stap();
}
@ -877,7 +877,7 @@ static ssize_t real_cssid_show(struct device *dev, struct device_attribute *a,
{
struct channel_subsystem *css = to_css(dev);
if (css->cssid < 0)
if (!css->id_valid)
return -EINVAL;
return sprintf(buf, "%x\n", css->cssid);
@ -975,7 +975,12 @@ static int __init setup_css(int nr)
css->device.dma_mask = &css->device.coherent_dma_mask;
mutex_init(&css->mutex);
css->cssid = chsc_get_cssid(nr);
ret = chsc_get_cssid_iid(nr, &css->cssid, &css->iid);
if (!ret) {
css->id_valid = true;
pr_info("Partition identifier %01x.%01x\n", css->cssid,
css->iid);
}
css_generate_pgid(css, (u32) (get_tod_clock() >> 32));
ret = device_register(&css->device);

View file

@ -115,7 +115,9 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
void css_update_ssd_info(struct subchannel *sch);
struct channel_subsystem {
int cssid;
u8 cssid;
u8 iid;
bool id_valid; /* cssid,iid */
struct channel_path *chps[__MAX_CHPID + 1];
struct device device;
struct pgid global_pgid;

View file

@ -733,6 +733,91 @@ int ccw_device_pnso(struct ccw_device *cdev,
}
EXPORT_SYMBOL_GPL(ccw_device_pnso);
/**
* ccw_device_get_cssid() - obtain Channel Subsystem ID
* @cdev: device to obtain the CSSID for
* @cssid: The resulting Channel Subsystem ID
*/
int ccw_device_get_cssid(struct ccw_device *cdev, u8 *cssid)
{
struct device *sch_dev = cdev->dev.parent;
struct channel_subsystem *css = to_css(sch_dev->parent);
if (css->id_valid)
*cssid = css->cssid;
return css->id_valid ? 0 : -ENODEV;
}
EXPORT_SYMBOL_GPL(ccw_device_get_cssid);
/**
* ccw_device_get_iid() - obtain MIF-image ID
* @cdev: device to obtain the MIF-image ID for
* @iid: The resulting MIF-image ID
*/
int ccw_device_get_iid(struct ccw_device *cdev, u8 *iid)
{
struct device *sch_dev = cdev->dev.parent;
struct channel_subsystem *css = to_css(sch_dev->parent);
if (css->id_valid)
*iid = css->iid;
return css->id_valid ? 0 : -ENODEV;
}
EXPORT_SYMBOL_GPL(ccw_device_get_iid);
/**
* ccw_device_get_chpid() - obtain Channel Path ID
* @cdev: device to obtain the Channel Path ID for
* @chp_idx: Index of the channel path
* @chpid: The resulting Channel Path ID
*/
int ccw_device_get_chpid(struct ccw_device *cdev, int chp_idx, u8 *chpid)
{
struct subchannel *sch = to_subchannel(cdev->dev.parent);
int mask;
if ((chp_idx < 0) || (chp_idx > 7))
return -EINVAL;
mask = 0x80 >> chp_idx;
if (!(sch->schib.pmcw.pim & mask))
return -ENODEV;
*chpid = sch->schib.pmcw.chpid[chp_idx];
return 0;
}
EXPORT_SYMBOL_GPL(ccw_device_get_chpid);
/**
* ccw_device_get_chid() - obtain Channel ID associated with specified CHPID
* @cdev: device to obtain the Channel ID for
* @chp_idx: Index of the channel path
* @chid: The resulting Channel ID
*/
int ccw_device_get_chid(struct ccw_device *cdev, int chp_idx, u16 *chid)
{
struct chp_id cssid_chpid;
struct channel_path *chp;
int rc;
chp_id_init(&cssid_chpid);
rc = ccw_device_get_chpid(cdev, chp_idx, &cssid_chpid.id);
if (rc)
return rc;
chp = chpid_to_chp(cssid_chpid);
if (!chp)
return -ENODEV;
mutex_lock(&chp->lock);
if (chp->desc_fmt1.flags & 0x10)
*chid = chp->desc_fmt1.chid;
else
rc = -ENODEV;
mutex_unlock(&chp->lock);
return rc;
}
EXPORT_SYMBOL_GPL(ccw_device_get_chid);
/*
* Allocate zeroed dma coherent 31 bit addressable memory using
* the subchannels dma pool. Maximal size of allocation supported