lkml.org 
[lkml]   [2017]   [May]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.11 003/197] USB: ene_usb6250: fix DMA to the stack
    Date
    4.11-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Alan Stern <stern@rowland.harvard.edu>

    commit 628c2893d44876ddd11602400c70606ade62e129 upstream.

    The ene_usb6250 sub-driver in usb-storage does USB I/O to buffers on
    the stack, which doesn't work with vmapped stacks. This patch fixes
    the problem by allocating a separate 512-byte buffer at probe time and
    using it for all of the offending I/O operations.

    Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
    Reported-and-tested-by: Andreas Hartmann <andihartmann@01019freenet.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/usb/storage/ene_ub6250.c | 90 +++++++++++++++++++++++----------------
    1 file changed, 55 insertions(+), 35 deletions(-)

    --- a/drivers/usb/storage/ene_ub6250.c
    +++ b/drivers/usb/storage/ene_ub6250.c
    @@ -446,6 +446,10 @@ struct ms_lib_ctrl {
    #define SD_BLOCK_LEN 9

    struct ene_ub6250_info {
    +
    + /* I/O bounce buffer */
    + u8 *bbuf;
    +
    /* for 6250 code */
    struct SD_STATUS SD_Status;
    struct MS_STATUS MS_Status;
    @@ -493,8 +497,11 @@ static int ene_load_bincode(struct us_da

    static void ene_ub6250_info_destructor(void *extra)
    {
    + struct ene_ub6250_info *info = (struct ene_ub6250_info *) extra;
    +
    if (!extra)
    return;
    + kfree(info->bbuf);
    }

    static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
    @@ -860,8 +867,9 @@ static int ms_read_readpage(struct us_da
    u8 PageNum, u32 *PageBuf, struct ms_lib_type_extdat *ExtraDat)
    {
    struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
    + struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
    + u8 *bbuf = info->bbuf;
    int result;
    - u8 ExtBuf[4];
    u32 bn = PhyBlockAddr * 0x20 + PageNum;

    result = ene_load_bincode(us, MS_RW_PATTERN);
    @@ -901,7 +909,7 @@ static int ms_read_readpage(struct us_da
    bcb->CDB[2] = (unsigned char)(PhyBlockAddr>>16);
    bcb->CDB[6] = 0x01;

    - result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0);
    + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
    if (result != USB_STOR_XFER_GOOD)
    return USB_STOR_TRANSPORT_ERROR;

    @@ -910,9 +918,9 @@ static int ms_read_readpage(struct us_da
    ExtraDat->status0 = 0x10; /* Not yet,fireware support */

    ExtraDat->status1 = 0x00; /* Not yet,fireware support */
    - ExtraDat->ovrflg = ExtBuf[0];
    - ExtraDat->mngflg = ExtBuf[1];
    - ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]);
    + ExtraDat->ovrflg = bbuf[0];
    + ExtraDat->mngflg = bbuf[1];
    + ExtraDat->logadr = memstick_logaddr(bbuf[2], bbuf[3]);

    return USB_STOR_TRANSPORT_GOOD;
    }
    @@ -1332,8 +1340,9 @@ static int ms_lib_read_extra(struct us_d
    u8 PageNum, struct ms_lib_type_extdat *ExtraDat)
    {
    struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
    + struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
    + u8 *bbuf = info->bbuf;
    int result;
    - u8 ExtBuf[4];

    memset(bcb, 0, sizeof(struct bulk_cb_wrap));
    bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
    @@ -1347,7 +1356,7 @@ static int ms_lib_read_extra(struct us_d
    bcb->CDB[2] = (unsigned char)(PhyBlock>>16);
    bcb->CDB[6] = 0x01;

    - result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0);
    + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
    if (result != USB_STOR_XFER_GOOD)
    return USB_STOR_TRANSPORT_ERROR;

    @@ -1355,9 +1364,9 @@ static int ms_lib_read_extra(struct us_d
    ExtraDat->intr = 0x80; /* Not yet, waiting for fireware support */
    ExtraDat->status0 = 0x10; /* Not yet, waiting for fireware support */
    ExtraDat->status1 = 0x00; /* Not yet, waiting for fireware support */
    - ExtraDat->ovrflg = ExtBuf[0];
    - ExtraDat->mngflg = ExtBuf[1];
    - ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]);
    + ExtraDat->ovrflg = bbuf[0];
    + ExtraDat->mngflg = bbuf[1];
    + ExtraDat->logadr = memstick_logaddr(bbuf[2], bbuf[3]);

    return USB_STOR_TRANSPORT_GOOD;
    }
    @@ -1556,9 +1565,9 @@ static int ms_lib_scan_logicalblocknumbe
    u16 PhyBlock, newblk, i;
    u16 LogStart, LogEnde;
    struct ms_lib_type_extdat extdat;
    - u8 buf[0x200];
    u32 count = 0, index = 0;
    struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
    + u8 *bbuf = info->bbuf;

    for (PhyBlock = 0; PhyBlock < info->MS_Lib.NumberOfPhyBlock;) {
    ms_lib_phy_to_log_range(PhyBlock, &LogStart, &LogEnde);
    @@ -1572,14 +1581,16 @@ static int ms_lib_scan_logicalblocknumbe
    }

    if (count == PhyBlock) {
    - ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, &buf);
    + ms_lib_read_extrablock(us, PhyBlock, 0, 0x80,
    + bbuf);
    count += 0x80;
    }
    index = (PhyBlock % 0x80) * 4;

    - extdat.ovrflg = buf[index];
    - extdat.mngflg = buf[index+1];
    - extdat.logadr = memstick_logaddr(buf[index+2], buf[index+3]);
    + extdat.ovrflg = bbuf[index];
    + extdat.mngflg = bbuf[index+1];
    + extdat.logadr = memstick_logaddr(bbuf[index+2],
    + bbuf[index+3]);

    if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) {
    ms_lib_setacquired_errorblock(us, PhyBlock);
    @@ -2062,9 +2073,9 @@ static int ene_ms_init(struct us_data *u
    {
    struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
    int result;
    - u8 buf[0x200];
    u16 MSP_BlockSize, MSP_UserAreaBlocks;
    struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
    + u8 *bbuf = info->bbuf;

    printk(KERN_INFO "transport --- ENE_MSInit\n");

    @@ -2083,13 +2094,13 @@ static int ene_ms_init(struct us_data *u
    bcb->CDB[0] = 0xF1;
    bcb->CDB[1] = 0x01;

    - result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
    + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
    if (result != USB_STOR_XFER_GOOD) {
    printk(KERN_ERR "Execution MS Init Code Fail !!\n");
    return USB_STOR_TRANSPORT_ERROR;
    }
    /* the same part to test ENE */
    - info->MS_Status = *(struct MS_STATUS *)&buf[0];
    + info->MS_Status = *(struct MS_STATUS *) bbuf;

    if (info->MS_Status.Insert && info->MS_Status.Ready) {
    printk(KERN_INFO "Insert = %x\n", info->MS_Status.Insert);
    @@ -2098,15 +2109,15 @@ static int ene_ms_init(struct us_data *u
    printk(KERN_INFO "IsMSPHG = %x\n", info->MS_Status.IsMSPHG);
    printk(KERN_INFO "WtP= %x\n", info->MS_Status.WtP);
    if (info->MS_Status.IsMSPro) {
    - MSP_BlockSize = (buf[6] << 8) | buf[7];
    - MSP_UserAreaBlocks = (buf[10] << 8) | buf[11];
    + MSP_BlockSize = (bbuf[6] << 8) | bbuf[7];
    + MSP_UserAreaBlocks = (bbuf[10] << 8) | bbuf[11];
    info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks;
    } else {
    ms_card_init(us); /* Card is MS (to ms.c)*/
    }
    usb_stor_dbg(us, "MS Init Code OK !!\n");
    } else {
    - usb_stor_dbg(us, "MS Card Not Ready --- %x\n", buf[0]);
    + usb_stor_dbg(us, "MS Card Not Ready --- %x\n", bbuf[0]);
    return USB_STOR_TRANSPORT_ERROR;
    }

    @@ -2116,9 +2127,9 @@ static int ene_ms_init(struct us_data *u
    static int ene_sd_init(struct us_data *us)
    {
    int result;
    - u8 buf[0x200];
    struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
    struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
    + u8 *bbuf = info->bbuf;

    usb_stor_dbg(us, "transport --- ENE_SDInit\n");
    /* SD Init Part-1 */
    @@ -2152,17 +2163,17 @@ static int ene_sd_init(struct us_data *u
    bcb->Flags = US_BULK_FLAG_IN;
    bcb->CDB[0] = 0xF1;

    - result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
    + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
    if (result != USB_STOR_XFER_GOOD) {
    usb_stor_dbg(us, "Execution SD Init Code Fail !!\n");
    return USB_STOR_TRANSPORT_ERROR;
    }

    - info->SD_Status = *(struct SD_STATUS *)&buf[0];
    + info->SD_Status = *(struct SD_STATUS *) bbuf;
    if (info->SD_Status.Insert && info->SD_Status.Ready) {
    struct SD_STATUS *s = &info->SD_Status;

    - ene_get_card_status(us, (unsigned char *)&buf);
    + ene_get_card_status(us, bbuf);
    usb_stor_dbg(us, "Insert = %x\n", s->Insert);
    usb_stor_dbg(us, "Ready = %x\n", s->Ready);
    usb_stor_dbg(us, "IsMMC = %x\n", s->IsMMC);
    @@ -2170,7 +2181,7 @@ static int ene_sd_init(struct us_data *u
    usb_stor_dbg(us, "HiSpeed = %x\n", s->HiSpeed);
    usb_stor_dbg(us, "WtP = %x\n", s->WtP);
    } else {
    - usb_stor_dbg(us, "SD Card Not Ready --- %x\n", buf[0]);
    + usb_stor_dbg(us, "SD Card Not Ready --- %x\n", bbuf[0]);
    return USB_STOR_TRANSPORT_ERROR;
    }
    return USB_STOR_TRANSPORT_GOOD;
    @@ -2180,13 +2191,15 @@ static int ene_sd_init(struct us_data *u
    static int ene_init(struct us_data *us)
    {
    int result;
    - u8 misc_reg03 = 0;
    + u8 misc_reg03;
    struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
    + u8 *bbuf = info->bbuf;

    - result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
    + result = ene_get_card_type(us, REG_CARD_STATUS, bbuf);
    if (result != USB_STOR_XFER_GOOD)
    return USB_STOR_TRANSPORT_ERROR;

    + misc_reg03 = bbuf[0];
    if (misc_reg03 & 0x01) {
    if (!info->SD_Status.Ready) {
    result = ene_sd_init(us);
    @@ -2303,8 +2316,9 @@ static int ene_ub6250_probe(struct usb_i
    const struct usb_device_id *id)
    {
    int result;
    - u8 misc_reg03 = 0;
    + u8 misc_reg03;
    struct us_data *us;
    + struct ene_ub6250_info *info;

    result = usb_stor_probe1(&us, intf, id,
    (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list,
    @@ -2313,11 +2327,16 @@ static int ene_ub6250_probe(struct usb_i
    return result;

    /* FIXME: where should the code alloc extra buf ? */
    - if (!us->extra) {
    - us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL);
    - if (!us->extra)
    - return -ENOMEM;
    - us->extra_destructor = ene_ub6250_info_destructor;
    + us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL);
    + if (!us->extra)
    + return -ENOMEM;
    + us->extra_destructor = ene_ub6250_info_destructor;
    +
    + info = (struct ene_ub6250_info *)(us->extra);
    + info->bbuf = kmalloc(512, GFP_KERNEL);
    + if (!info->bbuf) {
    + kfree(us->extra);
    + return -ENOMEM;
    }

    us->transport_name = "ene_ub6250";
    @@ -2329,12 +2348,13 @@ static int ene_ub6250_probe(struct usb_i
    return result;

    /* probe card type */
    - result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
    + result = ene_get_card_type(us, REG_CARD_STATUS, info->bbuf);
    if (result != USB_STOR_XFER_GOOD) {
    usb_stor_disconnect(intf);
    return USB_STOR_TRANSPORT_ERROR;
    }

    + misc_reg03 = info->bbuf[0];
    if (!(misc_reg03 & 0x01)) {
    pr_info("ums_eneub6250: This driver only supports SD/MS cards. "
    "It does not support SM cards.\n");

    \
     
     \ /
      Last update: 2017-05-24 00:34    [W:4.400 / U:0.368 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site