aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/cxgb3i
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/cxgb3i')
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_ddp.c90
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_ddp.h2
2 files changed, 71 insertions, 21 deletions
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c
index 99c912547902..344fd53b9954 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c
@@ -206,6 +206,31 @@ int cxgb3i_ddp_find_page_index(unsigned long pgsz)
206 return DDP_PGIDX_MAX; 206 return DDP_PGIDX_MAX;
207} 207}
208 208
209/**
210 * cxgb3i_ddp_adjust_page_table - adjust page table with PAGE_SIZE
211 * return the ddp page index, if no match is found return DDP_PGIDX_MAX.
212 */
213int cxgb3i_ddp_adjust_page_table(void)
214{
215 int i;
216 unsigned int base_order, order;
217
218 if (PAGE_SIZE < (1UL << ddp_page_shift[0])) {
219 ddp_log_info("PAGE_SIZE 0x%lx too small, min. 0x%lx.\n",
220 PAGE_SIZE, 1UL << ddp_page_shift[0]);
221 return -EINVAL;
222 }
223
224 base_order = get_order(1UL << ddp_page_shift[0]);
225 order = get_order(1 << PAGE_SHIFT);
226 for (i = 0; i < DDP_PGIDX_MAX; i++) {
227 /* first is the kernel page size, then just doubling the size */
228 ddp_page_order[i] = order - base_order + i;
229 ddp_page_shift[i] = PAGE_SHIFT + i;
230 }
231 return 0;
232}
233
209static inline void ddp_gl_unmap(struct pci_dev *pdev, 234static inline void ddp_gl_unmap(struct pci_dev *pdev,
210 struct cxgb3i_gather_list *gl) 235 struct cxgb3i_gather_list *gl)
211{ 236{
@@ -598,30 +623,40 @@ int cxgb3i_adapter_ddp_info(struct t3cdev *tdev,
598 * release all the resource held by the ddp pagepod manager for a given 623 * release all the resource held by the ddp pagepod manager for a given
599 * adapter if needed 624 * adapter if needed
600 */ 625 */
601void cxgb3i_ddp_cleanup(struct t3cdev *tdev) 626
627static void ddp_cleanup(struct kref *kref)
602{ 628{
629 struct cxgb3i_ddp_info *ddp = container_of(kref,
630 struct cxgb3i_ddp_info,
631 refcnt);
603 int i = 0; 632 int i = 0;
633
634 ddp_log_info("kref release ddp 0x%p, t3dev 0x%p.\n", ddp, ddp->tdev);
635
636 ddp->tdev->ulp_iscsi = NULL;
637 while (i < ddp->nppods) {
638 struct cxgb3i_gather_list *gl = ddp->gl_map[i];
639 if (gl) {
640 int npods = (gl->nelem + PPOD_PAGES_MAX - 1)
641 >> PPOD_PAGES_SHIFT;
642 ddp_log_info("t3dev 0x%p, ddp %d + %d.\n",
643 ddp->tdev, i, npods);
644 kfree(gl);
645 ddp_free_gl_skb(ddp, i, npods);
646 i += npods;
647 } else
648 i++;
649 }
650 cxgb3i_free_big_mem(ddp);
651}
652
653void cxgb3i_ddp_cleanup(struct t3cdev *tdev)
654{
604 struct cxgb3i_ddp_info *ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi; 655 struct cxgb3i_ddp_info *ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
605 656
606 ddp_log_info("t3dev 0x%p, release ddp 0x%p.\n", tdev, ddp); 657 ddp_log_info("t3dev 0x%p, release ddp 0x%p.\n", tdev, ddp);
607 658 if (ddp)
608 if (ddp) { 659 kref_put(&ddp->refcnt, ddp_cleanup);
609 tdev->ulp_iscsi = NULL;
610 while (i < ddp->nppods) {
611 struct cxgb3i_gather_list *gl = ddp->gl_map[i];
612 if (gl) {
613 int npods = (gl->nelem + PPOD_PAGES_MAX - 1)
614 >> PPOD_PAGES_SHIFT;
615 ddp_log_info("t3dev 0x%p, ddp %d + %d.\n",
616 tdev, i, npods);
617 kfree(gl);
618 ddp_free_gl_skb(ddp, i, npods);
619 i += npods;
620 } else
621 i++;
622 }
623 cxgb3i_free_big_mem(ddp);
624 }
625} 660}
626 661
627/** 662/**
@@ -631,12 +666,13 @@ void cxgb3i_ddp_cleanup(struct t3cdev *tdev)
631 */ 666 */
632static void ddp_init(struct t3cdev *tdev) 667static void ddp_init(struct t3cdev *tdev)
633{ 668{
634 struct cxgb3i_ddp_info *ddp; 669 struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi;
635 struct ulp_iscsi_info uinfo; 670 struct ulp_iscsi_info uinfo;
636 unsigned int ppmax, bits; 671 unsigned int ppmax, bits;
637 int i, err; 672 int i, err;
638 673
639 if (tdev->ulp_iscsi) { 674 if (ddp) {
675 kref_get(&ddp->refcnt);
640 ddp_log_warn("t3dev 0x%p, ddp 0x%p already set up.\n", 676 ddp_log_warn("t3dev 0x%p, ddp 0x%p already set up.\n",
641 tdev, tdev->ulp_iscsi); 677 tdev, tdev->ulp_iscsi);
642 return; 678 return;
@@ -670,6 +706,7 @@ static void ddp_init(struct t3cdev *tdev)
670 ppmax * 706 ppmax *
671 sizeof(struct cxgb3i_gather_list *)); 707 sizeof(struct cxgb3i_gather_list *));
672 spin_lock_init(&ddp->map_lock); 708 spin_lock_init(&ddp->map_lock);
709 kref_init(&ddp->refcnt);
673 710
674 ddp->tdev = tdev; 711 ddp->tdev = tdev;
675 ddp->pdev = uinfo.pdev; 712 ddp->pdev = uinfo.pdev;
@@ -715,6 +752,17 @@ void cxgb3i_ddp_init(struct t3cdev *tdev)
715{ 752{
716 if (page_idx == DDP_PGIDX_MAX) { 753 if (page_idx == DDP_PGIDX_MAX) {
717 page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE); 754 page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE);
755
756 if (page_idx == DDP_PGIDX_MAX) {
757 ddp_log_info("system PAGE_SIZE %lu, update hw.\n",
758 PAGE_SIZE);
759 if (cxgb3i_ddp_adjust_page_table() < 0) {
760 ddp_log_info("PAGE_SIZE %lu, ddp disabled.\n",
761 PAGE_SIZE);
762 return;
763 }
764 page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE);
765 }
718 ddp_log_info("system PAGE_SIZE %lu, ddp idx %u.\n", 766 ddp_log_info("system PAGE_SIZE %lu, ddp idx %u.\n",
719 PAGE_SIZE, page_idx); 767 PAGE_SIZE, page_idx);
720 } 768 }
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.h b/drivers/scsi/cxgb3i/cxgb3i_ddp.h
index 0d296de7cf32..87dd56b422bf 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_ddp.h
+++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.h
@@ -54,6 +54,7 @@ struct cxgb3i_gather_list {
54 * struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload 54 * struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload
55 * 55 *
56 * @list: list head to link elements 56 * @list: list head to link elements
57 * @refcnt: ref. count
57 * @tdev: pointer to t3cdev used by cxgb3 driver 58 * @tdev: pointer to t3cdev used by cxgb3 driver
58 * @max_txsz: max tx packet size for ddp 59 * @max_txsz: max tx packet size for ddp
59 * @max_rxsz: max rx packet size for ddp 60 * @max_rxsz: max rx packet size for ddp
@@ -70,6 +71,7 @@ struct cxgb3i_gather_list {
70 */ 71 */
71struct cxgb3i_ddp_info { 72struct cxgb3i_ddp_info {
72 struct list_head list; 73 struct list_head list;
74 struct kref refcnt;
73 struct t3cdev *tdev; 75 struct t3cdev *tdev;
74 struct pci_dev *pdev; 76 struct pci_dev *pdev;
75 unsigned int max_txsz; 77 unsigned int max_txsz;