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_ */
 
        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;
                u32 reserved2[3];
                struct {
                        u8 cssid;
-                       u32 : 24;
+                       u8 iid;
+                       u32 : 16;
                } list[0];
        } *sdcal_area;
        int ret;
        }
 
        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:
 
        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();
        }
 {
        struct channel_subsystem *css = to_css(dev);
 
-       if (css->cssid < 0)
+       if (!css->id_valid)
                return -EINVAL;
 
        return sprintf(buf, "%x\n", css->cssid);
        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);
 
 }
 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