powerpc/powernv: Fix major bugs in opal_flash
* The BIO bio_data may not be page aligned. Only the base address of each page worth of data is extracted to pass to OPAL. Without page alignment it can scribble over random memory when finishing the page read. Fix this by short-reading the first page to properly align for full page reads. * Fix the definition of OPAL_FLASH_ERASE. * Properly handle the async message result, as now returned from r345974.
This commit is contained in:
parent
947079ebee
commit
3c8c50f955
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=345975
@ -82,7 +82,7 @@ int opal_call(uint64_t token, ...);
|
||||
#define OPAL_I2C_REQUEST 109
|
||||
#define OPAL_FLASH_READ 110
|
||||
#define OPAL_FLASH_WRITE 111
|
||||
#define OPAL_FLASH_ERASE 111
|
||||
#define OPAL_FLASH_ERASE 112
|
||||
#define OPAL_INT_GET_XIRR 122
|
||||
#define OPAL_INT_SET_CPPR 123
|
||||
#define OPAL_INT_EOI 124
|
||||
|
@ -175,16 +175,22 @@ opalflash_read(struct opalflash_softc *sc, off_t off,
|
||||
* Read one page at a time. It's not guaranteed that the buffer is
|
||||
* physically contiguous.
|
||||
*/
|
||||
rv = 0;
|
||||
while (count > 0) {
|
||||
size = MIN(count, PAGE_SIZE);
|
||||
size = MIN(size, PAGE_SIZE - ((u_long)data & PAGE_MASK));
|
||||
rv = opal_call(OPAL_FLASH_READ, sc->sc_opal_id, off,
|
||||
vtophys(data), size, token);
|
||||
if (rv == OPAL_ASYNC_COMPLETION)
|
||||
if (rv == OPAL_ASYNC_COMPLETION) {
|
||||
rv = opal_wait_completion(&msg, sizeof(msg), token);
|
||||
if (rv == OPAL_SUCCESS)
|
||||
rv = msg.params[1];
|
||||
}
|
||||
if (rv != OPAL_SUCCESS)
|
||||
break;
|
||||
count -= size;
|
||||
off += size;
|
||||
data += size;
|
||||
}
|
||||
opal_free_async_token(token);
|
||||
if (rv == OPAL_SUCCESS)
|
||||
@ -209,8 +215,11 @@ opalflash_erase(struct opalflash_softc *sc, off_t off, off_t count)
|
||||
token = opal_alloc_async_token();
|
||||
|
||||
rv = opal_call(OPAL_FLASH_ERASE, sc->sc_opal_id, off, count, token);
|
||||
if (rv == OPAL_ASYNC_COMPLETION)
|
||||
if (rv == OPAL_ASYNC_COMPLETION) {
|
||||
rv = opal_wait_completion(&msg, sizeof(msg), token);
|
||||
if (rv == OPAL_SUCCESS)
|
||||
rv = msg.params[1];
|
||||
}
|
||||
opal_free_async_token(token);
|
||||
|
||||
if (rv == OPAL_SUCCESS)
|
||||
@ -246,14 +255,19 @@ opalflash_write(struct opalflash_softc *sc, off_t off,
|
||||
*/
|
||||
while (count > 0) {
|
||||
size = MIN(count, PAGE_SIZE);
|
||||
size = MIN(size, PAGE_SIZE - ((u_long)data & PAGE_MASK));
|
||||
rv = opal_call(OPAL_FLASH_WRITE, sc->sc_opal_id, off,
|
||||
vtophys(data), size, token);
|
||||
if (rv == OPAL_ASYNC_COMPLETION)
|
||||
if (rv == OPAL_ASYNC_COMPLETION) {
|
||||
rv = opal_wait_completion(&msg, sizeof(msg), token);
|
||||
if (rv == OPAL_SUCCESS)
|
||||
rv = msg.params[1];
|
||||
}
|
||||
if (rv != OPAL_SUCCESS)
|
||||
break;
|
||||
count -= size;
|
||||
off += size;
|
||||
data += size;
|
||||
}
|
||||
opal_free_async_token(token);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user