aboutsummaryrefslogtreecommitdiffstats
BranchCommit messageAuthorAge
archive/unc-master-3.0P-FP: fix BUG_ON releated to priority inheritanceBjoern Brandenburg13 years
archived-2013.1uncachedev: mmap memory that is not cached by CPUsGlenn Elliott12 years
archived-private-masterMerge branch 'wip-2.6.34' into old-private-masterAndrea Bastoni16 years
archived-semi-partMerge branch 'wip-semi-part' of ssh://cvs/cvs/proj/litmus/repo/litmus2010 int...Andrea Bastoni15 years
demoFurther refinementsJonathan Herman14 years
ecrts-pgm-finalMerge branch 'wip-ecrts14-pgm' of ssh://rtsrv.cs.unc.edu/home/litmus/litmus-r...Glenn Elliott12 years
ecrts14-pgm-finalMerge branch 'wip-ecrts14-pgm' of ssh://rtsrv.cs.unc.edu/home/litmus/litmus-r...Glenn Elliott12 years
gpusync-rtss12Final GPUSync implementation.Glenn Elliott13 years
gpusync/stagingRename IKGLP R2DGLP.Glenn Elliott12 years
linux-tipMerge branch 'slab/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/p...Linus Torvalds15 years
litmus2008-patch-seriesadd i386 feather-trace implementationBjoern B. Brandenburg16 years
masterPSN-EDF: use inferred_sporadic_job_release_atBjoern Brandenburg9 years
pgmmake it compileGlenn Elliott13 years
prop/litmus-signalsInfrastructure for Litmus signals.Glenn Elliott13 years
prop/robust-tie-breakFixed bug in edf_higher_prio().Glenn Elliott13 years
stagingFix tracepoint compilation errorFelipe Cerqueira13 years
test9/23/2016Namhoon Kim9 years
tracing-develTest kernel tracing events capabilitiesAndrea Bastoni16 years
v2.6.34-with-arm-patchessmsc911x: Add spinlocks around registers accessCatalin Marinas16 years
v2015.1Add ARM syscall def for get_current_budgetBjoern Brandenburg10 years
wip-2011.2-bbbLitmus core: simplify np-section protocolBjoern B. Brandenburg14 years
wip-2011.2-bbb-traceRefactor sched_trace_log_message() -> debug_trace_log_message()Andrea Bastoni14 years
wip-2012.3-gpuSOBLIV draining support for C-EDF.Glenn Elliott13 years
wip-2012.3-gpu-preportpick up last C-RM fileGlenn Elliott12 years
wip-2012.3-gpu-rtss13Fix critical bug in GPU tracker.Glenn Elliott12 years
wip-2012.3-gpu-sobliv-budget-w-ksharkProper sobliv draining and many bug fixes.Glenn Elliott13 years
wip-aedzl-finalMake it easier to compile AEDZL interfaces in liblitmus.Glenn Elliott15 years
wip-aedzl-revisedAdd sched_trace data for Apative EDZLGlenn Elliott15 years
wip-arbit-deadlineFix compilation bug.Glenn Elliott13 years
wip-aux-tasksDescription of refined aux task inheritance.Glenn Elliott13 years
wip-bbbGSN-EDF & Core: improve debug TRACE'ing for NP sectionsBjoern B. Brandenburg14 years
wip-bbb-prio-donuse correct timestampBjoern B. Brandenburg14 years
wip-better-breakImplement hash-based EDF tie-breaking.Glenn Elliott13 years
wip-binary-heapMake C-EDF work with simplified binheap_deleteGlenn Elliott14 years
wip-budgetAdded support for choices in budget policy enforcement.Glenn Elliott16 years
wip-colorSummarize schedulability with final recordJonathan Herman14 years
wip-color-jlhsched_color: Fixed two bugs causing crashing on experiment restart and a rare...Jonathan Herman14 years
wip-d10-hz1000Enable HZ=1000 on District 10Bjoern B. Brandenburg15 years
wip-default-clusteringFeature: Make default C-EDF clustering compile-time configurable.Glenn Elliott15 years
wip-dissipation-jericksoUpdate from 2.6.36 to 2.6.36.4Jeremy Erickson12 years
wip-dissipation2-jericksoUpdate 2.6.36 to 2.6.36.4Jeremy Erickson12 years
wip-ecrts14-pgmMerge branch 'wip-ecrts14-pgm' of ssh://rtsrv.cs.unc.edu/home/litmus/litmus-r...Glenn Elliott12 years
wip-edf-hsblast tested versionJonathan Herman14 years
wip-edf-osLookup table EDF-osJeremy Erickson13 years
wip-edf-tie-breakMerge branch 'wip-edf-tie-break' of ssh://rtsrv.cs.unc.edu/home/litmus/litmus...Glenn Elliott13 years
wip-edzl-critiqueUse hr_timer's active checks instead of having own flag.Glenn Elliott15 years
wip-edzl-finalImplementation of the EDZL scheduler.Glenn Elliott15 years
wip-edzl-revisedClean up comments.Glenn Elliott15 years
wip-eventsAdded support for tracing arbitrary actions.Jonathan Herman15 years
wip-extra-debugDBG: add additional tracingBjoern B. Brandenburg15 years
wip-fix-switch-jericksoAttempt to fix race condition with plugin switchingJeremy Erickson15 years
wip-fix3sched: show length of runqueue clock deactivation in /proc/sched_debugBjoern B. Brandenburg15 years
wip-fmlp-dequeueImprove FMLP queue management.Glenn Elliott15 years
wip-ft-irq-flagFeather-Trace: keep track of interrupt-related interference.Bjoern B. Brandenburg14 years
wip-gpu-cleanupEnable sched_trace log injection from userspaceGlenn Elliott13 years
wip-gpu-interruptsRemove option for threading of all softirqs.Glenn Elliott14 years
wip-gpu-rtas12Generalized GPU cost predictors + EWMA. (untested)Glenn Elliott13 years
wip-gpu-rtss12Final GPUSync implementation.Glenn Elliott14 years
wip-gpu-rtss12-srpexperimental changes to support GPUs under SRPGlenn Elliott14 years
wip-gpusync-mergeCleanup priority tracking for budget enforcement.Glenn Elliott12 years
wip-ikglpMove RSM and IKGLP imp. to own .c filesGlenn Elliott14 years
wip-k-fmlpMerge branch 'mpi-master' into wip-k-fmlpGlenn Elliott14 years
wip-kernel-coloringAdded recolor syscallNamhoon Kim8 years
wip-kernthreadsKludge work-queue processing into klitirqd.Glenn Elliott15 years
wip-klmirqd-to-auxAllow klmirqd threads to be given names.Glenn Elliott13 years
wip-ksharkMerge branch 'mpi-staging' into wip-ksharkJonathan Herman13 years
wip-litmus-3.2Merge commit 'v3.2' into litmus-stagingAndrea Bastoni13 years
wip-litmus2011.2Cleanup: Coding conformance for affinity stuff.Glenn Elliott15 years
wip-litmus3.0-2011.2Feather-Trace: keep track of interrupt-related interference.Bjoern B. Brandenburg14 years
wip-master-2.6.33-rtAvoid deadlock when switching task policy to BACKGROUND (ugly)Andrea Bastoni16 years
wip-mcRemoved ARM-specific hacks which disabled less common mixed-criticality featu...Jonathan Herman13 years
wip-mc-bipasaMC-EDF addedbipasa chattopadhyay14 years
wip-mc-jericksoSplit C/D queuesJeremy Erickson15 years
wip-mc2-cache-slackManually patched mc^2 related codeMing Yang10 years
wip-mcrit-maccosmeticMac Mollison15 years
wip-merge-3.0Prevent Linux to send IPI and queue tasks on remote CPUs.Andrea Bastoni14 years
wip-merge-v3.0Prevent Linux to send IPI and queue tasks on remote CPUs.Andrea Bastoni14 years
wip-migration-affinityNULL affinity dereference in C-EDF.Glenn Elliott15 years
wip-mmap-uncacheshare branch with othersGlenn Elliott13 years
wip-modechangeRTSS 2017 submissionNamhoon Kim9 years
wip-nested-lockingAppears to be working.Bryan Ward13 years
wip-omlp-gedfFirst implementation of G-OMLP.Glenn Elliott15 years
wip-paiSome cleanup of PAIGlenn Elliott14 years
wip-percore-lib9/21/2016Namhoon Kim9 years
wip-performanceCONFIG_DONT_PREEMPT_ON_TIE: Don't preeempt a scheduled task on priority tie.Glenn Elliott15 years
wip-pgmAdd PGM support to C-FLGlenn Elliott12 years
wip-pgm-splitFirst draft of C-FL-splitNamhoon Kim12 years
wip-pm-ovdAdd preemption-and-migration overhead tracing supportAndrea Bastoni16 years
wip-prio-inhP-EDF updated to use the generic pi framework.Glenn Elliott15 years
wip-prioq-dglBUG FIX: Support DGLs with PRIOQ_MUTEXGlenn Elliott13 years
wip-refactored-gedfGeneralizd architecture for GEDF-style scheduelrs to reduce code redundancy.Glenn Elliott15 years
wip-release-master-fixbugfix: release master CPU must signal task was pickedBjoern B. Brandenburg15 years
wip-robust-tie-breakEDF priority tie-breaks.Glenn Elliott13 years
wip-rt-ksharkMove task time accounting into the complete_job method.Jonathan Herman13 years
wip-rtas12-pgmScheduling of PGM jobs.Glenn Elliott14 years
wip-semi-partFix compile error with newer GCCJeremy Erickson13 years
wip-semi-part-edfos-jericksoUse initial CPU set by clientJeremy Erickson13 years
wip-shared-libTODO: Fix condition checks in replicate_page_move_mapping()Namhoon Kim9 years
wip-shared-lib2RTAS 2017 Submission ver.Namhoon Kim9 years
wip-shared-memInitial commit for shared libraryNamhoon Kim9 years
wip-splitting-jericksoFix release behaviorJeremy Erickson13 years
wip-splitting-omlp-jericksoBjoern's Dissertation Code with Priority DonationJeremy Erickson13 years
wip-stage-binheapAn efficient binary heap implementation.Glenn Elliott14 years
wip-sun-portDynamic memory allocation and clean exit for FeatherTraceChristopher Kenna15 years
wip-timer-tracebugfix: C-EDF, clear scheduled field of the correct CPU upon task_exitAndrea Bastoni15 years
wip-tracepointsAdd kernel-style events for sched_trace_XXX() functionsAndrea Bastoni14 years
 
TagDownloadAuthorAge
2015.1commit 8e51b37822...Bjoern Brandenburg10 years
2013.1commit bcaacec1ca...Glenn Elliott12 years
2012.3commit c158b5fbe4...Jonathan Herman13 years
2012.2commit b53c479a0f...Glenn Elliott13 years
2012.1commit 83b11ea1c6...Bjoern B. Brandenburg14 years
rtas12-mc-beta-expcommit 8e236ee20f...Christopher Kenna14 years
2011.1commit d11808b5c6...Christopher Kenna15 years
v2.6.37-rc4commit e8a7e48bb2...Linus Torvalds15 years
v2.6.37-rc3commit 3561d43fd2...Linus Torvalds15 years
v2.6.37-rc2commit e53beacd23...Linus Torvalds15 years
v2.6.37-rc1commit c8ddb2713c...Linus Torvalds15 years
v2.6.36commit f6f94e2ab1...Linus Torvalds15 years
2010.2commit 5c5456402d...Bjoern B. Brandenburg15 years
v2.6.36-rc8commit cd07202cc8...Linus Torvalds15 years
v2.6.36-rc7commit cb655d0f3d...Linus Torvalds15 years
v2.6.36-rc6commit 899611ee7d...Linus Torvalds15 years
v2.6.36-rc5commit b30a3f6257...Linus Torvalds15 years
v2.6.36-rc4commit 49553c2ef8...Linus Torvalds15 years
v2.6.36-rc3commit 2bfc96a127...Linus Torvalds15 years
v2.6.36-rc2commit 76be97c1fc...Linus Torvalds15 years
v2.6.36-rc1commit da5cabf80e...Linus Torvalds15 years
v2.6.35commit 9fe6206f40...Linus Torvalds15 years
v2.6.35-rc6commit b37fa16e78...Linus Torvalds15 years
v2.6.35-rc5commit 1c5474a65b...Linus Torvalds16 years
v2.6.35-rc4commit 815c4163b6...Linus Torvalds16 years
v2.6.35-rc3commit 7e27d6e778...Linus Torvalds16 years
v2.6.35-rc2commit e44a21b726...Linus Torvalds16 years
v2.6.35-rc1commit 67a3e12b05...Linus Torvalds16 years
2010.1commit 7c1ff4c544...Andrea Bastoni16 years
v2.6.34commit e40152ee1e...Linus Torvalds16 years
v2.6.33.4commit 4640b4e7d9...Greg Kroah-Hartman16 years
v2.6.34-rc7commit b57f95a382...Linus Torvalds16 years
v2.6.34-rc6commit 66f41d4c5c...Linus Torvalds16 years
v2.6.33.3commit 3e7ad8ed97...Greg Kroah-Hartman16 years
v2.6.34-rc5commit 01bf0b6457...Linus Torvalds16 years
v2.6.34-rc4commit 0d0fb0f9c5...Linus Torvalds16 years
v2.6.33.2commit 19f00f070c...Greg Kroah-Hartman16 years
v2.6.34-rc3commit 2eaa9cfdf3...Linus Torvalds16 years
v2.6.34-rc2commit 220bf991b0...Linus Torvalds16 years
v2.6.33.1commit dbdafe5ccf...Greg Kroah-Hartman16 years
v2.6.34-rc1commit 57d54889cd...Linus Torvalds16 years
v2.6.33commit 60b341b778...Linus Torvalds16 years
v2.6.33-rc8commit 724e6d3fe8...Linus Torvalds16 years
v2.6.33-rc7commit 29275254ca...Linus Torvalds16 years
v2.6.33-rc6commit abe94c756c...Linus Torvalds16 years
v2.6.33-rc5commit 92dcffb916...Linus Torvalds16 years
v2.6.33-rc4commit 7284ce6c9f...Linus Torvalds16 years
v2.6.33-rc3commit 74d2e4f8d7...Linus Torvalds16 years
v2.6.33-rc2commit 6b7b284958...Linus Torvalds16 years
v2.6.33-rc1commit 55639353a0...Linus Torvalds16 years
v2.6.32commit 22763c5cf3...Linus Torvalds16 years
v2.6.32-rc8commit 648f4e3e50...Linus Torvalds16 years
v2.6.32-rc7commit 156171c71a...Linus Torvalds16 years
v2.6.32-rc6commit b419148e56...Linus Torvalds16 years
v2.6.32-rc5commit 012abeea66...Linus Torvalds16 years
v2.6.32-rc4commit 161291396e...Linus Torvalds16 years
v2.6.32-rc3commit 374576a8b6...Linus Torvalds16 years
v2.6.32-rc1commit 17d857be64...Linus Torvalds16 years
v2.6.32-rc2commit 17d857be64...Linus Torvalds16 years
v2.6.31commit 74fca6a428...Linus Torvalds16 years
v2.6.31-rc9commit e07cccf404...Linus Torvalds16 years
v2.6.31-rc8commit 326ba5010a...Linus Torvalds16 years
v2.6.31-rc7commit 422bef879e...Linus Torvalds16 years
v2.6.31-rc6commit 64f1607ffb...Linus Torvalds16 years
v2.6.31-rc5commit ed680c4ad4...Linus Torvalds16 years
v2.6.31-rc4commit 4be3bd7849...Linus Torvalds16 years
v2.6.31-rc3commit 6847e154e3...Linus Torvalds17 years
v2.6.31-rc2commit 8e4a718ff3...Linus Torvalds17 years
v2.6.31-rc1commit 28d0325ce6...Linus Torvalds17 years
v2.6.30commit 07a2039b8e...Linus Torvalds17 years
v2.6.30-rc8commit 9fa7eb283c...Linus Torvalds17 years
v2.6.30-rc7commit 59a3759d0f...Linus Torvalds17 years
v2.6.30-rc6commit 1406de8e11...Linus Torvalds17 years
v2.6.30-rc5commit 091bf7624d...Linus Torvalds17 years
v2.6.30-rc4commit 091438dd56...Linus Torvalds17 years
v2.6.30-rc3commit 0910697403...Linus Torvalds17 years
v2.6.30-rc2commit 0882e8dd3a...Linus Torvalds17 years
v2.6.30-rc1commit 577c9c456f...Linus Torvalds17 years
v2.6.29commit 8e0ee43bc2...Linus Torvalds17 years
v2.6.29-rc8commit 041b62374c...Linus Torvalds17 years
v2.6.29-rc7commit fec6c6fec3...Linus Torvalds17 years
v2.6.29-rc6commit 20f4d6c3a2...Linus Torvalds17 years
v2.6.29-rc5commit d2f8d7ee1a...Linus Torvalds17 years
v2.6.29-rc4commit 8e4921515c...Linus Torvalds17 years
v2.6.29-rc3commit 18e352e4a7...Linus Torvalds17 years
v2.6.29-rc2commit 1de9e8e70f...Linus Torvalds17 years
v2.6.29-rc1commit c59765042f...Linus Torvalds17 years
v2.6.28commit 4a6908a3a0...Linus Torvalds17 years
v2.6.28-rc9commit 929096fe9f...Linus Torvalds17 years
v2.6.28-rc8commit 8b1fae4e42...Linus Torvalds17 years
v2.6.28-rc7commit 061e41fdb5...Linus Torvalds17 years
v2.6.28-rc6commit 13d428afc0...Linus Torvalds17 years
v2.6.28-rc5commit 9bf1a2445f...Linus Torvalds17 years
v2.6.28-rc4commit f7160c7573...Linus Torvalds17 years
v2.6.28-rc3commit 45beca08dd...Linus Torvalds17 years
v2.6.28-rc2commit 0173a3265b...Linus Torvalds17 years
v2.6.28-rc1commit 57f8f7b60d...Linus Torvalds17 years
v2.6.27commit 3fa8749e58...Linus Torvalds17 years
v2.6.27-rc9commit 4330ed8ed4...Linus Torvalds17 years
v2.6.27-rc8commit 94aca1dac6...Linus Torvalds17 years
v2.6.27-rc7commit 72d31053f6...Linus Torvalds17 years
v2.6.27-rc6commit adee14b2e1...Linus Torvalds17 years
v2.6.27-rc5commit 24342c34a0...Linus Torvalds17 years
v2.6.27-rc4commit 6a55617ed5...Linus Torvalds17 years
v2.6.27-rc3commit 30a2f3c60a...Linus Torvalds17 years
v2.6.27-rc2commit 0967d61ea0...Linus Torvalds17 years
v2.6.27-rc1commit 6e86841d05...Linus Torvalds17 years
v2.6.26commit bce7f793da...Linus Torvalds18 years
v2.6.26-rc9commit b7279469d6...Linus Torvalds18 years
v2.6.26-rc8commit 543cf4cb3f...Linus Torvalds18 years
v2.6.26-rc7commit d70ac829b7...Linus Torvalds18 years
v2.6.26-rc6commit 5dd34572ad...Linus Torvalds18 years
v2.6.26-rc5commit 53c8ba9540...Linus Torvalds18 years
v2.6.26-rc4commit e490517a03...Linus Torvalds18 years
v2.6.26-rc3commit b8291ad07a...Linus Torvalds18 years
v2.6.26-rc2commit 492c2e476e...Linus Torvalds18 years
v2.6.26-rc1commit 2ddcca36c8...Linus Torvalds18 years
v2.6.25commit 4b119e21d0...Linus Torvalds18 years
v2.6.25-rc9commit 120dd64cac...Linus Torvalds18 years
v2.6.25-rc8commit 0e81a8ae37...Linus Torvalds18 years
v2.6.25-rc7commit 05dda977f2...Linus Torvalds18 years
v2.6.25-rc6commit a978b30af3...Linus Torvalds18 years
v2.6.25-rc5commit cdeeeae056...Linus Torvalds18 years
v2.6.25-rc4commit 29e8c3c304...Linus Torvalds18 years
v2.6.25-rc3commit bfa274e243...Linus Torvalds18 years
v2.6.25-rc2commit 101142c37b...Linus Torvalds18 years
v2.6.25-rc1commit 19af35546d...Linus Torvalds18 years
v2.6.24commit 49914084e7...Linus Torvalds18 years
v2.6.24-rc8commit cbd9c88369...Linus Torvalds18 years
v2.6.24-rc7commit 3ce5445046...Linus Torvalds18 years
v2.6.24-rc6commit ea67db4cdb...Linus Torvalds18 years
v2.6.24-rc5commit 82d29bf6dc...Linus Torvalds18 years
v2.6.24-rc4commit 09b56adc98...Linus Torvalds18 years
v2.6.24-rc3commit d9f8bcbf67...Linus Torvalds18 years
v2.6.24-rc2commit dbeeb816e8...Linus Torvalds18 years
v2.6.24-rc1commit c9927c2bf4...Linus Torvalds18 years
v2.6.23commit bbf25010f1...Linus Torvalds18 years
v2.6.23-rc9commit 3146b39c18...Linus Torvalds18 years
v2.6.23-rc8commit 4942de4a0e...Linus Torvalds18 years
v2.6.23-rc7commit 81cfe79b9c...Linus Torvalds18 years
v2.6.23-rc6commit 0d4cbb5e7f...Linus Torvalds18 years
v2.6.23-rc5commit 40ffbfad6b...Linus Torvalds18 years
v2.6.23-rc4commit b07d68b5ca...Linus Torvalds18 years
v2.6.23-rc3commit 39d3520c92...Linus Torvalds18 years
v2.6.23-rc2commit d4ac2477fa...Linus Torvalds18 years
v2.6.23-rc1commit f695baf2df...Linus Torvalds18 years
v2.6.22commit 7dcca30a32...Linus Torvalds19 years
v2.6.22-rc7commit a38d6181ff...Linus Torvalds19 years
v2.6.22-rc6commit 189548642c...Linus Torvalds19 years
v2.6.22-rc5commit 188e1f81ba...Linus Torvalds19 years
v2.6.22-rc4commit 5ecd3100e6...Linus Torvalds19 years
v2.6.22-rc3commit c420bc9f09...Linus Torvalds19 years
v2.6.22-rc2commit 55b637c6a0...Linus Torvalds19 years
v2.6.22-rc1commit 39403865d2...Linus Torvalds19 years
v2.6.21commit de46c33745...Linus Torvalds19 years
v2.6.21-rc7commit 94a05509a9...Linus Torvalds19 years
v2.6.21-rc6commit a21bd69e15...Linus Torvalds19 years
v2.6.21-rc5commit e0f2e3a06b...Linus Torvalds19 years
v2.6.21-rc4commit db98e0b434...Linus Torvalds19 years
v2.6.21-rc3commit 08e15e81a4...Linus Torvalds19 years
v2.6.21-rc2commit 606135a308...Linus Torvalds19 years
v2.6.21-rc1commit c8f71b01a5...Linus Torvalds19 years
v2.6.20commit 62d0cfcb27...Linus Torvalds19 years
v2.6.20-rc7commit f56df2f4db...Linus Torvalds19 years
v2.6.20-rc6commit 99abfeafb5...Linus Torvalds19 years
v2.6.20-rc5commit a8b3485287...Linus Torvalds19 years
v2.6.20-rc4commit bf81b46482...Linus Torvalds19 years
v2.6.20-rc3commit 669df1b478...Linus Torvalds19 years
v2.6.20-rc2commit 3bf8ba38f3...Linus Torvalds19 years
v2.6.20-rc1commit cc016448b0...Linus Torvalds19 years
v2.6.19commit 0215ffb08c...Linus Torvalds19 years
v2.6.19-rc6commit 44597f65f6...Linus Torvalds19 years
v2.6.19-rc5commit 80c2188127...Linus Torvalds19 years
v2.6.19-rc4commit ae99a78af3...Linus Torvalds19 years
v2.6.19-rc3commit 7059abedd2...Linus Torvalds19 years
v2.6.19-rc2commit b4bd8c6643...Linus Torvalds19 years
v2.6.19-rc1commit d223a60106...Linus Torvalds19 years
v2.6.18commit e478bec0ba...Linus Torvalds19 years
v2.6.18-rc7commit 95064a75eb...Linus Torvalds19 years
v2.6.18-rc6commit c336923b66...Linus Torvalds19 years
v2.6.18-rc5commit 60d4684068...Linus Torvalds19 years
v2.6.18-rc4commit 9f737633e6...Linus Torvalds19 years
v2.6.18-rc3commit b6ff50833a...Linus Torvalds19 years
v2.6.18-rc2commit 82d6897fef...Linus Torvalds20 years
v2.6.18-rc1commit 120bda20c6...Linus Torvalds20 years
v2.6.17commit 427abfa28a...Linus Torvalds20 years
v2.6.17-rc6commit 1def630a6a...Linus Torvalds20 years
v2.6.17-rc5commit a8bd60705a...Linus Torvalds20 years
v2.6.17-rc4commit d8c3291c73...Linus Torvalds20 years
v2.6.17-rc3commit 2be4d50295...Linus Torvalds20 years
v2.6.17-rc2commit 8bbde0e6d5...Linus Torvalds20 years
v2.6.17-rc1commit 6246b6128b...Linus Torvalds20 years
v2.6.16commit 7705a8792b...Linus Torvalds20 years
v2.6.16-rc6commit 535744878e...Linus Torvalds20 years
v2.6.16-rc5commit b9a33cebac...Linus Torvalds20 years
v2.6.16-rc4commit bd71c2b174...Linus Torvalds20 years
v2.6.16-rc3commit e9bb4c9929...Linus Torvalds20 years
v2.6.16-rc2commit 826eeb53a6...Linus Torvalds20 years
v2.6.16-rc1commit 2664b25051...Linus Torvalds20 years
v2.6.15commit 88026842b0...Linus Torvalds20 years
v2.6.15-rc7commit f89f5948fc...Linus Torvalds20 years
v2.6.15-rc6commit df7addbb45...Linus Torvalds20 years
v2.6.15-rc5commit 436b0f76f2...Linus Torvalds20 years
v2.6.15-rc4commit 5666c0947e...Linus Torvalds20 years
v2.6.15-rc3commit 624f54be20...Linus Torvalds20 years
v2.6.15-rc2commit 3bedff1d73...Linus Torvalds20 years
v2.6.15-rc1commit cd52d1ee9a...Linus Torvalds20 years
v2.6.14commit 741b2252a5...Linus Torvalds20 years
v2.6.14-rc5commit 93918e9afc...Linus Torvalds20 years
v2.6.14-rc4commit 907a426179...Linus Torvalds20 years
v2.6.14-rc3commit 1c9426e8a5...Linus Torvalds20 years
v2.6.14-rc2commit 676d55ae30...Linus Torvalds20 years
v2.6.14-rc1commit 2f4ba45a75...Linus Torvalds20 years
v2.6.13commit 02b3e4e2d7...Linus Torvalds20 years
v2.6.13-rc7commit 0572e3da3f...Linus Torvalds20 years
v2.6.13-rc6commit 6fc32179de...Linus Torvalds20 years
v2.6.13-rc5commit 9a351e30d7...Linus Torvalds20 years
v2.6.13-rc4commit 6395352334...Linus Torvalds20 years
v2.6.11tree c39ae07f39...
v2.6.11-treetree c39ae07f39...
v2.6.12commit 9ee1c939d1...
v2.6.12-rc2commit 1da177e4c3...
v2.6.12-rc3commit a2755a80f4...
v2.6.12-rc4commit 88d7bd8cb9...
v2.6.12-rc5commit 2a24ab628a...
v2.6.12-rc6commit 7cef5677ef...
v2.6.13-rc1commit 4c91aedb75...
v2.6.13-rc2commit a18bcb7450...
v2.6.13-rc3commit c32511e271...
er_of(work, struct gelic_eurus_cmd, work); BUG_ON(cmd_info[cmd->cmd].pre_arg && cmd_info[cmd->cmd].post_arg); wl = cmd->wl; card = port_to_card(wl_port(wl)); if (cmd_info[cmd->cmd].pre_arg) { arg1 = (cmd->buffer) ? ps3_mm_phys_to_lpar(__pa(cmd->buffer)) : 0; arg2 = cmd->buf_size; } else { arg1 = 0; arg2 = 0; } init_completion(&wl->cmd_done_intr); pr_debug("%s: cmd='%s' start\n", __func__, cmdstr(cmd->cmd)); cmd->status = lv1_net_control(bus_id(card), dev_id(card), GELIC_LV1_POST_WLAN_CMD, cmd->cmd, arg1, arg2, &cmd->tag, &cmd->size); if (cmd->status) { complete(&cmd->done); pr_info("%s: cmd issue failed\n", __func__); return; } wait_for_completion(&wl->cmd_done_intr); if (cmd_info[cmd->cmd].post_arg) { arg1 = ps3_mm_phys_to_lpar(__pa(cmd->buffer)); arg2 = cmd->buf_size; } else { arg1 = 0; arg2 = 0; } cmd->status = lv1_net_control(bus_id(card), dev_id(card), GELIC_LV1_GET_WLAN_CMD_RESULT, cmd->tag, arg1, arg2, &cmd->cmd_status, &cmd->size); #ifdef DEBUG if (cmd->status || cmd->cmd_status) { pr_debug("%s: cmd done tag=%#lx arg1=%#lx, arg2=%#lx\n", __func__, cmd->tag, arg1, arg2); pr_debug("%s: cmd done status=%#x cmd_status=%#lx size=%#lx\n", __func__, cmd->status, cmd->cmd_status, cmd->size); } #endif complete(&cmd->done); pr_debug("%s: cmd='%s' done\n", __func__, cmdstr(cmd->cmd)); } static struct gelic_eurus_cmd *gelic_eurus_sync_cmd(struct gelic_wl_info *wl, unsigned int eurus_cmd, void *buffer, unsigned int buf_size) { struct gelic_eurus_cmd *cmd; /* allocate cmd */ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) return NULL; /* initialize members */ cmd->cmd = eurus_cmd; cmd->buffer = buffer; cmd->buf_size = buf_size; cmd->wl = wl; INIT_WORK(&cmd->work, gelic_eurus_sync_cmd_worker); init_completion(&cmd->done); queue_work(wl->eurus_cmd_queue, &cmd->work); /* wait for command completion */ wait_for_completion(&cmd->done); return cmd; } static u32 gelic_wl_get_link(struct net_device *netdev) { struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); u32 ret; pr_debug("%s: <-\n", __func__); mutex_lock(&wl->assoc_stat_lock); if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) ret = 1; else ret = 0; mutex_unlock(&wl->assoc_stat_lock); pr_debug("%s: ->\n", __func__); return ret; } static void gelic_wl_send_iwap_event(struct gelic_wl_info *wl, u8 *bssid) { union iwreq_data data; memset(&data, 0, sizeof(data)); if (bssid) memcpy(data.ap_addr.sa_data, bssid, ETH_ALEN); data.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(port_to_netdev(wl_port(wl)), SIOCGIWAP, &data, NULL); } /* * wireless extension handlers and helpers */ /* SIOGIWNAME */ static int gelic_wl_get_name(struct net_device *dev, struct iw_request_info *info, union iwreq_data *iwreq, char *extra) { strcpy(iwreq->name, "IEEE 802.11bg"); return 0; } static void gelic_wl_get_ch_info(struct gelic_wl_info *wl) { struct gelic_card *card = port_to_card(wl_port(wl)); u64 ch_info_raw, tmp; int status; if (!test_and_set_bit(GELIC_WL_STAT_CH_INFO, &wl->stat)) { status = lv1_net_control(bus_id(card), dev_id(card), GELIC_LV1_GET_CHANNEL, 0, 0, 0, &ch_info_raw, &tmp); /* some fw versions may return error */ if (status) { if (status != LV1_NO_ENTRY) pr_info("%s: available ch unknown\n", __func__); wl->ch_info = 0x07ff;/* 11 ch */ } else /* 16 bits of MSB has available channels */ wl->ch_info = ch_info_raw >> 48; } } /* SIOGIWRANGE */ static int gelic_wl_get_range(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *iwreq, char *extra) { struct iw_point *point = &iwreq->data; struct iw_range *range = (struct iw_range *)extra; struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); unsigned int i, chs; pr_debug("%s: <-\n", __func__); point->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); range->we_version_compiled = WIRELESS_EXT; range->we_version_source = 22; /* available channels and frequencies */ gelic_wl_get_ch_info(wl); for (i = 0, chs = 0; i < NUM_CHANNELS && chs < IW_MAX_FREQUENCIES; i++) if (wl->ch_info & (1 << i)) { range->freq[chs].i = i + 1; range->freq[chs].m = channel_freq[i]; range->freq[chs].e = 6; chs++; } range->num_frequency = chs; range->old_num_frequency = chs; range->num_channels = chs; range->old_num_channels = chs; /* bitrates */ for (i = 0; i < NUM_BITRATES; i++) range->bitrate[i] = bitrate_list[i]; range->num_bitrates = i; /* signal levels */ range->max_qual.qual = 100; /* relative value */ range->max_qual.level = 100; range->avg_qual.qual = 50; range->avg_qual.level = 50; range->sensitivity = 0; /* Event capability */ IW_EVENT_CAPA_SET_KERNEL(range->event_capa); IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); /* encryption capability */ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP | IW_ENC_CAPA_4WAY_HANDSHAKE; if (wpa2_capable()) range->enc_capa |= IW_ENC_CAPA_WPA2; range->encoding_size[0] = 5; /* 40bit WEP */ range->encoding_size[1] = 13; /* 104bit WEP */ range->encoding_size[2] = 32; /* WPA-PSK */ range->num_encoding_sizes = 3; range->max_encoding_tokens = GELIC_WEP_KEYS; /* scan capability */ range->scan_capa = IW_SCAN_CAPA_ESSID; pr_debug("%s: ->\n", __func__); return 0; } /* SIOC{G,S}IWSCAN */ static int gelic_wl_set_scan(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); struct iw_scan_req *req; u8 *essid = NULL; size_t essid_len = 0; if (wrqu->data.length == sizeof(struct iw_scan_req) && wrqu->data.flags & IW_SCAN_THIS_ESSID) { req = (struct iw_scan_req*)extra; essid = req->essid; essid_len = req->essid_len; pr_debug("%s: ESSID scan =%s\n", __func__, essid); } return gelic_wl_start_scan(wl, 1, essid, essid_len); } #define OUI_LEN 3 static const u8 rsn_oui[OUI_LEN] = { 0x00, 0x0f, 0xac }; static const u8 wpa_oui[OUI_LEN] = { 0x00, 0x50, 0xf2 }; /* * synthesize WPA/RSN IE data * See WiFi WPA specification and IEEE 802.11-2007 7.3.2.25 * for the format */ static size_t gelic_wl_synthesize_ie(u8 *buf, struct gelic_eurus_scan_info *scan) { const u8 *oui_header; u8 *start = buf; int rsn; int ccmp; pr_debug("%s: <- sec=%16x\n", __func__, scan->security); switch (be16_to_cpu(scan->security) & GELIC_EURUS_SCAN_SEC_MASK) { case GELIC_EURUS_SCAN_SEC_WPA: rsn = 0; break; case GELIC_EURUS_SCAN_SEC_WPA2: rsn = 1; break; default: /* WEP or none. No IE returned */ return 0; } switch (be16_to_cpu(scan->security) & GELIC_EURUS_SCAN_SEC_WPA_MASK) { case GELIC_EURUS_SCAN_SEC_WPA_TKIP: ccmp = 0; break; case GELIC_EURUS_SCAN_SEC_WPA_AES: ccmp = 1; break; default: if (rsn) { ccmp = 1; pr_info("%s: no cipher info. defaulted to CCMP\n", __func__); } else { ccmp = 0; pr_info("%s: no cipher info. defaulted to TKIP\n", __func__); } } if (rsn) oui_header = rsn_oui; else oui_header = wpa_oui; /* element id */ if (rsn) *buf++ = WLAN_EID_RSN; else *buf++ = WLAN_EID_GENERIC; /* length filed; set later */ buf++; /* wpa special header */ if (!rsn) { memcpy(buf, wpa_oui, OUI_LEN); buf += OUI_LEN; *buf++ = 0x01; } /* version */ *buf++ = 0x01; /* version 1.0 */ *buf++ = 0x00; /* group cipher */ memcpy(buf, oui_header, OUI_LEN); buf += OUI_LEN; if (ccmp) *buf++ = 0x04; /* CCMP */ else *buf++ = 0x02; /* TKIP */ /* pairwise key count always 1 */ *buf++ = 0x01; *buf++ = 0x00; /* pairwise key suit */ memcpy(buf, oui_header, OUI_LEN); buf += OUI_LEN; if (ccmp) *buf++ = 0x04; /* CCMP */ else *buf++ = 0x02; /* TKIP */ /* AKM count is 1 */ *buf++ = 0x01; *buf++ = 0x00; /* AKM suite is assumed as PSK*/ memcpy(buf, oui_header, OUI_LEN); buf += OUI_LEN; *buf++ = 0x02; /* PSK */ /* RSN capabilities is 0 */ *buf++ = 0x00; *buf++ = 0x00; /* set length field */ start[1] = (buf - start - 2); pr_debug("%s: ->\n", __func__); return (buf - start); } struct ie_item { u8 *data; u8 len; }; struct ie_info { struct ie_item wpa; struct ie_item rsn; }; static void gelic_wl_parse_ie(u8 *data, size_t len, struct ie_info *ie_info) { size_t data_left = len; u8 *pos = data; u8 item_len; u8 item_id; pr_debug("%s: data=%p len=%ld\n", __func__, data, len); memset(ie_info, 0, sizeof(struct ie_info)); while (2 <= data_left) { item_id = *pos++; item_len = *pos++; data_left -= 2; if (data_left < item_len) break; switch (item_id) { case WLAN_EID_GENERIC: if ((OUI_LEN + 1 <= item_len) && !memcmp(pos, wpa_oui, OUI_LEN) && pos[OUI_LEN] == 0x01) { ie_info->wpa.data = pos - 2; ie_info->wpa.len = item_len + 2; } break; case WLAN_EID_RSN: ie_info->rsn.data = pos - 2; /* length includes the header */ ie_info->rsn.len = item_len + 2; break; default: pr_debug("%s: ignore %#x,%d\n", __func__, item_id, item_len); break; } pos += item_len; data_left -= item_len; } pr_debug("%s: wpa=%p,%d wpa2=%p,%d\n", __func__, ie_info->wpa.data, ie_info->wpa.len, ie_info->rsn.data, ie_info->rsn.len); } /* * translate the scan informations from hypervisor to a * independent format */ static char *gelic_wl_translate_scan(struct net_device *netdev, struct iw_request_info *info, char *ev, char *stop, struct gelic_wl_scan_info *network) { struct iw_event iwe; struct gelic_eurus_scan_info *scan = network->hwinfo; char *tmp; u8 rate; unsigned int i, j, len; u8 buf[64]; /* arbitrary size large enough */ pr_debug("%s: <-\n", __func__); /* first entry should be AP's mac address */ iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, &scan->bssid[2], ETH_ALEN); ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_ADDR_LEN); /* ESSID */ iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; iwe.u.data.length = strnlen(scan->essid, 32); ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid); /* FREQUENCY */ iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = be16_to_cpu(scan->channel); iwe.u.freq.e = 0; /* table value in MHz */ iwe.u.freq.i = 0; ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_FREQ_LEN); /* RATES */ iwe.cmd = SIOCGIWRATE; iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; /* to stuff multiple values in one event */ tmp = ev + iwe_stream_lcp_len(info); /* put them in ascendant order (older is first) */ i = 0; j = 0; pr_debug("%s: rates=%d rate=%d\n", __func__, network->rate_len, network->rate_ext_len); while (i < network->rate_len) { if (j < network->rate_ext_len && ((scan->ext_rate[j] & 0x7f) < (scan->rate[i] & 0x7f))) rate = scan->ext_rate[j++] & 0x7f; else rate = scan->rate[i++] & 0x7f; iwe.u.bitrate.value = rate * 500000; /* 500kbps unit */ tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe, IW_EV_PARAM_LEN); } while (j < network->rate_ext_len) { iwe.u.bitrate.value = (scan->ext_rate[j++] & 0x7f) * 500000; tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe, IW_EV_PARAM_LEN); } /* Check if we added any rate */ if (iwe_stream_lcp_len(info) < (tmp - ev)) ev = tmp; /* ENCODE */ iwe.cmd = SIOCGIWENCODE; if (be16_to_cpu(scan->capability) & WLAN_CAPABILITY_PRIVACY) iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid); /* MODE */ iwe.cmd = SIOCGIWMODE; if (be16_to_cpu(scan->capability) & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { if (be16_to_cpu(scan->capability) & WLAN_CAPABILITY_ESS) iwe.u.mode = IW_MODE_MASTER; else iwe.u.mode = IW_MODE_ADHOC; ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_UINT_LEN); } /* QUAL */ iwe.cmd = IWEVQUAL; iwe.u.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID; iwe.u.qual.level = be16_to_cpu(scan->rssi); iwe.u.qual.qual = be16_to_cpu(scan->rssi); iwe.u.qual.noise = 0; ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_QUAL_LEN); /* RSN */ memset(&iwe, 0, sizeof(iwe)); if (be16_to_cpu(scan->size) <= sizeof(*scan)) { /* If wpa[2] capable station, synthesize IE and put it */ len = gelic_wl_synthesize_ie(buf, scan); if (len) { iwe.cmd = IWEVGENIE; iwe.u.data.length = len; ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); } } else { /* this scan info has IE data */ struct ie_info ie_info; size_t data_len; data_len = be16_to_cpu(scan->size) - sizeof(*scan); gelic_wl_parse_ie(scan->elements, data_len, &ie_info); if (ie_info.wpa.len && (ie_info.wpa.len <= sizeof(buf))) { memcpy(buf, ie_info.wpa.data, ie_info.wpa.len); iwe.cmd = IWEVGENIE; iwe.u.data.length = ie_info.wpa.len; ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); } if (ie_info.rsn.len && (ie_info.rsn.len <= sizeof(buf))) { memset(&iwe, 0, sizeof(iwe)); memcpy(buf, ie_info.rsn.data, ie_info.rsn.len); iwe.cmd = IWEVGENIE; iwe.u.data.length = ie_info.rsn.len; ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); } } pr_debug("%s: ->\n", __func__); return ev; } static int gelic_wl_get_scan(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); struct gelic_wl_scan_info *scan_info; char *ev = extra; char *stop = ev + wrqu->data.length; int ret = 0; unsigned long this_time = jiffies; pr_debug("%s: <-\n", __func__); if (mutex_lock_interruptible(&wl->scan_lock)) return -EAGAIN; switch (wl->scan_stat) { case GELIC_WL_SCAN_STAT_SCANNING: /* If a scan in progress, caller should call me again */ ret = -EAGAIN; goto out; break; case GELIC_WL_SCAN_STAT_INIT: /* last scan request failed or never issued */ ret = -ENODEV; goto out; break; case GELIC_WL_SCAN_STAT_GOT_LIST: /* ok, use current list */ break; } list_for_each_entry(scan_info, &wl->network_list, list) { if (wl->scan_age == 0 || time_after(scan_info->last_scanned + wl->scan_age, this_time)) ev = gelic_wl_translate_scan(netdev, info, ev, stop, scan_info); else pr_debug("%s:entry too old\n", __func__); if (stop - ev <= IW_EV_ADDR_LEN) { ret = -E2BIG; goto out; } } wrqu->data.length = ev - extra; wrqu->data.flags = 0; out: mutex_unlock(&wl->scan_lock); pr_debug("%s: -> %d %d\n", __func__, ret, wrqu->data.length); return ret; } #ifdef DEBUG static void scan_list_dump(struct gelic_wl_info *wl) { struct gelic_wl_scan_info *scan_info; int i; i = 0; list_for_each_entry(scan_info, &wl->network_list, list) { pr_debug("%s: item %d\n", __func__, i++); pr_debug("valid=%d eurusindex=%d last=%lx\n", scan_info->valid, scan_info->eurus_index, scan_info->last_scanned); pr_debug("r_len=%d r_ext_len=%d essid_len=%d\n", scan_info->rate_len, scan_info->rate_ext_len, scan_info->essid_len); /* -- */ pr_debug("bssid=%pM\n", &scan_info->hwinfo->bssid[2]); pr_debug("essid=%s\n", scan_info->hwinfo->essid); } } #endif static int gelic_wl_set_auth(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *data, char *extra) { struct iw_param *param = &data->param; struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); unsigned long irqflag; int ret = 0; pr_debug("%s: <- %d\n", __func__, param->flags & IW_AUTH_INDEX); spin_lock_irqsave(&wl->lock, irqflag); switch (param->flags & IW_AUTH_INDEX) { case IW_AUTH_WPA_VERSION: if (param->value & IW_AUTH_WPA_VERSION_DISABLED) { pr_debug("%s: NO WPA selected\n", __func__); wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; wl->group_cipher_method = GELIC_WL_CIPHER_WEP; wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP; } if (param->value & IW_AUTH_WPA_VERSION_WPA) { pr_debug("%s: WPA version 1 selected\n", __func__); wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA; wl->group_cipher_method = GELIC_WL_CIPHER_TKIP; wl->pairwise_cipher_method = GELIC_WL_CIPHER_TKIP; wl->auth_method = GELIC_EURUS_AUTH_OPEN; } if (param->value & IW_AUTH_WPA_VERSION_WPA2) { /* * As the hypervisor may not tell the cipher * information of the AP if it is WPA2, * you will not decide suitable cipher from * its beacon. * You should have knowledge about the AP's * cipher infomation in other method prior to * the association. */ if (!precise_ie()) pr_info("%s: WPA2 may not work\n", __func__); if (wpa2_capable()) { wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA2; wl->group_cipher_method = GELIC_WL_CIPHER_AES; wl->pairwise_cipher_method = GELIC_WL_CIPHER_AES; wl->auth_method = GELIC_EURUS_AUTH_OPEN; } else ret = -EINVAL; } break; case IW_AUTH_CIPHER_PAIRWISE: if (param->value & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { pr_debug("%s: WEP selected\n", __func__); wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP; } if (param->value & IW_AUTH_CIPHER_TKIP) { pr_debug("%s: TKIP selected\n", __func__); wl->pairwise_cipher_method = GELIC_WL_CIPHER_TKIP; } if (param->value & IW_AUTH_CIPHER_CCMP) { pr_debug("%s: CCMP selected\n", __func__); wl->pairwise_cipher_method = GELIC_WL_CIPHER_AES; } if (param->value & IW_AUTH_CIPHER_NONE) { pr_debug("%s: no auth selected\n", __func__); wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE; } break; case IW_AUTH_CIPHER_GROUP: if (param->value & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { pr_debug("%s: WEP selected\n", __func__); wl->group_cipher_method = GELIC_WL_CIPHER_WEP; } if (param->value & IW_AUTH_CIPHER_TKIP) { pr_debug("%s: TKIP selected\n", __func__); wl->group_cipher_method = GELIC_WL_CIPHER_TKIP; } if (param->value & IW_AUTH_CIPHER_CCMP) { pr_debug("%s: CCMP selected\n", __func__); wl->group_cipher_method = GELIC_WL_CIPHER_AES; } if (param->value & IW_AUTH_CIPHER_NONE) { pr_debug("%s: no auth selected\n", __func__); wl->group_cipher_method = GELIC_WL_CIPHER_NONE; } break; case IW_AUTH_80211_AUTH_ALG: if (param->value & IW_AUTH_ALG_SHARED_KEY) { pr_debug("%s: shared key specified\n", __func__); wl->auth_method = GELIC_EURUS_AUTH_SHARED; } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { pr_debug("%s: open system specified\n", __func__); wl->auth_method = GELIC_EURUS_AUTH_OPEN; } else ret = -EINVAL; break; case IW_AUTH_WPA_ENABLED: if (param->value) { pr_debug("%s: WPA enabled\n", __func__); wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA; } else { pr_debug("%s: WPA disabled\n", __func__); wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; } break; case IW_AUTH_KEY_MGMT: if (param->value & IW_AUTH_KEY_MGMT_PSK) break; /* intentionally fall through */ default: ret = -EOPNOTSUPP; break; } if (!ret) set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); spin_unlock_irqrestore(&wl->lock, irqflag); pr_debug("%s: -> %d\n", __func__, ret); return ret; } static int gelic_wl_get_auth(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *iwreq, char *extra) { struct iw_param *param = &iwreq->param; struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); unsigned long irqflag; int ret = 0; pr_debug("%s: <- %d\n", __func__, param->flags & IW_AUTH_INDEX); spin_lock_irqsave(&wl->lock, irqflag); switch (param->flags & IW_AUTH_INDEX) { case IW_AUTH_WPA_VERSION: switch (wl->wpa_level) { case GELIC_WL_WPA_LEVEL_WPA: param->value |= IW_AUTH_WPA_VERSION_WPA; break; case GELIC_WL_WPA_LEVEL_WPA2: param->value |= IW_AUTH_WPA_VERSION_WPA2; break; default: param->value |= IW_AUTH_WPA_VERSION_DISABLED; } break; case IW_AUTH_80211_AUTH_ALG: if (wl->auth_method == GELIC_EURUS_AUTH_SHARED) param->value = IW_AUTH_ALG_SHARED_KEY; else if (wl->auth_method == GELIC_EURUS_AUTH_OPEN) param->value = IW_AUTH_ALG_OPEN_SYSTEM; break; case IW_AUTH_WPA_ENABLED: switch (wl->wpa_level) { case GELIC_WL_WPA_LEVEL_WPA: case GELIC_WL_WPA_LEVEL_WPA2: param->value = 1; break; default: param->value = 0; break; } break; default: ret = -EOPNOTSUPP; } spin_unlock_irqrestore(&wl->lock, irqflag); pr_debug("%s: -> %d\n", __func__, ret); return ret; } /* SIOC{S,G}IWESSID */ static int gelic_wl_set_essid(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *data, char *extra) { struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); unsigned long irqflag; pr_debug("%s: <- l=%d f=%d\n", __func__, data->essid.length, data->essid.flags); if (IW_ESSID_MAX_SIZE < data->essid.length) return -EINVAL; spin_lock_irqsave(&wl->lock, irqflag); if (data->essid.flags) { wl->essid_len = data->essid.length; memcpy(wl->essid, extra, wl->essid_len); pr_debug("%s: essid = '%s'\n", __func__, extra); set_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat); } else { pr_debug("%s: ESSID any\n", __func__); clear_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat); } set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); spin_unlock_irqrestore(&wl->lock, irqflag); gelic_wl_try_associate(netdev); /* FIXME */ pr_debug("%s: ->\n", __func__); return 0; } static int gelic_wl_get_essid(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *data, char *extra) { struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); unsigned long irqflag; pr_debug("%s: <-\n", __func__); mutex_lock(&wl->assoc_stat_lock); spin_lock_irqsave(&wl->lock, irqflag); if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat) || wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) { memcpy(extra, wl->essid, wl->essid_len); data->essid.length = wl->essid_len; data->essid.flags = 1; } else data->essid.flags = 0; mutex_unlock(&wl->assoc_stat_lock); spin_unlock_irqrestore(&wl->lock, irqflag); pr_debug("%s: -> len=%d\n", __func__, data->essid.length); return 0; } /* SIO{S,G}IWENCODE */ static int gelic_wl_set_encode(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *data, char *extra) { struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); struct iw_point *enc = &data->encoding; __u16 flags; unsigned long irqflag; int key_index, index_specified; int ret = 0; pr_debug("%s: <-\n", __func__); flags = enc->flags & IW_ENCODE_FLAGS; key_index = enc->flags & IW_ENCODE_INDEX; pr_debug("%s: key_index = %d\n", __func__, key_index); pr_debug("%s: key_len = %d\n", __func__, enc->length); pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS); if (GELIC_WEP_KEYS < key_index) return -EINVAL; spin_lock_irqsave(&wl->lock, irqflag); if (key_index) { index_specified = 1; key_index--; } else { index_specified = 0; key_index = wl->current_key; } if (flags & IW_ENCODE_NOKEY) { /* if just IW_ENCODE_NOKEY, change current key index */ if (!flags && index_specified) { wl->current_key = key_index; goto done; } if (flags & IW_ENCODE_DISABLED) { if (!index_specified) { /* disable encryption */ wl->group_cipher_method = GELIC_WL_CIPHER_NONE; wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE; /* invalidate all key */ wl->key_enabled = 0; } else clear_bit(key_index, &wl->key_enabled); } if (flags & IW_ENCODE_OPEN) wl->auth_method = GELIC_EURUS_AUTH_OPEN; if (flags & IW_ENCODE_RESTRICTED) { pr_info("%s: shared key mode enabled\n", __func__); wl->auth_method = GELIC_EURUS_AUTH_SHARED; } } else { if (IW_ENCODING_TOKEN_MAX < enc->length) { ret = -EINVAL; goto done; } wl->key_len[key_index] = enc->length; memcpy(wl->key[key_index], extra, enc->length); set_bit(key_index, &wl->key_enabled); wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP; wl->group_cipher_method = GELIC_WL_CIPHER_WEP; } set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); done: spin_unlock_irqrestore(&wl->lock, irqflag); pr_debug("%s: ->\n", __func__); return ret; } static int gelic_wl_get_encode(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *data, char *extra) { struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); struct iw_point *enc = &data->encoding; unsigned long irqflag; unsigned int key_index, index_specified; int ret = 0; pr_debug("%s: <-\n", __func__); key_index = enc->flags & IW_ENCODE_INDEX; pr_debug("%s: flag=%#x point=%p len=%d extra=%p\n", __func__, enc->flags, enc->pointer, enc->length, extra); if (GELIC_WEP_KEYS < key_index) return -EINVAL; spin_lock_irqsave(&wl->lock, irqflag); if (key_index) { index_specified = 1; key_index--; } else { index_specified = 0; key_index = wl->current_key; } if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { switch (wl->auth_method) { case GELIC_EURUS_AUTH_OPEN: enc->flags = IW_ENCODE_OPEN; break; case GELIC_EURUS_AUTH_SHARED: enc->flags = IW_ENCODE_RESTRICTED; break; } } else enc->flags = IW_ENCODE_DISABLED; if (test_bit(key_index, &wl->key_enabled)) { if (enc->length < wl->key_len[key_index]) { ret = -EINVAL; goto done; } enc->length = wl->key_len[key_index]; memcpy(extra, wl->key[key_index], wl->key_len[key_index]); } else { enc->length = 0; enc->flags |= IW_ENCODE_NOKEY; } enc->flags |= key_index + 1; pr_debug("%s: -> flag=%x len=%d\n", __func__, enc->flags, enc->length); done: spin_unlock_irqrestore(&wl->lock, irqflag); return ret; } /* SIOC{S,G}IWAP */ static int gelic_wl_set_ap(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *data, char *extra) { struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); unsigned long irqflag; pr_debug("%s: <-\n", __func__); if (data->ap_addr.sa_family != ARPHRD_ETHER) return -EINVAL; spin_lock_irqsave(&wl->lock, irqflag); if (is_valid_ether_addr(data->ap_addr.sa_data)) { memcpy(wl->bssid, data->ap_addr.sa_data, ETH_ALEN); set_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat); set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); pr_debug("%s: bss=%pM\n", __func__, wl->bssid); } else { pr_debug("%s: clear bssid\n", __func__); clear_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat); memset(wl->bssid, 0, ETH_ALEN); } spin_unlock_irqrestore(&wl->lock, irqflag); pr_debug("%s: ->\n", __func__); return 0; } static int gelic_wl_get_ap(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *data, char *extra) { struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); unsigned long irqflag; pr_debug("%s: <-\n", __func__); mutex_lock(&wl->assoc_stat_lock); spin_lock_irqsave(&wl->lock, irqflag); if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) { data->ap_addr.sa_family = ARPHRD_ETHER; memcpy(data->ap_addr.sa_data, wl->active_bssid, ETH_ALEN); } else memset(data->ap_addr.sa_data, 0, ETH_ALEN); spin_unlock_irqrestore(&wl->lock, irqflag); mutex_unlock(&wl->assoc_stat_lock); pr_debug("%s: ->\n", __func__); return 0; } /* SIOC{S,G}IWENCODEEXT */ static int gelic_wl_set_encodeext(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *data, char *extra) { struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); struct iw_point *enc = &data->encoding; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; __u16 alg; __u16 flags; unsigned long irqflag; int key_index; int ret = 0; pr_debug("%s: <-\n", __func__); flags = enc->flags & IW_ENCODE_FLAGS; alg = ext->alg; key_index = enc->flags & IW_ENCODE_INDEX; pr_debug("%s: key_index = %d\n", __func__, key_index); pr_debug("%s: key_len = %d\n", __func__, enc->length); pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS); pr_debug("%s: ext_flag=%x\n", __func__, ext->ext_flags); pr_debug("%s: ext_key_len=%x\n", __func__, ext->key_len); if (GELIC_WEP_KEYS < key_index) return -EINVAL; spin_lock_irqsave(&wl->lock, irqflag); if (key_index) key_index--; else key_index = wl->current_key; if (!enc->length && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) { /* reques to change default key index */ pr_debug("%s: request to change default key to %d\n", __func__, key_index); wl->current_key = key_index; goto done; } if (alg == IW_ENCODE_ALG_NONE || (flags & IW_ENCODE_DISABLED)) { pr_debug("%s: alg disabled\n", __func__); wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; wl->group_cipher_method = GELIC_WL_CIPHER_NONE; wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE; wl->auth_method = GELIC_EURUS_AUTH_OPEN; /* should be open */ } else if (alg == IW_ENCODE_ALG_WEP) { pr_debug("%s: WEP requested\n", __func__); if (flags & IW_ENCODE_OPEN) { pr_debug("%s: open key mode\n", __func__); wl->auth_method = GELIC_EURUS_AUTH_OPEN; } if (flags & IW_ENCODE_RESTRICTED) { pr_debug("%s: shared key mode\n", __func__); wl->auth_method = GELIC_EURUS_AUTH_SHARED; } if (IW_ENCODING_TOKEN_MAX < ext->key_len) { pr_info("%s: key is too long %d\n", __func__, ext->key_len); ret = -EINVAL; goto done; } /* OK, update the key */ wl->key_len[key_index] = ext->key_len; memset(wl->key[key_index], 0, IW_ENCODING_TOKEN_MAX); memcpy(wl->key[key_index], ext->key, ext->key_len); set_bit(key_index, &wl->key_enabled); /* remember wep info changed */ set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); } else if (alg == IW_ENCODE_ALG_PMK) { if (ext->key_len != WPA_PSK_LEN) { pr_err("%s: PSK length wrong %d\n", __func__, ext->key_len); ret = -EINVAL; goto done; } memset(wl->psk, 0, sizeof(wl->psk)); memcpy(wl->psk, ext->key, ext->key_len); wl->psk_len = ext->key_len; wl->psk_type = GELIC_EURUS_WPA_PSK_BIN; /* remember PSK configured */ set_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat); } done: spin_unlock_irqrestore(&wl->lock, irqflag); pr_debug("%s: ->\n", __func__); return ret; } static int gelic_wl_get_encodeext(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *data, char *extra) { struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); struct iw_point *enc = &data->encoding; struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; unsigned long irqflag; int key_index; int ret = 0; int max_key_len; pr_debug("%s: <-\n", __func__); max_key_len = enc->length - sizeof(struct iw_encode_ext); if (max_key_len < 0) return -EINVAL; key_index = enc->flags & IW_ENCODE_INDEX; pr_debug("%s: key_index = %d\n", __func__, key_index); pr_debug("%s: key_len = %d\n", __func__, enc->length); pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS); if (GELIC_WEP_KEYS < key_index) return -EINVAL; spin_lock_irqsave(&wl->lock, irqflag); if (key_index) key_index--; else key_index = wl->current_key; memset(ext, 0, sizeof(struct iw_encode_ext)); switch (wl->group_cipher_method) { case GELIC_WL_CIPHER_WEP: ext->alg = IW_ENCODE_ALG_WEP; enc->flags |= IW_ENCODE_ENABLED; break; case GELIC_WL_CIPHER_TKIP: ext->alg = IW_ENCODE_ALG_TKIP; enc->flags |= IW_ENCODE_ENABLED; break; case GELIC_WL_CIPHER_AES: ext->alg = IW_ENCODE_ALG_CCMP; enc->flags |= IW_ENCODE_ENABLED; break; case GELIC_WL_CIPHER_NONE: default: ext->alg = IW_ENCODE_ALG_NONE; enc->flags |= IW_ENCODE_NOKEY; break; } if (!(enc->flags & IW_ENCODE_NOKEY)) { if (max_key_len < wl->key_len[key_index]) { ret = -E2BIG; goto out; } if (test_bit(key_index, &wl->key_enabled)) memcpy(ext->key, wl->key[key_index], wl->key_len[key_index]); else pr_debug("%s: disabled key requested ix=%d\n", __func__, key_index); } out: spin_unlock_irqrestore(&wl->lock, irqflag); pr_debug("%s: ->\n", __func__); return ret; } /* SIOC{S,G}IWMODE */ static int gelic_wl_set_mode(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *data, char *extra) { __u32 mode = data->mode; int ret; pr_debug("%s: <-\n", __func__); if (mode == IW_MODE_INFRA) ret = 0; else ret = -EOPNOTSUPP; pr_debug("%s: -> %d\n", __func__, ret); return ret; } static int gelic_wl_get_mode(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *data, char *extra) { __u32 *mode = &data->mode; pr_debug("%s: <-\n", __func__); *mode = IW_MODE_INFRA; pr_debug("%s: ->\n", __func__); return 0; } /* SIOCGIWNICKN */ static int gelic_wl_get_nick(struct net_device *net_dev, struct iw_request_info *info, union iwreq_data *data, char *extra) { strcpy(extra, "gelic_wl"); data->data.length = strlen(extra); data->data.flags = 1; return 0; } /* --- */ static struct iw_statistics *gelic_wl_get_wireless_stats( struct net_device *netdev) { struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); struct gelic_eurus_cmd *cmd; struct iw_statistics *is; struct gelic_eurus_rssi_info *rssi; void *buf; pr_debug("%s: <-\n", __func__); buf = (void *)__get_free_page(GFP_KERNEL); if (!buf) return NULL; is = &wl->iwstat; memset(is, 0, sizeof(*is)); cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_GET_RSSI_CFG, buf, sizeof(*rssi)); if (cmd && !cmd->status && !cmd->cmd_status) { rssi = buf; is->qual.level = be16_to_cpu(rssi->rssi); is->qual.updated = IW_QUAL_LEVEL_UPDATED | IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID; } else /* not associated */ is->qual.updated = IW_QUAL_ALL_INVALID; kfree(cmd); free_page((unsigned long)buf); pr_debug("%s: ->\n", __func__); return is; } /* * scanning helpers */ static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan, u8 *essid, size_t essid_len) { struct gelic_eurus_cmd *cmd; int ret = 0; void *buf = NULL; size_t len; pr_debug("%s: <- always=%d\n", __func__, always_scan); if (mutex_lock_interruptible(&wl->scan_lock)) return -ERESTARTSYS; /* * If already a scan in progress, do not trigger more */ if (wl->scan_stat == GELIC_WL_SCAN_STAT_SCANNING) { pr_debug("%s: scanning now\n", __func__); goto out; } init_completion(&wl->scan_done); /* * If we have already a bss list, don't try to get new * unless we are doing an ESSID scan */ if ((!essid_len && !always_scan) && wl->scan_stat == GELIC_WL_SCAN_STAT_GOT_LIST) { pr_debug("%s: already has the list\n", __func__); complete(&wl->scan_done); goto out; } /* ESSID scan ? */ if (essid_len && essid) { buf = (void *)__get_free_page(GFP_KERNEL); if (!buf) { ret = -ENOMEM; goto out; } len = IW_ESSID_MAX_SIZE; /* hypervisor always requires 32 */ memset(buf, 0, len); memcpy(buf, essid, essid_len); pr_debug("%s: essid scan='%s'\n", __func__, (char *)buf); } else len = 0; /* * issue start scan request */ wl->scan_stat = GELIC_WL_SCAN_STAT_SCANNING; cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_START_SCAN, buf, len); if (!cmd || cmd->status || cmd->cmd_status) { wl->scan_stat = GELIC_WL_SCAN_STAT_INIT; complete(&wl->scan_done); ret = -ENOMEM; goto out; } kfree(cmd); out: free_page((unsigned long)buf); mutex_unlock(&wl->scan_lock); pr_debug("%s: ->\n", __func__); return ret; } /* * retrieve scan result from the chip (hypervisor) * this function is invoked by schedule work. */ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl) { struct gelic_eurus_cmd *cmd = NULL; struct gelic_wl_scan_info *target, *tmp; struct gelic_wl_scan_info *oldest = NULL; struct gelic_eurus_scan_info *scan_info; unsigned int scan_info_size; union iwreq_data data; unsigned long this_time = jiffies; unsigned int data_len, i, found, r; void *buf; pr_debug("%s:start\n", __func__); mutex_lock(&wl->scan_lock); buf = (void *)__get_free_page(GFP_KERNEL); if (!buf) { pr_info("%s: scan buffer alloc failed\n", __func__); goto out; } if (wl->scan_stat != GELIC_WL_SCAN_STAT_SCANNING) { /* * stop() may be called while scanning, ignore result */ pr_debug("%s: scan complete when stat != scanning(%d)\n", __func__, wl->scan_stat); goto out; } cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_GET_SCAN, buf, PAGE_SIZE); if (!cmd || cmd->status || cmd->cmd_status) { wl->scan_stat = GELIC_WL_SCAN_STAT_INIT; pr_info("%s:cmd failed\n", __func__); kfree(cmd); goto out; } data_len = cmd->size; pr_debug("%s: data_len = %d\n", __func__, data_len); kfree(cmd); /* OK, bss list retrieved */ wl->scan_stat = GELIC_WL_SCAN_STAT_GOT_LIST; /* mark all entries are old */ list_for_each_entry_safe(target, tmp, &wl->network_list, list) { target->valid = 0; /* expire too old entries */ if (time_before(target->last_scanned + wl->scan_age, this_time)) { kfree(target->hwinfo); target->hwinfo = NULL; list_move_tail(&target->list, &wl->network_free_list); } } /* put them in the network_list */ for (i = 0, scan_info_size = 0, scan_info = buf; scan_info_size < data_len; i++, scan_info_size += be16_to_cpu(scan_info->size), scan_info = (void *)scan_info + be16_to_cpu(scan_info->size)) { pr_debug("%s:size=%d bssid=%pM scan_info=%p\n", __func__, be16_to_cpu(scan_info->size), &scan_info->bssid[2], scan_info); /* * The wireless firmware may return invalid channel 0 and/or * invalid rate if the AP emits zero length SSID ie. As this * scan information is useless, ignore it */ if (!be16_to_cpu(scan_info->channel) || !scan_info->rate[0]) { pr_debug("%s: invalid scan info\n", __func__); continue; } found = 0; oldest = NULL; list_for_each_entry(target, &wl->network_list, list) { if (!compare_ether_addr(&target->hwinfo->bssid[2], &scan_info->bssid[2])) { found = 1; pr_debug("%s: same BBS found scanned list\n", __func__); break; } if (!oldest || (target->last_scanned < oldest->last_scanned)) oldest = target; } if (!found) { /* not found in the list */ if (list_empty(&wl->network_free_list)) { /* expire oldest */ target = oldest; } else { target = list_entry(wl->network_free_list.next, struct gelic_wl_scan_info, list); } } /* update the item */ target->last_scanned = this_time; target->valid = 1; target->eurus_index = i; kfree(target->hwinfo); target->hwinfo = kzalloc(be16_to_cpu(scan_info->size), GFP_KERNEL); if (!target->hwinfo) { pr_info("%s: kzalloc failed\n", __func__); continue; } /* copy hw scan info */ memcpy(target->hwinfo, scan_info, scan_info->size); target->essid_len = strnlen(scan_info->essid, sizeof(scan_info->essid)); target->rate_len = 0; for (r = 0; r < 12; r++) if (scan_info->rate[r]) target->rate_len++; if (8 < target->rate_len) pr_info("%s: AP returns %d rates\n", __func__, target->rate_len); target->rate_ext_len = 0; for (r = 0; r < 16; r++) if (scan_info->ext_rate[r]) target->rate_ext_len++; list_move_tail(&target->list, &wl->network_list); } memset(&data, 0, sizeof(data)); wireless_send_event(port_to_netdev(wl_port(wl)), SIOCGIWSCAN, &data, NULL); out: free_page((unsigned long)buf); complete(&wl->scan_done); mutex_unlock(&wl->scan_lock); pr_debug("%s:end\n", __func__); } /* * Select an appropriate bss from current scan list regarding * current settings from userspace. * The caller must hold wl->scan_lock, * and on the state of wl->scan_state == GELIC_WL_SCAN_GOT_LIST */ static void update_best(struct gelic_wl_scan_info **best, struct gelic_wl_scan_info *candid, int *best_weight, int *weight) { if (*best_weight < ++(*weight)) { *best_weight = *weight; *best = candid; } } static struct gelic_wl_scan_info *gelic_wl_find_best_bss(struct gelic_wl_info *wl) { struct gelic_wl_scan_info *scan_info; struct gelic_wl_scan_info *best_bss; int weight, best_weight; u16 security; pr_debug("%s: <-\n", __func__); best_bss = NULL; best_weight = 0; list_for_each_entry(scan_info, &wl->network_list, list) { pr_debug("%s: station %p\n", __func__, scan_info); if (!scan_info->valid) { pr_debug("%s: station invalid\n", __func__); continue; } /* If bss specified, check it only */ if (test_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat)) { if (!compare_ether_addr(&scan_info->hwinfo->bssid[2], wl->bssid)) { best_bss = scan_info; pr_debug("%s: bssid matched\n", __func__); break; } else { pr_debug("%s: bssid unmached\n", __func__); continue; } } weight = 0; /* security */ security = be16_to_cpu(scan_info->hwinfo->security) & GELIC_EURUS_SCAN_SEC_MASK; if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA2) { if (security == GELIC_EURUS_SCAN_SEC_WPA2) update_best(&best_bss, scan_info, &best_weight, &weight); else continue; } else if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA) { if (security == GELIC_EURUS_SCAN_SEC_WPA) update_best(&best_bss, scan_info, &best_weight, &weight); else continue; } else if (wl->wpa_level == GELIC_WL_WPA_LEVEL_NONE && wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { if (security == GELIC_EURUS_SCAN_SEC_WEP) update_best(&best_bss, scan_info, &best_weight, &weight); else continue; } /* If ESSID is set, check it */ if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat)) { if ((scan_info->essid_len == wl->essid_len) && !strncmp(wl->essid, scan_info->hwinfo->essid, scan_info->essid_len)) update_best(&best_bss, scan_info, &best_weight, &weight); else continue; } } #ifdef DEBUG pr_debug("%s: -> bss=%p\n", __func__, best_bss); if (best_bss) { pr_debug("%s:addr=%pM\n", __func__, &best_bss->hwinfo->bssid[2]); } #endif return best_bss; } /* * Setup WEP configuration to the chip * The caller must hold wl->scan_lock, * and on the state of wl->scan_state == GELIC_WL_SCAN_GOT_LIST */ static int gelic_wl_do_wep_setup(struct gelic_wl_info *wl) { unsigned int i; struct gelic_eurus_wep_cfg *wep; struct gelic_eurus_cmd *cmd; int wep104 = 0; int have_key = 0; int ret = 0; pr_debug("%s: <-\n", __func__); /* we can assume no one should uses the buffer */ wep = (struct gelic_eurus_wep_cfg *)__get_free_page(GFP_KERNEL); if (!wep) return -ENOMEM; memset(wep, 0, sizeof(*wep)); if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { pr_debug("%s: WEP mode\n", __func__); for (i = 0; i < GELIC_WEP_KEYS; i++) { if (!test_bit(i, &wl->key_enabled)) continue; pr_debug("%s: key#%d enabled\n", __func__, i); have_key = 1; if (wl->key_len[i] == 13) wep104 = 1; else if (wl->key_len[i] != 5) { pr_info("%s: wrong wep key[%d]=%d\n", __func__, i, wl->key_len[i]); ret = -EINVAL; goto out; } memcpy(wep->key[i], wl->key[i], wl->key_len[i]); } if (!have_key) { pr_info("%s: all wep key disabled\n", __func__); ret = -EINVAL; goto out; } if (wep104) { pr_debug("%s: 104bit key\n", __func__); wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_104BIT); } else { pr_debug("%s: 40bit key\n", __func__); wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_40BIT); } } else { pr_debug("%s: NO encryption\n", __func__); wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_NONE); } /* issue wep setup */ cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_WEP_CFG, wep, sizeof(*wep)); if (!cmd) ret = -ENOMEM; else if (cmd->status || cmd->cmd_status) ret = -ENXIO; kfree(cmd); out: free_page((unsigned long)wep); pr_debug("%s: ->\n", __func__); return ret; } #ifdef DEBUG static const char *wpasecstr(enum gelic_eurus_wpa_security sec) { switch (sec) { case GELIC_EURUS_WPA_SEC_NONE: return "NONE"; break; case GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP: return "WPA_TKIP_TKIP"; break; case GELIC_EURUS_WPA_SEC_WPA_TKIP_AES: return "WPA_TKIP_AES"; break; case GELIC_EURUS_WPA_SEC_WPA_AES_AES: return "WPA_AES_AES"; break; case GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP: return "WPA2_TKIP_TKIP"; break; case GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES: return "WPA2_TKIP_AES"; break; case GELIC_EURUS_WPA_SEC_WPA2_AES_AES: return "WPA2_AES_AES"; break; } return ""; }; #endif static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl) { struct gelic_eurus_wpa_cfg *wpa; struct gelic_eurus_cmd *cmd; u16 security; int ret = 0; pr_debug("%s: <-\n", __func__); /* we can assume no one should uses the buffer */ wpa = (struct gelic_eurus_wpa_cfg *)__get_free_page(GFP_KERNEL); if (!wpa) return -ENOMEM; memset(wpa, 0, sizeof(*wpa)); if (!test_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat)) pr_info("%s: PSK not configured yet\n", __func__); /* copy key */ memcpy(wpa->psk, wl->psk, wl->psk_len); /* set security level */ if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA2) { if (wl->group_cipher_method == GELIC_WL_CIPHER_AES) { security = GELIC_EURUS_WPA_SEC_WPA2_AES_AES; } else { if (wl->pairwise_cipher_method == GELIC_WL_CIPHER_AES && precise_ie()) security = GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES; else security = GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP; } } else { if (wl->group_cipher_method == GELIC_WL_CIPHER_AES) { security = GELIC_EURUS_WPA_SEC_WPA_AES_AES; } else { if (wl->pairwise_cipher_method == GELIC_WL_CIPHER_AES && precise_ie()) security = GELIC_EURUS_WPA_SEC_WPA_TKIP_AES; else security = GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP; } } wpa->security = cpu_to_be16(security); /* PSK type */ wpa->psk_type = cpu_to_be16(wl->psk_type); #ifdef DEBUG pr_debug("%s: sec=%s psktype=%s\n", __func__, wpasecstr(wpa->security), (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ? "BIN" : "passphrase"); #if 0 /* * don't enable here if you plan to submit * the debug log because this dumps your precious * passphrase/key. */ pr_debug("%s: psk=%s\n", __func__, (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ? "N/A" : wpa->psk); #endif #endif /* issue wpa setup */ cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_WPA_CFG, wpa, sizeof(*wpa)); if (!cmd) ret = -ENOMEM; else if (cmd->status || cmd->cmd_status) ret = -ENXIO; kfree(cmd); free_page((unsigned long)wpa); pr_debug("%s: --> %d\n", __func__, ret); return ret; } /* * Start association. caller must hold assoc_stat_lock */ static int gelic_wl_associate_bss(struct gelic_wl_info *wl, struct gelic_wl_scan_info *bss) { struct gelic_eurus_cmd *cmd; struct gelic_eurus_common_cfg *common; int ret = 0; unsigned long rc; pr_debug("%s: <-\n", __func__); /* do common config */ common = (struct gelic_eurus_common_cfg *)__get_free_page(GFP_KERNEL); if (!common) return -ENOMEM; memset(common, 0, sizeof(*common)); common->bss_type = cpu_to_be16(GELIC_EURUS_BSS_INFRA); common->op_mode = cpu_to_be16(GELIC_EURUS_OPMODE_11BG); common->scan_index = cpu_to_be16(bss->eurus_index); switch (wl->auth_method) { case GELIC_EURUS_AUTH_OPEN: common->auth_method = cpu_to_be16(GELIC_EURUS_AUTH_OPEN); break; case GELIC_EURUS_AUTH_SHARED: common->auth_method = cpu_to_be16(GELIC_EURUS_AUTH_SHARED); break; } #ifdef DEBUG scan_list_dump(wl); #endif pr_debug("%s: common cfg index=%d bsstype=%d auth=%d\n", __func__, be16_to_cpu(common->scan_index), be16_to_cpu(common->bss_type), be16_to_cpu(common->auth_method)); cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_COMMON_CFG, common, sizeof(*common)); if (!cmd || cmd->status || cmd->cmd_status) { ret = -ENOMEM; kfree(cmd); goto out; } kfree(cmd); /* WEP/WPA */ switch (wl->wpa_level) { case GELIC_WL_WPA_LEVEL_NONE: /* If WEP or no security, setup WEP config */ ret = gelic_wl_do_wep_setup(wl); break; case GELIC_WL_WPA_LEVEL_WPA: case GELIC_WL_WPA_LEVEL_WPA2: ret = gelic_wl_do_wpa_setup(wl); break; } if (ret) { pr_debug("%s: WEP/WPA setup failed %d\n", __func__, ret); ret = -EPERM; gelic_wl_send_iwap_event(wl, NULL); goto out; } /* start association */ init_completion(&wl->assoc_done); wl->assoc_stat = GELIC_WL_ASSOC_STAT_ASSOCIATING; cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_ASSOC, NULL, 0); if (!cmd || cmd->status || cmd->cmd_status) { pr_debug("%s: assoc request failed\n", __func__); wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; kfree(cmd); ret = -ENOMEM; gelic_wl_send_iwap_event(wl, NULL); goto out; } kfree(cmd); /* wait for connected event */ rc = wait_for_completion_timeout(&wl->assoc_done, HZ * 4);/*FIXME*/ if (!rc) { /* timeouted. Maybe key or cyrpt mode is wrong */ pr_info("%s: connect timeout\n", __func__); cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC, NULL, 0); kfree(cmd); wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; gelic_wl_send_iwap_event(wl, NULL); ret = -ENXIO; } else { wl->assoc_stat = GELIC_WL_ASSOC_STAT_ASSOCIATED; /* copy bssid */ memcpy(wl->active_bssid, &bss->hwinfo->bssid[2], ETH_ALEN); /* send connect event */ gelic_wl_send_iwap_event(wl, wl->active_bssid); pr_info("%s: connected\n", __func__); } out: free_page((unsigned long)common); pr_debug("%s: ->\n", __func__); return ret; } /* * connected event */ static void gelic_wl_connected_event(struct gelic_wl_info *wl, u64 event) { u64 desired_event = 0; switch (wl->wpa_level) { case GELIC_WL_WPA_LEVEL_NONE: desired_event = GELIC_LV1_WL_EVENT_CONNECTED; break; case GELIC_WL_WPA_LEVEL_WPA: case GELIC_WL_WPA_LEVEL_WPA2: desired_event = GELIC_LV1_WL_EVENT_WPA_CONNECTED; break; } if (desired_event == event) {