Commit b983aa1f authored by Alexandra Winter's avatar Alexandra Winter Committed by David S. Miller

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: default avatarAlexandra Winter <wintera@linux.ibm.com>
Reviewed-by: default avatarVineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Acked-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4fea49a7
...@@ -240,4 +240,8 @@ u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx); ...@@ -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, int ccw_device_pnso(struct ccw_device *cdev,
struct chsc_pnso_area *pnso_area, u8 oc, struct chsc_pnso_area *pnso_area, u8 oc,
struct chsc_pnso_resume_token resume_token, int cnc); 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_ */ #endif /* _S390_CCWDEV_H_ */
...@@ -1116,7 +1116,7 @@ int chsc_enable_facility(int operation_code) ...@@ -1116,7 +1116,7 @@ int chsc_enable_facility(int operation_code)
return ret; return ret;
} }
int __init chsc_get_cssid(int idx) int __init chsc_get_cssid_iid(int idx, u8 *cssid, u8 *iid)
{ {
struct { struct {
struct chsc_header request; struct chsc_header request;
...@@ -1127,7 +1127,8 @@ int __init chsc_get_cssid(int idx) ...@@ -1127,7 +1127,8 @@ int __init chsc_get_cssid(int idx)
u32 reserved2[3]; u32 reserved2[3];
struct { struct {
u8 cssid; u8 cssid;
u32 : 24; u8 iid;
u32 : 16;
} list[0]; } list[0];
} *sdcal_area; } *sdcal_area;
int ret; int ret;
...@@ -1153,8 +1154,10 @@ int __init chsc_get_cssid(int idx) ...@@ -1153,8 +1154,10 @@ int __init chsc_get_cssid(int idx)
} }
if ((addr_t) &sdcal_area->list[idx] < if ((addr_t) &sdcal_area->list[idx] <
(addr_t) &sdcal_area->response + sdcal_area->response.length) (addr_t) &sdcal_area->response + sdcal_area->response.length) {
ret = sdcal_area->list[idx].cssid; *cssid = sdcal_area->list[idx].cssid;
*iid = sdcal_area->list[idx].iid;
}
else else
ret = -ENODEV; ret = -ENODEV;
exit: exit:
......
...@@ -208,7 +208,7 @@ int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token); ...@@ -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, int chsc_pnso(struct subchannel_id schid, struct chsc_pnso_area *pnso_area,
u8 oc, struct chsc_pnso_resume_token resume_token, int cnc); 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 #ifdef CONFIG_SCM_BUS
int scm_update_information(void); int scm_update_information(void);
......
...@@ -854,7 +854,7 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high) ...@@ -854,7 +854,7 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high)
if (css_general_characteristics.mcss) { if (css_general_characteristics.mcss) {
css->global_pgid.pgid_high.ext_cssid.version = 0x80; css->global_pgid.pgid_high.ext_cssid.version = 0x80;
css->global_pgid.pgid_high.ext_cssid.cssid = css->global_pgid.pgid_high.ext_cssid.cssid =
(css->cssid < 0) ? 0 : css->cssid; css->id_valid ? css->cssid : 0;
} else { } else {
css->global_pgid.pgid_high.cpu_addr = stap(); 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, ...@@ -877,7 +877,7 @@ static ssize_t real_cssid_show(struct device *dev, struct device_attribute *a,
{ {
struct channel_subsystem *css = to_css(dev); struct channel_subsystem *css = to_css(dev);
if (css->cssid < 0) if (!css->id_valid)
return -EINVAL; return -EINVAL;
return sprintf(buf, "%x\n", css->cssid); return sprintf(buf, "%x\n", css->cssid);
...@@ -975,7 +975,12 @@ static int __init setup_css(int nr) ...@@ -975,7 +975,12 @@ static int __init setup_css(int nr)
css->device.dma_mask = &css->device.coherent_dma_mask; css->device.dma_mask = &css->device.coherent_dma_mask;
mutex_init(&css->mutex); 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)); css_generate_pgid(css, (u32) (get_tod_clock() >> 32));
ret = device_register(&css->device); ret = device_register(&css->device);
......
...@@ -115,7 +115,9 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); ...@@ -115,7 +115,9 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
void css_update_ssd_info(struct subchannel *sch); void css_update_ssd_info(struct subchannel *sch);
struct channel_subsystem { struct channel_subsystem {
int cssid; u8 cssid;
u8 iid;
bool id_valid; /* cssid,iid */
struct channel_path *chps[__MAX_CHPID + 1]; struct channel_path *chps[__MAX_CHPID + 1];
struct device device; struct device device;
struct pgid global_pgid; struct pgid global_pgid;
......
...@@ -733,6 +733,91 @@ int ccw_device_pnso(struct ccw_device *cdev, ...@@ -733,6 +733,91 @@ int ccw_device_pnso(struct ccw_device *cdev,
} }
EXPORT_SYMBOL_GPL(ccw_device_pnso); 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 * Allocate zeroed dma coherent 31 bit addressable memory using
* the subchannels dma pool. Maximal size of allocation supported * the subchannels dma pool. Maximal size of allocation supported
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment