diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 1037 |
1 files changed, 397 insertions, 640 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 4580ff34c2d0..3564686add9a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -482,6 +482,15 @@ struct sdpcm_shared_le { | |||
482 | __le32 brpt_addr; | 482 | __le32 brpt_addr; |
483 | }; | 483 | }; |
484 | 484 | ||
485 | /* SDIO read frame info */ | ||
486 | struct brcmf_sdio_read { | ||
487 | u8 seq_num; | ||
488 | u8 channel; | ||
489 | u16 len; | ||
490 | u16 len_left; | ||
491 | u16 len_nxtfrm; | ||
492 | u8 dat_offset; | ||
493 | }; | ||
485 | 494 | ||
486 | /* misc chip info needed by some of the routines */ | 495 | /* misc chip info needed by some of the routines */ |
487 | /* Private data for SDIO bus interaction */ | 496 | /* Private data for SDIO bus interaction */ |
@@ -494,9 +503,8 @@ struct brcmf_sdio { | |||
494 | u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ | 503 | u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ |
495 | 504 | ||
496 | u32 hostintmask; /* Copy of Host Interrupt Mask */ | 505 | u32 hostintmask; /* Copy of Host Interrupt Mask */ |
497 | u32 intstatus; /* Intstatus bits (events) pending */ | 506 | atomic_t intstatus; /* Intstatus bits (events) pending */ |
498 | bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */ | 507 | atomic_t fcstate; /* State of dongle flow-control */ |
499 | bool fcstate; /* State of dongle flow-control */ | ||
500 | 508 | ||
501 | uint blocksize; /* Block size of SDIO transfers */ | 509 | uint blocksize; /* Block size of SDIO transfers */ |
502 | uint roundup; /* Max roundup limit */ | 510 | uint roundup; /* Max roundup limit */ |
@@ -508,9 +516,11 @@ struct brcmf_sdio { | |||
508 | 516 | ||
509 | u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN]; | 517 | u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN]; |
510 | u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ | 518 | u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ |
511 | u16 nextlen; /* Next Read Len from last header */ | ||
512 | u8 rx_seq; /* Receive sequence number (expected) */ | 519 | u8 rx_seq; /* Receive sequence number (expected) */ |
520 | struct brcmf_sdio_read cur_read; | ||
521 | /* info of current read frame */ | ||
513 | bool rxskip; /* Skip receive (awaiting NAK ACK) */ | 522 | bool rxskip; /* Skip receive (awaiting NAK ACK) */ |
523 | bool rxpending; /* Data frame pending in dongle */ | ||
514 | 524 | ||
515 | uint rxbound; /* Rx frames to read before resched */ | 525 | uint rxbound; /* Rx frames to read before resched */ |
516 | uint txbound; /* Tx frames to send before resched */ | 526 | uint txbound; /* Tx frames to send before resched */ |
@@ -531,7 +541,7 @@ struct brcmf_sdio { | |||
531 | 541 | ||
532 | bool intr; /* Use interrupts */ | 542 | bool intr; /* Use interrupts */ |
533 | bool poll; /* Use polling */ | 543 | bool poll; /* Use polling */ |
534 | bool ipend; /* Device interrupt is pending */ | 544 | atomic_t ipend; /* Device interrupt is pending */ |
535 | uint spurious; /* Count of spurious interrupts */ | 545 | uint spurious; /* Count of spurious interrupts */ |
536 | uint pollrate; /* Ticks between device polls */ | 546 | uint pollrate; /* Ticks between device polls */ |
537 | uint polltick; /* Tick counter */ | 547 | uint polltick; /* Tick counter */ |
@@ -549,12 +559,9 @@ struct brcmf_sdio { | |||
549 | s32 idleclock; /* How to set bus driver when idle */ | 559 | s32 idleclock; /* How to set bus driver when idle */ |
550 | s32 sd_rxchain; | 560 | s32 sd_rxchain; |
551 | bool use_rxchain; /* If brcmf should use PKT chains */ | 561 | bool use_rxchain; /* If brcmf should use PKT chains */ |
552 | bool sleeping; /* Is SDIO bus sleeping? */ | ||
553 | bool rxflow_mode; /* Rx flow control mode */ | 562 | bool rxflow_mode; /* Rx flow control mode */ |
554 | bool rxflow; /* Is rx flow control on */ | 563 | bool rxflow; /* Is rx flow control on */ |
555 | bool alp_only; /* Don't use HT clock (ALP only) */ | 564 | bool alp_only; /* Don't use HT clock (ALP only) */ |
556 | /* Field to decide if rx of control frames happen in rxbuf or lb-pool */ | ||
557 | bool usebufpool; | ||
558 | 565 | ||
559 | u8 *ctrl_frame_buf; | 566 | u8 *ctrl_frame_buf; |
560 | u32 ctrl_frame_len; | 567 | u32 ctrl_frame_len; |
@@ -570,8 +577,8 @@ struct brcmf_sdio { | |||
570 | bool wd_timer_valid; | 577 | bool wd_timer_valid; |
571 | uint save_ms; | 578 | uint save_ms; |
572 | 579 | ||
573 | struct task_struct *dpc_tsk; | 580 | struct workqueue_struct *brcmf_wq; |
574 | struct completion dpc_wait; | 581 | struct work_struct datawork; |
575 | struct list_head dpc_tsklst; | 582 | struct list_head dpc_tsklst; |
576 | spinlock_t dpc_tl_lock; | 583 | spinlock_t dpc_tl_lock; |
577 | 584 | ||
@@ -657,15 +664,6 @@ w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset) | |||
657 | 664 | ||
658 | #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) | 665 | #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) |
659 | 666 | ||
660 | /* Packet free applicable unconditionally for sdio and sdspi. | ||
661 | * Conditional if bufpool was present for gspi bus. | ||
662 | */ | ||
663 | static void brcmf_sdbrcm_pktfree2(struct brcmf_sdio *bus, struct sk_buff *pkt) | ||
664 | { | ||
665 | if (bus->usebufpool) | ||
666 | brcmu_pkt_buf_free_skb(pkt); | ||
667 | } | ||
668 | |||
669 | /* Turn backplane clock on or off */ | 667 | /* Turn backplane clock on or off */ |
670 | static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | 668 | static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) |
671 | { | 669 | { |
@@ -853,81 +851,6 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
853 | return 0; | 851 | return 0; |
854 | } | 852 | } |
855 | 853 | ||
856 | static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep) | ||
857 | { | ||
858 | int ret; | ||
859 | |||
860 | brcmf_dbg(INFO, "request %s (currently %s)\n", | ||
861 | sleep ? "SLEEP" : "WAKE", | ||
862 | bus->sleeping ? "SLEEP" : "WAKE"); | ||
863 | |||
864 | /* Done if we're already in the requested state */ | ||
865 | if (sleep == bus->sleeping) | ||
866 | return 0; | ||
867 | |||
868 | /* Going to sleep: set the alarm and turn off the lights... */ | ||
869 | if (sleep) { | ||
870 | /* Don't sleep if something is pending */ | ||
871 | if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) | ||
872 | return -EBUSY; | ||
873 | |||
874 | /* Make sure the controller has the bus up */ | ||
875 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | ||
876 | |||
877 | /* Tell device to start using OOB wakeup */ | ||
878 | ret = w_sdreg32(bus, SMB_USE_OOB, | ||
879 | offsetof(struct sdpcmd_regs, tosbmailbox)); | ||
880 | if (ret != 0) | ||
881 | brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"); | ||
882 | |||
883 | /* Turn off our contribution to the HT clock request */ | ||
884 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); | ||
885 | |||
886 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | ||
887 | SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); | ||
888 | |||
889 | /* Isolate the bus */ | ||
890 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, | ||
891 | SBSDIO_DEVCTL_PADS_ISO, NULL); | ||
892 | |||
893 | /* Change state */ | ||
894 | bus->sleeping = true; | ||
895 | |||
896 | } else { | ||
897 | /* Waking up: bus power up is ok, set local state */ | ||
898 | |||
899 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, | ||
900 | 0, NULL); | ||
901 | |||
902 | /* Make sure the controller has the bus up */ | ||
903 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | ||
904 | |||
905 | /* Send misc interrupt to indicate OOB not needed */ | ||
906 | ret = w_sdreg32(bus, 0, | ||
907 | offsetof(struct sdpcmd_regs, tosbmailboxdata)); | ||
908 | if (ret == 0) | ||
909 | ret = w_sdreg32(bus, SMB_DEV_INT, | ||
910 | offsetof(struct sdpcmd_regs, tosbmailbox)); | ||
911 | |||
912 | if (ret != 0) | ||
913 | brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"); | ||
914 | |||
915 | /* Make sure we have SD bus access */ | ||
916 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); | ||
917 | |||
918 | /* Change state */ | ||
919 | bus->sleeping = false; | ||
920 | } | ||
921 | |||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | static void bus_wake(struct brcmf_sdio *bus) | ||
926 | { | ||
927 | if (bus->sleeping) | ||
928 | brcmf_sdbrcm_bussleep(bus, false); | ||
929 | } | ||
930 | |||
931 | static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | 854 | static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) |
932 | { | 855 | { |
933 | u32 intstatus = 0; | 856 | u32 intstatus = 0; |
@@ -1056,7 +979,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
1056 | } | 979 | } |
1057 | 980 | ||
1058 | /* Clear partial in any case */ | 981 | /* Clear partial in any case */ |
1059 | bus->nextlen = 0; | 982 | bus->cur_read.len = 0; |
1060 | 983 | ||
1061 | /* If we can't reach the device, signal failure */ | 984 | /* If we can't reach the device, signal failure */ |
1062 | if (err) | 985 | if (err) |
@@ -1108,6 +1031,96 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus) | |||
1108 | } | 1031 | } |
1109 | } | 1032 | } |
1110 | 1033 | ||
1034 | static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, | ||
1035 | struct brcmf_sdio_read *rd) | ||
1036 | { | ||
1037 | u16 len, checksum; | ||
1038 | u8 rx_seq, fc, tx_seq_max; | ||
1039 | |||
1040 | /* | ||
1041 | * 4 bytes hardware header (frame tag) | ||
1042 | * Byte 0~1: Frame length | ||
1043 | * Byte 2~3: Checksum, bit-wise inverse of frame length | ||
1044 | */ | ||
1045 | len = get_unaligned_le16(header); | ||
1046 | checksum = get_unaligned_le16(header + sizeof(u16)); | ||
1047 | /* All zero means no more to read */ | ||
1048 | if (!(len | checksum)) { | ||
1049 | bus->rxpending = false; | ||
1050 | return false; | ||
1051 | } | ||
1052 | if ((u16)(~(len ^ checksum))) { | ||
1053 | brcmf_dbg(ERROR, "HW header checksum error\n"); | ||
1054 | bus->sdcnt.rx_badhdr++; | ||
1055 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1056 | return false; | ||
1057 | } | ||
1058 | if (len < SDPCM_HDRLEN) { | ||
1059 | brcmf_dbg(ERROR, "HW header length error\n"); | ||
1060 | return false; | ||
1061 | } | ||
1062 | rd->len = len; | ||
1063 | |||
1064 | /* | ||
1065 | * 8 bytes hardware header | ||
1066 | * Byte 0: Rx sequence number | ||
1067 | * Byte 1: 4 MSB Channel number, 4 LSB arbitrary flag | ||
1068 | * Byte 2: Length of next data frame | ||
1069 | * Byte 3: Data offset | ||
1070 | * Byte 4: Flow control bits | ||
1071 | * Byte 5: Maximum Sequence number allow for Tx | ||
1072 | * Byte 6~7: Reserved | ||
1073 | */ | ||
1074 | rx_seq = SDPCM_PACKET_SEQUENCE(&header[SDPCM_FRAMETAG_LEN]); | ||
1075 | rd->channel = SDPCM_PACKET_CHANNEL(&header[SDPCM_FRAMETAG_LEN]); | ||
1076 | if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL) { | ||
1077 | brcmf_dbg(ERROR, "HW header length too long\n"); | ||
1078 | bus->sdiodev->bus_if->dstats.rx_errors++; | ||
1079 | bus->sdcnt.rx_toolong++; | ||
1080 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1081 | rd->len = 0; | ||
1082 | return false; | ||
1083 | } | ||
1084 | rd->dat_offset = SDPCM_DOFFSET_VALUE(&header[SDPCM_FRAMETAG_LEN]); | ||
1085 | if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) { | ||
1086 | brcmf_dbg(ERROR, "seq %d: bad data offset\n", rx_seq); | ||
1087 | bus->sdcnt.rx_badhdr++; | ||
1088 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1089 | rd->len = 0; | ||
1090 | return false; | ||
1091 | } | ||
1092 | if (rd->seq_num != rx_seq) { | ||
1093 | brcmf_dbg(ERROR, "seq %d: sequence number error, expect %d\n", | ||
1094 | rx_seq, rd->seq_num); | ||
1095 | bus->sdcnt.rx_badseq++; | ||
1096 | rd->seq_num = rx_seq; | ||
1097 | } | ||
1098 | rd->len_nxtfrm = header[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; | ||
1099 | if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) { | ||
1100 | /* only warm for NON glom packet */ | ||
1101 | if (rd->channel != SDPCM_GLOM_CHANNEL) | ||
1102 | brcmf_dbg(ERROR, "seq %d: next length error\n", rx_seq); | ||
1103 | rd->len_nxtfrm = 0; | ||
1104 | } | ||
1105 | fc = SDPCM_FCMASK_VALUE(&header[SDPCM_FRAMETAG_LEN]); | ||
1106 | if (bus->flowcontrol != fc) { | ||
1107 | if (~bus->flowcontrol & fc) | ||
1108 | bus->sdcnt.fc_xoff++; | ||
1109 | if (bus->flowcontrol & ~fc) | ||
1110 | bus->sdcnt.fc_xon++; | ||
1111 | bus->sdcnt.fc_rcvd++; | ||
1112 | bus->flowcontrol = fc; | ||
1113 | } | ||
1114 | tx_seq_max = SDPCM_WINDOW_VALUE(&header[SDPCM_FRAMETAG_LEN]); | ||
1115 | if ((u8)(tx_seq_max - bus->tx_seq) > 0x40) { | ||
1116 | brcmf_dbg(ERROR, "seq %d: max tx seq number error\n", rx_seq); | ||
1117 | tx_seq_max = bus->tx_seq + 2; | ||
1118 | } | ||
1119 | bus->tx_max = tx_seq_max; | ||
1120 | |||
1121 | return true; | ||
1122 | } | ||
1123 | |||
1111 | static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | 1124 | static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) |
1112 | { | 1125 | { |
1113 | u16 dlen, totlen; | 1126 | u16 dlen, totlen; |
@@ -1122,6 +1135,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1122 | 1135 | ||
1123 | int ifidx = 0; | 1136 | int ifidx = 0; |
1124 | bool usechain = bus->use_rxchain; | 1137 | bool usechain = bus->use_rxchain; |
1138 | u16 next_len; | ||
1125 | 1139 | ||
1126 | /* If packets, issue read(s) and send up packet chain */ | 1140 | /* If packets, issue read(s) and send up packet chain */ |
1127 | /* Return sequence numbers consumed? */ | 1141 | /* Return sequence numbers consumed? */ |
@@ -1185,10 +1199,10 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1185 | if (pnext) { | 1199 | if (pnext) { |
1186 | brcmf_dbg(GLOM, "allocated %d-byte packet chain for %d subframes\n", | 1200 | brcmf_dbg(GLOM, "allocated %d-byte packet chain for %d subframes\n", |
1187 | totlen, num); | 1201 | totlen, num); |
1188 | if (BRCMF_GLOM_ON() && bus->nextlen && | 1202 | if (BRCMF_GLOM_ON() && bus->cur_read.len && |
1189 | totlen != bus->nextlen) { | 1203 | totlen != bus->cur_read.len) { |
1190 | brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n", | 1204 | brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n", |
1191 | bus->nextlen, totlen, rxseq); | 1205 | bus->cur_read.len, totlen, rxseq); |
1192 | } | 1206 | } |
1193 | pfirst = pnext = NULL; | 1207 | pfirst = pnext = NULL; |
1194 | } else { | 1208 | } else { |
@@ -1199,7 +1213,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1199 | /* Done with descriptor packet */ | 1213 | /* Done with descriptor packet */ |
1200 | brcmu_pkt_buf_free_skb(bus->glomd); | 1214 | brcmu_pkt_buf_free_skb(bus->glomd); |
1201 | bus->glomd = NULL; | 1215 | bus->glomd = NULL; |
1202 | bus->nextlen = 0; | 1216 | bus->cur_read.len = 0; |
1203 | } | 1217 | } |
1204 | 1218 | ||
1205 | /* Ok -- either we just generated a packet chain, | 1219 | /* Ok -- either we just generated a packet chain, |
@@ -1272,12 +1286,13 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1272 | 1286 | ||
1273 | chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); | 1287 | chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); |
1274 | seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); | 1288 | seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); |
1275 | bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; | 1289 | next_len = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; |
1276 | if ((bus->nextlen << 4) > MAX_RX_DATASZ) { | 1290 | if ((next_len << 4) > MAX_RX_DATASZ) { |
1277 | brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n", | 1291 | brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n", |
1278 | bus->nextlen, seq); | 1292 | next_len, seq); |
1279 | bus->nextlen = 0; | 1293 | next_len = 0; |
1280 | } | 1294 | } |
1295 | bus->cur_read.len = next_len << 4; | ||
1281 | doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); | 1296 | doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); |
1282 | txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); | 1297 | txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); |
1283 | 1298 | ||
@@ -1378,7 +1393,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1378 | bus->sdcnt.rxglomfail++; | 1393 | bus->sdcnt.rxglomfail++; |
1379 | brcmf_sdbrcm_free_glom(bus); | 1394 | brcmf_sdbrcm_free_glom(bus); |
1380 | } | 1395 | } |
1381 | bus->nextlen = 0; | 1396 | bus->cur_read.len = 0; |
1382 | return 0; | 1397 | return 0; |
1383 | } | 1398 | } |
1384 | 1399 | ||
@@ -1573,422 +1588,166 @@ static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen) | |||
1573 | } | 1588 | } |
1574 | } | 1589 | } |
1575 | 1590 | ||
1576 | static void | 1591 | static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) |
1577 | brcmf_alloc_pkt_and_read(struct brcmf_sdio *bus, u16 rdlen, | ||
1578 | struct sk_buff **pkt, u8 **rxbuf) | ||
1579 | { | 1592 | { |
1580 | int sdret; /* Return code from calls */ | ||
1581 | |||
1582 | *pkt = brcmu_pkt_buf_get_skb(rdlen + BRCMF_SDALIGN); | ||
1583 | if (*pkt == NULL) | ||
1584 | return; | ||
1585 | |||
1586 | pkt_align(*pkt, rdlen, BRCMF_SDALIGN); | ||
1587 | *rxbuf = (u8 *) ((*pkt)->data); | ||
1588 | /* Read the entire frame */ | ||
1589 | sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, | ||
1590 | SDIO_FUNC_2, F2SYNC, *pkt); | ||
1591 | bus->sdcnt.f2rxdata++; | ||
1592 | |||
1593 | if (sdret < 0) { | ||
1594 | brcmf_dbg(ERROR, "(nextlen): read %d bytes failed: %d\n", | ||
1595 | rdlen, sdret); | ||
1596 | brcmu_pkt_buf_free_skb(*pkt); | ||
1597 | bus->sdiodev->bus_if->dstats.rx_errors++; | ||
1598 | /* Force retry w/normal header read. | ||
1599 | * Don't attempt NAK for | ||
1600 | * gSPI | ||
1601 | */ | ||
1602 | brcmf_sdbrcm_rxfail(bus, true, true); | ||
1603 | *pkt = NULL; | ||
1604 | } | ||
1605 | } | ||
1606 | |||
1607 | /* Checks the header */ | ||
1608 | static int | ||
1609 | brcmf_check_rxbuf(struct brcmf_sdio *bus, struct sk_buff *pkt, u8 *rxbuf, | ||
1610 | u8 rxseq, u16 nextlen, u16 *len) | ||
1611 | { | ||
1612 | u16 check; | ||
1613 | bool len_consistent; /* Result of comparing readahead len and | ||
1614 | len from hw-hdr */ | ||
1615 | |||
1616 | memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN); | ||
1617 | |||
1618 | /* Extract hardware header fields */ | ||
1619 | *len = get_unaligned_le16(bus->rxhdr); | ||
1620 | check = get_unaligned_le16(bus->rxhdr + sizeof(u16)); | ||
1621 | |||
1622 | /* All zeros means readahead info was bad */ | ||
1623 | if (!(*len | check)) { | ||
1624 | brcmf_dbg(INFO, "(nextlen): read zeros in HW header???\n"); | ||
1625 | goto fail; | ||
1626 | } | ||
1627 | |||
1628 | /* Validate check bytes */ | ||
1629 | if ((u16)~(*len ^ check)) { | ||
1630 | brcmf_dbg(ERROR, "(nextlen): HW hdr error: nextlen/len/check 0x%04x/0x%04x/0x%04x\n", | ||
1631 | nextlen, *len, check); | ||
1632 | bus->sdcnt.rx_badhdr++; | ||
1633 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1634 | goto fail; | ||
1635 | } | ||
1636 | |||
1637 | /* Validate frame length */ | ||
1638 | if (*len < SDPCM_HDRLEN) { | ||
1639 | brcmf_dbg(ERROR, "(nextlen): HW hdr length invalid: %d\n", | ||
1640 | *len); | ||
1641 | goto fail; | ||
1642 | } | ||
1643 | |||
1644 | /* Check for consistency with readahead info */ | ||
1645 | len_consistent = (nextlen != (roundup(*len, 16) >> 4)); | ||
1646 | if (len_consistent) { | ||
1647 | /* Mismatch, force retry w/normal | ||
1648 | header (may be >4K) */ | ||
1649 | brcmf_dbg(ERROR, "(nextlen): mismatch, nextlen %d len %d rnd %d; expected rxseq %d\n", | ||
1650 | nextlen, *len, roundup(*len, 16), | ||
1651 | rxseq); | ||
1652 | brcmf_sdbrcm_rxfail(bus, true, true); | ||
1653 | goto fail; | ||
1654 | } | ||
1655 | |||
1656 | return 0; | ||
1657 | |||
1658 | fail: | ||
1659 | brcmf_sdbrcm_pktfree2(bus, pkt); | ||
1660 | return -EINVAL; | ||
1661 | } | ||
1662 | |||
1663 | /* Return true if there may be more frames to read */ | ||
1664 | static uint | ||
1665 | brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) | ||
1666 | { | ||
1667 | u16 len, check; /* Extracted hardware header fields */ | ||
1668 | u8 chan, seq, doff; /* Extracted software header fields */ | ||
1669 | u8 fcbits; /* Extracted fcbits from software header */ | ||
1670 | |||
1671 | struct sk_buff *pkt; /* Packet for event or data frames */ | 1593 | struct sk_buff *pkt; /* Packet for event or data frames */ |
1672 | u16 pad; /* Number of pad bytes to read */ | 1594 | u16 pad; /* Number of pad bytes to read */ |
1673 | u16 rdlen; /* Total number of bytes to read */ | ||
1674 | u8 rxseq; /* Next sequence number to expect */ | ||
1675 | uint rxleft = 0; /* Remaining number of frames allowed */ | 1595 | uint rxleft = 0; /* Remaining number of frames allowed */ |
1676 | int sdret; /* Return code from calls */ | 1596 | int sdret; /* Return code from calls */ |
1677 | u8 txmax; /* Maximum tx sequence offered */ | ||
1678 | u8 *rxbuf; | ||
1679 | int ifidx = 0; | 1597 | int ifidx = 0; |
1680 | uint rxcount = 0; /* Total frames read */ | 1598 | uint rxcount = 0; /* Total frames read */ |
1599 | struct brcmf_sdio_read *rd = &bus->cur_read, rd_new; | ||
1600 | u8 head_read = 0; | ||
1681 | 1601 | ||
1682 | brcmf_dbg(TRACE, "Enter\n"); | 1602 | brcmf_dbg(TRACE, "Enter\n"); |
1683 | 1603 | ||
1684 | /* Not finished unless we encounter no more frames indication */ | 1604 | /* Not finished unless we encounter no more frames indication */ |
1685 | *finished = false; | 1605 | bus->rxpending = true; |
1686 | 1606 | ||
1687 | for (rxseq = bus->rx_seq, rxleft = maxframes; | 1607 | for (rd->seq_num = bus->rx_seq, rxleft = maxframes; |
1688 | !bus->rxskip && rxleft && | 1608 | !bus->rxskip && rxleft && |
1689 | bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN; | 1609 | bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN; |
1690 | rxseq++, rxleft--) { | 1610 | rd->seq_num++, rxleft--) { |
1691 | 1611 | ||
1692 | /* Handle glomming separately */ | 1612 | /* Handle glomming separately */ |
1693 | if (bus->glomd || !skb_queue_empty(&bus->glom)) { | 1613 | if (bus->glomd || !skb_queue_empty(&bus->glom)) { |
1694 | u8 cnt; | 1614 | u8 cnt; |
1695 | brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n", | 1615 | brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n", |
1696 | bus->glomd, skb_peek(&bus->glom)); | 1616 | bus->glomd, skb_peek(&bus->glom)); |
1697 | cnt = brcmf_sdbrcm_rxglom(bus, rxseq); | 1617 | cnt = brcmf_sdbrcm_rxglom(bus, rd->seq_num); |
1698 | brcmf_dbg(GLOM, "rxglom returned %d\n", cnt); | 1618 | brcmf_dbg(GLOM, "rxglom returned %d\n", cnt); |
1699 | rxseq += cnt - 1; | 1619 | rd->seq_num += cnt - 1; |
1700 | rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1; | 1620 | rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1; |
1701 | continue; | 1621 | continue; |
1702 | } | 1622 | } |
1703 | 1623 | ||
1704 | /* Try doing single read if we can */ | 1624 | rd->len_left = rd->len; |
1705 | if (bus->nextlen) { | 1625 | /* read header first for unknow frame length */ |
1706 | u16 nextlen = bus->nextlen; | 1626 | if (!rd->len) { |
1707 | bus->nextlen = 0; | 1627 | sdret = brcmf_sdcard_recv_buf(bus->sdiodev, |
1708 | 1628 | bus->sdiodev->sbwad, | |
1709 | rdlen = len = nextlen << 4; | 1629 | SDIO_FUNC_2, F2SYNC, |
1710 | brcmf_pad(bus, &pad, &rdlen); | 1630 | bus->rxhdr, |
1711 | 1631 | BRCMF_FIRSTREAD); | |
1712 | /* | 1632 | bus->sdcnt.f2rxhdrs++; |
1713 | * After the frame is received we have to | 1633 | if (sdret < 0) { |
1714 | * distinguish whether it is data | 1634 | brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", |
1715 | * or non-data frame. | 1635 | sdret); |
1716 | */ | 1636 | bus->sdcnt.rx_hdrfail++; |
1717 | brcmf_alloc_pkt_and_read(bus, rdlen, &pkt, &rxbuf); | 1637 | brcmf_sdbrcm_rxfail(bus, true, true); |
1718 | if (pkt == NULL) { | ||
1719 | /* Give up on data, request rtx of events */ | ||
1720 | brcmf_dbg(ERROR, "(nextlen): brcmf_alloc_pkt_and_read failed: len %d rdlen %d expected rxseq %d\n", | ||
1721 | len, rdlen, rxseq); | ||
1722 | continue; | ||
1723 | } | ||
1724 | |||
1725 | if (brcmf_check_rxbuf(bus, pkt, rxbuf, rxseq, nextlen, | ||
1726 | &len) < 0) | ||
1727 | continue; | 1638 | continue; |
1728 | |||
1729 | /* Extract software header fields */ | ||
1730 | chan = SDPCM_PACKET_CHANNEL( | ||
1731 | &bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1732 | seq = SDPCM_PACKET_SEQUENCE( | ||
1733 | &bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1734 | doff = SDPCM_DOFFSET_VALUE( | ||
1735 | &bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1736 | txmax = SDPCM_WINDOW_VALUE( | ||
1737 | &bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1738 | |||
1739 | bus->nextlen = | ||
1740 | bus->rxhdr[SDPCM_FRAMETAG_LEN + | ||
1741 | SDPCM_NEXTLEN_OFFSET]; | ||
1742 | if ((bus->nextlen << 4) > MAX_RX_DATASZ) { | ||
1743 | brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n", | ||
1744 | bus->nextlen, seq); | ||
1745 | bus->nextlen = 0; | ||
1746 | } | 1639 | } |
1747 | 1640 | ||
1748 | bus->sdcnt.rx_readahead_cnt++; | 1641 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() || BRCMF_HDRS_ON(), |
1749 | |||
1750 | /* Handle Flow Control */ | ||
1751 | fcbits = SDPCM_FCMASK_VALUE( | ||
1752 | &bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1753 | |||
1754 | if (bus->flowcontrol != fcbits) { | ||
1755 | if (~bus->flowcontrol & fcbits) | ||
1756 | bus->sdcnt.fc_xoff++; | ||
1757 | |||
1758 | if (bus->flowcontrol & ~fcbits) | ||
1759 | bus->sdcnt.fc_xon++; | ||
1760 | |||
1761 | bus->sdcnt.fc_rcvd++; | ||
1762 | bus->flowcontrol = fcbits; | ||
1763 | } | ||
1764 | |||
1765 | /* Check and update sequence number */ | ||
1766 | if (rxseq != seq) { | ||
1767 | brcmf_dbg(INFO, "(nextlen): rx_seq %d, expected %d\n", | ||
1768 | seq, rxseq); | ||
1769 | bus->sdcnt.rx_badseq++; | ||
1770 | rxseq = seq; | ||
1771 | } | ||
1772 | |||
1773 | /* Check window for sanity */ | ||
1774 | if ((u8) (txmax - bus->tx_seq) > 0x40) { | ||
1775 | brcmf_dbg(ERROR, "got unlikely tx max %d with tx_seq %d\n", | ||
1776 | txmax, bus->tx_seq); | ||
1777 | txmax = bus->tx_seq + 2; | ||
1778 | } | ||
1779 | bus->tx_max = txmax; | ||
1780 | |||
1781 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), | ||
1782 | rxbuf, len, "Rx Data:\n"); | ||
1783 | brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && | ||
1784 | BRCMF_DATA_ON()) && | ||
1785 | BRCMF_HDRS_ON(), | ||
1786 | bus->rxhdr, SDPCM_HDRLEN, | 1642 | bus->rxhdr, SDPCM_HDRLEN, |
1787 | "RxHdr:\n"); | 1643 | "RxHdr:\n"); |
1788 | 1644 | ||
1789 | if (chan == SDPCM_CONTROL_CHANNEL) { | 1645 | if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd)) { |
1790 | brcmf_dbg(ERROR, "(nextlen): readahead on control packet %d?\n", | 1646 | if (!bus->rxpending) |
1791 | seq); | 1647 | break; |
1792 | /* Force retry w/normal header read */ | 1648 | else |
1793 | bus->nextlen = 0; | 1649 | continue; |
1794 | brcmf_sdbrcm_rxfail(bus, false, true); | ||
1795 | brcmf_sdbrcm_pktfree2(bus, pkt); | ||
1796 | continue; | ||
1797 | } | 1650 | } |
1798 | 1651 | ||
1799 | /* Validate data offset */ | 1652 | if (rd->channel == SDPCM_CONTROL_CHANNEL) { |
1800 | if ((doff < SDPCM_HDRLEN) || (doff > len)) { | 1653 | brcmf_sdbrcm_read_control(bus, bus->rxhdr, |
1801 | brcmf_dbg(ERROR, "(nextlen): bad data offset %d: HW len %d min %d\n", | 1654 | rd->len, |
1802 | doff, len, SDPCM_HDRLEN); | 1655 | rd->dat_offset); |
1803 | brcmf_sdbrcm_rxfail(bus, false, false); | 1656 | /* prepare the descriptor for the next read */ |
1804 | brcmf_sdbrcm_pktfree2(bus, pkt); | 1657 | rd->len = rd->len_nxtfrm << 4; |
1658 | rd->len_nxtfrm = 0; | ||
1659 | /* treat all packet as event if we don't know */ | ||
1660 | rd->channel = SDPCM_EVENT_CHANNEL; | ||
1805 | continue; | 1661 | continue; |
1806 | } | 1662 | } |
1807 | 1663 | rd->len_left = rd->len > BRCMF_FIRSTREAD ? | |
1808 | /* All done with this one -- now deliver the packet */ | 1664 | rd->len - BRCMF_FIRSTREAD : 0; |
1809 | goto deliver; | 1665 | head_read = BRCMF_FIRSTREAD; |
1810 | } | ||
1811 | |||
1812 | /* Read frame header (hardware and software) */ | ||
1813 | sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, | ||
1814 | SDIO_FUNC_2, F2SYNC, bus->rxhdr, | ||
1815 | BRCMF_FIRSTREAD); | ||
1816 | bus->sdcnt.f2rxhdrs++; | ||
1817 | |||
1818 | if (sdret < 0) { | ||
1819 | brcmf_dbg(ERROR, "RXHEADER FAILED: %d\n", sdret); | ||
1820 | bus->sdcnt.rx_hdrfail++; | ||
1821 | brcmf_sdbrcm_rxfail(bus, true, true); | ||
1822 | continue; | ||
1823 | } | ||
1824 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() || BRCMF_HDRS_ON(), | ||
1825 | bus->rxhdr, SDPCM_HDRLEN, "RxHdr:\n"); | ||
1826 | |||
1827 | |||
1828 | /* Extract hardware header fields */ | ||
1829 | len = get_unaligned_le16(bus->rxhdr); | ||
1830 | check = get_unaligned_le16(bus->rxhdr + sizeof(u16)); | ||
1831 | |||
1832 | /* All zeros means no more frames */ | ||
1833 | if (!(len | check)) { | ||
1834 | *finished = true; | ||
1835 | break; | ||
1836 | } | 1666 | } |
1837 | 1667 | ||
1838 | /* Validate check bytes */ | 1668 | brcmf_pad(bus, &pad, &rd->len_left); |
1839 | if ((u16) ~(len ^ check)) { | ||
1840 | brcmf_dbg(ERROR, "HW hdr err: len/check 0x%04x/0x%04x\n", | ||
1841 | len, check); | ||
1842 | bus->sdcnt.rx_badhdr++; | ||
1843 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1844 | continue; | ||
1845 | } | ||
1846 | 1669 | ||
1847 | /* Validate frame length */ | 1670 | pkt = brcmu_pkt_buf_get_skb(rd->len_left + head_read + |
1848 | if (len < SDPCM_HDRLEN) { | 1671 | BRCMF_SDALIGN); |
1849 | brcmf_dbg(ERROR, "HW hdr length invalid: %d\n", len); | ||
1850 | continue; | ||
1851 | } | ||
1852 | |||
1853 | /* Extract software header fields */ | ||
1854 | chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1855 | seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1856 | doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1857 | txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1858 | |||
1859 | /* Validate data offset */ | ||
1860 | if ((doff < SDPCM_HDRLEN) || (doff > len)) { | ||
1861 | brcmf_dbg(ERROR, "Bad data offset %d: HW len %d, min %d seq %d\n", | ||
1862 | doff, len, SDPCM_HDRLEN, seq); | ||
1863 | bus->sdcnt.rx_badhdr++; | ||
1864 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1865 | continue; | ||
1866 | } | ||
1867 | |||
1868 | /* Save the readahead length if there is one */ | ||
1869 | bus->nextlen = | ||
1870 | bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; | ||
1871 | if ((bus->nextlen << 4) > MAX_RX_DATASZ) { | ||
1872 | brcmf_dbg(INFO, "(nextlen): got frame w/nextlen too large (%d), seq %d\n", | ||
1873 | bus->nextlen, seq); | ||
1874 | bus->nextlen = 0; | ||
1875 | } | ||
1876 | |||
1877 | /* Handle Flow Control */ | ||
1878 | fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); | ||
1879 | |||
1880 | if (bus->flowcontrol != fcbits) { | ||
1881 | if (~bus->flowcontrol & fcbits) | ||
1882 | bus->sdcnt.fc_xoff++; | ||
1883 | |||
1884 | if (bus->flowcontrol & ~fcbits) | ||
1885 | bus->sdcnt.fc_xon++; | ||
1886 | |||
1887 | bus->sdcnt.fc_rcvd++; | ||
1888 | bus->flowcontrol = fcbits; | ||
1889 | } | ||
1890 | |||
1891 | /* Check and update sequence number */ | ||
1892 | if (rxseq != seq) { | ||
1893 | brcmf_dbg(INFO, "rx_seq %d, expected %d\n", seq, rxseq); | ||
1894 | bus->sdcnt.rx_badseq++; | ||
1895 | rxseq = seq; | ||
1896 | } | ||
1897 | |||
1898 | /* Check window for sanity */ | ||
1899 | if ((u8) (txmax - bus->tx_seq) > 0x40) { | ||
1900 | brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n", | ||
1901 | txmax, bus->tx_seq); | ||
1902 | txmax = bus->tx_seq + 2; | ||
1903 | } | ||
1904 | bus->tx_max = txmax; | ||
1905 | |||
1906 | /* Call a separate function for control frames */ | ||
1907 | if (chan == SDPCM_CONTROL_CHANNEL) { | ||
1908 | brcmf_sdbrcm_read_control(bus, bus->rxhdr, len, doff); | ||
1909 | continue; | ||
1910 | } | ||
1911 | |||
1912 | /* precondition: chan is either SDPCM_DATA_CHANNEL, | ||
1913 | SDPCM_EVENT_CHANNEL, SDPCM_TEST_CHANNEL or | ||
1914 | SDPCM_GLOM_CHANNEL */ | ||
1915 | |||
1916 | /* Length to read */ | ||
1917 | rdlen = (len > BRCMF_FIRSTREAD) ? (len - BRCMF_FIRSTREAD) : 0; | ||
1918 | |||
1919 | /* May pad read to blocksize for efficiency */ | ||
1920 | if (bus->roundup && bus->blocksize && | ||
1921 | (rdlen > bus->blocksize)) { | ||
1922 | pad = bus->blocksize - (rdlen % bus->blocksize); | ||
1923 | if ((pad <= bus->roundup) && (pad < bus->blocksize) && | ||
1924 | ((rdlen + pad + BRCMF_FIRSTREAD) < MAX_RX_DATASZ)) | ||
1925 | rdlen += pad; | ||
1926 | } else if (rdlen % BRCMF_SDALIGN) { | ||
1927 | rdlen += BRCMF_SDALIGN - (rdlen % BRCMF_SDALIGN); | ||
1928 | } | ||
1929 | |||
1930 | /* Satisfy length-alignment requirements */ | ||
1931 | if (rdlen & (ALIGNMENT - 1)) | ||
1932 | rdlen = roundup(rdlen, ALIGNMENT); | ||
1933 | |||
1934 | if ((rdlen + BRCMF_FIRSTREAD) > MAX_RX_DATASZ) { | ||
1935 | /* Too long -- skip this frame */ | ||
1936 | brcmf_dbg(ERROR, "too long: len %d rdlen %d\n", | ||
1937 | len, rdlen); | ||
1938 | bus->sdiodev->bus_if->dstats.rx_errors++; | ||
1939 | bus->sdcnt.rx_toolong++; | ||
1940 | brcmf_sdbrcm_rxfail(bus, false, false); | ||
1941 | continue; | ||
1942 | } | ||
1943 | |||
1944 | pkt = brcmu_pkt_buf_get_skb(rdlen + | ||
1945 | BRCMF_FIRSTREAD + BRCMF_SDALIGN); | ||
1946 | if (!pkt) { | 1672 | if (!pkt) { |
1947 | /* Give up on data, request rtx of events */ | 1673 | /* Give up on data, request rtx of events */ |
1948 | brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: rdlen %d chan %d\n", | 1674 | brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed\n"); |
1949 | rdlen, chan); | ||
1950 | bus->sdiodev->bus_if->dstats.rx_dropped++; | 1675 | bus->sdiodev->bus_if->dstats.rx_dropped++; |
1951 | brcmf_sdbrcm_rxfail(bus, false, RETRYCHAN(chan)); | 1676 | brcmf_sdbrcm_rxfail(bus, false, |
1677 | RETRYCHAN(rd->channel)); | ||
1952 | continue; | 1678 | continue; |
1953 | } | 1679 | } |
1680 | skb_pull(pkt, head_read); | ||
1681 | pkt_align(pkt, rd->len_left, BRCMF_SDALIGN); | ||
1954 | 1682 | ||
1955 | /* Leave room for what we already read, and align remainder */ | ||
1956 | skb_pull(pkt, BRCMF_FIRSTREAD); | ||
1957 | pkt_align(pkt, rdlen, BRCMF_SDALIGN); | ||
1958 | |||
1959 | /* Read the remaining frame data */ | ||
1960 | sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, | 1683 | sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, |
1961 | SDIO_FUNC_2, F2SYNC, pkt); | 1684 | SDIO_FUNC_2, F2SYNC, pkt); |
1962 | bus->sdcnt.f2rxdata++; | 1685 | bus->sdcnt.f2rxdata++; |
1963 | 1686 | ||
1964 | if (sdret < 0) { | 1687 | if (sdret < 0) { |
1965 | brcmf_dbg(ERROR, "read %d %s bytes failed: %d\n", rdlen, | 1688 | brcmf_dbg(ERROR, "read %d bytes from channel %d failed: %d\n", |
1966 | ((chan == SDPCM_EVENT_CHANNEL) ? "event" | 1689 | rd->len, rd->channel, sdret); |
1967 | : ((chan == SDPCM_DATA_CHANNEL) ? "data" | ||
1968 | : "test")), sdret); | ||
1969 | brcmu_pkt_buf_free_skb(pkt); | 1690 | brcmu_pkt_buf_free_skb(pkt); |
1970 | bus->sdiodev->bus_if->dstats.rx_errors++; | 1691 | bus->sdiodev->bus_if->dstats.rx_errors++; |
1971 | brcmf_sdbrcm_rxfail(bus, true, RETRYCHAN(chan)); | 1692 | brcmf_sdbrcm_rxfail(bus, true, |
1693 | RETRYCHAN(rd->channel)); | ||
1972 | continue; | 1694 | continue; |
1973 | } | 1695 | } |
1974 | 1696 | ||
1975 | /* Copy the already-read portion */ | 1697 | if (head_read) { |
1976 | skb_push(pkt, BRCMF_FIRSTREAD); | 1698 | skb_push(pkt, head_read); |
1977 | memcpy(pkt->data, bus->rxhdr, BRCMF_FIRSTREAD); | 1699 | memcpy(pkt->data, bus->rxhdr, head_read); |
1700 | head_read = 0; | ||
1701 | } else { | ||
1702 | memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN); | ||
1703 | rd_new.seq_num = rd->seq_num; | ||
1704 | if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new)) { | ||
1705 | rd->len = 0; | ||
1706 | brcmu_pkt_buf_free_skb(pkt); | ||
1707 | } | ||
1708 | bus->sdcnt.rx_readahead_cnt++; | ||
1709 | if (rd->len != roundup(rd_new.len, 16)) { | ||
1710 | brcmf_dbg(ERROR, "frame length mismatch:read %d, should be %d\n", | ||
1711 | rd->len, | ||
1712 | roundup(rd_new.len, 16) >> 4); | ||
1713 | rd->len = 0; | ||
1714 | brcmf_sdbrcm_rxfail(bus, true, true); | ||
1715 | brcmu_pkt_buf_free_skb(pkt); | ||
1716 | continue; | ||
1717 | } | ||
1718 | rd->len_nxtfrm = rd_new.len_nxtfrm; | ||
1719 | rd->channel = rd_new.channel; | ||
1720 | rd->dat_offset = rd_new.dat_offset; | ||
1721 | |||
1722 | brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && | ||
1723 | BRCMF_DATA_ON()) && | ||
1724 | BRCMF_HDRS_ON(), | ||
1725 | bus->rxhdr, SDPCM_HDRLEN, | ||
1726 | "RxHdr:\n"); | ||
1727 | |||
1728 | if (rd_new.channel == SDPCM_CONTROL_CHANNEL) { | ||
1729 | brcmf_dbg(ERROR, "readahead on control packet %d?\n", | ||
1730 | rd_new.seq_num); | ||
1731 | /* Force retry w/normal header read */ | ||
1732 | rd->len = 0; | ||
1733 | brcmf_sdbrcm_rxfail(bus, false, true); | ||
1734 | brcmu_pkt_buf_free_skb(pkt); | ||
1735 | continue; | ||
1736 | } | ||
1737 | } | ||
1978 | 1738 | ||
1979 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), | 1739 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), |
1980 | pkt->data, len, "Rx Data:\n"); | 1740 | pkt->data, rd->len, "Rx Data:\n"); |
1981 | 1741 | ||
1982 | deliver: | ||
1983 | /* Save superframe descriptor and allocate packet frame */ | 1742 | /* Save superframe descriptor and allocate packet frame */ |
1984 | if (chan == SDPCM_GLOM_CHANNEL) { | 1743 | if (rd->channel == SDPCM_GLOM_CHANNEL) { |
1985 | if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) { | 1744 | if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) { |
1986 | brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n", | 1745 | brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n", |
1987 | len); | 1746 | rd->len); |
1988 | brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), | 1747 | brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), |
1989 | pkt->data, len, | 1748 | pkt->data, rd->len, |
1990 | "Glom Data:\n"); | 1749 | "Glom Data:\n"); |
1991 | __skb_trim(pkt, len); | 1750 | __skb_trim(pkt, rd->len); |
1992 | skb_pull(pkt, SDPCM_HDRLEN); | 1751 | skb_pull(pkt, SDPCM_HDRLEN); |
1993 | bus->glomd = pkt; | 1752 | bus->glomd = pkt; |
1994 | } else { | 1753 | } else { |
@@ -1996,12 +1755,23 @@ deliver: | |||
1996 | "descriptor!\n", __func__); | 1755 | "descriptor!\n", __func__); |
1997 | brcmf_sdbrcm_rxfail(bus, false, false); | 1756 | brcmf_sdbrcm_rxfail(bus, false, false); |
1998 | } | 1757 | } |
1758 | /* prepare the descriptor for the next read */ | ||
1759 | rd->len = rd->len_nxtfrm << 4; | ||
1760 | rd->len_nxtfrm = 0; | ||
1761 | /* treat all packet as event if we don't know */ | ||
1762 | rd->channel = SDPCM_EVENT_CHANNEL; | ||
1999 | continue; | 1763 | continue; |
2000 | } | 1764 | } |
2001 | 1765 | ||
2002 | /* Fill in packet len and prio, deliver upward */ | 1766 | /* Fill in packet len and prio, deliver upward */ |
2003 | __skb_trim(pkt, len); | 1767 | __skb_trim(pkt, rd->len); |
2004 | skb_pull(pkt, doff); | 1768 | skb_pull(pkt, rd->dat_offset); |
1769 | |||
1770 | /* prepare the descriptor for the next read */ | ||
1771 | rd->len = rd->len_nxtfrm << 4; | ||
1772 | rd->len_nxtfrm = 0; | ||
1773 | /* treat all packet as event if we don't know */ | ||
1774 | rd->channel = SDPCM_EVENT_CHANNEL; | ||
2005 | 1775 | ||
2006 | if (pkt->len == 0) { | 1776 | if (pkt->len == 0) { |
2007 | brcmu_pkt_buf_free_skb(pkt); | 1777 | brcmu_pkt_buf_free_skb(pkt); |
@@ -2019,17 +1789,17 @@ deliver: | |||
2019 | brcmf_rx_packet(bus->sdiodev->dev, ifidx, pkt); | 1789 | brcmf_rx_packet(bus->sdiodev->dev, ifidx, pkt); |
2020 | down(&bus->sdsem); | 1790 | down(&bus->sdsem); |
2021 | } | 1791 | } |
1792 | |||
2022 | rxcount = maxframes - rxleft; | 1793 | rxcount = maxframes - rxleft; |
2023 | /* Message if we hit the limit */ | 1794 | /* Message if we hit the limit */ |
2024 | if (!rxleft) | 1795 | if (!rxleft) |
2025 | brcmf_dbg(DATA, "hit rx limit of %d frames\n", | 1796 | brcmf_dbg(DATA, "hit rx limit of %d frames\n", maxframes); |
2026 | maxframes); | ||
2027 | else | 1797 | else |
2028 | brcmf_dbg(DATA, "processed %d frames\n", rxcount); | 1798 | brcmf_dbg(DATA, "processed %d frames\n", rxcount); |
2029 | /* Back off rxseq if awaiting rtx, update rx_seq */ | 1799 | /* Back off rxseq if awaiting rtx, update rx_seq */ |
2030 | if (bus->rxskip) | 1800 | if (bus->rxskip) |
2031 | rxseq--; | 1801 | rd->seq_num--; |
2032 | bus->rx_seq = rxseq; | 1802 | bus->rx_seq = rd->seq_num; |
2033 | 1803 | ||
2034 | return rxcount; | 1804 | return rxcount; |
2035 | } | 1805 | } |
@@ -2227,7 +1997,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2227 | if (ret != 0) | 1997 | if (ret != 0) |
2228 | break; | 1998 | break; |
2229 | if (intstatus & bus->hostintmask) | 1999 | if (intstatus & bus->hostintmask) |
2230 | bus->ipend = true; | 2000 | atomic_set(&bus->ipend, 1); |
2231 | } | 2001 | } |
2232 | } | 2002 | } |
2233 | 2003 | ||
@@ -2259,16 +2029,8 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
2259 | bus->watchdog_tsk = NULL; | 2029 | bus->watchdog_tsk = NULL; |
2260 | } | 2030 | } |
2261 | 2031 | ||
2262 | if (bus->dpc_tsk && bus->dpc_tsk != current) { | ||
2263 | send_sig(SIGTERM, bus->dpc_tsk, 1); | ||
2264 | kthread_stop(bus->dpc_tsk); | ||
2265 | bus->dpc_tsk = NULL; | ||
2266 | } | ||
2267 | |||
2268 | down(&bus->sdsem); | 2032 | down(&bus->sdsem); |
2269 | 2033 | ||
2270 | bus_wake(bus); | ||
2271 | |||
2272 | /* Enable clock for device interrupts */ | 2034 | /* Enable clock for device interrupts */ |
2273 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 2035 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); |
2274 | 2036 | ||
@@ -2327,7 +2089,7 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) | |||
2327 | unsigned long flags; | 2089 | unsigned long flags; |
2328 | 2090 | ||
2329 | spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags); | 2091 | spin_lock_irqsave(&bus->sdiodev->irq_en_lock, flags); |
2330 | if (!bus->sdiodev->irq_en && !bus->ipend) { | 2092 | if (!bus->sdiodev->irq_en && !atomic_read(&bus->ipend)) { |
2331 | enable_irq(bus->sdiodev->irq); | 2093 | enable_irq(bus->sdiodev->irq); |
2332 | bus->sdiodev->irq_en = true; | 2094 | bus->sdiodev->irq_en = true; |
2333 | } | 2095 | } |
@@ -2339,21 +2101,69 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) | |||
2339 | } | 2101 | } |
2340 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | 2102 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ |
2341 | 2103 | ||
2342 | static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | 2104 | static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus) |
2105 | { | ||
2106 | struct list_head *new_hd; | ||
2107 | unsigned long flags; | ||
2108 | |||
2109 | if (in_interrupt()) | ||
2110 | new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC); | ||
2111 | else | ||
2112 | new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL); | ||
2113 | if (new_hd == NULL) | ||
2114 | return; | ||
2115 | |||
2116 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
2117 | list_add_tail(new_hd, &bus->dpc_tsklst); | ||
2118 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2119 | } | ||
2120 | |||
2121 | static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) | ||
2343 | { | 2122 | { |
2344 | u32 intstatus, newstatus = 0; | 2123 | u8 idx; |
2124 | u32 addr; | ||
2125 | unsigned long val; | ||
2126 | int n, ret; | ||
2127 | |||
2128 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | ||
2129 | addr = bus->ci->c_inf[idx].base + | ||
2130 | offsetof(struct sdpcmd_regs, intstatus); | ||
2131 | |||
2132 | ret = brcmf_sdio_regrw_helper(bus->sdiodev, addr, &val, false); | ||
2133 | bus->sdcnt.f1regdata++; | ||
2134 | if (ret != 0) | ||
2135 | val = 0; | ||
2136 | |||
2137 | val &= bus->hostintmask; | ||
2138 | atomic_set(&bus->fcstate, !!(val & I_HMB_FC_STATE)); | ||
2139 | |||
2140 | /* Clear interrupts */ | ||
2141 | if (val) { | ||
2142 | ret = brcmf_sdio_regrw_helper(bus->sdiodev, addr, &val, true); | ||
2143 | bus->sdcnt.f1regdata++; | ||
2144 | } | ||
2145 | |||
2146 | if (ret) { | ||
2147 | atomic_set(&bus->intstatus, 0); | ||
2148 | } else if (val) { | ||
2149 | for_each_set_bit(n, &val, 32) | ||
2150 | set_bit(n, (unsigned long *)&bus->intstatus.counter); | ||
2151 | } | ||
2152 | |||
2153 | return ret; | ||
2154 | } | ||
2155 | |||
2156 | static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | ||
2157 | { | ||
2158 | u32 newstatus = 0; | ||
2159 | unsigned long intstatus; | ||
2345 | uint rxlimit = bus->rxbound; /* Rx frames to read before resched */ | 2160 | uint rxlimit = bus->rxbound; /* Rx frames to read before resched */ |
2346 | uint txlimit = bus->txbound; /* Tx frames to send before resched */ | 2161 | uint txlimit = bus->txbound; /* Tx frames to send before resched */ |
2347 | uint framecnt = 0; /* Temporary counter of tx/rx frames */ | 2162 | uint framecnt = 0; /* Temporary counter of tx/rx frames */ |
2348 | bool rxdone = true; /* Flag for no more read data */ | 2163 | int err = 0, n; |
2349 | bool resched = false; /* Flag indicating resched wanted */ | ||
2350 | int err; | ||
2351 | 2164 | ||
2352 | brcmf_dbg(TRACE, "Enter\n"); | 2165 | brcmf_dbg(TRACE, "Enter\n"); |
2353 | 2166 | ||
2354 | /* Start with leftover status bits */ | ||
2355 | intstatus = bus->intstatus; | ||
2356 | |||
2357 | down(&bus->sdsem); | 2167 | down(&bus->sdsem); |
2358 | 2168 | ||
2359 | /* If waiting for HTAVAIL, check status */ | 2169 | /* If waiting for HTAVAIL, check status */ |
@@ -2399,39 +2209,22 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2399 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2209 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
2400 | } | 2210 | } |
2401 | bus->clkstate = CLK_AVAIL; | 2211 | bus->clkstate = CLK_AVAIL; |
2402 | } else { | ||
2403 | goto clkwait; | ||
2404 | } | 2212 | } |
2405 | } | 2213 | } |
2406 | 2214 | ||
2407 | bus_wake(bus); | ||
2408 | |||
2409 | /* Make sure backplane clock is on */ | 2215 | /* Make sure backplane clock is on */ |
2410 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true); | 2216 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true); |
2411 | if (bus->clkstate == CLK_PENDING) | ||
2412 | goto clkwait; | ||
2413 | 2217 | ||
2414 | /* Pending interrupt indicates new device status */ | 2218 | /* Pending interrupt indicates new device status */ |
2415 | if (bus->ipend) { | 2219 | if (atomic_read(&bus->ipend) > 0) { |
2416 | bus->ipend = false; | 2220 | atomic_set(&bus->ipend, 0); |
2417 | err = r_sdreg32(bus, &newstatus, | 2221 | sdio_claim_host(bus->sdiodev->func[1]); |
2418 | offsetof(struct sdpcmd_regs, intstatus)); | 2222 | err = brcmf_sdio_intr_rstatus(bus); |
2419 | bus->sdcnt.f1regdata++; | 2223 | sdio_release_host(bus->sdiodev->func[1]); |
2420 | if (err != 0) | ||
2421 | newstatus = 0; | ||
2422 | newstatus &= bus->hostintmask; | ||
2423 | bus->fcstate = !!(newstatus & I_HMB_FC_STATE); | ||
2424 | if (newstatus) { | ||
2425 | err = w_sdreg32(bus, newstatus, | ||
2426 | offsetof(struct sdpcmd_regs, | ||
2427 | intstatus)); | ||
2428 | bus->sdcnt.f1regdata++; | ||
2429 | } | ||
2430 | } | 2224 | } |
2431 | 2225 | ||
2432 | /* Merge new bits with previous */ | 2226 | /* Start with leftover status bits */ |
2433 | intstatus |= newstatus; | 2227 | intstatus = atomic_xchg(&bus->intstatus, 0); |
2434 | bus->intstatus = 0; | ||
2435 | 2228 | ||
2436 | /* Handle flow-control change: read new state in case our ack | 2229 | /* Handle flow-control change: read new state in case our ack |
2437 | * crossed another change interrupt. If change still set, assume | 2230 | * crossed another change interrupt. If change still set, assume |
@@ -2445,8 +2238,8 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2445 | err = r_sdreg32(bus, &newstatus, | 2238 | err = r_sdreg32(bus, &newstatus, |
2446 | offsetof(struct sdpcmd_regs, intstatus)); | 2239 | offsetof(struct sdpcmd_regs, intstatus)); |
2447 | bus->sdcnt.f1regdata += 2; | 2240 | bus->sdcnt.f1regdata += 2; |
2448 | bus->fcstate = | 2241 | atomic_set(&bus->fcstate, |
2449 | !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); | 2242 | !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE))); |
2450 | intstatus |= (newstatus & bus->hostintmask); | 2243 | intstatus |= (newstatus & bus->hostintmask); |
2451 | } | 2244 | } |
2452 | 2245 | ||
@@ -2483,32 +2276,34 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2483 | intstatus &= ~I_HMB_FRAME_IND; | 2276 | intstatus &= ~I_HMB_FRAME_IND; |
2484 | 2277 | ||
2485 | /* On frame indication, read available frames */ | 2278 | /* On frame indication, read available frames */ |
2486 | if (PKT_AVAILABLE()) { | 2279 | if (PKT_AVAILABLE() && bus->clkstate == CLK_AVAIL) { |
2487 | framecnt = brcmf_sdbrcm_readframes(bus, rxlimit, &rxdone); | 2280 | framecnt = brcmf_sdio_readframes(bus, rxlimit); |
2488 | if (rxdone || bus->rxskip) | 2281 | if (!bus->rxpending) |
2489 | intstatus &= ~I_HMB_FRAME_IND; | 2282 | intstatus &= ~I_HMB_FRAME_IND; |
2490 | rxlimit -= min(framecnt, rxlimit); | 2283 | rxlimit -= min(framecnt, rxlimit); |
2491 | } | 2284 | } |
2492 | 2285 | ||
2493 | /* Keep still-pending events for next scheduling */ | 2286 | /* Keep still-pending events for next scheduling */ |
2494 | bus->intstatus = intstatus; | 2287 | if (intstatus) { |
2288 | for_each_set_bit(n, &intstatus, 32) | ||
2289 | set_bit(n, (unsigned long *)&bus->intstatus.counter); | ||
2290 | } | ||
2495 | 2291 | ||
2496 | clkwait: | ||
2497 | brcmf_sdbrcm_clrintr(bus); | 2292 | brcmf_sdbrcm_clrintr(bus); |
2498 | 2293 | ||
2499 | if (data_ok(bus) && bus->ctrl_frame_stat && | 2294 | if (data_ok(bus) && bus->ctrl_frame_stat && |
2500 | (bus->clkstate == CLK_AVAIL)) { | 2295 | (bus->clkstate == CLK_AVAIL)) { |
2501 | int ret, i; | 2296 | int i; |
2502 | 2297 | ||
2503 | ret = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad, | 2298 | err = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad, |
2504 | SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf, | 2299 | SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf, |
2505 | (u32) bus->ctrl_frame_len); | 2300 | (u32) bus->ctrl_frame_len); |
2506 | 2301 | ||
2507 | if (ret < 0) { | 2302 | if (err < 0) { |
2508 | /* On failure, abort the command and | 2303 | /* On failure, abort the command and |
2509 | terminate the frame */ | 2304 | terminate the frame */ |
2510 | brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", | 2305 | brcmf_dbg(INFO, "sdio error %d, abort command and terminate frame\n", |
2511 | ret); | 2306 | err); |
2512 | bus->sdcnt.tx_sderrs++; | 2307 | bus->sdcnt.tx_sderrs++; |
2513 | 2308 | ||
2514 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2309 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); |
@@ -2530,42 +2325,34 @@ clkwait: | |||
2530 | break; | 2325 | break; |
2531 | } | 2326 | } |
2532 | 2327 | ||
2533 | } | 2328 | } else { |
2534 | if (ret == 0) | ||
2535 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; | 2329 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; |
2536 | 2330 | } | |
2537 | brcmf_dbg(INFO, "Return_dpc value is : %d\n", ret); | ||
2538 | bus->ctrl_frame_stat = false; | 2331 | bus->ctrl_frame_stat = false; |
2539 | brcmf_sdbrcm_wait_event_wakeup(bus); | 2332 | brcmf_sdbrcm_wait_event_wakeup(bus); |
2540 | } | 2333 | } |
2541 | /* Send queued frames (limit 1 if rx may still be pending) */ | 2334 | /* Send queued frames (limit 1 if rx may still be pending) */ |
2542 | else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && | 2335 | else if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) && |
2543 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit | 2336 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit |
2544 | && data_ok(bus)) { | 2337 | && data_ok(bus)) { |
2545 | framecnt = rxdone ? txlimit : min(txlimit, bus->txminmax); | 2338 | framecnt = bus->rxpending ? min(txlimit, bus->txminmax) : |
2339 | txlimit; | ||
2546 | framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt); | 2340 | framecnt = brcmf_sdbrcm_sendfromq(bus, framecnt); |
2547 | txlimit -= framecnt; | 2341 | txlimit -= framecnt; |
2548 | } | 2342 | } |
2549 | 2343 | ||
2550 | /* Resched if events or tx frames are pending, | ||
2551 | else await next interrupt */ | ||
2552 | /* On failed register access, all bets are off: | ||
2553 | no resched or interrupts */ | ||
2554 | if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) { | 2344 | if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) { |
2555 | brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation\n"); | 2345 | brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation\n"); |
2556 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2346 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
2557 | bus->intstatus = 0; | 2347 | atomic_set(&bus->intstatus, 0); |
2558 | } else if (bus->clkstate == CLK_PENDING) { | 2348 | } else if (atomic_read(&bus->intstatus) || |
2559 | brcmf_dbg(INFO, "rescheduled due to CLK_PENDING awaiting I_CHIPACTIVE interrupt\n"); | 2349 | atomic_read(&bus->ipend) > 0 || |
2560 | resched = true; | 2350 | (!atomic_read(&bus->fcstate) && |
2561 | } else if (bus->intstatus || bus->ipend || | 2351 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && |
2562 | (!bus->fcstate && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) | 2352 | data_ok(bus)) || PKT_AVAILABLE()) { |
2563 | && data_ok(bus)) || PKT_AVAILABLE()) { | 2353 | brcmf_sdbrcm_adddpctsk(bus); |
2564 | resched = true; | ||
2565 | } | 2354 | } |
2566 | 2355 | ||
2567 | bus->dpc_sched = resched; | ||
2568 | |||
2569 | /* If we're done for now, turn off clock request. */ | 2356 | /* If we're done for now, turn off clock request. */ |
2570 | if ((bus->clkstate != CLK_PENDING) | 2357 | if ((bus->clkstate != CLK_PENDING) |
2571 | && bus->idletime == BRCMF_IDLE_IMMEDIATE) { | 2358 | && bus->idletime == BRCMF_IDLE_IMMEDIATE) { |
@@ -2574,65 +2361,6 @@ clkwait: | |||
2574 | } | 2361 | } |
2575 | 2362 | ||
2576 | up(&bus->sdsem); | 2363 | up(&bus->sdsem); |
2577 | |||
2578 | return resched; | ||
2579 | } | ||
2580 | |||
2581 | static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus) | ||
2582 | { | ||
2583 | struct list_head *new_hd; | ||
2584 | unsigned long flags; | ||
2585 | |||
2586 | if (in_interrupt()) | ||
2587 | new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC); | ||
2588 | else | ||
2589 | new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL); | ||
2590 | if (new_hd == NULL) | ||
2591 | return; | ||
2592 | |||
2593 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
2594 | list_add_tail(new_hd, &bus->dpc_tsklst); | ||
2595 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2596 | } | ||
2597 | |||
2598 | static int brcmf_sdbrcm_dpc_thread(void *data) | ||
2599 | { | ||
2600 | struct brcmf_sdio *bus = (struct brcmf_sdio *) data; | ||
2601 | struct list_head *cur_hd, *tmp_hd; | ||
2602 | unsigned long flags; | ||
2603 | |||
2604 | allow_signal(SIGTERM); | ||
2605 | /* Run until signal received */ | ||
2606 | while (1) { | ||
2607 | if (kthread_should_stop()) | ||
2608 | break; | ||
2609 | |||
2610 | if (list_empty(&bus->dpc_tsklst)) | ||
2611 | if (wait_for_completion_interruptible(&bus->dpc_wait)) | ||
2612 | break; | ||
2613 | |||
2614 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
2615 | list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) { | ||
2616 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2617 | |||
2618 | if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) { | ||
2619 | /* after stopping the bus, exit thread */ | ||
2620 | brcmf_sdbrcm_bus_stop(bus->sdiodev->dev); | ||
2621 | bus->dpc_tsk = NULL; | ||
2622 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
2623 | break; | ||
2624 | } | ||
2625 | |||
2626 | if (brcmf_sdbrcm_dpc(bus)) | ||
2627 | brcmf_sdbrcm_adddpctsk(bus); | ||
2628 | |||
2629 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
2630 | list_del(cur_hd); | ||
2631 | kfree(cur_hd); | ||
2632 | } | ||
2633 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2634 | } | ||
2635 | return 0; | ||
2636 | } | 2364 | } |
2637 | 2365 | ||
2638 | static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | 2366 | static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) |
@@ -2642,6 +2370,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2642 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2370 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
2643 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2371 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
2644 | struct brcmf_sdio *bus = sdiodev->bus; | 2372 | struct brcmf_sdio *bus = sdiodev->bus; |
2373 | unsigned long flags; | ||
2645 | 2374 | ||
2646 | brcmf_dbg(TRACE, "Enter\n"); | 2375 | brcmf_dbg(TRACE, "Enter\n"); |
2647 | 2376 | ||
@@ -2680,13 +2409,15 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2680 | if (pktq_plen(&bus->txq, prec) > qcount[prec]) | 2409 | if (pktq_plen(&bus->txq, prec) > qcount[prec]) |
2681 | qcount[prec] = pktq_plen(&bus->txq, prec); | 2410 | qcount[prec] = pktq_plen(&bus->txq, prec); |
2682 | #endif | 2411 | #endif |
2683 | /* Schedule DPC if needed to send queued packet(s) */ | 2412 | |
2684 | if (!bus->dpc_sched) { | 2413 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); |
2685 | bus->dpc_sched = true; | 2414 | if (list_empty(&bus->dpc_tsklst)) { |
2686 | if (bus->dpc_tsk) { | 2415 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); |
2687 | brcmf_sdbrcm_adddpctsk(bus); | 2416 | |
2688 | complete(&bus->dpc_wait); | 2417 | brcmf_sdbrcm_adddpctsk(bus); |
2689 | } | 2418 | queue_work(bus->brcmf_wq, &bus->datawork); |
2419 | } else { | ||
2420 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2690 | } | 2421 | } |
2691 | 2422 | ||
2692 | return ret; | 2423 | return ret; |
@@ -2707,6 +2438,8 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data, | |||
2707 | else | 2438 | else |
2708 | dsize = size; | 2439 | dsize = size; |
2709 | 2440 | ||
2441 | sdio_claim_host(bus->sdiodev->func[1]); | ||
2442 | |||
2710 | /* Set the backplane window to include the start address */ | 2443 | /* Set the backplane window to include the start address */ |
2711 | bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address); | 2444 | bcmerror = brcmf_sdcard_set_sbaddr_window(bus->sdiodev, address); |
2712 | if (bcmerror) { | 2445 | if (bcmerror) { |
@@ -2748,6 +2481,8 @@ xfer_done: | |||
2748 | brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n", | 2481 | brcmf_dbg(ERROR, "FAILED to set window back to 0x%x\n", |
2749 | bus->sdiodev->sbwad); | 2482 | bus->sdiodev->sbwad); |
2750 | 2483 | ||
2484 | sdio_release_host(bus->sdiodev->func[1]); | ||
2485 | |||
2751 | return bcmerror; | 2486 | return bcmerror; |
2752 | } | 2487 | } |
2753 | 2488 | ||
@@ -2882,6 +2617,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2882 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2617 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
2883 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2618 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
2884 | struct brcmf_sdio *bus = sdiodev->bus; | 2619 | struct brcmf_sdio *bus = sdiodev->bus; |
2620 | unsigned long flags; | ||
2885 | 2621 | ||
2886 | brcmf_dbg(TRACE, "Enter\n"); | 2622 | brcmf_dbg(TRACE, "Enter\n"); |
2887 | 2623 | ||
@@ -2918,8 +2654,6 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2918 | /* Need to lock here to protect txseq and SDIO tx calls */ | 2654 | /* Need to lock here to protect txseq and SDIO tx calls */ |
2919 | down(&bus->sdsem); | 2655 | down(&bus->sdsem); |
2920 | 2656 | ||
2921 | bus_wake(bus); | ||
2922 | |||
2923 | /* Make sure backplane clock is on */ | 2657 | /* Make sure backplane clock is on */ |
2924 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 2658 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); |
2925 | 2659 | ||
@@ -2967,9 +2701,15 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2967 | } while (ret < 0 && retries++ < TXRETRIES); | 2701 | } while (ret < 0 && retries++ < TXRETRIES); |
2968 | } | 2702 | } |
2969 | 2703 | ||
2970 | if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) { | 2704 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); |
2705 | if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && | ||
2706 | list_empty(&bus->dpc_tsklst)) { | ||
2707 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2708 | |||
2971 | bus->activity = false; | 2709 | bus->activity = false; |
2972 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); | 2710 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); |
2711 | } else { | ||
2712 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
2973 | } | 2713 | } |
2974 | 2714 | ||
2975 | up(&bus->sdsem); | 2715 | up(&bus->sdsem); |
@@ -3774,23 +3514,20 @@ void brcmf_sdbrcm_isr(void *arg) | |||
3774 | } | 3514 | } |
3775 | /* Count the interrupt call */ | 3515 | /* Count the interrupt call */ |
3776 | bus->sdcnt.intrcount++; | 3516 | bus->sdcnt.intrcount++; |
3777 | bus->ipend = true; | 3517 | if (in_interrupt()) |
3778 | 3518 | atomic_set(&bus->ipend, 1); | |
3779 | /* Shouldn't get this interrupt if we're sleeping? */ | 3519 | else |
3780 | if (bus->sleeping) { | 3520 | if (brcmf_sdio_intr_rstatus(bus)) { |
3781 | brcmf_dbg(ERROR, "INTERRUPT WHILE SLEEPING??\n"); | 3521 | brcmf_dbg(ERROR, "failed backplane access\n"); |
3782 | return; | 3522 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
3783 | } | 3523 | } |
3784 | 3524 | ||
3785 | /* Disable additional interrupts (is this needed now)? */ | 3525 | /* Disable additional interrupts (is this needed now)? */ |
3786 | if (!bus->intr) | 3526 | if (!bus->intr) |
3787 | brcmf_dbg(ERROR, "isr w/o interrupt configured!\n"); | 3527 | brcmf_dbg(ERROR, "isr w/o interrupt configured!\n"); |
3788 | 3528 | ||
3789 | bus->dpc_sched = true; | 3529 | brcmf_sdbrcm_adddpctsk(bus); |
3790 | if (bus->dpc_tsk) { | 3530 | queue_work(bus->brcmf_wq, &bus->datawork); |
3791 | brcmf_sdbrcm_adddpctsk(bus); | ||
3792 | complete(&bus->dpc_wait); | ||
3793 | } | ||
3794 | } | 3531 | } |
3795 | 3532 | ||
3796 | static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | 3533 | static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) |
@@ -3798,13 +3535,10 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3798 | #ifdef DEBUG | 3535 | #ifdef DEBUG |
3799 | struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); | 3536 | struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); |
3800 | #endif /* DEBUG */ | 3537 | #endif /* DEBUG */ |
3538 | unsigned long flags; | ||
3801 | 3539 | ||
3802 | brcmf_dbg(TIMER, "Enter\n"); | 3540 | brcmf_dbg(TIMER, "Enter\n"); |
3803 | 3541 | ||
3804 | /* Ignore the timer if simulating bus down */ | ||
3805 | if (bus->sleeping) | ||
3806 | return false; | ||
3807 | |||
3808 | down(&bus->sdsem); | 3542 | down(&bus->sdsem); |
3809 | 3543 | ||
3810 | /* Poll period: check device if appropriate. */ | 3544 | /* Poll period: check device if appropriate. */ |
@@ -3818,27 +3552,30 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3818 | if (!bus->intr || | 3552 | if (!bus->intr || |
3819 | (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { | 3553 | (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { |
3820 | 3554 | ||
3821 | if (!bus->dpc_sched) { | 3555 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); |
3556 | if (list_empty(&bus->dpc_tsklst)) { | ||
3822 | u8 devpend; | 3557 | u8 devpend; |
3558 | spin_unlock_irqrestore(&bus->dpc_tl_lock, | ||
3559 | flags); | ||
3823 | devpend = brcmf_sdio_regrb(bus->sdiodev, | 3560 | devpend = brcmf_sdio_regrb(bus->sdiodev, |
3824 | SDIO_CCCR_INTx, | 3561 | SDIO_CCCR_INTx, |
3825 | NULL); | 3562 | NULL); |
3826 | intstatus = | 3563 | intstatus = |
3827 | devpend & (INTR_STATUS_FUNC1 | | 3564 | devpend & (INTR_STATUS_FUNC1 | |
3828 | INTR_STATUS_FUNC2); | 3565 | INTR_STATUS_FUNC2); |
3566 | } else { | ||
3567 | spin_unlock_irqrestore(&bus->dpc_tl_lock, | ||
3568 | flags); | ||
3829 | } | 3569 | } |
3830 | 3570 | ||
3831 | /* If there is something, make like the ISR and | 3571 | /* If there is something, make like the ISR and |
3832 | schedule the DPC */ | 3572 | schedule the DPC */ |
3833 | if (intstatus) { | 3573 | if (intstatus) { |
3834 | bus->sdcnt.pollcnt++; | 3574 | bus->sdcnt.pollcnt++; |
3835 | bus->ipend = true; | 3575 | atomic_set(&bus->ipend, 1); |
3836 | 3576 | ||
3837 | bus->dpc_sched = true; | 3577 | brcmf_sdbrcm_adddpctsk(bus); |
3838 | if (bus->dpc_tsk) { | 3578 | queue_work(bus->brcmf_wq, &bus->datawork); |
3839 | brcmf_sdbrcm_adddpctsk(bus); | ||
3840 | complete(&bus->dpc_wait); | ||
3841 | } | ||
3842 | } | 3579 | } |
3843 | } | 3580 | } |
3844 | 3581 | ||
@@ -3876,7 +3613,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3876 | 3613 | ||
3877 | up(&bus->sdsem); | 3614 | up(&bus->sdsem); |
3878 | 3615 | ||
3879 | return bus->ipend; | 3616 | return (atomic_read(&bus->ipend) > 0); |
3880 | } | 3617 | } |
3881 | 3618 | ||
3882 | static bool brcmf_sdbrcm_chipmatch(u16 chipid) | 3619 | static bool brcmf_sdbrcm_chipmatch(u16 chipid) |
@@ -3892,6 +3629,26 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid) | |||
3892 | return false; | 3629 | return false; |
3893 | } | 3630 | } |
3894 | 3631 | ||
3632 | static void brcmf_sdio_dataworker(struct work_struct *work) | ||
3633 | { | ||
3634 | struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, | ||
3635 | datawork); | ||
3636 | struct list_head *cur_hd, *tmp_hd; | ||
3637 | unsigned long flags; | ||
3638 | |||
3639 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
3640 | list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) { | ||
3641 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
3642 | |||
3643 | brcmf_sdbrcm_dpc(bus); | ||
3644 | |||
3645 | spin_lock_irqsave(&bus->dpc_tl_lock, flags); | ||
3646 | list_del(cur_hd); | ||
3647 | kfree(cur_hd); | ||
3648 | } | ||
3649 | spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); | ||
3650 | } | ||
3651 | |||
3895 | static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) | 3652 | static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) |
3896 | { | 3653 | { |
3897 | brcmf_dbg(TRACE, "Enter\n"); | 3654 | brcmf_dbg(TRACE, "Enter\n"); |
@@ -4024,7 +3781,6 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) | |||
4024 | SDIO_FUNC_ENABLE_1, NULL); | 3781 | SDIO_FUNC_ENABLE_1, NULL); |
4025 | 3782 | ||
4026 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 3783 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
4027 | bus->sleeping = false; | ||
4028 | bus->rxflow = false; | 3784 | bus->rxflow = false; |
4029 | 3785 | ||
4030 | /* Done with backplane-dependent accesses, can drop clock... */ | 3786 | /* Done with backplane-dependent accesses, can drop clock... */ |
@@ -4105,6 +3861,9 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) | |||
4105 | /* De-register interrupt handler */ | 3861 | /* De-register interrupt handler */ |
4106 | brcmf_sdio_intr_unregister(bus->sdiodev); | 3862 | brcmf_sdio_intr_unregister(bus->sdiodev); |
4107 | 3863 | ||
3864 | cancel_work_sync(&bus->datawork); | ||
3865 | destroy_workqueue(bus->brcmf_wq); | ||
3866 | |||
4108 | if (bus->sdiodev->bus_if->drvr) { | 3867 | if (bus->sdiodev->bus_if->drvr) { |
4109 | brcmf_detach(bus->sdiodev->dev); | 3868 | brcmf_detach(bus->sdiodev->dev); |
4110 | brcmf_sdbrcm_release_dongle(bus); | 3869 | brcmf_sdbrcm_release_dongle(bus); |
@@ -4144,8 +3903,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
4144 | bus->rxbound = BRCMF_RXBOUND; | 3903 | bus->rxbound = BRCMF_RXBOUND; |
4145 | bus->txminmax = BRCMF_TXMINMAX; | 3904 | bus->txminmax = BRCMF_TXMINMAX; |
4146 | bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; | 3905 | bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; |
4147 | bus->usebufpool = false; /* Use bufpool if allocated, | ||
4148 | else use locally malloced rxbuf */ | ||
4149 | 3906 | ||
4150 | /* attempt to attach to the dongle */ | 3907 | /* attempt to attach to the dongle */ |
4151 | if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) { | 3908 | if (!(brcmf_sdbrcm_probe_attach(bus, regsva))) { |
@@ -4157,6 +3914,13 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
4157 | init_waitqueue_head(&bus->ctrl_wait); | 3914 | init_waitqueue_head(&bus->ctrl_wait); |
4158 | init_waitqueue_head(&bus->dcmd_resp_wait); | 3915 | init_waitqueue_head(&bus->dcmd_resp_wait); |
4159 | 3916 | ||
3917 | bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq"); | ||
3918 | if (bus->brcmf_wq == NULL) { | ||
3919 | brcmf_dbg(ERROR, "insufficient memory to create txworkqueue\n"); | ||
3920 | goto fail; | ||
3921 | } | ||
3922 | INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); | ||
3923 | |||
4160 | /* Set up the watchdog timer */ | 3924 | /* Set up the watchdog timer */ |
4161 | init_timer(&bus->timer); | 3925 | init_timer(&bus->timer); |
4162 | bus->timer.data = (unsigned long)bus; | 3926 | bus->timer.data = (unsigned long)bus; |
@@ -4174,15 +3938,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
4174 | bus->watchdog_tsk = NULL; | 3938 | bus->watchdog_tsk = NULL; |
4175 | } | 3939 | } |
4176 | /* Initialize DPC thread */ | 3940 | /* Initialize DPC thread */ |
4177 | init_completion(&bus->dpc_wait); | ||
4178 | INIT_LIST_HEAD(&bus->dpc_tsklst); | 3941 | INIT_LIST_HEAD(&bus->dpc_tsklst); |
4179 | spin_lock_init(&bus->dpc_tl_lock); | 3942 | spin_lock_init(&bus->dpc_tl_lock); |
4180 | bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread, | ||
4181 | bus, "brcmf_dpc"); | ||
4182 | if (IS_ERR(bus->dpc_tsk)) { | ||
4183 | pr_warn("brcmf_dpc thread failed to start\n"); | ||
4184 | bus->dpc_tsk = NULL; | ||
4185 | } | ||
4186 | 3943 | ||
4187 | /* Assign bus interface call back */ | 3944 | /* Assign bus interface call back */ |
4188 | bus->sdiodev->bus_if->brcmf_bus_stop = brcmf_sdbrcm_bus_stop; | 3945 | bus->sdiodev->bus_if->brcmf_bus_stop = brcmf_sdbrcm_bus_stop; |