From 04de96c9c6981c5957aa5db39bbdc4d958d07efa Mon Sep 17 00:00:00 2001 From: Tracey Dent Date: Wed, 19 Jan 2011 08:25:02 -0700 Subject: drivers/block/Makefile: replace the use of -objs with -y Change Makefile to use -y instead of -objs because -objs is deprecated and should now be switched. According to (documentation/kbuild/makefiles.txt). Signed-off-by: Tracey Dent Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/Makefile b/drivers/block/Makefile index d7f463d6312d..40528ba56d1b 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -39,4 +39,4 @@ obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o obj-$(CONFIG_BLK_DEV_DRBD) += drbd/ obj-$(CONFIG_BLK_DEV_RBD) += rbd.o -swim_mod-objs := swim.o swim_asm.o +swim_mod-y := swim.o swim_asm.o -- cgit v1.2.3 From ee71a968672a9951aee6014c55511007596425bc Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Wed, 19 Jan 2011 08:25:02 -0700 Subject: loop: queue_lock NULL pointer derefence in blk_throtl_exit Performing $ sudo mount -o loop -o umask=0 /dev/sdb1 /mnt/ mount: wrong fs type, bad option, bad superblock on /dev/loop0, missing codepage or helper program, or other error In some cases useful info is found in syslog - try dmesg | tail or so $ sudo modprobe -r loop results in oops: BUG: unable to handle kernel NULL pointer dereference at 0000000000000004 IP: [] do_raw_spin_lock+0x14/0x122 Process modprobe (pid: 6189, threadinfo ffff88009a898000, task ffff880154a88000) Call Trace: [] _raw_spin_lock_irq+0x4a/0x51 [] ? blk_throtl_exit+0x3b/0xa0 [] ? cancel_delayed_work_sync+0xd/0xf [] blk_throtl_exit+0x3b/0xa0 [] blk_release_queue+0x21/0x65 [] kobject_release+0x51/0x66 [] ? kobject_release+0x0/0x66 [] kref_put+0x43/0x4d [] kobject_put+0x47/0x4b [] blk_cleanup_queue+0x56/0x5b [] loop_exit+0x68/0x844 [loop] [] sys_delete_module+0x1e8/0x25b [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x16/0x1b because of an attempt to acquire NULL queue_lock. I added the same lines as in blk_queue_make_request - index 44e18c0..49e6a54 100644`fall back to embedded per-queue lock'. Signed-off-by: Sergey Senozhatsky Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/loop.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 44e18c073c44..49e6a545eb63 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1641,6 +1641,9 @@ out: static void loop_free(struct loop_device *lo) { + if (!lo->lo_queue->queue_lock) + lo->lo_queue->queue_lock = &lo->lo_queue->__queue_lock; + blk_cleanup_queue(lo->lo_queue); put_disk(lo->lo_disk); list_del(&lo->lo_list); -- cgit v1.2.3 From a0700bdd0b0150ea445159b1dee587f1507c272f Mon Sep 17 00:00:00 2001 From: Tracey Dent Date: Wed, 19 Jan 2011 08:25:02 -0700 Subject: drivers/block/aoe/Makefile: replace the use of -objs with -y Change Makefile to use -y instead of -objs because -objs is deprecated and should now be switched. According to (documentation/kbuild/makefiles.txt). Signed-off-by: Tracey Dent Cc: "Ed L. Cashin" Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/aoe/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/aoe/Makefile b/drivers/block/aoe/Makefile index e76d997183c6..06ea82cdf27d 100644 --- a/drivers/block/aoe/Makefile +++ b/drivers/block/aoe/Makefile @@ -3,4 +3,4 @@ # obj-$(CONFIG_ATA_OVER_ETH) += aoe.o -aoe-objs := aoeblk.o aoechr.o aoecmd.o aoedev.o aoemain.o aoenet.o +aoe-y := aoeblk.o aoechr.o aoecmd.o aoedev.o aoemain.o aoenet.o -- cgit v1.2.3 From 68264e9d6781f7163e92c517769bb470fa43f6cd Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Wed, 19 Jan 2011 08:25:02 -0700 Subject: cciss: make cciss_revalidate not loop through CISS_MAX_LUNS volumes unnecessarily. Signed-off-by: Stephen M. Cameron Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 516d5bbec2b6..9279272b3732 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2833,7 +2833,7 @@ static int cciss_revalidate(struct gendisk *disk) sector_t total_size; InquiryData_struct *inq_buff = NULL; - for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { + for (logvol = 0; logvol <= h->highest_lun; logvol++) { if (!h->drv[logvol]) continue; if (memcmp(h->drv[logvol]->LunID, drv->LunID, -- cgit v1.2.3 From 8a6afb9a950de01457a4267bcbe3292e56412326 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 21 Jan 2011 16:56:47 +0100 Subject: spi/spi_sh_msiof: fix wrong address calculation, which leads to an Oops NULL + != NULL, but reading from that address is usually not a very good idea and often leads to problems, like kernel Oopses in this case, easily reproducible by writing to an SD-card, used in SPI mode. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Grant Likely --- drivers/spi/spi_sh_msiof.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi_sh_msiof.c b/drivers/spi/spi_sh_msiof.c index 56f60c8ea0ab..2c665fceaac7 100644 --- a/drivers/spi/spi_sh_msiof.c +++ b/drivers/spi/spi_sh_msiof.c @@ -509,9 +509,11 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t) bytes_done = 0; while (bytes_done < t->len) { + void *rx_buf = t->rx_buf ? t->rx_buf + bytes_done : NULL; + const void *tx_buf = t->tx_buf ? t->tx_buf + bytes_done : NULL; n = sh_msiof_spi_txrx_once(p, tx_fifo, rx_fifo, - t->tx_buf + bytes_done, - t->rx_buf + bytes_done, + tx_buf, + rx_buf, words, bits); if (n < 0) break; -- cgit v1.2.3 From 509e7861d8a5e26bb07b5a3a13e2b9e442283631 Mon Sep 17 00:00:00 2001 From: "Cho, Yu-Chen" Date: Wed, 26 Jan 2011 17:10:59 +0800 Subject: Bluetooth: add Atheros BT AR9285 fw supported Add the btusb.c blacklist [03f0:311d] for Atheros AR9285 Malbec BT and add to ath3k.c ath3-1.fw (md5:1211fa34c09e10ba48381586b7c3883d) supported this device. Signed-off-by: Cho, Yu-Chen Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/ath3k.c | 2 ++ drivers/bluetooth/btusb.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index a126e614601f..333c21289d97 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -39,6 +39,8 @@ static struct usb_device_id ath3k_table[] = { /* Atheros AR3011 with sflash firmware*/ { USB_DEVICE(0x0CF3, 0x3002) }, + /* Atheros AR9285 Malbec with sflash firmware */ + { USB_DEVICE(0x03F0, 0x311D) }, { } /* Terminating entry */ }; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 1da773f899a2..4cefa91e6c34 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -102,6 +102,9 @@ static struct usb_device_id blacklist_table[] = { /* Atheros 3011 with sflash firmware */ { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE }, + /* Atheros AR9285 Malbec with sflash firmware */ + { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, + /* Broadcom BCM2035 */ { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, -- cgit v1.2.3 From 6866fd3b7289a283741752b73e0e09f410b7639d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 12 Jan 2011 11:18:14 +0100 Subject: dmaengine i.MX SDMA: Fix firmware loading When loading the microcode to the SDMA engine we have to use the ram_code_start_addr found in the firmware image. The copy in the sdma engine is not initialized correctly. This is broken since: 5b28aa3 dmaengine i.MX SDMA: Allow to run without firmware Signed-off-by: Sascha Hauer Signed-off-by: Dan Williams --- drivers/dma/imx-sdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index d5a5d4d9c19b..75df8b937413 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1135,7 +1135,7 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma, /* download the RAM image for SDMA */ sdma_load_script(sdma, ram_code, header->ram_code_size, - sdma->script_addrs->ram_code_start_addr); + addr->ram_code_start_addr); clk_disable(sdma->clk); sdma_add_scripts(sdma, addr); -- cgit v1.2.3 From 939fd4f077269dd863cd630a3b3195a20acf7d02 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 19 Jan 2011 19:13:06 +0800 Subject: dmaengine: imx-sdma: propagate error in sdma_probe() instead of returning 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Shawn Guo Acked-by: Uwe Kleine-König Signed-off-by: Dan Williams --- drivers/dma/imx-sdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 75df8b937413..1dbaf61eea2d 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1348,7 +1348,7 @@ err_clk: err_request_region: err_irq: kfree(sdma); - return 0; + return ret; } static int __exit sdma_remove(struct platform_device *pdev) -- cgit v1.2.3 From d718f4ebddcb0bebdbf771a6672756b666e5c31b Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 17 Jan 2011 22:39:24 +0800 Subject: dmaengine: imx-sdma: fix inconsistent naming in sdma_assign_cookie() Variable name sdma and sdmac are consistently used as the pointer to sdma_engine and sdma_channel respectively throughout the file. The patch fixes the inconsistency seen in function sdma_assign_cookie(). Signed-off-by: Shawn Guo Signed-off-by: Dan Williams --- drivers/dma/imx-sdma.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 1dbaf61eea2d..e89fd1033df9 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -770,15 +770,15 @@ static void sdma_enable_channel(struct sdma_engine *sdma, int channel) __raw_writel(1 << channel, sdma->regs + SDMA_H_START); } -static dma_cookie_t sdma_assign_cookie(struct sdma_channel *sdma) +static dma_cookie_t sdma_assign_cookie(struct sdma_channel *sdmac) { - dma_cookie_t cookie = sdma->chan.cookie; + dma_cookie_t cookie = sdmac->chan.cookie; if (++cookie < 0) cookie = 1; - sdma->chan.cookie = cookie; - sdma->desc.cookie = cookie; + sdmac->chan.cookie = cookie; + sdmac->desc.cookie = cookie; return cookie; } -- cgit v1.2.3 From de171cb9a52598cc023adceafc6c166112401386 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 31 Jan 2011 11:57:42 +1100 Subject: md: revert change to raid_disks on failure. If we try to update_raid_disks and it fails, we should put 'delta_disks' back to zero. This is important because some code, such as slot_store, assumes that delta_disks has been validated. Signed-off-by: NeilBrown --- drivers/md/md.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index b76cfc89e1b5..e636e404e9a5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5578,6 +5578,8 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks) mddev->delta_disks = raid_disks - mddev->raid_disks; rv = mddev->pers->check_reshape(mddev); + if (rv < 0) + mddev->delta_disks = 0; return rv; } -- cgit v1.2.3 From 87a8dec91e15954f0cf86be6c21741d991d83621 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 31 Jan 2011 11:57:43 +1100 Subject: md: simplify some 'if' conditionals in raid5_start_reshape. There are two consecutive 'if' statements. if (mddev->delta_disks >= 0) .... if (mddev->delta_disks > 0) The code in the second is equally valid if delta_disks == 0, and these two statements are the only place that 'added_devices' is used. So make them a single if statement, make added_devices a local variable, and re-indent it all. No functional change. Signed-off-by: NeilBrown --- drivers/md/raid5.c | 55 +++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 5044babfcda0..fa5519389a17 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5517,7 +5517,6 @@ static int raid5_start_reshape(mddev_t *mddev) raid5_conf_t *conf = mddev->private; mdk_rdev_t *rdev; int spares = 0; - int added_devices = 0; unsigned long flags; if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) @@ -5571,34 +5570,36 @@ static int raid5_start_reshape(mddev_t *mddev) * to correctly record the "partially reconstructed" state of * such devices during the reshape and confusion could result. */ - if (mddev->delta_disks >= 0) - list_for_each_entry(rdev, &mddev->disks, same_set) - if (rdev->raid_disk < 0 && - !test_bit(Faulty, &rdev->flags)) { - if (raid5_add_disk(mddev, rdev) == 0) { - char nm[20]; - if (rdev->raid_disk >= conf->previous_raid_disks) { - set_bit(In_sync, &rdev->flags); - added_devices++; + if (mddev->delta_disks >= 0) { + int added_devices = 0; + list_for_each_entry(rdev, &mddev->disks, same_set) + if (rdev->raid_disk < 0 && + !test_bit(Faulty, &rdev->flags)) { + if (raid5_add_disk(mddev, rdev) == 0) { + char nm[20]; + if (rdev->raid_disk + >= conf->previous_raid_disks) { + set_bit(In_sync, &rdev->flags); + added_devices++; + } else + rdev->recovery_offset = 0; + sprintf(nm, "rd%d", rdev->raid_disk); + if (sysfs_create_link(&mddev->kobj, + &rdev->kobj, nm)) + /* Failure here is OK */; } else - rdev->recovery_offset = 0; - sprintf(nm, "rd%d", rdev->raid_disk); - if (sysfs_create_link(&mddev->kobj, - &rdev->kobj, nm)) - /* Failure here is OK */; - } else - break; - } else if (rdev->raid_disk >= conf->previous_raid_disks - && !test_bit(Faulty, &rdev->flags)) { - /* This is a spare that was manually added */ - set_bit(In_sync, &rdev->flags); - added_devices++; - } + break; + } else if (rdev->raid_disk >= conf->previous_raid_disks + && !test_bit(Faulty, &rdev->flags)) { + /* This is a spare that was manually added */ + set_bit(In_sync, &rdev->flags); + added_devices++; + } - /* When a reshape changes the number of devices, ->degraded - * is measured against the larger of the pre and post number of - * devices.*/ - if (mddev->delta_disks > 0) { + /* When a reshape changes the number of devices, + * ->degraded is measured against the larger of the + * pre and post number of devices. + */ spin_lock_irqsave(&conf->device_lock, flags); mddev->degraded += (conf->raid_disks - conf->previous_raid_disks) - added_devices; -- cgit v1.2.3 From 469518a3455c79619e9231aeffeffa2e2989f738 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 31 Jan 2011 11:57:43 +1100 Subject: md: fix the test for finding spares in raid5_start_reshape. As spares can be added to the array before the reshape is started, we need to find and count them when checking there are enough. The array could have been degraded, so we need to check all devices, no just those out side of the range of devices in the array before the reshape. So instead of checking the index, check the In_sync flag as that reliably tells if the device is a spare or this purpose. Signed-off-by: NeilBrown --- drivers/md/raid5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index fa5519389a17..a6d2c3ddeee4 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5526,8 +5526,8 @@ static int raid5_start_reshape(mddev_t *mddev) return -ENOSPC; list_for_each_entry(rdev, &mddev->disks, same_set) - if ((rdev->raid_disk < 0 || rdev->raid_disk >= conf->raid_disks) - && !test_bit(Faulty, &rdev->flags)) + if (!test_bit(In_sync, &rdev->flags) + && !test_bit(Faulty, &rdev->flags)) spares++; if (spares - mddev->degraded < mddev->delta_disks - conf->max_degraded) -- cgit v1.2.3 From 50da08409654e036c4c964a473567a61a654cb83 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 31 Jan 2011 11:57:43 +1100 Subject: md: don't abort checking spares as soon as one cannot be added. As spares can be added manually before a reshape starts, we need to find them all to mark some of them as in_sync. Previously we would abort looking for spares when we found an unallocated spare what could not be added to the array (implying there was no room for new spares). However already-added spares could be later in the list, so we need to keep searching. Signed-off-by: NeilBrown --- drivers/md/raid5.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index a6d2c3ddeee4..702812824195 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5587,8 +5587,7 @@ static int raid5_start_reshape(mddev_t *mddev) if (sysfs_create_link(&mddev->kobj, &rdev->kobj, nm)) /* Failure here is OK */; - } else - break; + } } else if (rdev->raid_disk >= conf->previous_raid_disks && !test_bit(Faulty, &rdev->flags)) { /* This is a spare that was manually added */ -- cgit v1.2.3 From f21e9ff7f77d41ceca4e1e5ee5a4efa5ad7a5e40 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 31 Jan 2011 12:10:09 +1100 Subject: md: Remove the AllReserved flag for component devices. This flag is not needed and is used badly. Devices that are included in a native-metadata array are reserved exclusively for that array - and currently have AllReserved set. They all are bd_claimed for the rdev and so cannot be shared. Devices that are included in external-metadata arrays can be shared among multiple arrays - providing there is no overlap. These are bd_claimed for md in general - not for a particular rdev. When changing the amount of a device that is used in an array we need to check for overlap. This currently includes a check on AllReserved So even without overlap, sharing with an AllReserved device is not allowed. However the bd_claim usage already precludes sharing with these devices, so the test on AllReserved is not needed. And in fact it is wrong. As this is the only use of AllReserved, simply remove all usage and definition of AllReserved. Signed-off-by: NeilBrown --- drivers/md/md.c | 13 +++++-------- drivers/md/md.h | 2 -- 2 files changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index e636e404e9a5..f539b587ca72 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1947,8 +1947,6 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared) __bdevname(dev, b)); return PTR_ERR(bdev); } - if (!shared) - set_bit(AllReserved, &rdev->flags); rdev->bdev = bdev; return err; } @@ -2610,12 +2608,11 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) mddev_lock(mddev); list_for_each_entry(rdev2, &mddev->disks, same_set) - if (test_bit(AllReserved, &rdev2->flags) || - (rdev->bdev == rdev2->bdev && - rdev != rdev2 && - overlaps(rdev->data_offset, rdev->sectors, - rdev2->data_offset, - rdev2->sectors))) { + if (rdev->bdev == rdev2->bdev && + rdev != rdev2 && + overlaps(rdev->data_offset, rdev->sectors, + rdev2->data_offset, + rdev2->sectors)) { overlap = 1; break; } diff --git a/drivers/md/md.h b/drivers/md/md.h index eec517ced31a..7e90b8593b2a 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -93,8 +93,6 @@ struct mdk_rdev_s #define Faulty 1 /* device is known to have a fault */ #define In_sync 2 /* device is in_sync with rest of array */ #define WriteMostly 4 /* Avoid reading if at all possible */ -#define AllReserved 6 /* If whole device is reserved for - * one array */ #define AutoDetected 7 /* added by auto-detect */ #define Blocked 8 /* An error occured on an externally * managed array, don't allow writes -- cgit v1.2.3 From fc3a08b85b7a4f6c1069e5f71f6ad40d925ff55b Mon Sep 17 00:00:00 2001 From: Krzysztof Wojcik Date: Mon, 31 Jan 2011 13:47:13 +1100 Subject: Add raid1->raid0 takeover support This patch introduces raid 1 to raid0 takeover operation in kernel space. Signed-off-by: Krzysztof Wojcik Signed-off-by: Neil Brown --- drivers/md/raid0.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'drivers') diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index a39f4c355e55..637a96855edb 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -179,6 +179,14 @@ static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf) rdev1->new_raid_disk = j; } + if (mddev->level == 1) { + /* taiking over a raid1 array- + * we have only one active disk + */ + j = 0; + rdev1->new_raid_disk = j; + } + if (j < 0 || j >= mddev->raid_disks) { printk(KERN_ERR "md/raid0:%s: bad disk number %d - " "aborting!\n", mdname(mddev), j); @@ -644,12 +652,38 @@ static void *raid0_takeover_raid10(mddev_t *mddev) return priv_conf; } +static void *raid0_takeover_raid1(mddev_t *mddev) +{ + raid0_conf_t *priv_conf; + + /* Check layout: + * - (N - 1) mirror drives must be already faulty + */ + if ((mddev->raid_disks - 1) != mddev->degraded) { + printk(KERN_ERR "md/raid0:%s: (N - 1) mirrors drives must be already faulty!\n", + mdname(mddev)); + return ERR_PTR(-EINVAL); + } + + /* Set new parameters */ + mddev->new_level = 0; + mddev->new_layout = 0; + mddev->new_chunk_sectors = 128; /* by default set chunk size to 64k */ + mddev->delta_disks = 1 - mddev->raid_disks; + /* make sure it will be not marked as dirty */ + mddev->recovery_cp = MaxSector; + + create_strip_zones(mddev, &priv_conf); + return priv_conf; +} + static void *raid0_takeover(mddev_t *mddev) { /* raid0 can take over: * raid4 - if all data disks are active. * raid5 - providing it is Raid4 layout and one disk is faulty * raid10 - assuming we have all necessary active disks + * raid1 - with (N -1) mirror drives faulty */ if (mddev->level == 4) return raid0_takeover_raid45(mddev); @@ -665,6 +699,12 @@ static void *raid0_takeover(mddev_t *mddev) if (mddev->level == 10) return raid0_takeover_raid10(mddev); + if (mddev->level == 1) + return raid0_takeover_raid1(mddev); + + printk(KERN_ERR "Takeover from raid%i to raid0 not supported\n", + mddev->level); + return ERR_PTR(-EINVAL); } -- cgit v1.2.3 From a8c42c7f476b5bb39bb3a5b32d5473b9a46cadb9 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 31 Jan 2011 13:47:13 +1100 Subject: md: Don't use remove_and_add_spares to remove failed devices from a read-only array remove_and_add_spares is called in two places where the needs really are very different. remove_and_add_spares should not be called on an array which is about to be reshaped as some extra devices might have been manually added and that would remove them. However if the array is 'read-auto', that will currently happen, which is bad. So in the 'ro != 0' case don't call remove_and_add_spares but simply remove the failed devices as the comment suggests is needed. Signed-off-by: NeilBrown --- drivers/md/md.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index f539b587ca72..5b93829f3d49 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7027,7 +7027,7 @@ static int remove_and_add_spares(mddev_t *mddev) } } - if (mddev->degraded && ! mddev->ro && !mddev->recovery_disabled) { + if (mddev->degraded && !mddev->recovery_disabled) { list_for_each_entry(rdev, &mddev->disks, same_set) { if (rdev->raid_disk >= 0 && !test_bit(In_sync, &rdev->flags) && @@ -7150,7 +7150,20 @@ void md_check_recovery(mddev_t *mddev) /* Only thing we do on a ro array is remove * failed devices. */ - remove_and_add_spares(mddev); + mdk_rdev_t *rdev; + list_for_each_entry(rdev, &mddev->disks, same_set) + if (rdev->raid_disk >= 0 && + !test_bit(Blocked, &rdev->flags) && + test_bit(Faulty, &rdev->flags) && + atomic_read(&rdev->nr_pending)==0) { + if (mddev->pers->hot_remove_disk( + mddev, rdev->raid_disk)==0) { + char nm[20]; + sprintf(nm,"rd%d", rdev->raid_disk); + sysfs_remove_link(&mddev->kobj, nm); + rdev->raid_disk = -1; + } + } clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); goto unlock; } -- cgit v1.2.3 From 7281f8129c362436237b82c8c026494dd36479dc Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 31 Jan 2011 14:30:27 +1100 Subject: md: don't clear curr_resync_completed at end of resync. There is no need to set this to zero at this point. It will be set to zero by remove_and_add_spares or at the start of md_do_sync at the latest. And setting it to zero before MD_RECOVERY_RUNNING is cleared can make a 'zero' appear briefly in the 'sync_completed' sysfs attribute just as resync is finishing. So simply remove this setting to zero. Signed-off-by: NeilBrown --- drivers/md/md.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 5b93829f3d49..f2d5628d51cb 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -6984,9 +6984,6 @@ void md_do_sync(mddev_t *mddev) } else if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) mddev->resync_min = mddev->curr_resync_completed; mddev->curr_resync = 0; - if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) - mddev->curr_resync_completed = 0; - sysfs_notify(&mddev->kobj, NULL, "sync_completed"); wake_up(&resync_wait); set_bit(MD_RECOVERY_DONE, &mddev->recovery); md_wakeup_thread(mddev->thread); -- cgit v1.2.3 From fb526210b2b961b5d590b89fd8f45c0ca5769688 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Thu, 27 Jan 2011 12:32:53 +0000 Subject: DMA: PL08x: fix infinite wait when terminating transfers If we try to pause a channel when terminating a transfer, we could end up spinning for it to become inactive indefinitely, and can result in an uninterruptible wait requiring a reset to recover from. Terminating a transfer is supposed to take effect immediately, but may result in data loss. To make this clear, rename the function to pl08x_terminate_phy_chan(). Also, make sure it is always consistently called - with the spinlock held and IRQs disabled, and ensure that the TC and ERR interrupt status is always cleared. Signed-off-by: Russell King Acked-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/amba-pl08x.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 297f48b0cba9..8321a3997c95 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -267,19 +267,24 @@ static void pl08x_resume_phy_chan(struct pl08x_phy_chan *ch) } -/* Stops the channel */ -static void pl08x_stop_phy_chan(struct pl08x_phy_chan *ch) +/* + * pl08x_terminate_phy_chan() stops the channel, clears the FIFO and + * clears any pending interrupt status. This should not be used for + * an on-going transfer, but as a method of shutting down a channel + * (eg, when it's no longer used) or terminating a transfer. + */ +static void pl08x_terminate_phy_chan(struct pl08x_driver_data *pl08x, + struct pl08x_phy_chan *ch) { - u32 val; + u32 val = readl(ch->base + PL080_CH_CONFIG); - pl08x_pause_phy_chan(ch); + val &= ~(PL080_CONFIG_ENABLE | PL080_CONFIG_ERR_IRQ_MASK | + PL080_CONFIG_TC_IRQ_MASK); - /* Disable channel */ - val = readl(ch->base + PL080_CH_CONFIG); - val &= ~PL080_CONFIG_ENABLE; - val &= ~PL080_CONFIG_ERR_IRQ_MASK; - val &= ~PL080_CONFIG_TC_IRQ_MASK; writel(val, ch->base + PL080_CH_CONFIG); + + writel(1 << ch->id, pl08x->base + PL080_ERR_CLEAR); + writel(1 << ch->id, pl08x->base + PL080_TC_CLEAR); } static inline u32 get_bytes_in_cctl(u32 cctl) @@ -404,13 +409,12 @@ static inline void pl08x_put_phy_channel(struct pl08x_driver_data *pl08x, { unsigned long flags; + spin_lock_irqsave(&ch->lock, flags); + /* Stop the channel and clear its interrupts */ - pl08x_stop_phy_chan(ch); - writel((1 << ch->id), pl08x->base + PL080_ERR_CLEAR); - writel((1 << ch->id), pl08x->base + PL080_TC_CLEAR); + pl08x_terminate_phy_chan(pl08x, ch); /* Mark it as free */ - spin_lock_irqsave(&ch->lock, flags); ch->serving = NULL; spin_unlock_irqrestore(&ch->lock, flags); } @@ -1449,7 +1453,7 @@ static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, plchan->state = PL08X_CHAN_IDLE; if (plchan->phychan) { - pl08x_stop_phy_chan(plchan->phychan); + pl08x_terminate_phy_chan(pl08x, plchan->phychan); /* * Mark physical channel as free and free any slave -- cgit v1.2.3 From 8179661694595eb3a4f2ff9bb0b73acbb7d2f4a9 Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux Date: Thu, 27 Jan 2011 12:37:44 +0000 Subject: DMA: PL08x: fix channel pausing to timeout rather than lockup If a transfer is initiated from memory to a peripheral, then data is fetched and the channel is marked busy. This busy status persists until the HALT bit is set and the queued data has been transfered to the peripheral. Waiting indefinitely after setting the HALT bit results in system lockups. Timeout this operation, and print an error when this happens. Signed-off-by: Russell King Acked-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/amba-pl08x.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 8321a3997c95..07bca4970e50 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -79,6 +79,7 @@ #include #include #include +#include #include #include #include @@ -235,16 +236,19 @@ static void pl08x_start_txd(struct pl08x_dma_chan *plchan, } /* - * Overall DMAC remains enabled always. + * Pause the channel by setting the HALT bit. * - * Disabling individual channels could lose data. + * For M->P transfers, pause the DMAC first and then stop the peripheral - + * the FIFO can only drain if the peripheral is still requesting data. + * (note: this can still timeout if the DMAC FIFO never drains of data.) * - * Disable the peripheral DMA after disabling the DMAC in order to allow - * the DMAC FIFO to drain, and hence allow the channel to show inactive + * For P->M transfers, disable the peripheral first to stop it filling + * the DMAC FIFO, and then pause the DMAC. */ static void pl08x_pause_phy_chan(struct pl08x_phy_chan *ch) { u32 val; + int timeout; /* Set the HALT bit and wait for the FIFO to drain */ val = readl(ch->base + PL080_CH_CONFIG); @@ -252,8 +256,13 @@ static void pl08x_pause_phy_chan(struct pl08x_phy_chan *ch) writel(val, ch->base + PL080_CH_CONFIG); /* Wait for channel inactive */ - while (pl08x_phy_channel_busy(ch)) - cpu_relax(); + for (timeout = 1000; timeout; timeout--) { + if (!pl08x_phy_channel_busy(ch)) + break; + udelay(1); + } + if (pl08x_phy_channel_busy(ch)) + pr_err("pl08x: channel%u timeout waiting for pause\n", ch->id); } static void pl08x_resume_phy_chan(struct pl08x_phy_chan *ch) -- cgit v1.2.3 From b9b3f82f94b52ebb0bbdf6cd77ccc5e8ee3f53b5 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 12 Jan 2011 12:12:31 +0100 Subject: dmaengine i.MX sdma: set maximum segment size for our device Signed-off-by: Sascha Hauer --- drivers/dma/imx-sdma.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index d5a5d4d9c19b..c50305043f15 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -301,6 +301,7 @@ struct sdma_firmware_header { struct sdma_engine { struct device *dev; + struct device_dma_parameters dma_parms; struct sdma_channel channel[MAX_DMA_CHANNELS]; struct sdma_channel_control *channel_control; void __iomem *regs; @@ -1317,6 +1318,8 @@ static int __init sdma_probe(struct platform_device *pdev) sdma->dma_device.device_prep_dma_cyclic = sdma_prep_dma_cyclic; sdma->dma_device.device_control = sdma_control; sdma->dma_device.device_issue_pending = sdma_issue_pending; + sdma->dma_device.dev->dma_parms = &sdma->dma_parms; + dma_set_max_seg_size(sdma->dma_device.dev, 65535); ret = dma_async_device_register(&sdma->dma_device); if (ret) { -- cgit v1.2.3 From 1fa81c270da4d8dffa84fcca448654a10ed0a5dc Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 12 Jan 2011 13:02:28 +0100 Subject: dmaengine i.MX sdma: check sg entries for valid addresses and lengths This patch lets sdma_prep_slave_sg fail if the entries of an sg list do not start on multiples of the word size or if the lengths are not multiple of the word size. Also, catch the previously unhandled DMA_SLAVE_BUSWIDTH_8_BYTES and DMA_SLAVE_BUSWIDTH_UNDEFINED cases. Signed-off-by: Sascha Hauer --- drivers/dma/imx-sdma.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index c50305043f15..8707723e36da 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -925,10 +925,24 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( ret = -EINVAL; goto err_out; } - if (sdmac->word_size == DMA_SLAVE_BUSWIDTH_4_BYTES) + + switch (sdmac->word_size) { + case DMA_SLAVE_BUSWIDTH_4_BYTES: bd->mode.command = 0; - else - bd->mode.command = sdmac->word_size; + if (count & 3 || sg->dma_address & 3) + return NULL; + break; + case DMA_SLAVE_BUSWIDTH_2_BYTES: + bd->mode.command = 2; + if (count & 1 || sg->dma_address & 1) + return NULL; + break; + case DMA_SLAVE_BUSWIDTH_1_BYTE: + bd->mode.command = 1; + break; + default: + return NULL; + } param = BD_DONE | BD_EXTD | BD_CONT; -- cgit v1.2.3 From 7a0e9b2557902bdca563a5eb1bbac87560bd7d20 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 31 Jan 2011 10:19:53 +0100 Subject: dmaengine i.MX SDMA: do not initialize chan_id field This is bogus as the dmaengine core will overwrite this field. Signed-off-by: Sascha Hauer --- drivers/dma/imx-sdma.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 8707723e36da..3e848ee9a18a 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1307,7 +1307,6 @@ static int __init sdma_probe(struct platform_device *pdev) dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask); sdmac->chan.device = &sdma->dma_device; - sdmac->chan.chan_id = i; sdmac->channel = i; /* Add the channel to the DMAC list */ -- cgit v1.2.3 From 7214a8b14f63a1603401124bc150e17b145aa476 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 31 Jan 2011 10:21:35 +0100 Subject: dmaengine i.MX SDMA: initialize dma capabilities outside channel loop The capabilities are device specific fields, not channel specific fields. Signed-off-by: Sascha Hauer --- drivers/dma/imx-sdma.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 3e848ee9a18a..eb250681804b 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1295,6 +1295,9 @@ static int __init sdma_probe(struct platform_device *pdev) sdma->version = pdata->sdma_version; + dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask); + dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask); + INIT_LIST_HEAD(&sdma->dma_device.channels); /* Initialize channel parameters */ for (i = 0; i < MAX_DMA_CHANNELS; i++) { @@ -1303,9 +1306,6 @@ static int __init sdma_probe(struct platform_device *pdev) sdmac->sdma = sdma; spin_lock_init(&sdmac->lock); - dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask); - dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask); - sdmac->chan.device = &sdma->dma_device; sdmac->channel = i; -- cgit v1.2.3 From 23889c6352ab4a842a30221bb412ff49954b2fb3 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 31 Jan 2011 10:56:58 +0100 Subject: dmaengine i.MX SDMA: reserve channel 0 by not registering it We need channel 0 of the sdma engine for internal purposes. We accomplished this by calling dma_request_channel() in the probe function. This does not work when multiple dma engines are present which is the case when IPU support for i.MX31/35 is compiled in. So instead of registering channel 0 and reserving it afterwards simply do not register it in the first place. With this the dmaengine channel counting does not match sdma channel counting anymore, so we have to use sdma channel counting in the driver. Signed-off-by: Sascha Hauer --- drivers/dma/imx-sdma.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index eb250681804b..1eb3f0077403 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -230,7 +230,7 @@ struct sdma_engine; * struct sdma_channel - housekeeping for a SDMA channel * * @sdma pointer to the SDMA engine for this channel - * @channel the channel number, matches dmaengine chan_id + * @channel the channel number, matches dmaengine chan_id + 1 * @direction transfer type. Needed for setting SDMA script * @peripheral_type Peripheral type. Needed for setting SDMA script * @event_id0 aka dma request line @@ -799,7 +799,7 @@ static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx) cookie = sdma_assign_cookie(sdmac); - sdma_enable_channel(sdma, tx->chan->chan_id); + sdma_enable_channel(sdma, sdmac->channel); spin_unlock_irq(&sdmac->lock); @@ -812,10 +812,6 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan) struct imx_dma_data *data = chan->private; int prio, ret; - /* No need to execute this for internal channel 0 */ - if (chan->chan_id == 0) - return 0; - if (!data) return -EINVAL; @@ -880,7 +876,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( struct sdma_channel *sdmac = to_sdma_chan(chan); struct sdma_engine *sdma = sdmac->sdma; int ret, i, count; - int channel = chan->chan_id; + int channel = sdmac->channel; struct scatterlist *sg; if (sdmac->status == DMA_IN_PROGRESS) @@ -978,7 +974,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( struct sdma_channel *sdmac = to_sdma_chan(chan); struct sdma_engine *sdma = sdmac->sdma; int num_periods = buf_len / period_len; - int channel = chan->chan_id; + int channel = sdmac->channel; int ret, i = 0, buf = 0; dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel); @@ -1252,7 +1248,6 @@ static int __init sdma_probe(struct platform_device *pdev) struct resource *iores; struct sdma_platform_data *pdata = pdev->dev.platform_data; int i; - dma_cap_mask_t mask; struct sdma_engine *sdma; sdma = kzalloc(sizeof(*sdma), GFP_KERNEL); @@ -1309,8 +1304,14 @@ static int __init sdma_probe(struct platform_device *pdev) sdmac->chan.device = &sdma->dma_device; sdmac->channel = i; - /* Add the channel to the DMAC list */ - list_add_tail(&sdmac->chan.device_node, &sdma->dma_device.channels); + /* + * Add the channel to the DMAC list. Do not add channel 0 though + * because we need it internally in the SDMA driver. This also means + * that channel 0 in dmaengine counting matches sdma channel 1. + */ + if (i) + list_add_tail(&sdmac->chan.device_node, + &sdma->dma_device.channels); } ret = sdma_init(sdma); @@ -1340,13 +1341,6 @@ static int __init sdma_probe(struct platform_device *pdev) goto err_init; } - /* request channel 0. This is an internal control channel - * to the SDMA engine and not available to clients. - */ - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - dma_request_channel(mask, NULL, NULL); - dev_info(sdma->dev, "initialized\n"); return 0; -- cgit v1.2.3 From 1e070a60997f5bbaadd498c34380e2aa110336cf Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 12 Jan 2011 13:14:37 +0100 Subject: dmaengine i.MX dma: set maximum segment size for our device Signed-off-by: Sascha Hauer --- drivers/dma/imx-dma.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index e53d438142bb..a46e1d9fa3e4 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -49,6 +49,7 @@ struct imxdma_channel { struct imxdma_engine { struct device *dev; + struct device_dma_parameters dma_parms; struct dma_device dma_device; struct imxdma_channel channel[MAX_DMA_CHANNELS]; }; @@ -370,6 +371,9 @@ static int __init imxdma_probe(struct platform_device *pdev) platform_set_drvdata(pdev, imxdma); + imxdma->dma_device.dev->dma_parms = &imxdma->dma_parms; + dma_set_max_seg_size(imxdma->dma_device.dev, 0xffffff); + ret = dma_async_device_register(&imxdma->dma_device); if (ret) { dev_err(&pdev->dev, "unable to register\n"); -- cgit v1.2.3 From d07102a1bb0e759ce4571df30c62998ef5d8a8d3 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 12 Jan 2011 14:13:23 +0100 Subject: dmaengine i.MX dma: check sg entries for valid addresses and lengths Signed-off-by: Sascha Hauer --- drivers/dma/imx-dma.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index a46e1d9fa3e4..a1eac99a5fa1 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -243,6 +243,21 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg( else dmamode = DMA_MODE_WRITE; + switch (imxdmac->word_size) { + case DMA_SLAVE_BUSWIDTH_4_BYTES: + if (sgl->length & 3 || sgl->dma_address & 3) + return NULL; + break; + case DMA_SLAVE_BUSWIDTH_2_BYTES: + if (sgl->length & 1 || sgl->dma_address & 1) + return NULL; + break; + case DMA_SLAVE_BUSWIDTH_1_BYTE: + break; + default: + return NULL; + } + ret = imx_dma_setup_sg(imxdmac->imxdma_channel, sgl, sg_len, dma_length, imxdmac->per_address, dmamode); if (ret) -- cgit v1.2.3 From 97a43dfe84119528ec2576129b91d619219ab716 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 31 Jan 2011 11:35:44 +0100 Subject: dmaengine i.MX DMA: do not initialize chan_id field Signed-off-by: Sascha Hauer --- drivers/dma/imx-dma.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index a1eac99a5fa1..82627087b550 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -366,7 +366,6 @@ static int __init imxdma_probe(struct platform_device *pdev) dma_cap_set(DMA_CYCLIC, imxdma->dma_device.cap_mask); imxdmac->chan.device = &imxdma->dma_device; - imxdmac->chan.chan_id = i; imxdmac->channel = i; /* Add the channel to the DMAC list */ -- cgit v1.2.3 From f8a356ff96a9070156f863e4f7716e2a0eb8c995 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Mon, 31 Jan 2011 11:35:59 +0100 Subject: dmaengine i.MX dma: initialize dma capabilities outside channel loop The capabilities are device specific fields, not channel specific fields. Signed-off-by: Sascha Hauer --- drivers/dma/imx-dma.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 82627087b550..e18eaabe92b9 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -345,6 +345,9 @@ static int __init imxdma_probe(struct platform_device *pdev) INIT_LIST_HEAD(&imxdma->dma_device.channels); + dma_cap_set(DMA_SLAVE, imxdma->dma_device.cap_mask); + dma_cap_set(DMA_CYCLIC, imxdma->dma_device.cap_mask); + /* Initialize channel parameters */ for (i = 0; i < MAX_DMA_CHANNELS; i++) { struct imxdma_channel *imxdmac = &imxdma->channel[i]; @@ -362,9 +365,6 @@ static int __init imxdma_probe(struct platform_device *pdev) imxdmac->imxdma = imxdma; spin_lock_init(&imxdmac->lock); - dma_cap_set(DMA_SLAVE, imxdma->dma_device.cap_mask); - dma_cap_set(DMA_CYCLIC, imxdma->dma_device.cap_mask); - imxdmac->chan.device = &imxdma->dma_device; imxdmac->channel = i; -- cgit v1.2.3 From 1797c33f0edcdcc9a483c06233a203786666a97f Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 20 Jan 2011 05:50:35 +0800 Subject: dmaengine: imx-sdma: remove IMX_DMA_SG_LOOP handling in sdma_prep_slave_sg() This is a leftover from the time that the driver did not have sdma_prep_dma_cyclic callback and implemented sound dma as a looped sg chain. And it can be removed now. Signed-off-by: Shawn Guo Signed-off-by: Sascha Hauer --- drivers/dma/imx-sdma.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index d5a5d4d9c19b..cf8cc0b8e7f7 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -931,12 +931,6 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( param = BD_DONE | BD_EXTD | BD_CONT; - if (sdmac->flags & IMX_DMA_SG_LOOP) { - param |= BD_INTR; - if (i + 1 == sg_len) - param |= BD_WRAP; - } - if (i + 1 == sg_len) param |= BD_INTR; -- cgit v1.2.3 From 4b2ce9ddb370c4eb573540611c347d78ac4b54a0 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 20 Jan 2011 05:50:36 +0800 Subject: dmaengine: imx-sdma: set sdmac->status to DMA_ERROR in err_out of sdma_prep_slave_sg() sdma_prep_dma_cyclic() sets sdmac->status to DMA_ERROR in err_out, and sdma_prep_slave_sg() needs to do the same. Otherwise, sdmac->status stays at DMA_IN_PROGRESS, which will make the function return immediately next time it gets called. Signed-off-by: Shawn Guo Signed-off-by: Sascha Hauer --- drivers/dma/imx-sdma.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index cf8cc0b8e7f7..6fc04d85be6b 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -947,6 +947,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( return &sdmac->desc; err_out: + sdmac->status = DMA_ERROR; return NULL; } -- cgit v1.2.3 From 8a9659114c7be6f88253618252881ea6fe0588b4 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 20 Jan 2011 05:50:37 +0800 Subject: dmaengine: imx-sdma: return sdmac->status in sdma_tx_status() The sdmac->status was designed to reflect the status of the tx, so simply return it in sdma_tx_status(). Then dma client can call dma_async_is_tx_complete() to know the status of the tx. Signed-off-by: Shawn Guo Signed-off-by: Sascha Hauer --- drivers/dma/imx-sdma.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 6fc04d85be6b..f331ae0f7ec3 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1061,14 +1061,12 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan, { struct sdma_channel *sdmac = to_sdma_chan(chan); dma_cookie_t last_used; - enum dma_status ret; last_used = chan->cookie; - ret = dma_async_is_complete(cookie, sdmac->last_completed, last_used); dma_set_tx_state(txstate, sdmac->last_completed, last_used, 0); - return ret; + return sdmac->status; } static void sdma_issue_pending(struct dma_chan *chan) -- cgit v1.2.3 From 1e9cebb42de57f1243261939c77ab5b0f9bcf311 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 20 Jan 2011 05:50:38 +0800 Subject: dmaengine: imx-sdma: correct sdmac->status in sdma_handle_channel_loop() sdma_handle_channel_loop() is the handler of cyclic tx. One period success does not really mean the success of the tx. Instead of DMA_SUCCESS, DMA_IN_PROGRESS should be the one to tell. Signed-off-by: Shawn Guo Signed-off-by: Sascha Hauer --- drivers/dma/imx-sdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index f331ae0f7ec3..cf93d1737f1e 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -449,7 +449,7 @@ static void sdma_handle_channel_loop(struct sdma_channel *sdmac) if (bd->mode.status & BD_RROR) sdmac->status = DMA_ERROR; else - sdmac->status = DMA_SUCCESS; + sdmac->status = DMA_IN_PROGRESS; bd->mode.status |= BD_DONE; sdmac->buf_tail++; -- cgit v1.2.3 From 341b9419a8c0a4cdb75773c576870f1eb655516d Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 20 Jan 2011 05:50:39 +0800 Subject: dmaengine: imx-sdma: fix up param for the last BD in sdma_prep_slave_sg() As per the reference manual, bit "L" should be set while bit "C" should be cleared for the last buffer descriptor in the non-cyclic chain, so that sdma can stop trying to find the next BD and end the transfer. In case of sdma_prep_slave_sg(), BD_LAST needs to be set and BD_CONT be cleared for the last BD. Signed-off-by: Shawn Guo Signed-off-by: Sascha Hauer --- drivers/dma/imx-sdma.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index cf93d1737f1e..4535f98b3553 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -931,8 +931,11 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( param = BD_DONE | BD_EXTD | BD_CONT; - if (i + 1 == sg_len) + if (i + 1 == sg_len) { param |= BD_INTR; + param |= BD_LAST; + param &= ~BD_CONT; + } dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%08x %s%s\n", i, count, sg->dma_address, -- cgit v1.2.3 From 28a1bc1c0a5a15e72afae1050b227761227b6af2 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Mon, 31 Jan 2011 21:06:38 -0800 Subject: Input: wacom_w8001 - report resolution to userland Serial devices send both pen and touch data through the same logical port. Since we scaled touch to pen maximum, we use pen resolution for touch as well here. This is under the assumption that pen and touch share the same physical surface. In the case when a small physical dimensional difference occurs between pen and touch, we assume the tolerance for touch point precision is higher than pen and the difference is within touch point tolerance. A per-MT tool based resolution mechanism should be introduced if the above assumption does not hold true for the pen and touch devices any more. Signed-off-by: Ping Cheng Reviewed-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wacom_w8001.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 5cb8449c909d..c14412ef4648 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -51,6 +51,10 @@ MODULE_LICENSE("GPL"); #define W8001_PKTLEN_TPCCTL 11 /* control packet */ #define W8001_PKTLEN_TOUCH2FG 13 +/* resolution in points/mm */ +#define W8001_PEN_RESOLUTION 100 +#define W8001_TOUCH_RESOLUTION 10 + struct w8001_coord { u8 rdy; u8 tsw; @@ -198,7 +202,7 @@ static void parse_touchquery(u8 *data, struct w8001_touch_query *query) query->y = 1024; if (query->panel_res) query->x = query->y = (1 << query->panel_res); - query->panel_res = 10; + query->panel_res = W8001_TOUCH_RESOLUTION; } } @@ -394,6 +398,8 @@ static int w8001_setup(struct w8001 *w8001) input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); + input_abs_set_res(dev, ABS_X, W8001_PEN_RESOLUTION); + input_abs_set_res(dev, ABS_Y, W8001_PEN_RESOLUTION); input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0); if (coord.tilt_x && coord.tilt_y) { input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); @@ -418,14 +424,17 @@ static int w8001_setup(struct w8001 *w8001) w8001->max_touch_x = touch.x; w8001->max_touch_y = touch.y; - /* scale to pen maximum */ if (w8001->max_pen_x && w8001->max_pen_y) { + /* if pen is supported scale to pen maximum */ touch.x = w8001->max_pen_x; touch.y = w8001->max_pen_y; + touch.panel_res = W8001_PEN_RESOLUTION; } input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0); input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0); + input_abs_set_res(dev, ABS_X, touch.panel_res); + input_abs_set_res(dev, ABS_Y, touch.panel_res); switch (touch.sensor_id) { case 0: -- cgit v1.2.3 From 456bb1697ec08c034449c81e03094fe26bedb9e9 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 21 Dec 2010 21:16:11 +0800 Subject: usb: musb: fix kernel panic during s2ram(v2) This patch fixes kernel panic during s2ram, which is caused by the below: - musb is not put into drv data of musb platform device if CONFIG_USB_MUSB_HDRC_HCD is defined - glue layer driver always get musb instance via platform_get_drvdata. The patch fixes the issue by always puting musb into drv data of musb platform device, which is doable even the platform device is a host controller device. Cc: Alan Stern Cc: Sergei Shtylyov Signed-off-by: Ming Lei Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 07cf394e491b..12b515b3b69e 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -128,12 +128,7 @@ MODULE_ALIAS("platform:" MUSB_DRIVER_NAME); static inline struct musb *dev_to_musb(struct device *dev) { -#ifdef CONFIG_USB_MUSB_HDRC_HCD - /* usbcore insists dev->driver_data is a "struct hcd *" */ - return hcd_to_musb(dev_get_drvdata(dev)); -#else return dev_get_drvdata(dev); -#endif } /*-------------------------------------------------------------------------*/ @@ -1876,10 +1871,9 @@ allocate_instance(struct device *dev, musb = kzalloc(sizeof *musb, GFP_KERNEL); if (!musb) return NULL; - dev_set_drvdata(dev, musb); #endif - + dev_set_drvdata(dev, musb); musb->mregs = mbase; musb->ctrl_base = mbase; musb->nIrq = -ENODEV; -- cgit v1.2.3 From 541079de88735152a993ff93e90096643730a054 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 10 Dec 2010 21:03:29 +0300 Subject: usb: musb: core: fix IRQ check musb_probe() only regards 0 as a wrong IRQ number, despite platform_get_irq() that it calls returns -ENXIO in that case. It leads to musb_init_controller() calling request_irq() with a negative IRQ number, and when it naturally fails, the following is printed to the console: request_irq -6 failed! musb_init_controller failed with status -19 Fix musb_probe() to filter out the error values as well as 0. Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 12b515b3b69e..54a8bd1047d6 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2185,7 +2185,7 @@ static int __init musb_probe(struct platform_device *pdev) void __iomem *base; iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iomem || irq == 0) + if (!iomem || irq <= 0) return -ENODEV; base = ioremap(iomem->start, resource_size(iomem)); -- cgit v1.2.3 From 9c668079c864c3b49d8deb56dafedf916b2a72d0 Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Wed, 5 Jan 2011 17:36:41 +0800 Subject: usb: musb: hsdma: change back to use musb_read/writew Blackfin platform doesn't support 32bits musbdma registers, so change back to use musb_read/writew instead of musb_read/writel and simply some format casts. Signed-off-by: Bob Liu Signed-off-by: Felipe Balbi --- drivers/usb/musb/musbhsdma.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h index f763d62f151c..21056c924c74 100644 --- a/drivers/usb/musb/musbhsdma.h +++ b/drivers/usb/musb/musbhsdma.h @@ -94,24 +94,33 @@ static inline void musb_write_hsdma_addr(void __iomem *mbase, { musb_writew(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_LOW), - ((u16)((u32) dma_addr & 0xFFFF))); + dma_addr); musb_writew(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_HIGH), - ((u16)(((u32) dma_addr >> 16) & 0xFFFF))); + (dma_addr >> 16)); } static inline u32 musb_read_hsdma_count(void __iomem *mbase, u8 bchannel) { - return musb_readl(mbase, + u32 count = musb_readw(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_HIGH)); + + count = count << 16; + + count |= musb_readw(mbase, + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_LOW)); + + return count; } static inline void musb_write_hsdma_count(void __iomem *mbase, u8 bchannel, u32 len) { - musb_writel(mbase, + musb_writew(mbase, + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_LOW),len); + musb_writew(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_HIGH), - len); + (len >> 16)); } #endif /* CONFIG_BLACKFIN */ -- cgit v1.2.3 From 0662481855c389b75a0a54c32870cc90563d80a9 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 21 Jan 2011 13:39:20 +0800 Subject: usb: musb: disable double buffering when it's broken We know that blackfin doesn't support double buffering feature as of today. So we add a flag set by musb_platform_init() to forcefully disable that feature. Such flag is created and marked as deprecated to force us to find a solution for the missing double buffering support on blackfin. Signed-off-by: Felipe Balbi --- drivers/usb/musb/blackfin.c | 1 + drivers/usb/musb/musb_core.h | 12 ++++++++++++ drivers/usb/musb/musb_gadget.c | 12 ++++++++++-- drivers/usb/musb/musb_host.c | 11 +++++------ 4 files changed, 28 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index eeba228eb2af..9d49d1cd7ce2 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -404,6 +404,7 @@ static int bfin_musb_init(struct musb *musb) musb->xceiv->set_power = bfin_musb_set_power; musb->isr = blackfin_interrupt; + musb->double_buffer_not_ok = true; return 0; } diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index d0c236f8e191..d74a8113ae74 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -488,6 +488,18 @@ struct musb { unsigned set_address:1; unsigned test_mode:1; unsigned softconnect:1; + /* + * FIXME: Remove this flag. + * + * This is only added to allow Blackfin to work + * with current driver. For some unknown reason + * Blackfin doesn't work with double buffering + * and that's enabled by default. + * + * We added this flag to forcefully disable double + * buffering until we get it working. + */ + unsigned double_buffer_not_ok:1 __deprecated; u8 address; u8 test_mode_nr; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index ed58c6c8f15c..23dad4c8785d 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -989,7 +989,11 @@ static int musb_gadget_enable(struct usb_ep *ep, /* Set TXMAXP with the FIFO size of the endpoint * to disable double buffering mode. */ - musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11)); + if (musb->double_buffer_not_ok) + musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx); + else + musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz + | (musb_ep->hb_mult << 11)); csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG; if (musb_readw(regs, MUSB_TXCSR) @@ -1025,7 +1029,11 @@ static int musb_gadget_enable(struct usb_ep *ep, /* Set RXMAXP with the FIFO size of the endpoint * to disable double buffering mode. */ - musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11)); + if (musb->double_buffer_not_ok) + musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_tx); + else + musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz + | (musb_ep->hb_mult << 11)); /* force shared fifo to OUT-only mode */ if (hw_ep->is_shared_fifo) { diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 4d5bcb4e14d2..0f523d7db57b 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -609,7 +609,7 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) /* Set RXMAXP with the FIFO size of the endpoint * to disable double buffer mode. */ - if (musb->hwvers < MUSB_HWVERS_2000) + if (musb->double_buffer_not_ok) musb_writew(ep->regs, MUSB_RXMAXP, ep->max_packet_sz_rx); else musb_writew(ep->regs, MUSB_RXMAXP, @@ -784,14 +784,13 @@ static void musb_ep_program(struct musb *musb, u8 epnum, /* protocol/endpoint/interval/NAKlimit */ if (epnum) { musb_writeb(epio, MUSB_TXTYPE, qh->type_reg); - if (can_bulk_split(musb, qh->type)) + if (musb->double_buffer_not_ok) musb_writew(epio, MUSB_TXMAXP, - packet_sz - | ((hw_ep->max_packet_sz_tx / - packet_sz) - 1) << 11); + hw_ep->max_packet_sz_tx); else musb_writew(epio, MUSB_TXMAXP, - packet_sz); + qh->maxpacket | + ((qh->hb_mult - 1) << 11)); musb_writ