diff options
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_init_chip.c')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_init_chip.c | 86 |
1 files changed, 54 insertions, 32 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c index d4f6b5239ef..7045ba68949 100644 --- a/drivers/infiniband/hw/ipath/ipath_init_chip.c +++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c | |||
@@ -216,6 +216,20 @@ static int bringup_link(struct ipath_devdata *dd) | |||
216 | return ret; | 216 | return ret; |
217 | } | 217 | } |
218 | 218 | ||
219 | static struct ipath_portdata *create_portdata0(struct ipath_devdata *dd) | ||
220 | { | ||
221 | struct ipath_portdata *pd = NULL; | ||
222 | |||
223 | pd = kzalloc(sizeof(*pd), GFP_KERNEL); | ||
224 | if (pd) { | ||
225 | pd->port_dd = dd; | ||
226 | pd->port_cnt = 1; | ||
227 | /* The port 0 pkey table is used by the layer interface. */ | ||
228 | pd->port_pkeys[0] = IPATH_DEFAULT_P_KEY; | ||
229 | } | ||
230 | return pd; | ||
231 | } | ||
232 | |||
219 | static int init_chip_first(struct ipath_devdata *dd, | 233 | static int init_chip_first(struct ipath_devdata *dd, |
220 | struct ipath_portdata **pdp) | 234 | struct ipath_portdata **pdp) |
221 | { | 235 | { |
@@ -271,20 +285,16 @@ static int init_chip_first(struct ipath_devdata *dd, | |||
271 | goto done; | 285 | goto done; |
272 | } | 286 | } |
273 | 287 | ||
274 | dd->ipath_pd[0] = kzalloc(sizeof(*pd), GFP_KERNEL); | 288 | pd = create_portdata0(dd); |
275 | 289 | ||
276 | if (!dd->ipath_pd[0]) { | 290 | if (!pd) { |
277 | ipath_dev_err(dd, "Unable to allocate portdata for port " | 291 | ipath_dev_err(dd, "Unable to allocate portdata for port " |
278 | "0, failing\n"); | 292 | "0, failing\n"); |
279 | ret = -ENOMEM; | 293 | ret = -ENOMEM; |
280 | goto done; | 294 | goto done; |
281 | } | 295 | } |
282 | pd = dd->ipath_pd[0]; | 296 | dd->ipath_pd[0] = pd; |
283 | pd->port_dd = dd; | 297 | |
284 | pd->port_port = 0; | ||
285 | pd->port_cnt = 1; | ||
286 | /* The port 0 pkey table is used by the layer interface. */ | ||
287 | pd->port_pkeys[0] = IPATH_DEFAULT_P_KEY; | ||
288 | dd->ipath_rcvtidcnt = | 298 | dd->ipath_rcvtidcnt = |
289 | ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt); | 299 | ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvtidcnt); |
290 | dd->ipath_rcvtidbase = | 300 | dd->ipath_rcvtidbase = |
@@ -590,6 +600,10 @@ static int init_housekeeping(struct ipath_devdata *dd, | |||
590 | goto done; | 600 | goto done; |
591 | } | 601 | } |
592 | 602 | ||
603 | |||
604 | /* clear diagctrl register, in case diags were running and crashed */ | ||
605 | ipath_write_kreg (dd, dd->ipath_kregs->kr_hwdiagctrl, 0); | ||
606 | |||
593 | /* clear the initial reset flag, in case first driver load */ | 607 | /* clear the initial reset flag, in case first driver load */ |
594 | ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, | 608 | ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, |
595 | INFINIPATH_E_RESET); | 609 | INFINIPATH_E_RESET); |
@@ -668,6 +682,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) | |||
668 | { | 682 | { |
669 | int ret = 0, i; | 683 | int ret = 0, i; |
670 | u32 val32, kpiobufs; | 684 | u32 val32, kpiobufs; |
685 | u32 piobufs, uports; | ||
671 | u64 val; | 686 | u64 val; |
672 | struct ipath_portdata *pd = NULL; /* keep gcc4 happy */ | 687 | struct ipath_portdata *pd = NULL; /* keep gcc4 happy */ |
673 | gfp_t gfp_flags = GFP_USER | __GFP_COMP; | 688 | gfp_t gfp_flags = GFP_USER | __GFP_COMP; |
@@ -702,16 +717,17 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) | |||
702 | * the in memory DMA'ed copies of the registers. This has to | 717 | * the in memory DMA'ed copies of the registers. This has to |
703 | * be done early, before we calculate lastport, etc. | 718 | * be done early, before we calculate lastport, etc. |
704 | */ | 719 | */ |
705 | val = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k; | 720 | piobufs = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k; |
706 | /* | 721 | /* |
707 | * calc number of pioavail registers, and save it; we have 2 | 722 | * calc number of pioavail registers, and save it; we have 2 |
708 | * bits per buffer. | 723 | * bits per buffer. |
709 | */ | 724 | */ |
710 | dd->ipath_pioavregs = ALIGN(val, sizeof(u64) * BITS_PER_BYTE / 2) | 725 | dd->ipath_pioavregs = ALIGN(piobufs, sizeof(u64) * BITS_PER_BYTE / 2) |
711 | / (sizeof(u64) * BITS_PER_BYTE / 2); | 726 | / (sizeof(u64) * BITS_PER_BYTE / 2); |
727 | uports = dd->ipath_cfgports ? dd->ipath_cfgports - 1 : 0; | ||
712 | if (ipath_kpiobufs == 0) { | 728 | if (ipath_kpiobufs == 0) { |
713 | /* not set by user (this is default) */ | 729 | /* not set by user (this is default) */ |
714 | if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) > 128) | 730 | if (piobufs >= (uports * IPATH_MIN_USER_PORT_BUFCNT) + 32) |
715 | kpiobufs = 32; | 731 | kpiobufs = 32; |
716 | else | 732 | else |
717 | kpiobufs = 16; | 733 | kpiobufs = 16; |
@@ -719,31 +735,25 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) | |||
719 | else | 735 | else |
720 | kpiobufs = ipath_kpiobufs; | 736 | kpiobufs = ipath_kpiobufs; |
721 | 737 | ||
722 | if (kpiobufs > | 738 | if (kpiobufs + (uports * IPATH_MIN_USER_PORT_BUFCNT) > piobufs) { |
723 | (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - | 739 | i = (int) piobufs - |
724 | (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT))) { | 740 | (int) (uports * IPATH_MIN_USER_PORT_BUFCNT); |
725 | i = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - | ||
726 | (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT); | ||
727 | if (i < 0) | 741 | if (i < 0) |
728 | i = 0; | 742 | i = 0; |
729 | dev_info(&dd->pcidev->dev, "Allocating %d PIO bufs for " | 743 | dev_info(&dd->pcidev->dev, "Allocating %d PIO bufs of " |
730 | "kernel leaves too few for %d user ports " | 744 | "%d for kernel leaves too few for %d user ports " |
731 | "(%d each); using %u\n", kpiobufs, | 745 | "(%d each); using %u\n", kpiobufs, |
732 | dd->ipath_cfgports - 1, | 746 | piobufs, uports, IPATH_MIN_USER_PORT_BUFCNT, i); |
733 | IPATH_MIN_USER_PORT_BUFCNT, i); | ||
734 | /* | 747 | /* |
735 | * shouldn't change ipath_kpiobufs, because could be | 748 | * shouldn't change ipath_kpiobufs, because could be |
736 | * different for different devices... | 749 | * different for different devices... |
737 | */ | 750 | */ |
738 | kpiobufs = i; | 751 | kpiobufs = i; |
739 | } | 752 | } |
740 | dd->ipath_lastport_piobuf = | 753 | dd->ipath_lastport_piobuf = piobufs - kpiobufs; |
741 | dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - kpiobufs; | 754 | dd->ipath_pbufsport = |
742 | dd->ipath_pbufsport = dd->ipath_cfgports > 1 | 755 | uports ? dd->ipath_lastport_piobuf / uports : 0; |
743 | ? dd->ipath_lastport_piobuf / (dd->ipath_cfgports - 1) | 756 | val32 = dd->ipath_lastport_piobuf - (dd->ipath_pbufsport * uports); |
744 | : 0; | ||
745 | val32 = dd->ipath_lastport_piobuf - | ||
746 | (dd->ipath_pbufsport * (dd->ipath_cfgports - 1)); | ||
747 | if (val32 > 0) { | 757 | if (val32 > 0) { |
748 | ipath_dbg("allocating %u pbufs/port leaves %u unused, " | 758 | ipath_dbg("allocating %u pbufs/port leaves %u unused, " |
749 | "add to kernel\n", dd->ipath_pbufsport, val32); | 759 | "add to kernel\n", dd->ipath_pbufsport, val32); |
@@ -754,8 +764,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) | |||
754 | dd->ipath_lastpioindex = dd->ipath_lastport_piobuf; | 764 | dd->ipath_lastpioindex = dd->ipath_lastport_piobuf; |
755 | ipath_cdbg(VERBOSE, "%d PIO bufs for kernel out of %d total %u " | 765 | ipath_cdbg(VERBOSE, "%d PIO bufs for kernel out of %d total %u " |
756 | "each for %u user ports\n", kpiobufs, | 766 | "each for %u user ports\n", kpiobufs, |
757 | dd->ipath_piobcnt2k + dd->ipath_piobcnt4k, | 767 | piobufs, dd->ipath_pbufsport, uports); |
758 | dd->ipath_pbufsport, dd->ipath_cfgports - 1); | ||
759 | 768 | ||
760 | dd->ipath_f_early_init(dd); | 769 | dd->ipath_f_early_init(dd); |
761 | 770 | ||
@@ -839,11 +848,24 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) | |||
839 | * Set up the port 0 (kernel) rcvhdr q and egr TIDs. If doing | 848 | * Set up the port 0 (kernel) rcvhdr q and egr TIDs. If doing |
840 | * re-init, the simplest way to handle this is to free | 849 | * re-init, the simplest way to handle this is to free |
841 | * existing, and re-allocate. | 850 | * existing, and re-allocate. |
851 | * Need to re-create rest of port 0 portdata as well. | ||
842 | */ | 852 | */ |
843 | if (reinit) { | 853 | if (reinit) { |
844 | struct ipath_portdata *pd = dd->ipath_pd[0]; | 854 | /* Alloc and init new ipath_portdata for port0, |
845 | dd->ipath_pd[0] = NULL; | 855 | * Then free old pd. Could lead to fragmentation, but also |
846 | ipath_free_pddata(dd, pd); | 856 | * makes later support for hot-swap easier. |
857 | */ | ||
858 | struct ipath_portdata *npd; | ||
859 | npd = create_portdata0(dd); | ||
860 | if (npd) { | ||
861 | ipath_free_pddata(dd, pd); | ||
862 | dd->ipath_pd[0] = pd = npd; | ||
863 | } else { | ||
864 | ipath_dev_err(dd, "Unable to allocate portdata for" | ||
865 | " port 0, failing\n"); | ||
866 | ret = -ENOMEM; | ||
867 | goto done; | ||
868 | } | ||
847 | } | 869 | } |
848 | dd->ipath_f_tidtemplate(dd); | 870 | dd->ipath_f_tidtemplate(dd); |
849 | ret = ipath_create_rcvhdrq(dd, pd); | 871 | ret = ipath_create_rcvhdrq(dd, pd); |