[S390] cio: obtain mdc value per channel path
Add support to accumulate the number of 64K-bytes blocks all paths to a device at least support for a transport command. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
37e8952174
commit
ce322ccd53
|
@ -204,6 +204,8 @@ int ccw_device_tm_start_timeout(struct ccw_device *, struct tcw *,
|
||||||
unsigned long, u8, int);
|
unsigned long, u8, int);
|
||||||
int ccw_device_tm_intrg(struct ccw_device *cdev);
|
int ccw_device_tm_intrg(struct ccw_device *cdev);
|
||||||
|
|
||||||
|
int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask);
|
||||||
|
|
||||||
extern int ccw_device_set_online(struct ccw_device *cdev);
|
extern int ccw_device_set_online(struct ccw_device *cdev);
|
||||||
extern int ccw_device_set_offline(struct ccw_device *cdev);
|
extern int ccw_device_set_offline(struct ccw_device *cdev);
|
||||||
|
|
||||||
|
|
|
@ -695,6 +695,25 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int chsc_determine_fmt1_channel_path_desc(struct chp_id chpid,
|
||||||
|
struct channel_path_desc_fmt1 *desc)
|
||||||
|
{
|
||||||
|
struct chsc_response_struct *chsc_resp;
|
||||||
|
struct chsc_scpd *scpd_area;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
spin_lock_irq(&chsc_page_lock);
|
||||||
|
scpd_area = chsc_page;
|
||||||
|
ret = chsc_determine_channel_path_desc(chpid, 0, 0, 1, 0, scpd_area);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
chsc_resp = (void *)&scpd_area->response;
|
||||||
|
memcpy(desc, &chsc_resp->data, sizeof(*desc));
|
||||||
|
out:
|
||||||
|
spin_unlock_irq(&chsc_page_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,
|
chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,
|
||||||
struct cmg_chars *chars)
|
struct cmg_chars *chars)
|
||||||
|
|
|
@ -35,6 +35,22 @@ struct channel_path_desc {
|
||||||
u8 chpp;
|
u8 chpp;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct channel_path_desc_fmt1 {
|
||||||
|
u8 flags;
|
||||||
|
u8 lsn;
|
||||||
|
u8 desc;
|
||||||
|
u8 chpid;
|
||||||
|
u32:24;
|
||||||
|
u8 chpp;
|
||||||
|
u32 unused[3];
|
||||||
|
u16 mdc;
|
||||||
|
u16:13;
|
||||||
|
u8 r:1;
|
||||||
|
u8 s:1;
|
||||||
|
u8 f:1;
|
||||||
|
u32 zeros[2];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct channel_path;
|
struct channel_path;
|
||||||
|
|
||||||
struct css_chsc_char {
|
struct css_chsc_char {
|
||||||
|
@ -92,6 +108,8 @@ int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt,
|
||||||
int c, int m, void *page);
|
int c, int m, void *page);
|
||||||
int chsc_determine_base_channel_path_desc(struct chp_id chpid,
|
int chsc_determine_base_channel_path_desc(struct chp_id chpid,
|
||||||
struct channel_path_desc *desc);
|
struct channel_path_desc *desc);
|
||||||
|
int chsc_determine_fmt1_channel_path_desc(struct chp_id chpid,
|
||||||
|
struct channel_path_desc_fmt1 *desc);
|
||||||
void chsc_chp_online(struct chp_id chpid);
|
void chsc_chp_online(struct chp_id chpid);
|
||||||
void chsc_chp_offline(struct chp_id chpid);
|
void chsc_chp_offline(struct chp_id chpid);
|
||||||
int chsc_get_channel_measurement_chars(struct channel_path *chp);
|
int chsc_get_channel_measurement_chars(struct channel_path *chp);
|
||||||
|
|
|
@ -686,6 +686,46 @@ int ccw_device_tm_start_timeout(struct ccw_device *cdev, struct tcw *tcw,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ccw_device_tm_start_timeout);
|
EXPORT_SYMBOL(ccw_device_tm_start_timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ccw_device_get_mdc - accumulate max data count
|
||||||
|
* @cdev: ccw device for which the max data count is accumulated
|
||||||
|
* @mask: mask of paths to use
|
||||||
|
*
|
||||||
|
* Return the number of 64K-bytes blocks all paths at least support
|
||||||
|
* for a transport command. Return values <= 0 indicate failures.
|
||||||
|
*/
|
||||||
|
int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask)
|
||||||
|
{
|
||||||
|
struct subchannel *sch = to_subchannel(cdev->dev.parent);
|
||||||
|
struct channel_path_desc_fmt1 desc;
|
||||||
|
struct chp_id chpid;
|
||||||
|
int mdc = 0, ret, i;
|
||||||
|
|
||||||
|
/* Adjust requested path mask to excluded varied off paths. */
|
||||||
|
if (mask)
|
||||||
|
mask &= sch->lpm;
|
||||||
|
else
|
||||||
|
mask = sch->lpm;
|
||||||
|
|
||||||
|
chp_id_init(&chpid);
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (!(mask & (0x80 >> i)))
|
||||||
|
continue;
|
||||||
|
chpid.id = sch->schib.pmcw.chpid[i];
|
||||||
|
ret = chsc_determine_fmt1_channel_path_desc(chpid, &desc);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
if (!desc.f)
|
||||||
|
return 0;
|
||||||
|
if (!desc.r)
|
||||||
|
mdc = 1;
|
||||||
|
mdc = mdc ? min(mdc, (int)desc.mdc) : desc.mdc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mdc;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ccw_device_get_mdc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ccw_device_tm_intrg - perform interrogate function
|
* ccw_device_tm_intrg - perform interrogate function
|
||||||
* @cdev: ccw device on which to perform the interrogate function
|
* @cdev: ccw device on which to perform the interrogate function
|
||||||
|
|
Loading…
Reference in New Issue