aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/mtip32xx/mtip32xx.c
diff options
context:
space:
mode:
authorAsai Thambi S P <asamymuthupa@micron.com>2013-04-29 15:19:49 -0400
committerJens Axboe <axboe@kernel.dk>2013-04-29 15:19:49 -0400
commit2077d947260c620550ba06f76aa4affd0106f4da (patch)
tree1c81837535f27e94ff0fb6d57db47c0c5cf61bde /drivers/block/mtip32xx/mtip32xx.c
parent68466cbf92367c0808bfd2c64bc6faddd7a97b6f (diff)
mtip32xx: Workaround for unaligned writes
Workaround for handling unaligned writes: limit number of outstanding unaligned writes Signed-off-by: Sam Bradshaw <sbradshaw@micron.com> Signed-off-by: Asai Thambi S P <asamymuthupa@micron.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block/mtip32xx/mtip32xx.c')
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c59
1 files changed, 47 insertions, 12 deletions
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 30a03ab7efc9..c0d38734041c 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -712,7 +712,10 @@ static void mtip_async_complete(struct mtip_port *port,
712 atomic_set(&port->commands[tag].active, 0); 712 atomic_set(&port->commands[tag].active, 0);
713 release_slot(port, tag); 713 release_slot(port, tag);
714 714
715 up(&port->cmd_slot); 715 if (unlikely(command->unaligned))
716 up(&port->cmd_slot_unal);
717 else
718 up(&port->cmd_slot);
716} 719}
717 720
718/* 721/*
@@ -2557,7 +2560,7 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,
2557 */ 2560 */
2558static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector, 2561static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector,
2559 int nsect, int nents, int tag, void *callback, 2562 int nsect, int nents, int tag, void *callback,
2560 void *data, int dir) 2563 void *data, int dir, int unaligned)
2561{ 2564{
2562 struct host_to_dev_fis *fis; 2565 struct host_to_dev_fis *fis;
2563 struct mtip_port *port = dd->port; 2566 struct mtip_port *port = dd->port;
@@ -2570,6 +2573,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector,
2570 2573
2571 command->scatter_ents = nents; 2574 command->scatter_ents = nents;
2572 2575
2576 command->unaligned = unaligned;
2573 /* 2577 /*
2574 * The number of retries for this command before it is 2578 * The number of retries for this command before it is
2575 * reported as a failure to the upper layers. 2579 * reported as a failure to the upper layers.
@@ -2598,6 +2602,9 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector,
2598 fis->res3 = 0; 2602 fis->res3 = 0;
2599 fill_command_sg(dd, command, nents); 2603 fill_command_sg(dd, command, nents);
2600 2604
2605 if (unaligned)
2606 fis->device |= 1 << 7;
2607
2601 /* Populate the command header */ 2608 /* Populate the command header */
2602 command->command_header->opts = 2609 command->command_header->opts =
2603 __force_bit2int cpu_to_le32( 2610 __force_bit2int cpu_to_le32(
@@ -2644,9 +2651,13 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector,
2644 * return value 2651 * return value
2645 * None 2652 * None
2646 */ 2653 */
2647static void mtip_hw_release_scatterlist(struct driver_data *dd, int tag) 2654static void mtip_hw_release_scatterlist(struct driver_data *dd, int tag,
2655 int unaligned)
2648{ 2656{
2657 struct semaphore *sem = unaligned ? &dd->port->cmd_slot_unal :
2658 &dd->port->cmd_slot;
2649 release_slot(dd->port, tag); 2659 release_slot(dd->port, tag);
2660 up(sem);
2650} 2661}
2651 2662
2652/* 2663/*
@@ -2661,22 +2672,25 @@ static void mtip_hw_release_scatterlist(struct driver_data *dd, int tag)
2661 * or NULL if no command slots are available. 2672 * or NULL if no command slots are available.
2662 */ 2673 */
2663static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd, 2674static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd,
2664 int *tag) 2675 int *tag, int unaligned)
2665{ 2676{
2677 struct semaphore *sem = unaligned ? &dd->port->cmd_slot_unal :
2678 &dd->port->cmd_slot;
2679
2666 /* 2680 /*
2667 * It is possible that, even with this semaphore, a thread 2681 * It is possible that, even with this semaphore, a thread
2668 * may think that no command slots are available. Therefore, we 2682 * may think that no command slots are available. Therefore, we
2669 * need to make an attempt to get_slot(). 2683 * need to make an attempt to get_slot().
2670 */ 2684 */
2671 down(&dd->port->cmd_slot); 2685 down(sem);
2672 *tag = get_slot(dd->port); 2686 *tag = get_slot(dd->port);
2673 2687
2674 if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))) { 2688 if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))) {
2675 up(&dd->port->cmd_slot); 2689 up(sem);
2676 return NULL; 2690 return NULL;
2677 } 2691 }
2678 if (unlikely(*tag < 0)) { 2692 if (unlikely(*tag < 0)) {
2679 up(&dd->port->cmd_slot); 2693 up(sem);
2680 return NULL; 2694 return NULL;
2681 } 2695 }
2682 2696
@@ -2909,6 +2923,11 @@ static inline void hba_setup(struct driver_data *dd)
2909 dd->mmio + HOST_HSORG); 2923 dd->mmio + HOST_HSORG);
2910} 2924}
2911 2925
2926static int mtip_device_unaligned_constrained(struct driver_data *dd)
2927{
2928 return (dd->pdev->device == P420M_DEVICE_ID ? 1 : 0);
2929}
2930
2912/* 2931/*
2913 * Detect the details of the product, and store anything needed 2932 * Detect the details of the product, and store anything needed
2914 * into the driver data structure. This includes product type and 2933 * into the driver data structure. This includes product type and
@@ -3131,8 +3150,15 @@ static int mtip_hw_init(struct driver_data *dd)
3131 for (i = 0; i < MTIP_MAX_SLOT_GROUPS; i++) 3150 for (i = 0; i < MTIP_MAX_SLOT_GROUPS; i++)
3132 dd->work[i].port = dd->port; 3151 dd->work[i].port = dd->port;
3133 3152
3153 /* Enable unaligned IO constraints for some devices */
3154 if (mtip_device_unaligned_constrained(dd))
3155 dd->unal_qdepth = MTIP_MAX_UNALIGNED_SLOTS;
3156 else
3157 dd->unal_qdepth = 0;
3158
3134 /* Counting semaphore to track command slot usage */ 3159 /* Counting semaphore to track command slot usage */
3135 sema_init(&dd->port->cmd_slot, num_command_slots - 1); 3160 sema_init(&dd->port->cmd_slot, num_command_slots - 1 - dd->unal_qdepth);
3161 sema_init(&dd->port->cmd_slot_unal, dd->unal_qdepth);
3136 3162
3137 /* Spinlock to prevent concurrent issue */ 3163 /* Spinlock to prevent concurrent issue */
3138 for (i = 0; i < MTIP_MAX_SLOT_GROUPS; i++) 3164 for (i = 0; i < MTIP_MAX_SLOT_GROUPS; i++)
@@ -3735,7 +3761,7 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
3735 struct scatterlist *sg; 3761 struct scatterlist *sg;
3736 struct bio_vec *bvec; 3762 struct bio_vec *bvec;
3737 int nents = 0; 3763 int nents = 0;
3738 int tag = 0; 3764 int tag = 0, unaligned = 0;
3739 3765
3740 if (unlikely(dd->dd_flag & MTIP_DDF_STOP_IO)) { 3766 if (unlikely(dd->dd_flag & MTIP_DDF_STOP_IO)) {
3741 if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, 3767 if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
@@ -3771,7 +3797,15 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
3771 return; 3797 return;
3772 } 3798 }
3773 3799
3774 sg = mtip_hw_get_scatterlist(dd, &tag); 3800 if (bio_data_dir(bio) == WRITE && bio_sectors(bio) <= 64 &&
3801 dd->unal_qdepth) {
3802 if (bio->bi_sector % 8 != 0) /* Unaligned on 4k boundaries */
3803 unaligned = 1;
3804 else if (bio_sectors(bio) % 8 != 0) /* Aligned but not 4k/8k */
3805 unaligned = 1;
3806 }
3807
3808 sg = mtip_hw_get_scatterlist(dd, &tag, unaligned);
3775 if (likely(sg != NULL)) { 3809 if (likely(sg != NULL)) {
3776 blk_queue_bounce(queue, &bio); 3810 blk_queue_bounce(queue, &bio);
3777 3811
@@ -3779,7 +3813,7 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
3779 dev_warn(&dd->pdev->dev, 3813 dev_warn(&dd->pdev->dev,
3780 "Maximum number of SGL entries exceeded\n"); 3814 "Maximum number of SGL entries exceeded\n");
3781 bio_io_error(bio); 3815 bio_io_error(bio);
3782 mtip_hw_release_scatterlist(dd, tag); 3816 mtip_hw_release_scatterlist(dd, tag, unaligned);
3783 return; 3817 return;
3784 } 3818 }
3785 3819
@@ -3799,7 +3833,8 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
3799 tag, 3833 tag,
3800 bio_endio, 3834 bio_endio,
3801 bio, 3835 bio,
3802 bio_data_dir(bio)); 3836 bio_data_dir(bio),
3837 unaligned);
3803 } else 3838 } else
3804 bio_io_error(bio); 3839 bio_io_error(bio);
3805} 3840}