|
@@ -348,7 +348,7 @@ static void cciss_unmap_sg_chain_block(ctlr_info_t *h, CommandList_struct *c)
|
|
pci_unmap_single(h->pdev, temp64.val, chain_sg->Len, PCI_DMA_TODEVICE);
|
|
pci_unmap_single(h->pdev, temp64.val, chain_sg->Len, PCI_DMA_TODEVICE);
|
|
}
|
|
}
|
|
|
|
|
|
-static void cciss_map_sg_chain_block(ctlr_info_t *h, CommandList_struct *c,
|
|
|
|
|
|
+static int cciss_map_sg_chain_block(ctlr_info_t *h, CommandList_struct *c,
|
|
SGDescriptor_struct *chain_block, int len)
|
|
SGDescriptor_struct *chain_block, int len)
|
|
{
|
|
{
|
|
SGDescriptor_struct *chain_sg;
|
|
SGDescriptor_struct *chain_sg;
|
|
@@ -359,8 +359,16 @@ static void cciss_map_sg_chain_block(ctlr_info_t *h, CommandList_struct *c,
|
|
chain_sg->Len = len;
|
|
chain_sg->Len = len;
|
|
temp64.val = pci_map_single(h->pdev, chain_block, len,
|
|
temp64.val = pci_map_single(h->pdev, chain_block, len,
|
|
PCI_DMA_TODEVICE);
|
|
PCI_DMA_TODEVICE);
|
|
|
|
+ if (dma_mapping_error(&h->pdev->dev, temp64.val)) {
|
|
|
|
+ dev_warn(&h->pdev->dev,
|
|
|
|
+ "%s: error mapping chain block for DMA\n",
|
|
|
|
+ __func__);
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
chain_sg->Addr.lower = temp64.val32.lower;
|
|
chain_sg->Addr.lower = temp64.val32.lower;
|
|
chain_sg->Addr.upper = temp64.val32.upper;
|
|
chain_sg->Addr.upper = temp64.val32.upper;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
#include "cciss_scsi.c" /* For SCSI tape support */
|
|
#include "cciss_scsi.c" /* For SCSI tape support */
|
|
@@ -3369,15 +3377,31 @@ static void do_cciss_request(struct request_queue *q)
|
|
temp64.val = (__u64) pci_map_page(h->pdev, sg_page(&tmp_sg[i]),
|
|
temp64.val = (__u64) pci_map_page(h->pdev, sg_page(&tmp_sg[i]),
|
|
tmp_sg[i].offset,
|
|
tmp_sg[i].offset,
|
|
tmp_sg[i].length, dir);
|
|
tmp_sg[i].length, dir);
|
|
|
|
+ if (dma_mapping_error(&h->pdev->dev, temp64.val)) {
|
|
|
|
+ dev_warn(&h->pdev->dev,
|
|
|
|
+ "%s: error mapping page for DMA\n", __func__);
|
|
|
|
+ creq->errors = make_status_bytes(SAM_STAT_GOOD,
|
|
|
|
+ 0, DRIVER_OK,
|
|
|
|
+ DID_SOFT_ERROR);
|
|
|
|
+ cmd_free(h, c);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
curr_sg[sg_index].Addr.lower = temp64.val32.lower;
|
|
curr_sg[sg_index].Addr.lower = temp64.val32.lower;
|
|
curr_sg[sg_index].Addr.upper = temp64.val32.upper;
|
|
curr_sg[sg_index].Addr.upper = temp64.val32.upper;
|
|
curr_sg[sg_index].Ext = 0; /* we are not chaining */
|
|
curr_sg[sg_index].Ext = 0; /* we are not chaining */
|
|
++sg_index;
|
|
++sg_index;
|
|
}
|
|
}
|
|
- if (chained)
|
|
|
|
- cciss_map_sg_chain_block(h, c, h->cmd_sg_list[c->cmdindex],
|
|
|
|
|
|
+ if (chained) {
|
|
|
|
+ if (cciss_map_sg_chain_block(h, c, h->cmd_sg_list[c->cmdindex],
|
|
(seg - (h->max_cmd_sgentries - 1)) *
|
|
(seg - (h->max_cmd_sgentries - 1)) *
|
|
- sizeof(SGDescriptor_struct));
|
|
|
|
|
|
+ sizeof(SGDescriptor_struct))) {
|
|
|
|
+ creq->errors = make_status_bytes(SAM_STAT_GOOD,
|
|
|
|
+ 0, DRIVER_OK,
|
|
|
|
+ DID_SOFT_ERROR);
|
|
|
|
+ cmd_free(h, c);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
/* track how many SG entries we are using */
|
|
/* track how many SG entries we are using */
|
|
if (seg > h->maxSG)
|
|
if (seg > h->maxSG)
|