aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/fcoe/fcoe.c5
-rw-r--r--drivers/scsi/libfc/fc_fcp.c20
-rw-r--r--drivers/scsi/libfc/fc_frame.c5
3 files changed, 16 insertions, 14 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 28029a34289..b570f39faa3 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -1267,10 +1267,11 @@ err2:
1267 */ 1267 */
1268static inline int fcoe_start_io(struct sk_buff *skb) 1268static inline int fcoe_start_io(struct sk_buff *skb)
1269{ 1269{
1270 struct sk_buff *nskb;
1270 int rc; 1271 int rc;
1271 1272
1272 skb_get(skb); 1273 nskb = skb_clone(skb, GFP_ATOMIC);
1273 rc = dev_queue_xmit(skb); 1274 rc = dev_queue_xmit(nskb);
1274 if (rc != 0) 1275 if (rc != 0)
1275 return rc; 1276 return rc;
1276 kfree_skb(skb); 1277 kfree_skb(skb);
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index db252e2722d..c4b58d042f6 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -530,11 +530,13 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
530 struct scatterlist *sg; 530 struct scatterlist *sg;
531 struct fc_frame *fp = NULL; 531 struct fc_frame *fp = NULL;
532 struct fc_lport *lport = fsp->lp; 532 struct fc_lport *lport = fsp->lp;
533 struct page *page;
533 size_t remaining; 534 size_t remaining;
534 size_t t_blen; 535 size_t t_blen;
535 size_t tlen; 536 size_t tlen;
536 size_t sg_bytes; 537 size_t sg_bytes;
537 size_t frame_offset, fh_parm_offset; 538 size_t frame_offset, fh_parm_offset;
539 size_t off;
538 int error; 540 int error;
539 void *data = NULL; 541 void *data = NULL;
540 void *page_addr; 542 void *page_addr;
@@ -605,28 +607,26 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
605 fh_parm_offset = frame_offset; 607 fh_parm_offset = frame_offset;
606 fr_max_payload(fp) = fsp->max_payload; 608 fr_max_payload(fp) = fsp->max_payload;
607 } 609 }
610
611 off = offset + sg->offset;
608 sg_bytes = min(tlen, sg->length - offset); 612 sg_bytes = min(tlen, sg->length - offset);
613 sg_bytes = min(sg_bytes,
614 (size_t) (PAGE_SIZE - (off & ~PAGE_MASK)));
615 page = sg_page(sg) + (off >> PAGE_SHIFT);
609 if (using_sg) { 616 if (using_sg) {
610 get_page(sg_page(sg)); 617 get_page(page);
611 skb_fill_page_desc(fp_skb(fp), 618 skb_fill_page_desc(fp_skb(fp),
612 skb_shinfo(fp_skb(fp))->nr_frags, 619 skb_shinfo(fp_skb(fp))->nr_frags,
613 sg_page(sg), sg->offset + offset, 620 page, off & ~PAGE_MASK, sg_bytes);
614 sg_bytes);
615 fp_skb(fp)->data_len += sg_bytes; 621 fp_skb(fp)->data_len += sg_bytes;
616 fr_len(fp) += sg_bytes; 622 fr_len(fp) += sg_bytes;
617 fp_skb(fp)->truesize += PAGE_SIZE; 623 fp_skb(fp)->truesize += PAGE_SIZE;
618 } else { 624 } else {
619 size_t off = offset + sg->offset;
620
621 /* 625 /*
622 * The scatterlist item may be bigger than PAGE_SIZE, 626 * The scatterlist item may be bigger than PAGE_SIZE,
623 * but we must not cross pages inside the kmap. 627 * but we must not cross pages inside the kmap.
624 */ 628 */
625 sg_bytes = min(sg_bytes, (size_t) (PAGE_SIZE - 629 page_addr = kmap_atomic(page, KM_SOFTIRQ0);
626 (off & ~PAGE_MASK)));
627 page_addr = kmap_atomic(sg_page(sg) +
628 (off >> PAGE_SHIFT),
629 KM_SOFTIRQ0);
630 memcpy(data, (char *)page_addr + (off & ~PAGE_MASK), 630 memcpy(data, (char *)page_addr + (off & ~PAGE_MASK),
631 sg_bytes); 631 sg_bytes);
632 kunmap_atomic(page_addr, KM_SOFTIRQ0); 632 kunmap_atomic(page_addr, KM_SOFTIRQ0);
diff --git a/drivers/scsi/libfc/fc_frame.c b/drivers/scsi/libfc/fc_frame.c
index 79c956501bd..6da01c61696 100644
--- a/drivers/scsi/libfc/fc_frame.c
+++ b/drivers/scsi/libfc/fc_frame.c
@@ -58,12 +58,13 @@ struct fc_frame *_fc_frame_alloc(size_t len)
58 58
59 WARN_ON((len % sizeof(u32)) != 0); 59 WARN_ON((len % sizeof(u32)) != 0);
60 len += sizeof(struct fc_frame_header); 60 len += sizeof(struct fc_frame_header);
61 skb = dev_alloc_skb(len + FC_FRAME_HEADROOM + FC_FRAME_TAILROOM); 61 skb = alloc_skb_fclone(len + FC_FRAME_HEADROOM + FC_FRAME_TAILROOM +
62 NET_SKB_PAD, GFP_ATOMIC);
62 if (!skb) 63 if (!skb)
63 return NULL; 64 return NULL;
65 skb_reserve(skb, NET_SKB_PAD + FC_FRAME_HEADROOM);
64 fp = (struct fc_frame *) skb; 66 fp = (struct fc_frame *) skb;
65 fc_frame_init(fp); 67 fc_frame_init(fp);
66 skb_reserve(skb, FC_FRAME_HEADROOM);
67 skb_put(skb, len); 68 skb_put(skb, len);
68 return fp; 69 return fp;
69} 70}