diff -r 0f39e1e7b288 -r d70aad2f131f devices/ccat/update.c --- a/devices/ccat/update.c Tue May 06 17:32:10 2014 +0200 +++ b/devices/ccat/update.c Thu Jun 05 16:07:52 2014 +0200 @@ -61,10 +61,9 @@ static void ccat_wait_status_cleared(void __iomem * const ioaddr); static int ccat_read_flash(void __iomem * const ioaddr, char __user * buf, - uint32_t len, loff_t * off); + u32 len, loff_t * off); static void ccat_write_flash(const struct update_buffer *const buf); -static void ccat_update_cmd(void __iomem * const ioaddr, uint8_t cmd, - uint16_t clocks); +static void ccat_update_cmd(void __iomem * const ioaddr, u8 cmd, u16 clocks); static void ccat_update_destroy(struct kref *ref); /** @@ -84,6 +83,7 @@ struct ccat_update *update = container_of(i->i_cdev, struct ccat_update, cdev); struct update_buffer *buf; + kref_get(&update->refcount); if (atomic_read(&update->refcount.refcount) > 2) { kref_put(&update->refcount, ccat_update_destroy); @@ -105,6 +105,7 @@ { const struct update_buffer *const buf = f->private_data; struct ccat_update *const update = buf->update; + if (buf->size > 0) { ccat_update_cmd(update->ioaddr, CCAT_WRITE_ENABLE); ccat_update_cmd(update->ioaddr, CCAT_BULK_ERASE); @@ -133,6 +134,7 @@ size_t len, loff_t * off) { struct update_buffer *update = f->private_data; + if (!buf || !off) { return -EINVAL; } @@ -162,6 +164,7 @@ size_t len, loff_t * off) { struct update_buffer *const update = f->private_data; + if (*off + len > sizeof(update->data)) return 0; @@ -190,8 +193,8 @@ * * no write memory barrier is called and the busy flag is not evaluated */ -static inline void __ccat_update_cmd(void __iomem * const ioaddr, uint8_t cmd, - uint16_t clocks) +static inline void __ccat_update_cmd(void __iomem * const ioaddr, u8 cmd, + u16 clocks) { iowrite8((0xff00 & clocks) >> 8, ioaddr); iowrite8(0x00ff & clocks, ioaddr + 0x8); @@ -207,8 +210,8 @@ * Triggers a full flash command cycle with write memory barrier and * command activate. This call blocks until the busy flag is reset. */ -static inline void ccat_update_cmd(void __iomem * const ioaddr, uint8_t cmd, - uint16_t clocks) +static inline void ccat_update_cmd(void __iomem * const ioaddr, u8 cmd, + u16 clocks) { __ccat_update_cmd(ioaddr, cmd, clocks); wmb(); @@ -227,12 +230,12 @@ * command activate. This call blocks until the busy flag is reset. */ static inline void ccat_update_cmd_addr(void __iomem * const ioaddr, - uint8_t cmd, uint16_t clocks, - uint32_t addr) -{ - const uint8_t addr_0 = SWAP_BITS(addr & 0xff); - const uint8_t addr_1 = SWAP_BITS((addr & 0xff00) >> 8); - const uint8_t addr_2 = SWAP_BITS((addr & 0xff0000) >> 16); + u8 cmd, u16 clocks, u32 addr) +{ + const u8 addr_0 = SWAP_BITS(addr & 0xff); + const u8 addr_1 = SWAP_BITS((addr & 0xff00) >> 8); + const u8 addr_2 = SWAP_BITS((addr & 0xff0000) >> 16); + __ccat_update_cmd(ioaddr, cmd, clocks); iowrite8(addr_2, ioaddr + 0x18); iowrite8(addr_1, ioaddr + 0x20); @@ -248,7 +251,7 @@ * * Return: the CCAT FPGA's PROM identifier */ -uint8_t ccat_get_prom_id(void __iomem * const ioaddr) +u8 ccat_get_prom_id(void __iomem * const ioaddr) { ccat_update_cmd(ioaddr, CCAT_GET_PROM_ID); return ioread8(ioaddr + 0x38); @@ -260,7 +263,7 @@ * * Return: the current status of the CCAT Update function */ -static uint8_t ccat_get_status(void __iomem * const ioaddr) +static u8 ccat_get_status(void __iomem * const ioaddr) { ccat_update_cmd(ioaddr, CCAT_READ_STATUS); return ioread8(ioaddr + 0x20); @@ -272,10 +275,10 @@ * * Blocks until bit 7 of the CCAT Update status is reset */ - static void ccat_wait_status_cleared(void __iomem * const ioaddr) { - uint8_t status; + u8 status; + do { status = ccat_get_status(ioaddr); } while (status & (1 << 7)); @@ -296,11 +299,12 @@ * Return: the number of bytes copied */ static int ccat_read_flash_block(void __iomem * const ioaddr, - const uint32_t addr, const uint16_t len, + const u32 addr, const u16 len, char __user * const buf) { - uint16_t i; - const uint16_t clocks = 8 * len; + u16 i; + const u16 clocks = 8 * len; + ccat_update_cmd_addr(ioaddr, CCAT_READ_FLASH + clocks, addr); for (i = 0; i < len; i++) { put_user(ioread8(ioaddr + CCAT_DATA_IN_4 + 8 * i), buf + i); @@ -321,9 +325,10 @@ * Return: the number of bytes copied */ static int ccat_read_flash(void __iomem * const ioaddr, char __user * buf, - uint32_t len, loff_t * off) + u32 len, loff_t * off) { const loff_t start = *off; + while (len > CCAT_DATA_BLOCK_SIZE) { *off += ccat_read_flash_block(ioaddr, *off, CCAT_DATA_BLOCK_SIZE, @@ -347,11 +352,12 @@ * Return: the number of bytes copied */ static int ccat_write_flash_block(void __iomem * const ioaddr, - const uint32_t addr, const uint16_t len, + const u32 addr, const u16 len, const char *const buf) { - const uint16_t clocks = 8 * len; - uint16_t i; + const u16 clocks = 8 * len; + u16 i; + ccat_update_cmd(ioaddr, CCAT_WRITE_ENABLE); for (i = 0; i < len; i++) { iowrite8(buf[i], ioaddr + CCAT_DATA_OUT_4 + 8 * i); @@ -368,17 +374,17 @@ static void ccat_write_flash(const struct update_buffer *const update) { const char *buf = update->data; - uint32_t off = 0; + u32 off = 0; size_t len = update->size; + while (len > CCAT_WRITE_BLOCK_SIZE) { ccat_write_flash_block(update->update->ioaddr, off, - (uint16_t) CCAT_WRITE_BLOCK_SIZE, buf); + (u16) CCAT_WRITE_BLOCK_SIZE, buf); off += CCAT_WRITE_BLOCK_SIZE; buf += CCAT_WRITE_BLOCK_SIZE; len -= CCAT_WRITE_BLOCK_SIZE; } - ccat_write_flash_block(update->update->ioaddr, off, (uint16_t) len, - buf); + ccat_write_flash_block(update->update->ioaddr, off, (u16) len, buf); } /** @@ -388,6 +394,7 @@ void __iomem * const addr) { struct ccat_update *const update = kzalloc(sizeof(*update), GFP_KERNEL); + if (!update) { return NULL; } @@ -443,6 +450,7 @@ { struct ccat_update *update = container_of(ref, struct ccat_update, refcount); + cdev_del(&update->cdev); device_destroy(update->class, update->dev); class_destroy(update->class);