[S390] cio: introduce cio_commit_config
To change the configuration of a subchannel we alter the modifiable bits of the subchannel's schib field and issue a modify subchannel. There can be the case that not all changes were applied -or worse- quietly overwritten by the hardware. With the next store subchannel we obtain the current state of the hardware but lose our target configuration. With this patch we introduce a subchannel_config structure which contains the target subchannel configuration. Additionally the msch wrapper cio_modify is replaced with cio_commit_config which copies the desired changes to a temporary schib. msch is then called with the temporary schib. This schib is only written back to the subchannel if all changes were applied. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
committed by
Martin Schwidefsky
parent
cdb912a40d
commit
13952ec12d
@@ -330,27 +330,67 @@ cio_cancel (struct subchannel *sch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Function: cio_modify
|
|
||||||
* Issues a "Modify Subchannel" on the specified subchannel
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cio_modify (struct subchannel *sch)
|
|
||||||
{
|
|
||||||
int ccode, retry, ret;
|
|
||||||
|
|
||||||
ret = 0;
|
static void cio_apply_config(struct subchannel *sch, struct schib *schib)
|
||||||
|
{
|
||||||
|
schib->pmcw.intparm = sch->config.intparm;
|
||||||
|
schib->pmcw.mbi = sch->config.mbi;
|
||||||
|
schib->pmcw.isc = sch->config.isc;
|
||||||
|
schib->pmcw.ena = sch->config.ena;
|
||||||
|
schib->pmcw.mme = sch->config.mme;
|
||||||
|
schib->pmcw.mp = sch->config.mp;
|
||||||
|
schib->pmcw.csense = sch->config.csense;
|
||||||
|
schib->pmcw.mbfc = sch->config.mbfc;
|
||||||
|
if (sch->config.mbfc)
|
||||||
|
schib->mba = sch->config.mba;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cio_check_config(struct subchannel *sch, struct schib *schib)
|
||||||
|
{
|
||||||
|
return (schib->pmcw.intparm == sch->config.intparm) &&
|
||||||
|
(schib->pmcw.mbi == sch->config.mbi) &&
|
||||||
|
(schib->pmcw.isc == sch->config.isc) &&
|
||||||
|
(schib->pmcw.ena == sch->config.ena) &&
|
||||||
|
(schib->pmcw.mme == sch->config.mme) &&
|
||||||
|
(schib->pmcw.mp == sch->config.mp) &&
|
||||||
|
(schib->pmcw.csense == sch->config.csense) &&
|
||||||
|
(schib->pmcw.mbfc == sch->config.mbfc) &&
|
||||||
|
(!sch->config.mbfc || (schib->mba == sch->config.mba));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cio_commit_config - apply configuration to the subchannel
|
||||||
|
*/
|
||||||
|
int cio_commit_config(struct subchannel *sch)
|
||||||
|
{
|
||||||
|
struct schib schib;
|
||||||
|
int ccode, retry, ret = 0;
|
||||||
|
|
||||||
|
if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
for (retry = 0; retry < 5; retry++) {
|
for (retry = 0; retry < 5; retry++) {
|
||||||
ccode = msch_err (sch->schid, &sch->schib);
|
/* copy desired changes to local schib */
|
||||||
|
cio_apply_config(sch, &schib);
|
||||||
|
ccode = msch_err(sch->schid, &schib);
|
||||||
if (ccode < 0) /* -EIO if msch gets a program check. */
|
if (ccode < 0) /* -EIO if msch gets a program check. */
|
||||||
return ccode;
|
return ccode;
|
||||||
switch (ccode) {
|
switch (ccode) {
|
||||||
case 0: /* successfull */
|
case 0: /* successfull */
|
||||||
|
if (stsch(sch->schid, &schib) ||
|
||||||
|
!css_sch_is_valid(&schib))
|
||||||
|
return -ENODEV;
|
||||||
|
if (cio_check_config(sch, &schib)) {
|
||||||
|
/* commit changes from local schib */
|
||||||
|
memcpy(&sch->schib, &schib, sizeof(schib));
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
ret = -EAGAIN;
|
||||||
|
break;
|
||||||
case 1: /* status pending */
|
case 1: /* status pending */
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
case 2: /* busy */
|
case 2: /* busy */
|
||||||
udelay (100); /* allow for recovery */
|
udelay(100); /* allow for recovery */
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
break;
|
break;
|
||||||
case 3: /* not operational */
|
case 3: /* not operational */
|
||||||
@@ -396,32 +436,24 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
|
|||||||
if (cio_update_schib(sch))
|
if (cio_update_schib(sch))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
for (retry = 5, ret = 0; retry > 0; retry--) {
|
sch->config.ena = 1;
|
||||||
sch->schib.pmcw.ena = 1;
|
sch->config.isc = sch->isc;
|
||||||
sch->schib.pmcw.isc = sch->isc;
|
sch->config.intparm = intparm;
|
||||||
sch->schib.pmcw.intparm = intparm;
|
|
||||||
ret = cio_modify(sch);
|
for (retry = 0; retry < 3; retry++) {
|
||||||
if (ret == -ENODEV)
|
ret = cio_commit_config(sch);
|
||||||
break;
|
if (ret == -EIO) {
|
||||||
if (ret == -EIO)
|
|
||||||
/*
|
/*
|
||||||
* Got a program check in cio_modify. Try without
|
* Got a program check in msch. Try without
|
||||||
* the concurrent sense bit the next time.
|
* the concurrent sense bit the next time.
|
||||||
*/
|
*/
|
||||||
sch->schib.pmcw.csense = 0;
|
sch->config.csense = 0;
|
||||||
if (ret == 0) {
|
} else if (ret == -EBUSY) {
|
||||||
if (cio_update_schib(sch)) {
|
|
||||||
ret = -ENODEV;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (sch->schib.pmcw.ena)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ret == -EBUSY) {
|
|
||||||
struct irb irb;
|
struct irb irb;
|
||||||
if (tsch(sch->schid, &irb) != 0)
|
if (tsch(sch->schid, &irb) != 0)
|
||||||
break;
|
break;
|
||||||
}
|
} else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
sprintf (dbf_txt, "ret:%d", ret);
|
sprintf (dbf_txt, "ret:%d", ret);
|
||||||
CIO_TRACE_EVENT (2, dbf_txt);
|
CIO_TRACE_EVENT (2, dbf_txt);
|
||||||
@@ -436,7 +468,6 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel);
|
|||||||
int cio_disable_subchannel(struct subchannel *sch)
|
int cio_disable_subchannel(struct subchannel *sch)
|
||||||
{
|
{
|
||||||
char dbf_txt[15];
|
char dbf_txt[15];
|
||||||
int retry;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
CIO_TRACE_EVENT (2, "dissch");
|
CIO_TRACE_EVENT (2, "dissch");
|
||||||
@@ -454,27 +485,9 @@ int cio_disable_subchannel(struct subchannel *sch)
|
|||||||
*/
|
*/
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
for (retry = 5, ret = 0; retry > 0; retry--) {
|
sch->config.ena = 0;
|
||||||
sch->schib.pmcw.ena = 0;
|
ret = cio_commit_config(sch);
|
||||||
ret = cio_modify(sch);
|
|
||||||
if (ret == -ENODEV)
|
|
||||||
break;
|
|
||||||
if (ret == -EBUSY)
|
|
||||||
/*
|
|
||||||
* The subchannel is busy or status pending.
|
|
||||||
* We'll disable when the next interrupt was delivered
|
|
||||||
* via the state machine.
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
if (ret == 0) {
|
|
||||||
if (cio_update_schib(sch)) {
|
|
||||||
ret = -ENODEV;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!sch->schib.pmcw.ena)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sprintf (dbf_txt, "ret:%d", ret);
|
sprintf (dbf_txt, "ret:%d", ret);
|
||||||
CIO_TRACE_EVENT (2, dbf_txt);
|
CIO_TRACE_EVENT (2, dbf_txt);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -817,10 +830,9 @@ cio_probe_console(void)
|
|||||||
* enable console I/O-interrupt subclass
|
* enable console I/O-interrupt subclass
|
||||||
*/
|
*/
|
||||||
isc_register(CONSOLE_ISC);
|
isc_register(CONSOLE_ISC);
|
||||||
console_subchannel.schib.pmcw.isc = CONSOLE_ISC;
|
console_subchannel.config.isc = CONSOLE_ISC;
|
||||||
console_subchannel.schib.pmcw.intparm =
|
console_subchannel.config.intparm = (u32)(addr_t)&console_subchannel;
|
||||||
(u32)(addr_t)&console_subchannel;
|
ret = cio_commit_config(&console_subchannel);
|
||||||
ret = cio_modify(&console_subchannel);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
isc_unregister(CONSOLE_ISC);
|
isc_unregister(CONSOLE_ISC);
|
||||||
console_subchannel_in_use = 0;
|
console_subchannel_in_use = 0;
|
||||||
@@ -832,8 +844,8 @@ cio_probe_console(void)
|
|||||||
void
|
void
|
||||||
cio_release_console(void)
|
cio_release_console(void)
|
||||||
{
|
{
|
||||||
console_subchannel.schib.pmcw.intparm = 0;
|
console_subchannel.config.intparm = 0;
|
||||||
cio_modify(&console_subchannel);
|
cio_commit_config(&console_subchannel);
|
||||||
isc_unregister(CONSOLE_ISC);
|
isc_unregister(CONSOLE_ISC);
|
||||||
console_subchannel_in_use = 0;
|
console_subchannel_in_use = 0;
|
||||||
}
|
}
|
||||||
|
@@ -45,6 +45,19 @@ struct pmcw {
|
|||||||
/* ... in an operand exception. */
|
/* ... in an operand exception. */
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/* Target SCHIB configuration. */
|
||||||
|
struct schib_config {
|
||||||
|
u64 mba;
|
||||||
|
u32 intparm;
|
||||||
|
u16 mbi;
|
||||||
|
u32 isc:3;
|
||||||
|
u32 ena:1;
|
||||||
|
u32 mme:2;
|
||||||
|
u32 mp:1;
|
||||||
|
u32 csense:1;
|
||||||
|
u32 mbfc:1;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* subchannel information block
|
* subchannel information block
|
||||||
*/
|
*/
|
||||||
@@ -83,6 +96,7 @@ struct subchannel {
|
|||||||
struct css_driver *driver;
|
struct css_driver *driver;
|
||||||
void *private; /* private per subchannel type data */
|
void *private; /* private per subchannel type data */
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
|
struct schib_config config;
|
||||||
} __attribute__ ((aligned(8)));
|
} __attribute__ ((aligned(8)));
|
||||||
|
|
||||||
#define IO_INTERRUPT_TYPE 0 /* I/O interrupt type */
|
#define IO_INTERRUPT_TYPE 0 /* I/O interrupt type */
|
||||||
@@ -101,8 +115,8 @@ extern int cio_start_key (struct subchannel *, struct ccw1 *, __u8, __u8);
|
|||||||
extern int cio_cancel (struct subchannel *);
|
extern int cio_cancel (struct subchannel *);
|
||||||
extern int cio_set_options (struct subchannel *, int);
|
extern int cio_set_options (struct subchannel *, int);
|
||||||
extern int cio_get_options (struct subchannel *);
|
extern int cio_get_options (struct subchannel *);
|
||||||
extern int cio_modify (struct subchannel *);
|
|
||||||
extern int cio_update_schib(struct subchannel *sch);
|
extern int cio_update_schib(struct subchannel *sch);
|
||||||
|
extern int cio_commit_config(struct subchannel *sch);
|
||||||
|
|
||||||
int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key);
|
int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key);
|
||||||
int cio_tm_intrg(struct subchannel *sch);
|
int cio_tm_intrg(struct subchannel *sch);
|
||||||
|
@@ -185,58 +185,19 @@ static inline void cmf_activate(void *area, unsigned int onoff)
|
|||||||
static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc,
|
static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc,
|
||||||
unsigned long address)
|
unsigned long address)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
int retry;
|
|
||||||
struct subchannel *sch;
|
struct subchannel *sch;
|
||||||
struct schib *schib;
|
|
||||||
|
|
||||||
sch = to_subchannel(cdev->dev.parent);
|
sch = to_subchannel(cdev->dev.parent);
|
||||||
schib = &sch->schib;
|
|
||||||
/* msch can silently fail, so do it again if necessary */
|
sch->config.mme = mme;
|
||||||
for (retry = 0; retry < 3; retry++) {
|
sch->config.mbfc = mbfc;
|
||||||
/* prepare schib */
|
|
||||||
if (cio_update_schib(sch))
|
|
||||||
return -ENODEV;
|
|
||||||
schib->pmcw.mme = mme;
|
|
||||||
schib->pmcw.mbfc = mbfc;
|
|
||||||
/* address can be either a block address or a block index */
|
/* address can be either a block address or a block index */
|
||||||
if (mbfc)
|
if (mbfc)
|
||||||
schib->mba = address;
|
sch->config.mba = address;
|
||||||
else
|
else
|
||||||
schib->pmcw.mbi = address;
|
sch->config.mbi = address;
|
||||||
|
|
||||||
/* try to submit it */
|
return cio_commit_config(sch);
|
||||||
switch(ret = msch_err(sch->schid, schib)) {
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
case 2: /* in I/O or status pending */
|
|
||||||
ret = -EBUSY;
|
|
||||||
break;
|
|
||||||
case 3: /* subchannel is no longer valid */
|
|
||||||
ret = -ENODEV;
|
|
||||||
break;
|
|
||||||
default: /* msch caught an exception */
|
|
||||||
ret = -EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (cio_update_schib(sch))
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* check if it worked */
|
|
||||||
if (schib->pmcw.mme == mme &&
|
|
||||||
schib->pmcw.mbfc == mbfc &&
|
|
||||||
(mbfc ? (schib->mba == address)
|
|
||||||
: (schib->pmcw.mbi == address)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ret = -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct set_schib_struct {
|
struct set_schib_struct {
|
||||||
|
@@ -128,8 +128,8 @@ css_free_subchannel(struct subchannel *sch)
|
|||||||
{
|
{
|
||||||
if (sch) {
|
if (sch) {
|
||||||
/* Reset intparm to zeroes. */
|
/* Reset intparm to zeroes. */
|
||||||
sch->schib.pmcw.intparm = 0;
|
sch->config.intparm = 0;
|
||||||
cio_modify(sch);
|
cio_commit_config(sch);
|
||||||
kfree(sch->lock);
|
kfree(sch->lock);
|
||||||
kfree(sch);
|
kfree(sch);
|
||||||
}
|
}
|
||||||
|
@@ -1020,8 +1020,8 @@ static void ccw_device_call_sch_unregister(struct work_struct *work)
|
|||||||
sch = to_subchannel(cdev->dev.parent);
|
sch = to_subchannel(cdev->dev.parent);
|
||||||
css_sch_device_unregister(sch);
|
css_sch_device_unregister(sch);
|
||||||
/* Reset intparm to zeroes. */
|
/* Reset intparm to zeroes. */
|
||||||
sch->schib.pmcw.intparm = 0;
|
sch->config.intparm = 0;
|
||||||
cio_modify(sch);
|
cio_commit_config(sch);
|
||||||
/* Release cdev reference for workqueue processing.*/
|
/* Release cdev reference for workqueue processing.*/
|
||||||
put_device(&cdev->dev);
|
put_device(&cdev->dev);
|
||||||
/* Release subchannel reference for local processing. */
|
/* Release subchannel reference for local processing. */
|
||||||
@@ -1148,8 +1148,8 @@ static void ccw_device_move_to_sch(struct work_struct *work)
|
|||||||
spin_unlock_irq(former_parent->lock);
|
spin_unlock_irq(former_parent->lock);
|
||||||
css_sch_device_unregister(former_parent);
|
css_sch_device_unregister(former_parent);
|
||||||
/* Reset intparm to zeroes. */
|
/* Reset intparm to zeroes. */
|
||||||
former_parent->schib.pmcw.intparm = 0;
|
former_parent->config.intparm = 0;
|
||||||
cio_modify(former_parent);
|
cio_commit_config(former_parent);
|
||||||
}
|
}
|
||||||
sch_attach_device(sch, cdev);
|
sch_attach_device(sch, cdev);
|
||||||
out:
|
out:
|
||||||
@@ -1170,6 +1170,14 @@ static void io_subchannel_irq(struct subchannel *sch)
|
|||||||
dev_fsm_event(cdev, DEV_EVENT_INTERRUPT);
|
dev_fsm_event(cdev, DEV_EVENT_INTERRUPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void io_subchannel_init_config(struct subchannel *sch)
|
||||||
|
{
|
||||||
|
memset(&sch->config, 0, sizeof(sch->config));
|
||||||
|
sch->config.csense = 1;
|
||||||
|
if ((sch->lpm & (sch->lpm - 1)) != 0)
|
||||||
|
sch->config.mp = 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void io_subchannel_init_fields(struct subchannel *sch)
|
static void io_subchannel_init_fields(struct subchannel *sch)
|
||||||
{
|
{
|
||||||
if (cio_is_console(sch->schid))
|
if (cio_is_console(sch->schid))
|
||||||
@@ -1184,16 +1192,8 @@ static void io_subchannel_init_fields(struct subchannel *sch)
|
|||||||
sch->schib.pmcw.dev, sch->schid.ssid,
|
sch->schib.pmcw.dev, sch->schid.ssid,
|
||||||
sch->schid.sch_no, sch->schib.pmcw.pim,
|
sch->schid.sch_no, sch->schib.pmcw.pim,
|
||||||
sch->schib.pmcw.pam, sch->schib.pmcw.pom);
|
sch->schib.pmcw.pam, sch->schib.pmcw.pom);
|
||||||
/* Initially set up some fields in the pmcw. */
|
|
||||||
sch->schib.pmcw.ena = 0;
|
io_subchannel_init_config(sch);
|
||||||
sch->schib.pmcw.csense = 1; /* concurrent sense */
|
|
||||||
if ((sch->lpm & (sch->lpm - 1)) != 0)
|
|
||||||
sch->schib.pmcw.mp = 1; /* multipath mode */
|
|
||||||
/* clean up possible residual cmf stuff */
|
|
||||||
sch->schib.pmcw.mme = 0;
|
|
||||||
sch->schib.pmcw.mbfc = 0;
|
|
||||||
sch->schib.pmcw.mbi = 0;
|
|
||||||
sch->schib.mba = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void io_subchannel_do_unreg(struct work_struct *work)
|
static void io_subchannel_do_unreg(struct work_struct *work)
|
||||||
@@ -1203,8 +1203,8 @@ static void io_subchannel_do_unreg(struct work_struct *work)
|
|||||||
sch = container_of(work, struct subchannel, work);
|
sch = container_of(work, struct subchannel, work);
|
||||||
css_sch_device_unregister(sch);
|
css_sch_device_unregister(sch);
|
||||||
/* Reset intparm to zeroes. */
|
/* Reset intparm to zeroes. */
|
||||||
sch->schib.pmcw.intparm = 0;
|
sch->config.intparm = 0;
|
||||||
cio_modify(sch);
|
cio_commit_config(sch);
|
||||||
put_device(&sch->dev);
|
put_device(&sch->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1680,8 +1680,8 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow)
|
|||||||
spin_lock_irqsave(sch->lock, flags);
|
spin_lock_irqsave(sch->lock, flags);
|
||||||
|
|
||||||
/* Reset intparm to zeroes. */
|
/* Reset intparm to zeroes. */
|
||||||
sch->schib.pmcw.intparm = 0;
|
sch->config.intparm = 0;
|
||||||
cio_modify(sch);
|
cio_commit_config(sch);
|
||||||
break;
|
break;
|
||||||
case REPROBE:
|
case REPROBE:
|
||||||
ccw_device_trigger_reprobe(cdev);
|
ccw_device_trigger_reprobe(cdev);
|
||||||
|
@@ -76,6 +76,7 @@ extern wait_queue_head_t ccw_device_init_wq;
|
|||||||
extern atomic_t ccw_device_init_count;
|
extern atomic_t ccw_device_init_count;
|
||||||
|
|
||||||
void io_subchannel_recog_done(struct ccw_device *cdev);
|
void io_subchannel_recog_done(struct ccw_device *cdev);
|
||||||
|
void io_subchannel_init_config(struct subchannel *sch);
|
||||||
|
|
||||||
int ccw_device_cancel_halt_clear(struct ccw_device *);
|
int ccw_device_cancel_halt_clear(struct ccw_device *);
|
||||||
|
|
||||||
|
@@ -1026,11 +1026,12 @@ void ccw_device_trigger_reprobe(struct ccw_device *cdev)
|
|||||||
* we have before performing device selection :/
|
* we have before performing device selection :/
|
||||||
*/
|
*/
|
||||||
sch->lpm = sch->schib.pmcw.pam & sch->opm;
|
sch->lpm = sch->schib.pmcw.pam & sch->opm;
|
||||||
/* Re-set some bits in the pmcw that were lost. */
|
/*
|
||||||
sch->schib.pmcw.csense = 1;
|
* Use the initial configuration since we can't be shure that the old
|
||||||
sch->schib.pmcw.ena = 0;
|
* paths are valid.
|
||||||
if ((sch->lpm & (sch->lpm - 1)) != 0)
|
*/
|
||||||
sch->schib.pmcw.mp = 1;
|
io_subchannel_init_config(sch);
|
||||||
|
|
||||||
/* We should also udate ssd info, but this has to wait. */
|
/* We should also udate ssd info, but this has to wait. */
|
||||||
/* Check if this is another device which appeared on the same sch. */
|
/* Check if this is another device which appeared on the same sch. */
|
||||||
if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {
|
if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {
|
||||||
|
Reference in New Issue
Block a user