On Mon, Dec 23, 2013 at 05:52:05PM +0800, rogera...@realtek.com wrote:
> +static int rtsx_usb_seq_write_register(struct rtsx_ucr *ucr,
> +             u16 addr, u16 len, u8 *data)
> +{
> +     u16 cmd_len = len + 12;
> +
> +     if (data == NULL)
> +             return -EINVAL;
> +
> +     cmd_len = (cmd_len <= CMD_BUF_LEN) ? cmd_len : CMD_BUF_LEN;
> +


I do not like how you have three names for the same buffer length.

> +#define IOBUF_SIZE           1024
> +#define CMD_BUF_LEN          1024
> +#define RSP_BUF_LEN          1024

The buffer is allocated as IOBUF_SIZE and then CMD_BUF_LEN is used as
a limiter here and one other place.  RSP_BUF_LEN is not used at all.

> +     if (cmd_len % 4)
> +             cmd_len += (4 - cmd_len % 4);
> +
> +
> +     ucr->cmd_buf[0] = 'R';
> +     ucr->cmd_buf[1] = 'T';
> +     ucr->cmd_buf[2] = 'C';
> +     ucr->cmd_buf[3] = 'R';
> +     ucr->cmd_buf[PACKET_TYPE] = SEQ_WRITE;
> +     ucr->cmd_buf[5] = (u8)(len >> 8);
> +     ucr->cmd_buf[6] = (u8)len;
> +     ucr->cmd_buf[STAGE_FLAG] = 0;
> +     ucr->cmd_buf[8] = (u8)(addr >> 8);
> +     ucr->cmd_buf[9] = (u8)addr;
> +
> +     memcpy(ucr->cmd_buf + 12, data, len);

Buffer overflow here because ->cmd_buf is only IOBUF_SIZE long.
Probably the earlier two uses of "len" are buffer overflows as well.

> +int rtsx_usb_ep0_write_register(struct rtsx_ucr *ucr, u16 addr,
> +             u8 mask, u8 data)
> +{
> +     u16 value = 0, index = 0;
> +
> +     value |= (u16)(3 & 0x03) << 14;
> +     value |= (u16)(addr & 0x3FFF);

Don't do pointless things:

        value |= 0x03 << 14;
        value |= addr & 0x3FFF;

> +     value = ((value << 8) & 0xFF00) | ((value >> 8) & 0x00FF);

This is an endian conversion?  It is buggy.  Use the kernel endian
conversion functions cpu_to_le16().

> +     index |= (u16)mask;
> +     index |= (u16)data << 8;
> +
> +     return usb_control_msg(ucr->pusb_dev,
> +                     usb_sndctrlpipe(ucr->pusb_dev, 0), 0, 0x40,
> +                     value, index, NULL, 0, 100);
> +}
> +EXPORT_SYMBOL_GPL(rtsx_usb_ep0_write_register);
> +
> +int rtsx_usb_ep0_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data)
> +{
> +     u16 value = 0;
> +
> +     if (data == NULL)
> +             return -EINVAL;
> +     *data = 0;
> +
> +     value |= (u16)(2 & 0x03) << 14;
> +     value |= (u16)(addr & 0x3FFF);
> +     value = ((value << 8) & 0xFF00) | ((value >> 8) & 0x00FF);

same.

The rest of my comments below are minor white space nits.

> +
> +     return usb_control_msg(ucr->pusb_dev,
> +                     usb_rcvctrlpipe(ucr->pusb_dev, 0), 0, 0xC0,
> +                     value, 0, data, 1, 100);
> +}
> +EXPORT_SYMBOL_GPL(rtsx_usb_ep0_read_register);
> +
> +void rtsx_usb_add_cmd(struct rtsx_ucr *ucr,
> +                 u8 cmd_type,
> +                 u16 reg_addr,
> +                 u8 mask,
> +                 u8 data)
> +{
> +     int i;
> +
> +     if (ucr->cmd_idx < ((CMD_BUF_LEN - CMD_OFFSET) / 4)) {
> +             i = CMD_OFFSET + ucr->cmd_idx * 4;
> +
> +             ucr->cmd_buf[i++] = ((cmd_type & 0x03) << 6) |
> +                     (u8)((reg_addr >> 8) & 0x3F);
> +             ucr->cmd_buf[i++] = (u8)reg_addr;
> +             ucr->cmd_buf[i++] = mask;
> +             ucr->cmd_buf[i++] = data;
> +
> +             ucr->cmd_idx++;
> +     }
> +}
> +EXPORT_SYMBOL_GPL(rtsx_usb_add_cmd);
> +
> +int rtsx_usb_send_cmd(struct rtsx_ucr *ucr, u8 flag, int timeout)
> +{
> +     int ret;
> +
> +     ucr->cmd_buf[CNT_H] = (u8)(ucr->cmd_idx >> 8);
> +     ucr->cmd_buf[CNT_L] = (u8)(ucr->cmd_idx);
> +     ucr->cmd_buf[STAGE_FLAG] = flag;
> +
> +     ret = rtsx_usb_transfer_data(ucr,
> +                     usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
> +                     ucr->cmd_buf, ucr->cmd_idx * 4 + CMD_OFFSET,
> +                     0, NULL, timeout);
> +     if (ret) {
> +             /* clear HW error*/
> +             rtsx_usb_ep0_write_register(ucr, SFSM_ED, 0xf8, 0xf8);

Make this into a function and remove the comment.

                rtsx_usb_ep0_clear_hw_error(ucr);

> +             return ret;
> +     }
> +
> +     return 0;
> +}
> +EXPORT_SYMBOL_GPL(rtsx_usb_send_cmd);
> +
> +int rtsx_usb_get_rsp(struct rtsx_ucr *ucr, int rsp_len, int timeout)
> +{
> +     if (rsp_len <= 0)
> +             return -EINVAL;
> +
> +     if (rsp_len % 4)
> +             rsp_len += (4 - rsp_len % 4);
> +
> +     return rtsx_usb_transfer_data(ucr,
> +                     usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN),
> +                     ucr->rsp_buf, rsp_len, 0, NULL, timeout);
> +}
> +EXPORT_SYMBOL_GPL(rtsx_usb_get_rsp);
> +
> +static int rtsx_usb_get_status_with_bulk(struct rtsx_ucr *ucr, u16 *status)
> +{
> +     int ret;
> +
> +     rtsx_usb_init_cmd(ucr);
> +     rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_EXIST, 0x00, 0x00);
> +     rtsx_usb_add_cmd(ucr, READ_REG_CMD, OCPSTAT, 0x00, 0x00);
> +     ret = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
> +     if (ret)
> +             return ret;
> +
> +     ret = rtsx_usb_get_rsp(ucr, 2, 100);
> +     if (ret)
> +             return ret;
> +
> +     *status = (u16)((ucr->rsp_buf[0] >> 2) & 0x0f) |
> +             ((ucr->rsp_buf[1] & 0x03) << 4);

The cast to u16 is not needed.  Align it like this:

        *status = ((ucr->rsp_buf[0] >> 2) & 0x0f) |
                  ((ucr->rsp_buf[1] & 0x03) << 4);

> +
> +     return 0;
> +}
> +

[ snip ]

> +int rtsx_usb_switch_clock(struct rtsx_ucr *ucr, unsigned int card_clock,
> +             u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk)
> +{
> +     int ret;
> +     u8 n, clk_divider, mcu_cnt, div;
> +
> +     if (!card_clock) {
> +             ucr->cur_clk = 0;
> +             return 0;
> +     }
> +
> +     if (initial_mode) {
> +             /* We use 250k(around) here, in initial stage */
> +             clk_divider = SD_CLK_DIVIDE_128;
> +             card_clock = 30000000;
> +     } else {
> +             clk_divider = SD_CLK_DIVIDE_0;
> +     }
> +
> +     ret = rtsx_usb_write_register(ucr, SD_CFG1,
> +                     SD_CLK_DIVIDE_MASK, clk_divider);
> +     if (ret < 0)
> +             return ret;
> +
> +     card_clock /= 1000000;
> +     dev_dbg(&ucr->pusb_intf->dev,
> +                     "Switch card clock to %dMHz\n", card_clock);
> +
> +     if (!initial_mode && double_clk)
> +             card_clock *= 2;
> +     dev_dbg(&ucr->pusb_intf->dev,
> +                     "Internal SSC clock: %dMHz (cur_clk = %d)\n",
> +                     card_clock, ucr->cur_clk);
> +
> +     if (card_clock == ucr->cur_clk)
> +             return 0;
> +
> +     /* Converting clock value into internal settings: n and div */
> +     n = (u8)(card_clock - 2);

Unneeded cast.

> +     if ((card_clock <= 2) || (n > MAX_DIV_N))
> +             return -EINVAL;
> +
> +     mcu_cnt = (u8)(60/card_clock + 3);

Unneeded cast.  Obviously it fits in u8.

> +     if (mcu_cnt > 15)
> +             mcu_cnt = 15;
> +
> +     /* Make sure that the SSC clock div_n is not less than MIN_DIV_N */
> +
> +     div = CLK_DIV_1;
> +     while ((n < MIN_DIV_N) && (div < CLK_DIV_4)) {

Unneeded parenthesis.

> +             n = (n + 2) * 2 - 2;
> +             div++;
> +     }

[ snip ]

> +static int rtsx_usb_init_chip(struct rtsx_ucr *ucr)
> +{
> +     int ret;
> +     u8 val;
> +
> +     /* clear HW error*/
> +     rtsx_usb_ep0_write_register(ucr, SFSM_ED, 0xf8, 0xf8);
> +
> +     /* power on SSC*/
> +     ret = rtsx_usb_write_register(ucr,
> +                     FPDCTL, SSC_POWER_MASK, SSC_POWER_ON);
> +     if (ret)
> +             goto err_out;
> +
> +     usleep_range(100, 1000);
> +     ret = rtsx_usb_write_register(ucr, CLK_DIV, CLK_CHANGE, 0x00);
> +     if (ret)
> +             goto err_out;
> +
> +     /* determine IC version */
> +     ret = rtsx_usb_read_register(ucr, HW_VERSION, &val);
> +     if (ret)
> +             goto err_out;
> +
> +     ucr->ic_version = val & HW_VER_MASK;
> +
> +     /* determine package */
> +     ret = rtsx_usb_read_register(ucr, CARD_SHARE_MODE, &val);
> +     if (ret)
> +             goto err_out;
> +     if (val & CARD_SHARE_LQFP_SEL) {
> +             ucr->package = LQFP48;
> +             dev_dbg(&ucr->pusb_intf->dev, "Package: LQFP48\n");
> +     } else {
> +             ucr->package = QFN24;
> +             dev_dbg(&ucr->pusb_intf->dev, "Package: QFN24\n");
> +     }
> +
> +     /* determine IC variations */
> +     rtsx_usb_read_register(ucr, CFG_MODE_1, &val);
> +     if (val & RTS5179) {
> +             ucr->is_rts5179 = 1;
> +             dev_dbg(&ucr->pusb_intf->dev, "Device is rts5179\n");
> +     } else {
> +             ucr->is_rts5179 = 0;
> +     }
> +
> +     ret = rtsx_usb_reset_chip(ucr);
> +     if (ret)
> +             goto err_out;
> +
> +     return 0;
> +err_out:
> +     return ret;

Gar...  Just return directly instead of adding do-nothing-gotos...  No
one likes skipping back and forth within a function to find what a goto
does and then it does nothing, it just returns.

> +}
> +
> +static int rtsx_usb_probe(struct usb_interface *intf,
> +                      const struct usb_device_id *id)
> +{
> +     struct usb_device *usb_dev = interface_to_usbdev(intf);
> +     struct rtsx_ucr *ucr;
> +     int i;
> +     int ret;
> +
> +     dev_dbg(&intf->dev,
> +             ": Realtek USB Card Reader found at bus %03d address %03d\n",
> +              usb_dev->bus->busnum, usb_dev->devnum);
> +
> +     ucr = kzalloc(sizeof(struct rtsx_ucr), GFP_KERNEL);
> +     if (!ucr) {
> +             dev_err(&intf->dev, "Out of memory\n");

This printk is pointless.  kzalloc() already has a much usefull
printk().

> +             return -ENOMEM;
> +     }
> +
> +     ucr->pusb_dev = usb_dev;
> +
> +     /* alloc coherent buffer */
> +     ucr->iobuf = usb_alloc_coherent(ucr->pusb_dev, IOBUF_SIZE,
> +                     GFP_KERNEL, &ucr->iobuf_dma);
> +     if (!ucr->iobuf) {
> +             ret = -ENOMEM;
> +             goto out_free_chip;
> +     }
> +
> +     /* set USB interface data */
> +     usb_set_intfdata(intf, ucr);
> +
> +     ucr->vendor_id = id->idVendor;
> +     ucr->product_id = id->idProduct;
> +     ucr->cmd_buf = ucr->rsp_buf = ucr->iobuf;
> +
> +     mutex_init(&ucr->dev_mutex);
> +
> +     ucr->pusb_intf = intf;
> +
> +     /* initialize */
> +     ret = rtsx_usb_init_chip(ucr);
> +     if (ret)
> +             goto out_init_fail;
> +
> +     for (i = 0; i < ARRAY_SIZE(rtsx_usb_cells); i++) {
> +             rtsx_usb_cells[i].platform_data = &ucr;
> +             rtsx_usb_cells[i].pdata_size = sizeof(*ucr);
> +     }
> +     ret = mfd_add_devices(&intf->dev, usb_dev->devnum, rtsx_usb_cells,
> +                     ARRAY_SIZE(rtsx_usb_cells), NULL, 0, NULL);
> +

Don't put a blank line here.

> +     if (ret)
> +             goto out_init_fail;
> +     /* initialize USB SG transfer timer */
> +     init_timer(&ucr->sg_timer);
> +     setup_timer(&ucr->sg_timer, rtsx_usb_sg_timed_out, (unsigned long) ucr);
> +#ifdef CONFIG_PM
> +     intf->needs_remote_wakeup = 1;
> +     usb_enable_autosuspend(usb_dev);
> +#endif
> +
> +     return 0;
> +
> +out_init_fail:
> +     usb_set_intfdata(ucr->pusb_intf, NULL);
> +     usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
> +                     ucr->iobuf_dma);
> +
> +out_free_chip:
> +     kfree(ucr);
> +     dev_err(&intf->dev, "%s failed\n", __func__);
> +     return ret;
> +}

[ snip ]

> +#define CARD_DMA1_CTL                        0xFD5C
> +#define CARD_PULL_CTL1                       0xFD60
> +#define CARD_PULL_CTL2                       0xFD61
> +#define CARD_PULL_CTL3                       0xFD62
> +#define CARD_PULL_CTL4                       0xFD63
> +#define CARD_PULL_CTL5                       0xFD64
> +#define CARD_PULL_CTL6                       0xFD65
> +#define CARD_EXIST                           0xFD6F

In the email CARD_EXIST looks aligned correctly, but in the actual .h
file then it's out of line.

> +#define CARD_INT_PEND                        0xFD71
> +

[ snip ]

> +#define MC_IRQ                               0xFF00
> +#define MC_IRQEN                     0xFF01
> +#define MC_FIFO_CTL                  0xFF02
> +#define MC_FIFO_BC0                  0xFF03
> +#define MC_FIFO_BC1                  0xFF04
> +#define MC_FIFO_STAT                 0xFF05
> +#define MC_FIFO_MODE                 0xFF06
> +#define MC_FIFO_RD_PTR0              0xFF07
> +#define MC_FIFO_RD_PTR1              0xFF08

MC_FIFO_RD_PTR0 and MC_FIFO_RD_PTR1 are not aligned correctly.

> +#define MC_DMA_CTL                   0xFF10
> +#define MC_DMA_TC0                   0xFF11

regards,
dan carpenter

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to