@@ -0,0 +1,636 @@+/*-+*BSDLICENSE+*+*Copyright(c)2017IntelCorporation.Allrightsreserved.+*+*Redistributionanduseinsourceandbinaryforms,withorwithout+*modification,arepermittedprovidedthatthefollowingconditions+*aremet:+*+**Redistributionsofsourcecodemustretaintheabovecopyright+*notice,thislistofconditionsandthefollowingdisclaimer.+**Redistributionsinbinaryformmustreproducetheabovecopyright+*notice,thislistofconditionsandthefollowingdisclaimerin+*thedocumentationand/orothermaterialsprovidedwiththe+*distribution.+**NeitherthenameofIntelCorporationnorthenamesofits+*contributorsmaybeusedtoendorseorpromoteproductsderived+*fromthissoftwarewithoutspecificpriorwrittenpermission.+*+*THISSOFTWAREISPROVIDEDBYTHECOPYRIGHTHOLDERSANDCONTRIBUTORS+*"AS IS"ANDANYEXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOT+*LIMITEDTO,THEIMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFOR+*APARTICULARPURPOSEAREDISCLAIMED.INNOEVENTSHALLTHECOPYRIGHT+*OWNERORCONTRIBUTORSBELIABLEFORANYDIRECT,INDIRECT,INCIDENTAL,+*SPECIAL,EXEMPLARY,ORCONSEQUENTIALDAMAGES(INCLUDING,BUTNOT+*LIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODSORSERVICES;LOSSOFUSE,+*DATA,ORPROFITS;ORBUSINESSINTERRUPTION)HOWEVERCAUSEDANDONANY+*THEORYOFLIABILITY,WHETHERINCONTRACT,STRICTLIABILITY,ORTORT+*(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAYOUTOFTHEUSE+*OFTHISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOFSUCHDAMAGE.+*/++#ifndef _RTE_BBDEV_H_+#define _RTE_BBDEV_H_++/**+*@filerte_bbdev.h+*+*WirelessbasebanddeviceapplicationAPIs.+*+*@warning+*@bEXPERIMENTAL:thisAPImaychangewithoutpriornotice+*+*ThisAPIallowsanapplicationtodiscover,configureanduseadeviceto+*processoperations.AnasynchronousAPI(enqueue,followedbylaterdequeue)+*isusedforprocessingoperations.+*+*ThefunctionsinthisAPIarenotthread-safewhencalledonthesame+*targetobject(adevice,oraqueueonadevice),withtheexceptionthat+*onethreadcanenqueueoperationstoaqueuewhileanotherthreaddequeues+*fromthesamequeue.+*/++#ifdef __cplusplus+extern"C"{+#endif++#include<stdint.h>+#include<stdbool.h>+#include<string.h>++#include<rte_pci.h>+#include<rte_cpuflags.h>+#include<rte_memory.h>++#include"rte_bbdev_op.h"++#ifndef RTE_BBDEV_MAX_DEVS+#define RTE_BBDEV_MAX_DEVS 128 /**< Max number of devices */+#endif++/**+*Getthetotalnumberofdevicesthathavebeensuccessfullyinitialised.+*+*@return+*Thetotalnumberofusabledevices.+*/+uint8_t+rte_bbdev_count(void);++/**+*Checkifadeviceisvalid.+*+*@paramdev_id+*Theidentifierofthedevice.+*+*@return+*trueifdeviceIDisvalidanddeviceisattached,falseotherwise.+*/+bool+rte_bbdev_is_valid(uint8_tdev_id);++/**+*Getthenextenableddevice.+*+*@paramdev_id+*Thecurrentdevice+*+*@return+*-Thenextdevice,or+*-RTE_BBDEV_MAX_DEVSifnonefound+*/+uint8_t+rte_bbdev_find_next(uint8_tdev_id);++/** Iterate through all enabled devices */+#define RTE_BBDEV_FOREACH(i) for (i = rte_bbdev_find_next(-1); \+i<RTE_BBDEV_MAX_DEVS;\+i=rte_bbdev_find_next(i))++/** Device configuration structure */+structrte_bbdev_conf{+intsocket;/**< NUMA socket used for memory allocation */+};++/**+*Configureadevice.+*Thisfunctionmustbecalledonadevicebeforesettingupthequeuesand+*startingthedevice.Itcanalsobecalledwhenadeviceisinthestopped+*state.Ifanydevicequeueshavebeenconfiguredtheirconfigurationwillbe+*clearedbyacalltothisfunction.+*+*@paramdev_id+*Theidentifierofthedevice.+*@paramnum_queues+*Numberofqueuestoconfigureondevice.+*@paramconf+*Thedeviceconfiguration.IfNULL,adefaultconfigurationwillbeused.+*+*@return+*-0onsuccess+*-EINVALifnum_queuesisinvalid,0orgreaterthanmaximum+*-EBUSYiftheidentifieddevicehasalreadystarted+*-ENOMEMifunabletoallocatememory+*/+int+rte_bbdev_configure(uint8_tdev_id,uint16_tnum_queues,+conststructrte_bbdev_conf*conf);++/** Device queue configuration structure */+structrte_bbdev_queue_conf{+intsocket;/**< NUMA socket used for memory allocation */+uint32_tqueue_size;/**< Size of queue */+uint8_tpriority;/**< Queue priority */+booldeferred_start;/**< Do not start queue when device is started. */+enumrte_bbdev_op_typeop_type;/**< Operation type */+};++/**+*Configureaqueueonadevice.+*Thisfunctioncanbecalledafterdeviceconfiguration,andbeforestarting.+*Itcanalsobecalledwhenthedeviceorthequeueisinthestoppedstate.+*+*@paramdev_id+*Theidentifierofthedevice.+*@paramqueue_id+*Theindexofthequeue.+*@paramconf+*Thequeueconfiguration.IfNULL,adefaultconfigurationwillbeused.+*+*@return+*-0onsuccess+*-EINVALiftheidentifiedqueuesizeorpriorityareinvalid+*-EBUSYiftheidentifiedqueueoritsdevicehavealreadystarted+*/+int+rte_bbdev_queue_configure(uint8_tdev_id,uint16_tqueue_id,+conststructrte_bbdev_queue_conf*conf);++/**+*Startadevice.+*Thisisthelaststepneededbeforeenqueueingoperationsispossible.+*+*@paramdev_id+*Theidentifierofthedevice.+*+*@return+*-0onsuccess+*-negativevalueonfailure-asreturnedfromPMDdriver+*/+int+rte_bbdev_start(uint8_tdev_id);++/**+*Stopadevice.+*Thedevicecanbereconfigured,andrestartedafterbeingstopped.+*+*@paramdev_id+*Theidentifierofthedevice.+*+*@return+*-0onsuccess+*/+int+rte_bbdev_stop(uint8_tdev_id);++/**+*Closeadevice.+*Thedevicecannotberestartedwithoutreconfiguration!+*+*@paramdev_id+*Theidentifierofthedevice.+*+*@return+*-0onsuccess+*/+int+rte_bbdev_close(uint8_tdev_id);++/**+*Startaspecifiedqueueonadevice.+*Thisisonlyneededifthequeuehasbeenstopped,orifthedeferred_start+*flaghasbeensetwhenconfiguringthequeue.+*+*@paramdev_id+*Theidentifierofthedevice.+*@paramqueue_id+*Theindexofthequeue.+*+*@return+*-0onsuccess+*-negativevalueonfailure-asreturnedfromPMDdriver+*/+int+rte_bbdev_queue_start(uint8_tdev_id,uint16_tqueue_id);++/**+*Stopaspecifiedqueueonadevice,toallowreconfiguration.+*+*@paramdev_id+*Theidentifierofthedevice.+*@paramqueue_id+*Theindexofthequeue.+*+*@return+*-0onsuccess+*-negativevalueonfailure-asreturnedfromPMDdriver+*/+int+rte_bbdev_queue_stop(uint8_tdev_id,uint16_tqueue_id);++/** Device statistics. */+structrte_bbdev_stats{+uint64_tenqueued_count;/**< Count of all operations enqueued */+uint64_tdequeued_count;/**< Count of all operations dequeued */+/** Total error count on operations enqueued */+uint64_tenqueue_err_count;+/** Total error count on operations dequeued */+uint64_tdequeue_err_count;+};++/**+*RetrievethegeneralI/Ostatisticsofadevice.+*+*@paramdev_id+*Theidentifierofthedevice.+*@paramstats+*Pointertostructuretowherestatisticswillbecopied.Onerror,this+*locationmayormaynothavebeenmodified.+*+*@return+*-0onsuccess+*-EINVALifinvalidparameterpointerisprovided+*/+int+rte_bbdev_stats_get(uint8_tdev_id,structrte_bbdev_stats*stats);++/**+*Resetthestatisticsofadevice.+*+*@paramdev_id+*Theidentifierofthedevice.+*@return+*-0onsuccess+*/+int+rte_bbdev_stats_reset(uint8_tdev_id);++/** Device information supplied by the device's driver */+structrte_bbdev_driver_info{+/** Driver name */+constchar*driver_name;++/** Maximum number of queues supported by the device */+unsignedintmax_num_queues;+/** Queue size limit (queue size must also be power of 2) */+uint32_tqueue_size_lim;+/** Set if device off-loads operation to hardware */+boolhardware_accelerated;+/** Max value supported by queue priority */+uint8_tmax_queue_priority;+/** Set if device supports per-queue interrupts */+boolqueue_intr_supported;+/** Minimum alignment of buffers, in bytes */+uint16_tmin_alignment;+/** Default configuration used if none is supplied */+structrte_bbdev_confdefault_conf;+/** Default queue configuration used if none is supplied */+structrte_bbdev_queue_confdefault_queue_conf;+/** Device operation capabilities */+conststructrte_bbdev_op_cap*capabilities;+/** Device cpu_flag requirements */+constenumrte_cpu_flag_t*cpu_flag_reqs;+};++/** Macro used at end of bbdev PMD list */+#define RTE_BBDEV_END_OF_CAPABILITIES_LIST() \+{RTE_BBDEV_OP_NONE}++/* Forward declaration */+structrte_pci_device;++/** Device information structure used by an application to discover a devices+*capabilitiesandcurrentconfiguration+*/+structrte_bbdev_info{+intsocket_id;/**< NUMA socket that device is on */+constchar*dev_name;/**< Unique device name */+conststructrte_pci_device*pci_dev;/**< PCI information */+unsignedintnum_queues;/**< Number of queues currently configured */+structrte_bbdev_confconf;/**< Current device configuration */+boolstarted;/**< Set if device is currently started */+structrte_bbdev_driver_infodrv;/**< Info from device driver */+};++/**+*Retrieveinformationaboutadevice.+*+*@paramdev_id+*Theidentifierofthedevice.+*@paramdev_info+*Pointertostructuretowhereinformationwillbecopied.Onerror,this+*locationmayormaynothavebeenmodified.+*+*@return+*-0onsuccess+*-EINVALifinvalidparameterpointerisprovided+*/+int+rte_bbdev_info_get(uint8_tdev_id,structrte_bbdev_info*dev_info);++/** Queue information */+structrte_bbdev_queue_info{+/** Current device configuration */+structrte_bbdev_queue_confconf;+/** Set if queue is currently started */+boolstarted;+};++/**+*Retrieveinformationaboutaspecificqueueonadevice.+*+*@paramdev_id+*Theidentifierofthedevice.+*@paramqueue_id+*Theindexofthequeue.+*@paramdev_info+*Pointertostructuretowhereinformationwillbecopied.Onerror,this+*locationmayormaynothavebeenmodified.+*+*@return+*-0onsuccess+*-EINVALifinvalidparameterpointerisprovided+*/+int+rte_bbdev_queue_info_get(uint8_tdev_id,uint16_tqueue_id,+structrte_bbdev_queue_info*dev_info);++/** @internal The data structure associated with each queue of a device. */+structrte_bbdev_queue_data{+void*queue_private;/**< Driver-specific per-queue data */+structrte_bbdev_queue_confconf;/**< Current configuration */+structrte_bbdev_statsqueue_stats;/**< Queue statistics */+boolstarted;/**< Queue state */+};++/** @internal Enqueue operations for processing on queue of a device. */+typedefuint16_t(*rte_bbdev_enqueue_ops_t)(structrte_bbdev_queue_data*q_data,+structrte_bbdev_op**ops,uint16_tnum);++/** @internal Dequeue operations from a queue of a device. */+typedefuint16_t(*rte_bbdev_dequeue_ops_t)(structrte_bbdev_queue_data*q_data,+structrte_bbdev_op**ops,uint16_tnum);++#ifndef RTE_BBDEV_NAME_MAX_LEN+#define RTE_BBDEV_NAME_MAX_LEN 64 /**< Max length of device name */+#endif++/**+*@internalThedataassociatedwithadevice,withnofunctionpointers.+*Thisstructureissafetoplaceinsharedmemorytobecommonamong+*differentprocessesinamulti-processconfiguration.Driverscanaccess+*thesefields,butshouldneverwritetothem!+*/+structrte_bbdev_data{+charname[RTE_BBDEV_NAME_MAX_LEN];/**< Unique identifier name */+void*dev_private;/**< Driver-specific private data */+uint16_tnum_queues;/**< Number of currently configured queues */+structrte_bbdev_queue_data*queues;/**< Queue structures */+uint8_tdev_id;/**< Device ID */+intsocket_id;/**< NUMA socket that device is on */+structrte_bbdev_confconf;/**< Current configuration */+boolstarted;/**< Device run-time state */+};++/* Forward declarations */+structrte_bbdev_ops;+structrte_bbdev_callback;+structrte_intr_handle;++/** Structure to keep track of registered callbacks */+TAILQ_HEAD(rte_bbdev_cb_list,rte_bbdev_callback);++/**+*@internalThedatastructureassociatedwithadevice.Driverscanaccess+*thesefields,butshouldonlywritetothe*_opsfields.+*/+struct__rte_cache_alignedrte_bbdev{+rte_bbdev_enqueue_ops_tenqueue_ops;/**< Enqueue function */+rte_bbdev_dequeue_ops_tdequeue_ops;/**< Dequeue function */+conststructrte_bbdev_ops*dev_ops;/**< Functions exported by PMD */+structrte_bbdev_data*data;/**< Pointer to device data */+boolattached;/**< If device is currently attached or not */+structrte_device*device;/**< Backing device (HW only) */+/** User application callback for interrupts if present */+structrte_bbdev_cb_listlist_cbs;+structrte_intr_handle*intr_handle;/**< Device interrupt handle */+};++/** @internal array of all devices */+externstructrte_bbdevrte_bbdev_devices[];++/**+*Enqueueaburstofprocessedoperationstoaqueueofthedevice.+*Thisfunctionsonlyenqueuesasmanyoperationsascurrentlypossibleand+*doesnotblockuntil@pnum_opsentriesinthequeueareavailable.+*Thisfunctiondoesnotprovideanyerrornotificationtoavoidthe+*correspondingoverhead.+*+*@paramdev_id+*Theidentifierofthedevice.+*@paramqueue_id+*Theindexofthequeue.+*@paramops+*PointerarraycontainingoperationstobeenqueuedMusthaveatleast+*@pnum_opsentries+*@paramnum_ops+*Themaximumnumberofoperationstoenqueue.+*+*@return+*Thenumberofoperationsactuallyenqueued(thisisthenumberofprocessed+*entriesinthe@popsarray).+*/+staticinlineuint16_t+rte_bbdev_enqueue_ops(uint8_tdev_id,uint16_tqueue_id,+structrte_bbdev_op**ops,uint16_tnum_ops)+{+structrte_bbdev*dev=&rte_bbdev_devices[dev_id];+structrte_bbdev_queue_data*q_data=&dev->data->queues[queue_id];+uint16_tn=dev->enqueue_ops(q_data,ops,num_ops);++RTE_LOG_DP(DEBUG,BBDEV,"%u ops enqueued to dev%u,q%u. Type = %s\n",+num_ops,dev_id,queue_id,+rte_bbdev_op_type_str(ops[0]->type));++returnn;+}++/**+*Dequeueaburstofprocessedoperationsfromaqueueofthedevice.+*Thisfunctionsreturnsonlythecurrentcontentsofthequeue,anddoesnot+*blockuntil@num_opsisavailable.+*Thisfunctiondoesnotprovideanyerrornotificationtoavoidthe+*correspondingoverhead.+*+*@paramdev_id+*Theidentifierofthedevice.+*@paramqueue_id+*Theindexofthequeue.+*@paramops+*Pointerarraywhereoperationswillbedequeuedto.Musthaveatleast+*@pnum_opsentries+*@paramnum_ops+*Themaximumnumberofoperationstodequeue.+*+*@return+*Thenumberofoperationsactuallydequeued(thisisthenumberofentries+*copiedintothe@popsarray).+*/+staticinlineuint16_t+rte_bbdev_dequeue_ops(uint8_tdev_id,uint16_tqueue_id,+structrte_bbdev_op**ops,uint16_tnum_ops)+{+structrte_bbdev*dev=&rte_bbdev_devices[dev_id];+structrte_bbdev_queue_data*q_data=&dev->data->queues[queue_id];+uint16_tn=dev->dequeue_ops(q_data,ops,num_ops);++RTE_LOG_DP(DEBUG,BBDEV,"%u ops dequeued to dev%u,q%u\n",+n,dev_id,queue_id);++returnn;+}++/** Definitions of device event types */+enumrte_bbdev_event_type{+RTE_BBDEV_EVENT_UNKNOWN,/**< unknown event type */+RTE_BBDEV_EVENT_ERROR,/**< error interrupt event */+RTE_BBDEV_EVENT_MAX/**< max value of this enum */+};++/**+*Typedefforapplicationcallbackfunctionregisteredbyapplication+*softwarefornotificationofdeviceevents+*+*@paramdev_id+*Deviceidentifier+*@paramevent+*Deviceeventtoregisterfornotificationof.+*@paramcb_arg+*Userspecifiedparametertobepassedtouser'scallbackfunction.+*/+typedefvoid(*rte_bbdev_cb_fn)(uint8_tdev_id,+enumrte_bbdev_event_typeevent,void*cb_arg);++/**+*Registeracallbackfunctionforspecificdeviceid.Multiplecallbackscan+*beaddedandwillbecalledintheordertheyareaddedwhenaneventis+*triggered.CallbacksarecalledinaseparatethreadcreatedbytheDPDKEAL.+*+*@paramdev_id+*Deviceid.+*@paramevent+*Theeventthatthecallbackwillberegisteredfor.+*@paramcb_fn+*Usersuppliedcallbackfunctiontobecalled.+*@paramcb_arg+*Pointertoparameterthatwillbepassedtothecallback.+*+*@return+*Zeroonsuccess,negativevalueonfailure.+*/+int+rte_bbdev_callback_register(uint8_tdev_id,enumrte_bbdev_event_typeevent,+rte_bbdev_cb_fncb_fn,void*cb_arg);++/**+*Unregisteracallbackfunctionforspecificdeviceid.+*+*@paramdev_id+*Thedeviceidentifier.+*@paramevent+*Theeventthatthecallbackwillbeunregisteredfor.+*@paramcb_fn+*Usersuppliedcallbackfunctiontobeunregistered.+*@paramcb_arg+*Pointertotheparametersuppliedwhenregisteringthecallback.+*(void*)-1meanstoremoveallregisteredcallbackswiththespecified+*functionaddress.+*+*@return+*-0onsuccess+*-EINVALifinvalidparameterpointerisprovided+*-EAGAINiftheprovidedcallbackpointerdoesnotexist+*/+int+rte_bbdev_callback_unregister(uint8_tdev_id,enumrte_bbdev_event_typeevent,+rte_bbdev_cb_fncb_fn,void*cb_arg);++/**+*Enableaone-shotinterruptonthenextoperationenqueuedtoaparticular+*queue.Theinterruptwillbetriggeredwhentheoperationisreadytobe+*dequeued.Tohandletheinterrupt,anepollfiledescriptormustbe+*registeredusingrte_bbdev_queue_intr_ctl(),andthenanapplication+*thread/lcorecanwaitfortheinterruptusingrte_epoll_wait().+*+*@paramdev_id+*Thedeviceidentifier.+*@paramqueue_id+*Theindexofthequeue.+*+*@return+*-0onsuccess+*-negativevalueonfailure-asreturnedfromPMDdriver+*/+int+rte_bbdev_queue_intr_enable(uint8_tdev_id,uint16_tqueue_id);++/**+*Disableaone-shotinterruptonthenextoperationenqueuedtoaparticular+*queue(ifithasbeenenabled).+*+*@paramdev_id+*Thedeviceidentifier.+*@paramqueue_id+*Theindexofthequeue.+*+*@return+*-0onsuccess+*-negativevalueonfailure-asreturnedfromPMDdriver+*/+int+rte_bbdev_queue_intr_disable(uint8_tdev_id,uint16_tqueue_id);++/**+*Controlinterfaceforper-queueinterrupts.+*+*@paramdev_id+*Thedeviceidentifier.+*@paramqueue_id+*Theindexofthequeue.+*@paramepfd+*Epollfiledescriptorthatwillbeassociatedwiththeinterruptsource.+*IfthespecialvalueRTE_EPOLL_PER_THREADisprovided,aperthreadepoll+*filedescriptorcreatedbytheEALisused(RTE_EPOLL_PER_THREADcanalso+*beusedwhencallingrte_epoll_wait()).+*@paramop+*Theoperationbeperformedforthevector.RTE_INTR_EVENT_ADDor+*RTE_INTR_EVENT_DEL.+*@paramdata+*Usercontext,thatwillbereturnedintheepdata.datafieldofthe+*rte_epoll_eventstructurefilledinbyrte_epoll_wait().+*+*@return+*-0onsuccess+*-ENOTSUPifinterruptsarenotsupportedbytheidentifieddevice+*-negativevalueonfailure-asreturnedfromPMDdriver+*/+int+rte_bbdev_queue_intr_ctl(uint8_tdev_id,uint16_tqueue_id,intepfd,intop,+void*data);++#ifdef __cplusplus+}+#endif++#endif /* _RTE_BBDEV_H_ */
@@ -0,0 +1,333 @@+/*-+*BSDLICENSE+*+*Copyright(c)2017IntelCorporation.Allrightsreserved.+*+*Redistributionanduseinsourceandbinaryforms,withorwithout+*modification,arepermittedprovidedthatthefollowingconditions+*aremet:+*+**Redistributionsofsourcecodemustretaintheabovecopyright+*notice,thislistofconditionsandthefollowingdisclaimer.+**Redistributionsinbinaryformmustreproducetheabovecopyright+*notice,thislistofconditionsandthefollowingdisclaimerin+*thedocumentationand/orothermaterialsprovidedwiththe+*distribution.+**NeitherthenameofIntelCorporationnorthenamesofits+*contributorsmaybeusedtoendorseorpromoteproductsderived+*fromthissoftwarewithoutspecificpriorwrittenpermission.+*+*THISSOFTWAREISPROVIDEDBYTHECOPYRIGHTHOLDERSANDCONTRIBUTORS+*"AS IS"ANDANYEXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOT+*LIMITEDTO,THEIMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFOR+*APARTICULARPURPOSEAREDISCLAIMED.INNOEVENTSHALLTHECOPYRIGHT+*OWNERORCONTRIBUTORSBELIABLEFORANYDIRECT,INDIRECT,INCIDENTAL,+*SPECIAL,EXEMPLARY,ORCONSEQUENTIALDAMAGES(INCLUDING,BUTNOT+*LIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODSORSERVICES;LOSSOFUSE,+*DATA,ORPROFITS;ORBUSINESSINTERRUPTION)HOWEVERCAUSEDANDONANY+*THEORYOFLIABILITY,WHETHERINCONTRACT,STRICTLIABILITY,ORTORT+*(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAYOUTOFTHEUSE+*OFTHISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOFSUCHDAMAGE.+*/++#ifndef _RTE_BBDEV_OP_H_+#define _RTE_BBDEV_OP_H_++/**+*@filerte_bbdev_op.h+*+*Defineswirelessbasebandlayer1operationsandcapabilities+*+*@warning+*@bEXPERIMENTAL:thisAPImaychangewithoutpriornotice+*/++#ifdef __cplusplus+extern"C"{+#endif++#include<stdint.h>++#include<rte_common.h>+#include<rte_mbuf.h>+#include<rte_memory.h>+#include<rte_mempool.h>++/** Flags for turbo decoder operation and capability structure */+enumrte_bbdev_op_td_flag_bitmasks{+/** If sub block de-interleaving is to be performed. */+RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE=(1ULL<<0),+/** To use CRC Type 24B (otherwise use CRC Type 24A). */+RTE_BBDEV_TURBO_CRC_TYPE_24B=(1ULL<<1),+/** If turbo equalization is to be performed. */+RTE_BBDEV_TURBO_EQUALIZER=(1ULL<<2),+/** If set, saturate soft output to +/-127 */+RTE_BBDEV_TURBO_SOFT_OUT_SATURATE=(1ULL<<3),+/**+*Setto1tostartiterationfromeven,elseodd;oneiteration=+*max_iteration+0.5+*/+RTE_BBDEV_TURBO_HALF_ITERATION_EVEN=(1ULL<<4),+/**+*If0,TDstopsafterCRCmatches;elseif1,runstoendofnext+*odditerationafterCRCmatches+*/+RTE_BBDEV_TURBO_CONTINUE_CRC_MATCH=(1ULL<<5),+/** Set if soft output is required to be output */+RTE_BBDEV_TURBO_SOFT_OUTPUT=(1ULL<<6),+/** Set to enable early termination mode */+RTE_BBDEV_TURBO_EARLY_TERMINATION=(1ULL<<7),+/**+*Setiftheinputisarawdata(Ebytes,noNULLbytes).Ifnotset+*theinputisafullcircularbufferwithdata(Kwbytes)asdecribed+*inspec.36.212,chapter5.1.4.1.2.+*/+RTE_BBDEV_TURBO_RAW_INPUT_DATA=(1ULL<<8),+};++/** Flags for turbo encoder operation and capability structure */+enumrte_bbdev_op_te_flag_bitmasks{+/** Ignore rv_index and set K0 = 0 */+RTE_BBDEV_TURBO_RV_INDEX_BYPASS=(1ULL<<0),+/** If rate matching is to be performed */+RTE_BBDEV_TURBO_RATE_MATCH=(1ULL<<1),+/** This bit must be set to enable CRC-24B generation */+RTE_BBDEV_TURBO_CRC_24B_ATTACH=(1ULL<<2),+/** This bit must be set to enable CRC-24A generation */+RTE_BBDEV_TURBO_CRC_24A_ATTACH=(1ULL<<3)+};++/** Data input and output buffer for Turbo operations */+structrte_bbdev_op_data{+structrte_mbuf*data;+/**< First mbuf segment with input/output data. */+uint32_toffset;+/**< The starting point for the Turbo input/output, in bytes, from the+*startofthedatainthedatabuffer.Itmustbesmallerthan+*data_lenofthembuf'sfirstsegment!+*/+uint32_tlength;+/**< For input operations: the length, in bytes, of the source buffer+*onwhichtheTurboencode/decodewillbecomputed.+*Foroutputoperations:thelength,inbytes,oftheoutputbuffer+*oftheTurbooperation.+*/+};++/** Operation structure for the Turbo Decoder */+structrte_bbdev_op_turbo_dec{+structrte_bbdev_op_datainput;/**< input src data */+structrte_bbdev_op_datahard_output;/**< hard output buffer */+structrte_bbdev_op_datasoft_output;/**< soft output buffer */++uint32_top_flags;/**< Flags from rte_bbdev_op_td_flag_bitmasks */+uint32_te;/**< E parameter for TEQ rate matching */+uint16_tk;/**< size of the input code block in bits (40 - 6144) */+uint8_trv_index;/**< Rv index for rate matching (0 - 3) */+uint8_titer_min:4;/**< min number of iterations */+uint8_titer_max:4;/**< max number of iterations */+uint8_titer_count;/**< Actual num. of iterations performed */+/** 5 bit extrinsic scale (scale factor on extrinsic info) */+uint8_text_scale;+/** Number of MAP engines, must be power of 2 (or 0 to auto-select) */+uint8_tnum_maps;+};++/** Operation structure for the Turbo Encoder */+structrte_bbdev_op_turbo_enc{+structrte_bbdev_op_datainput;/**< input src data */+structrte_bbdev_op_dataoutput;/**< output buffer */++uint32_top_flags;/**< Flags from rte_bbdev_op_te_flag_bitmasks */+uint16_tk;/**< size of the input code block in bits (40 - 6144) */+uint32_te;/**< length in bits of the rate match output (17 bits) */+int32_tn_soft;/**< total number of soft bits according to UE cat. */+int32_tk_mimo;/**< MIMO type */+int32_tmdl_harq;/**< the maximum number of DL HARQ processes */+/** total number of bits available for transmission of one TB */+int32_tg;+int32_tnl;/**< number of layer */+int32_tqm;/**< modulation type */+/** Ncb parameter for rate matching, range [k : 3(k+4)] */+uint16_tncb;+uint8_trv_index;/**< Rv index for rate matching (0 - 3) */+};++/** List of the capabilities for the Turbo Decoder */+structrte_bbdev_op_cap_turbo_dec{+/** Flags from rte_bbdev_op_td_flag_bitmasks */+uint32_tcapability_flags;+uint8_tnum_buffers_src;/**< Num scatter-gather buffers */+uint8_tnum_buffers_hard_out;/**< Num scatter-gather buffers */+uint8_tnum_buffers_soft_out;/**< Num scatter-gather buffers */+};++/** List of the capabilities for the Turbo Encoder */+structrte_bbdev_op_cap_turbo_enc{+/** Flags from rte_bbdev_op_te_flag_bitmasks */+uint32_tcapability_flags;+uint8_tnum_buffers_src;/**< Num scatter-gather buffers */+uint8_tnum_buffers_dst;/**< Num scatter-gather buffers */+};++/** Different operation types supported by the device */+enumrte_bbdev_op_type{+RTE_BBDEV_OP_NONE=0,/**< Dummy operation that does nothing */+RTE_BBDEV_OP_TURBO_DEC,/**< Turbo decode */+RTE_BBDEV_OP_TURBO_ENC,/**< Turbo encode */+RTE_BBDEV_OP_TYPE_COUNT,/**< Count of different op types */+};++/** Bit indexes of possible errors reported through status field */+enum{+RTE_BBDEV_DRV_ERROR=0,+RTE_BBDEV_DATA_ERROR,+RTE_BBDEV_CRC_ERROR,+};++/** Structure specifying a single operation */+structrte_bbdev_op{+enumrte_bbdev_op_typetype;/**< Type of this operation */+intstatus;/**< Status of operation that was performed */+structrte_mempool*mempool;/**< Mempool which op instance is in */+void*opaque_data;/**< Opaque pointer for user data */+/**+*Anonymousunionofoperation-typespecificparameters.Whenallocated+*usingrte_bbdev_op_pool_create(),spaceisallocatedforthe+*parametersattheendofeachrte_bbdev_opstructure,andthe+*pointersherepointtoit.+*/+RTE_STD_C11+union{+void*generic;+structrte_bbdev_op_turbo_dec*turbo_dec;+structrte_bbdev_op_turbo_enc*turbo_enc;+};+};++/** Operation capabilities supported by a device */+structrte_bbdev_op_cap{+enumrte_bbdev_op_typetype;/**< Type of operation */+union{+structrte_bbdev_op_cap_turbo_decturbo_dec;+structrte_bbdev_op_cap_turbo_encturbo_enc;+}cap;/**< Operation-type specific capabilities */+};++/** @internal Private data structure stored with operation pool. */+structrte_bbdev_op_pool_private{+enumrte_bbdev_op_typetype;/**< Type of operations in a pool */+};++/**+*Convertsqueueoperationtypefromenumtostring+*+*@paramop_type+*Operationtypeasenum+*+*@returns+*Operationtypeasstring+*+*/+constchar*+rte_bbdev_op_type_str(enumrte_bbdev_op_typeop_type);++/**+*Createsabbdevoperationmempool+*+*@paramname+*Poolname.+*@paramtype+*Operationtype,useRTE_BBDEV_OP_NONEforapoolwhichsupportsall+*operationtypes.+*@paramnum_elements+*Numberofelementsinthepool.+*@paramcache_size+*Numberofelementstocacheonanlcore,seerte_mempool_create()for+*furtherdetailsaboutcachesize.+*@paramsocket_id+*Sockettoallocatememoryon.+*+*@return+*-Pointertoamempoolonsuccess,+*-NULLpointeronfailure.+*/+structrte_mempool*+rte_bbdev_op_pool_create(constchar*name,enumrte_bbdev_op_typetype,+unsignedintnum_elements,unsignedintcache_size,+intsocket_id);++/**+*Bulkallocateoperationsfromamempoolwithparameterdefaultsreset.+*+*@parammempool+*Operationmempool,createdbyrte_bbdev_op_pool_create().+*@paramtype+*Operationtypetoallocate+*@paramops+*Outputarraytoplaceallocatedoperations+*@paramnum_ops+*Numberofoperationstoallocate+*+*@returns+*-0onsuccess+*-EINVALifinvalidmempoolisprovided+*/+staticinlineint+rte_bbdev_op_alloc_bulk(structrte_mempool*mempool,+enumrte_bbdev_op_typetype,structrte_bbdev_op**ops,+uint16_tnum_ops)+{+structrte_bbdev_op_pool_private*priv;+uint16_ti;+intret;++/* Check type */+priv=(structrte_bbdev_op_pool_private*)+rte_mempool_get_priv(mempool);+if(unlikely((priv->type!=type)&&+(priv->type!=RTE_BBDEV_OP_NONE)))+return-EINVAL;++/* Get elements */+ret=rte_mempool_get_bulk(mempool,(void**)ops,num_ops);+if(unlikely(ret<0))+returnret;++/* Reset to default */+for(i=0;i<num_ops;i++){+structrte_bbdev_op*op=ops[i];+op->type=type;+}++RTE_LOG_DP(DEBUG,BBDEV,"%u ops allocated from %s, type = %s\n",+num_ops,mempool->name,+rte_bbdev_op_type_str(type));++return0;+}++/**+*Freeoperationstructuresthatwereallocatedbyrte_bbdev_op_alloc_bulk().+*Allstructuresmustbelongtothesamemempool.+*+*@paramops+*Operationstructures+*@paramnum_ops+*Numberofstructures+*/+staticinlinevoid+rte_bbdev_op_free_bulk(structrte_bbdev_op**ops,unsignedintnum_ops)+{+if(num_ops>0){+rte_mempool_put_bulk(ops[0]->mempool,(void**)ops,num_ops);+RTE_LOG_DP(DEBUG,BBDEV,"%u ops freed to %s\n",num_ops,+ops[0]->mempool->name);+}+}++#ifdef __cplusplus+}+#endif++#endif /* _RTE_BBDEV_OP_H_ */
@@ -0,0 +1,407 @@+/*-+*BSDLICENSE+*+*Copyright(c)2017IntelCorporation.Allrightsreserved.+*+*Redistributionanduseinsourceandbinaryforms,withorwithout+*modification,arepermittedprovidedthatthefollowingconditions+*aremet:+*+**Redistributionsofsourcecodemustretaintheabovecopyright+*notice,thislistofconditionsandthefollowingdisclaimer.+**Redistributionsinbinaryformmustreproducetheabovecopyright+*notice,thislistofconditionsandthefollowingdisclaimerin+*thedocumentationand/orothermaterialsprovidedwiththe+*distribution.+**NeitherthenameofIntelCorporationnorthenamesofits+*contributorsmaybeusedtoendorseorpromoteproductsderived+*fromthissoftwarewithoutspecificpriorwrittenpermission.+*+*THISSOFTWAREISPROVIDEDBYTHECOPYRIGHTHOLDERSANDCONTRIBUTORS+*"AS IS"ANDANYEXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOT+*LIMITEDTO,THEIMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFOR+*APARTICULARPURPOSEAREDISCLAIMED.INNOEVENTSHALLTHECOPYRIGHT+*OWNERORCONTRIBUTORSBELIABLEFORANYDIRECT,INDIRECT,INCIDENTAL,+*SPECIAL,EXEMPLARY,ORCONSEQUENTIALDAMAGES(INCLUDING,BUTNOT+*LIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODSORSERVICES;LOSSOFUSE,+*DATA,ORPROFITS;ORBUSINESSINTERRUPTION)HOWEVERCAUSEDANDONANY+*THEORYOFLIABILITY,WHETHERINCONTRACT,STRICTLIABILITY,ORTORT+*(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAYOUTOFTHEUSE+*OFTHISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOFSUCHDAMAGE.+*/++#ifndef _RTE_BBDEV_PMD_H_+#define _RTE_BBDEV_PMD_H_++/**+*@filerte_bbdev_pmd.h+*+*Wirelessbasebanddriver-facingAPIs.+*+*@warning+*@bEXPERIMENTAL:thisAPImaychangewithoutpriornotice+*+*ThisAPIprovidesthemechanismfordevicedriverstoregisterwiththe+*bbdevinterface.UserapplicationsshouldnotusethisAPI.+*/++#ifdef __cplusplus+extern"C"{+#endif++#include<stdint.h>+#include<rte_pci.h>+#include<rte_log.h>++#include"rte_bbdev.h"++/**+*Helpermacroforlogging+*+*@paramlevel+*Loglevel:EMERG,ALERT,CRIT,ERR,WARNING,NOTICE,INFO,orDEBUG+*@paramfmt+*Theformatstring,asinprintf(3).+*@param...+*Thevariableargumentsrequiredbytheformatstring.+*+*@return+*-0onsuccess+*-Negativeonerror+*/+#define rte_bbdev_log(level, fmt, ...) \+RTE_LOG(level,BBDEV,fmt"\n",##__VA_ARGS__)++/**+*Helpermacrofordebugloggingwithextrasourceinfo+*+*@paramfmt+*Theformatstring,asinprintf(3).+*@param...+*Thevariableargumentsrequiredbytheformatstring.+*+*@return+*-0onsuccess+*-Negativeonerror+*/+#define rte_bbdev_log_debug(fmt, ...) \+rte_bbdev_log(DEBUG,RTE_STR(__LINE__)":%s() "fmt,__func__,\+##__VA_ARGS__)++/**+*Helpermacroforextraconditionalloggingfromdatapath+*+*@paramfmt+*Theformatstring,asinprintf(3).+*@param...+*Thevariableargumentsrequiredbytheformatstring.+*+*@return+*-0onsuccess+*-Negativeonerror+*/+#ifdef RTE_LIBRTE_BBDEV_DEBUG+#define rte_bbdev_log_verbose(fmt, ...) rte_bbdev_log_debug(fmt, ##__VA_ARGS__)+#else+#define rte_bbdev_log_verbose(fmt, ...)+#endif++/** Suggested value for SW based devices */+#define RTE_BBDEV_DEFAULT_MAX_NB_QUEUES RTE_MAX_LCORE++/** Suggested value for SW based devices */+#define RTE_BBDEV_QUEUE_SIZE_LIMIT 16384++/**+*InitialisationfunctionofaHWdriverinvokedforeachmatchingHWdevice+*detectedduringtheEALinitialisationphase,orwhenanewdeviceis+*attached.Thedrivershouldinitialisethedeviceanditsownsoftware+*context.+*+*@paramdev+*Thisisanewdevicestructureinstancethatisassociatedwiththe+*matchingdevice.+*Thedriver*must*populatethefollowingfields:+*-dev_ops+*-enqueue_ops+*-dequeue_ops+*+*@return+*-0onsuccess+*/+typedefint(*rte_bbdev_init_t)(structrte_bbdev*dev);++/**+*FinalizationfunctionofaHWdriverinvokedforeachmatchingHWdevice+*detectedduringtheclosingphase,orwhenadeviceisdetached.+*+*@paramdev+*Thedevicestructureinstancethatisassociatedwiththematchingdevice.+*+*@return+*-0onsuccess+*/+typedefint(*rte_bbdev_uninit_t)(structrte_bbdev*dev);++/**+*@internal+*Wrapperforusebypcidriversasa.probefunctiontoattachtoabbdev+*interface.+*/+int+rte_bbdev_pci_generic_probe(structrte_pci_device*pci_dev,+size_tprivate_data_size,+rte_bbdev_init_tdev_init);++/**+*@internal+*Wrapperforusebypcidriversasa.removefunctiontodetachabbdev+*interface.+*/+int+rte_bbdev_pci_generic_remove(structrte_pci_device*pci_dev,+rte_bbdev_uninit_tdev_uninit);++/**+*Createsandinitialisesanewdevice.Thisfunctionshouldbecalledbythe+*.probecallbackdefinedin"struct rte_vdev_driver"forvirtualdriversand+*in"struct rte_pci_driver"forhardwaredrivers.SinceHWshoulduse+*rte_bbdev_hw_probe()thisfunctionmustbecalledbyaspecificvirtual+*deviceprobe()function.+*+*Exampleusage:+*@code+*staticint+*my_vdevice_driver_probe(constchar*name,constchar*args)+*{+*...+*vdev=rte_bbdev_driver_init(name,+*sizeof(structmy_device_private_data),socket)+*...+*}+*+*staticstructrte_vdev_drivermy_vdevice_eal_driver={+*.probe=my_vdevice_driver_probe,+*.remove=my_vdevice_driver_remove,+*};+*+*RTE_PMD_REGISTER_VDEV(driver_name,my_vdevice_eal_driver);+*RTE_PMD_REGISTER_ALIAS(driver_name,alias);+*RTE_PMD_REGISTER_PARAM_STRING(driver_name,custom_params_format);+*@endcode+*+*@paramname+*Uniquedevicename.+*@paramdev_private_size+*Sizeofdeviceprivatedata.+*@paramsocket_id+*Sockettoallocateresourceson.+*+*@return+*-Pointertothenewdevice.+*Thecallerofthisfunction*must*thenpopulatethefollowingfields+*andonlythesefieldsbeforereturning.+*-dev_ops+*-enqueue_ops+*-dequeue_ops+*-NULLotherwise+*/+structrte_bbdev*+rte_bbdev_driver_init(constchar*name,size_tdev_private_size,+intsocket_id);++/**+*Destroysapreviouslycreateddevice.Thisfunctionshouldbecalledbythe+*.removecallbackdefinedin"struct rte_vdev_driver"forvirtualdriversand+*in"struct rte_pci_driver"forhardwaredrivers.SinceHWshoulduse+*rte_bbdev_hw_remove()thisfunctionmustbecalledbyaspecificvirtual+*deviceremove()function.+*+*Exampleusage:+*@code+*staticint+*my_vdevice_driver_remove(constchar*name)+*{+*...+*vdev=rte_bbdev_driver_uninit(name)+*...+*}+*+*staticstructrte_vdev_drivermy_vdevice_eal_driver={+*.probe=my_vdevice_driver_probe,+*.remove=my_vdevice_driver_remove,+*};+*+*RTE_PMD_REGISTER_VDEV(driver_name,my_vdevice_eal_driver);+*RTE_PMD_REGISTER_ALIAS(driver_name,alias);+*RTE_PMD_REGISTER_PARAM_STRING(driver_name,custom_params_format);+*@endcode+*+*@paramname+*Uniquedevicename.+*+*@return+*-0onsuccess+*-EINVALifinvalidparameterpointerisprovided+*-ENODEVifunabletofindthenameddevice+*/+int+rte_bbdev_driver_uninit(constchar*name);++/**+*Getthedevicestructureforanameddevice.+*+*@paramname+*Nameofthedevice+*+*@return+*-Thedevicestructurepointer,or+*-NULLotherwise+*+*/+structrte_bbdev*+rte_bbdev_get_named_dev(constchar*name);++/**+*Definitionsofallfunctionsexportedbyadriverthroughthethegeneric+*structureoftype*rte_bbdev_ops*suppliedinthe*rte_bbdev*structure+*associatedwithadevice.+*/++/** @internal Function used to configure a device. */+typedefint(*rte_bbdev_configure_t)(structrte_bbdev*dev,uint16_tnum_queues,+conststructrte_bbdev_conf*conf);++/** @internal Function to allocate and configure a device queue. */+typedefint(*rte_bbdev_queue_setup_t)(structrte_bbdev*dev,+uint16_tqueue_id,conststructrte_bbdev_queue_conf*conf);++/* @internal+*Functiontoreleasememoryresourcesallocatedforadevicequeue.+*/+typedefint(*rte_bbdev_queue_release_t)(structrte_bbdev*dev,+uint16_tqueue_id);++/** @internal Function to start a configured device. */+typedefint(*rte_bbdev_start_t)(structrte_bbdev*dev);++/** @internal Function to stop a device. */+typedefvoid(*rte_bbdev_stop_t)(structrte_bbdev*dev);++/** @internal Function to close a device. */+typedefint(*rte_bbdev_close_t)(structrte_bbdev*dev);++/** @internal Function to start a device queue. */+typedefint(*rte_bbdev_queue_start_t)(structrte_bbdev*dev,+uint16_tqueue_id);++/** @internal Function to stop a device queue. */+typedefint(*rte_bbdev_queue_stop_t)(structrte_bbdev*dev,uint16_tqueue_id);++/** @internal Function to read stats from a device. */+typedefvoid(*rte_bbdev_stats_get_t)(structrte_bbdev*dev,+structrte_bbdev_stats*stats);++/** @internal Function to reset stats on a device. */+typedefvoid(*rte_bbdev_stats_reset_t)(structrte_bbdev*dev);++/** @internal Function to retrieve specific information of a device. */+typedefvoid(*rte_bbdev_info_get_t)(structrte_bbdev*dev,+structrte_bbdev_driver_info*dev_info);++/** @internal Function to retrieve specific information of a device. */+typedefvoid(*rte_bbdev_info_get_t)(structrte_bbdev*dev,+structrte_bbdev_driver_info*dev_info);++/* @internal+*Functiontoenableinterruptfornextoponaqueueofadevice.+*/+typedefint(*rte_bbdev_queue_intr_enable_t)(structrte_bbdev*dev,+uint16_tqueue_id);++/* @internal+*Functiontodisableinterruptfornextoponaqueueofadevice.+*/+typedefint(*rte_bbdev_queue_intr_disable_t)(structrte_bbdev*dev,+uint16_tqueue_id);++/**+*Operationsimplementedbydrivers.Fieldsmarkedas"Required"mustbe+*providedbyadriverforadevicetohavebasicfunctionality."Optional"+*fieldsarefornon-vitaloperations+*/+structrte_bbdev_ops{+/**< Configure device. Optional. */+rte_bbdev_configure_tconfigure;+/**< Start device. Optional. */+rte_bbdev_start_tstart;+/**< Stop device. Optional. */+rte_bbdev_stop_tstop;+/**< Close device. Optional. */+rte_bbdev_close_tclose;++/**< Get device info. Required. */+rte_bbdev_info_get_tinfo_get;+/** Get device statistics. Optional. */+rte_bbdev_stats_get_tstats_get;+/** Reset device statistics. Optional. */+rte_bbdev_stats_reset_tstats_reset;++/** Set up a device queue. Required. */+rte_bbdev_queue_setup_tqueue_setup;+/** Release a queue. Required. */+rte_bbdev_queue_release_tqueue_release;+/** Start a queue. Optional. */+rte_bbdev_queue_start_tqueue_start;+/**< Stop a queue pair. Optional. */+rte_bbdev_queue_stop_tqueue_stop;++/** Enable queue interrupt. Optional */+rte_bbdev_queue_intr_enable_tqueue_intr_enable;+/** Disable queue interrupt. Optional */+rte_bbdev_queue_intr_disable_tqueue_intr_disable;+};++/**+*Executesalltheuserapplicationregisteredcallbacksforthespecific+*deviceandeventtype.+*+*@paramdev+*Pointertothedevicestructure.+*@paramevent+*Eventtype.+*/+void+rte_bbdev_pmd_callback_process(structrte_bbdev*dev,+enumrte_bbdev_event_typeevent);++/**+*Initialisationparamsstructurethatcanbeusedbysoftwarebaseddrivers+*/+structrte_bbdev_init_params{+intsocket_id;/**< Base band null device socket */+uint16_tqueues_num;/**< Base band null device queues number */+};++/**+*Parsegenericparametersthatcouldbeusedforsoftwarebaseddevices.+*+*@paramparams+*Pointertostructurethatwillholdtheparsedparameters.+*@paraminput_args+*Pointertoargumentstobeparsed.+*+*@return+*-0onsuccess+*-EINVALifinvalidparameterpointerisprovided+*-EFAULTifunabletoparseprovidedarguments+*/+int+rte_bbdev_parse_params(structrte_bbdev_init_params*params,+constchar*input_args);++#ifdef __cplusplus+}+#endif++#endif /* _RTE_BBDEV_PMD_H_ */
From: Amr Mokhtar <hidden> Date: 2017-08-25 13:46:55
This RFC describes a proposal for the Wireless Base Band Device (bbdev) in DPDK
that abstracts HW accelerators based on FPGA and/or Fixed Function Accelerators
that assist with LTE Physical Layer processing. Furthermore, it decouples the
application from the compute-intensive wireless functions by abstracting their
optimized libraries to appear as virtual bbdev devices.
This makes bbdev a common programming framework that enables the same
application code to be run on different systems with a single software
architecture and programming model. If the system has hardware accelerators,
they will be used, but if the system does not have hardware accelerators,
software implementations can be used.
The proposed bbdev is designed in a lookaside model where the operation to be
processed is first enqueued asynchronously, and then the result is later
dequeued similar to existing lookaside models.
The proposed DPDK Base Band device framework meets the following requirements:
1. Enumerates bbdev hardware devices and load corresponding drivers.
2. Abstracts the same functionality through the optimized software libraries in
case HW device is not existent.
3. Seamless interface for underlying operations (software or hardware)
4. Pluggable drivers for various parts of the packet processing
5. APIs to:
- Probe wireless device capabilities and resources
- Configure, start, stop, close and retrieve information of wireless devices
- Configure, start, stop and retrieve information of operating queues
- Enqueue/dequeue operations to wireless device queues
- Reset and retrieve device and queue statistics
- Support interrupts from HW
The proposed approach is to have a single wireless device interface (bbdev) that
is used for CRC, Rate (De)Matching and Turbo coding functionality supporting LTE
physical Layer use cases. A general term for base band is used in the naming to
allow for a combination of functions to be deployed for flexible and
programmable devices are used such as FPGAs.
The wireless Base Band device interface (bbdev) cannot be looked at as a
subsidiary device class of cryptodev framework, bbdev follows similar design
approach but it is different in definition and from operation perspective.
The bbdev does not require the session management approach that cryptodev needs
to function. Furthermore, bbdev is an abstraction framework that abstracts
various device functions for numerous operations in the LTE physical layer like
Turbo coding and rate matching, which cannot be considered operations of
cryptography. Also, a bbdev device can support multiple wireless functions under
one device ID.
Other design approaches where considered during design selection phase like a
wireless device interface is to have individual interfaces for each operation
type within the LTE physical layer. This somewhat follows the cryptodev model,
where the device interface can be used to perform a single class of operation
type. However, it is difficult to map a device which performs multiple
operations into this model. Consider the hardware accelerator that performs
Rate (De)Matching, Turbo encoding/decoding (Turbo is a Forward Error Correction
algorithm) and CRC handling. The device would have to register with three
interfaces, and it would need three look-aside operations to do the processing
(impacting performance).
It is not correct to use it with a FEC (Forward Error Correction) device
interface, as the device does more than that. Also, there is a wide range of
FEC algorithms, many of which have no parameters or use-cases in common with
Turbo (for example Reed-Solomon used in storage), so the usefulness of such an
interface is questionable.
The initial release of the bbdev includes CRC attachment, Turbo Coding and
Rate (De)Matching supported in software.
A device reports its capabilities when registering itself in the bbdev framework.
With the aid of this capabilities mechanism, an application can query devices to
discover which operations within the LTE physical layer they are capable of
performing.
Turbo code software library can be added as a virtual device to simulate the
functionality being performed by the HW in case it is not existent or in case
the application needs to use the two flavors to suit different types of
workloads, for example: short payloads to use software Turbo and the HW for
larger payloads. This software library is not part of DPDK mainstream, but it
can be downloaded from an external link and linked to DPDK at compile time.
For simplicity, the initial software devices are designed to perform the
operation in the thread context that calls the enqueue function. The result of
the operation will be put onto an internal rte_ring based queue, waiting for
dequeue to be called. As device queues are not thread safe, the single-producer,
single-consumer version of rte_ring queue can be used.
A device ID represents a handle that is used by the application to refer to a
specific instance of a bbdev device. The range of device IDs for bbdevs is not
linked or related in any way with device IDs used for cryptodevs or ethdevs.
The application can query how many bbdevs were discovered by the EAL through
rte_bbdev_count() and then knows the range of valid device IDs that can be used
for further device interaction.
Once a device is present in the applications context, the application can
discover some information about the exact device type and capabilities by
calling rte_bbdev_info_get(dev_id, &info). Capabilities (in terms of operations
supported, max number of queues, etc.) may be different for each device type so
this is an important step for an application that is not highly coupled to a
specific device type.
From the application point of view, each instance of a bbdev device consists of
one or more queues identified by queue IDs. While different devices may have
different capabilities (e.g. support different operation types), all queues on
a device support identical configuration possibilities. A queue is configured
for only one type of operation and is configured at initializations time.
When an operation is enqueued to a specific queue ID, the result is dequeued
from the same queue ID.
Configuration of a device has two different levels: configuration that applies
to the whole device, and configuration that applies to a single queue.
Device configuration is applied with rte_bbdev_configure(dev_id,num_queues,conf)
and queue configuration is applied with
rte_bbdev_queue_configure(dev_id, queue_id,conf). Note that, although all queues
on a device support same capabilities, they can be configured differently and
will then behave differently.
After initialization, devices are in a stopped state, so must be started by the
application. By default, all queues are started when the device is started, but
they can be stopped individually. If an application is finished using a device
it can close the device. Once closed, it cannot be restarted without
reconfiguration.
rte_bbdev_start(dev_id)
rte_bbdev_queue_start(dev_id, queue_id)
rte_bbdev_queue_stop(dev_id, queue_id)
rte_bbdev_stop(dev_id)
rte_bbdev_close(dev_id)
Operations on a buffer (or buffers) are performed by an asynchronous API.
Operations are enqueued to the device, and then dequeued later.
Ordering of operations is maintained between the enqueue and dequeue.
rte_bbdev_enqueue_ops(dev_id, queue_id, **ops, num_ops)
rte_bbdev_dequeue_ops(dev_id, queue_id, **ops, num_ops)
Queues are not thread-safe and the use of multiple queues or application-level
locking is required for multi-threaded applications that share a device.
Note that it is however acceptable for one thread to enqueue to a queue ID and
another thread to dequeue from the same queue ID. This could be used to
implement a multithreaded pipeline where each thread dequeues from a bbdev
device, before enqueueing to the next.
The number of queues supported by the device can be queried through
rte_bbdev_info_get().
**ops is an array of pointers to struct rte_bbdev_op structures which contain
all the details needed by the device to perform a single operation.
As the bbdev interface supports different operation types (although individual
devices may only support a subset of these), it contains a type field, and a
union of parameters for each operation type.
struct rte_bbdev_op {
enum rte_bbdev_op_type type;
â¦
union {
void *generic;
struct rte_bbdev_op_turbo_dec *turbo_dec;
struct rte_bbdev_op_turbo_enc *turbo_enc;
};
};
Find the enclosed patch for the complete API specification, application- and
driver-facing APIs.
Looking forward to getting comments from both the application and driver
Amr Mokhtar (1):
Wireless Base Band Device (bbdev)
lib/librte_bbdev/rte_bbdev.h | 636 +++++++++++++++++++++++++++++++++++++++
lib/librte_bbdev/rte_bbdev_op.h | 333 ++++++++++++++++++++
lib/librte_bbdev/rte_bbdev_pmd.h | 407 +++++++++++++++++++++++++
3 files changed, 1376 insertions(+)
create mode 100644 lib/librte_bbdev/rte_bbdev.h
create mode 100644 lib/librte_bbdev/rte_bbdev_op.h
create mode 100644 lib/librte_bbdev/rte_bbdev_pmd.h
--
1.9.1
From: Mokhtar, Amr <hidden> Date: 2017-09-01 19:38:20
Hello,
Following on the proposal of bbdev, is there any comments. You feedback is highly appreciated.
May I propose to take this topic up to discussion by the Technical Board at next convenient time?
Regards,
Amr
-----Original Message-----
From: Mokhtar, Amr
Sent: Friday 25 August 2017 14:47
To: dev@dpdk.org
Cc: Mokhtar, Amr <redacted>
Subject: [RFC] Wireless Base Band Device (bbdev)
This RFC describes a proposal for the Wireless Base Band Device (bbdev) in DPDK
that abstracts HW accelerators based on FPGA and/or Fixed Function
Accelerators
that assist with LTE Physical Layer processing. Furthermore, it decouples the
application from the compute-intensive wireless functions by abstracting their
optimized libraries to appear as virtual bbdev devices.
This makes bbdev a common programming framework that enables the same
application code to be run on different systems with a single software
architecture and programming model. If the system has hardware accelerators,
they will be used, but if the system does not have hardware accelerators,
software implementations can be used.
The proposed bbdev is designed in a lookaside model where the operation to be
processed is first enqueued asynchronously, and then the result is later
dequeued similar to existing lookaside models.
The proposed DPDK Base Band device framework meets the following
requirements:
1. Enumerates bbdev hardware devices and load corresponding drivers.
2. Abstracts the same functionality through the optimized software libraries in
case HW device is not existent.
3. Seamless interface for underlying operations (software or hardware)
4. Pluggable drivers for various parts of the packet processing
5. APIs to:
- Probe wireless device capabilities and resources
- Configure, start, stop, close and retrieve information of wireless devices
- Configure, start, stop and retrieve information of operating queues
- Enqueue/dequeue operations to wireless device queues
- Reset and retrieve device and queue statistics
- Support interrupts from HW
The proposed approach is to have a single wireless device interface (bbdev) that
is used for CRC, Rate (De)Matching and Turbo coding functionality supporting
LTE
physical Layer use cases. A general term for base band is used in the naming to
allow for a combination of functions to be deployed for flexible and
programmable devices are used such as FPGAs.
The wireless Base Band device interface (bbdev) cannot be looked at as a
subsidiary device class of cryptodev framework, bbdev follows similar design
approach but it is different in definition and from operation perspective.
The bbdev does not require the session management approach that cryptodev
needs
to function. Furthermore, bbdev is an abstraction framework that abstracts
various device functions for numerous operations in the LTE physical layer like
Turbo coding and rate matching, which cannot be considered operations of
cryptography. Also, a bbdev device can support multiple wireless functions under
one device ID.
Other design approaches where considered during design selection phase like a
wireless device interface is to have individual interfaces for each operation
type within the LTE physical layer. This somewhat follows the cryptodev model,
where the device interface can be used to perform a single class of operation
type. However, it is difficult to map a device which performs multiple
operations into this model. Consider the hardware accelerator that performs
Rate (De)Matching, Turbo encoding/decoding (Turbo is a Forward Error
Correction
algorithm) and CRC handling. The device would have to register with three
interfaces, and it would need three look-aside operations to do the processing
(impacting performance).
It is not correct to use it with a FEC (Forward Error Correction) device
interface, as the device does more than that. Also, there is a wide range of
FEC algorithms, many of which have no parameters or use-cases in common
with
Turbo (for example Reed-Solomon used in storage), so the usefulness of such an
interface is questionable.
The initial release of the bbdev includes CRC attachment, Turbo Coding and
Rate (De)Matching supported in software.
A device reports its capabilities when registering itself in the bbdev framework.
With the aid of this capabilities mechanism, an application can query devices to
discover which operations within the LTE physical layer they are capable of
performing.
Turbo code software library can be added as a virtual device to simulate the
functionality being performed by the HW in case it is not existent or in case
the application needs to use the two flavors to suit different types of
workloads, for example: short payloads to use software Turbo and the HW for
larger payloads. This software library is not part of DPDK mainstream, but it
can be downloaded from an external link and linked to DPDK at compile time.
For simplicity, the initial software devices are designed to perform the
operation in the thread context that calls the enqueue function. The result of
the operation will be put onto an internal rte_ring based queue, waiting for
dequeue to be called. As device queues are not thread safe, the single-producer,
single-consumer version of rte_ring queue can be used.
A device ID represents a handle that is used by the application to refer to a
specific instance of a bbdev device. The range of device IDs for bbdevs is not
linked or related in any way with device IDs used for cryptodevs or ethdevs.
The application can query how many bbdevs were discovered by the EAL through
rte_bbdev_count() and then knows the range of valid device IDs that can be used
for further device interaction.
Once a device is present in the applications context, the application can
discover some information about the exact device type and capabilities by
calling rte_bbdev_info_get(dev_id, &info). Capabilities (in terms of operations
supported, max number of queues, etc.) may be different for each device type
so
this is an important step for an application that is not highly coupled to a
specific device type.
From the application point of view, each instance of a bbdev device consists of
one or more queues identified by queue IDs. While different devices may have
different capabilities (e.g. support different operation types), all queues on
a device support identical configuration possibilities. A queue is configured
for only one type of operation and is configured at initializations time.
When an operation is enqueued to a specific queue ID, the result is dequeued
from the same queue ID.
Configuration of a device has two different levels: configuration that applies
to the whole device, and configuration that applies to a single queue.
Device configuration is applied with
rte_bbdev_configure(dev_id,num_queues,conf)
and queue configuration is applied with
rte_bbdev_queue_configure(dev_id, queue_id,conf). Note that, although all
queues
on a device support same capabilities, they can be configured differently and
will then behave differently.
After initialization, devices are in a stopped state, so must be started by the
application. By default, all queues are started when the device is started, but
they can be stopped individually. If an application is finished using a device
it can close the device. Once closed, it cannot be restarted without
reconfiguration.
rte_bbdev_start(dev_id)
rte_bbdev_queue_start(dev_id, queue_id)
rte_bbdev_queue_stop(dev_id, queue_id)
rte_bbdev_stop(dev_id)
rte_bbdev_close(dev_id)
Operations on a buffer (or buffers) are performed by an asynchronous API.
Operations are enqueued to the device, and then dequeued later.
Ordering of operations is maintained between the enqueue and dequeue.
rte_bbdev_enqueue_ops(dev_id, queue_id, **ops, num_ops)
rte_bbdev_dequeue_ops(dev_id, queue_id, **ops, num_ops)
Queues are not thread-safe and the use of multiple queues or application-level
locking is required for multi-threaded applications that share a device.
Note that it is however acceptable for one thread to enqueue to a queue ID and
another thread to dequeue from the same queue ID. This could be used to
implement a multithreaded pipeline where each thread dequeues from a bbdev
device, before enqueueing to the next.
The number of queues supported by the device can be queried through
rte_bbdev_info_get().
**ops is an array of pointers to struct rte_bbdev_op structures which contain
all the details needed by the device to perform a single operation.
As the bbdev interface supports different operation types (although individual
devices may only support a subset of these), it contains a type field, and a
union of parameters for each operation type.
struct rte_bbdev_op {
enum rte_bbdev_op_type type;
…
union {
void *generic;
struct rte_bbdev_op_turbo_dec *turbo_dec;
struct rte_bbdev_op_turbo_enc *turbo_enc;
};
};
Find the enclosed patch for the complete API specification, application- and
driver-facing APIs.
Looking forward to getting comments from both the application and driver
Amr Mokhtar (1):
Wireless Base Band Device (bbdev)
lib/librte_bbdev/rte_bbdev.h | 636
+++++++++++++++++++++++++++++++++++++++
lib/librte_bbdev/rte_bbdev_op.h | 333 ++++++++++++++++++++
lib/librte_bbdev/rte_bbdev_pmd.h | 407 +++++++++++++++++++++++++
3 files changed, 1376 insertions(+)
create mode 100644 lib/librte_bbdev/rte_bbdev.h
create mode 100644 lib/librte_bbdev/rte_bbdev_op.h
create mode 100644 lib/librte_bbdev/rte_bbdev_pmd.h
--
1.9.1
From: Stephen Hemminger <stephen@networkplumber.org> Date: 2017-09-01 20:03:42
+/* Forward declaration */
+struct rte_pci_device;
+
+/** Device information structure used by an application to discover a devices
+ * capabilities and current configuration
+ */
+struct rte_bbdev_info {
+ int socket_id; /**< NUMA socket that device is on */
+ const char *dev_name; /**< Unique device name */
+ const struct rte_pci_device *pci_dev; /**< PCI information */
+ unsigned int num_queues; /**< Number of queues currently configured */
+ struct rte_bbdev_conf conf; /**< Current device configuration */
+ bool started; /**< Set if device is currently started */
+ struct rte_bbdev_driver_info drv; /**< Info from device driver */
+};
Please don't build in dependency on PCI from the beginning.
Number of queues can be uint16_t ?
From: Mokhtar, Amr <hidden> Date: 2017-09-01 21:35:10
Thanks Stephen.
Agree. Will remove dependency on PCI for now. And num_queues should have been declared as uint16_t.
-----Original Message-----
From: Stephen Hemminger [mailto:stephen@networkplumber.org]
Sent: Friday 1 September 2017 21:04
To: Mokhtar, Amr <redacted>
Cc: dev@dpdk.org
Subject: Re: [dpdk-dev] [RFC] Wireless Base Band Device (bbdev)
quoted
+/* Forward declaration */
+struct rte_pci_device;
+
+/** Device information structure used by an application to discover a
+devices
+ * capabilities and current configuration */ struct rte_bbdev_info {
+ int socket_id; /**< NUMA socket that device is on */
+ const char *dev_name; /**< Unique device name */
+ const struct rte_pci_device *pci_dev; /**< PCI information */
+ unsigned int num_queues; /**< Number of queues currently configured
*/
quoted
+ struct rte_bbdev_conf conf; /**< Current device configuration */
+ bool started; /**< Set if device is currently started */
+ struct rte_bbdev_driver_info drv; /**< Info from device driver */
+};
Please don't build in dependency on PCI from the beginning.
Number of queues can be uint16_t ?
From: Thomas Monjalon <hidden> Date: 2017-09-21 14:34:43
25/08/2017 15:46, Amr Mokhtar:
This RFC describes a proposal for the Wireless Base Band Device (bbdev) in DPDK
that abstracts HW accelerators based on FPGA and/or Fixed Function Accelerators
that assist with LTE Physical Layer processing. Furthermore, it decouples the
application from the compute-intensive wireless functions by abstracting their
optimized libraries to appear as virtual bbdev devices.
This makes bbdev a common programming framework that enables the same
application code to be run on different systems with a single software
architecture and programming model. If the system has hardware accelerators,
they will be used, but if the system does not have hardware accelerators,
software implementations can be used.
Looks interesting.
When do you plan to send the first version?
The description done in this RFC is very complete and clear. Thanks
I will ask few questions below.
I assume packets are mbuf and Rx/Tx is done by ethdev. Right?
Did you think about the API required for inline processing
(i.e. bbdev combined with ethdev Rx/Tx)?
[...]
Other design approaches where considered during design selection phase like a
wireless device interface is to have individual interfaces for each operation
type within the LTE physical layer. This somewhat follows the cryptodev model,
where the device interface can be used to perform a single class of operation
type. However, it is difficult to map a device which performs multiple
operations into this model. Consider the hardware accelerator that performs
Rate (De)Matching, Turbo encoding/decoding (Turbo is a Forward Error Correction
algorithm) and CRC handling. The device would have to register with three
interfaces, and it would need three look-aside operations to do the processing
(impacting performance).
It is not correct to use it with a FEC (Forward Error Correction) device
interface, as the device does more than that. Also, there is a wide range of
FEC algorithms, many of which have no parameters or use-cases in common with
Turbo (for example Reed-Solomon used in storage), so the usefulness of such an
interface is questionable.
So you decided to dedicate an API to the wireless base band functions,
which is a functional split.
I think the cryptodev API is a different split: it is targetting all
processing which falls into the crypto category.
Some crypto algorithms are associated to the wireless function,
while others are more generic.
It is very difficult to know how to split the scope of an API.
With the proposed scheme, if a wireless LTE device implements ZUC algorithm,
we will have to support it in a cryptodev PMD while having a bbdev PMD
for other wireless functions.
Thoughts?
The initial release of the bbdev includes CRC attachment, Turbo Coding and
Rate (De)Matching supported in software.
A device reports its capabilities when registering itself in the bbdev framework.
With the aid of this capabilities mechanism, an application can query devices to
discover which operations within the LTE physical layer they are capable of
performing.
Turbo code software library can be added as a virtual device to simulate the
functionality being performed by the HW in case it is not existent or in case
the application needs to use the two flavors to suit different types of
workloads, for example: short payloads to use software Turbo and the HW for
larger payloads. This software library is not part of DPDK mainstream, but it
can be downloaded from an external link and linked to DPDK at compile time.
Do you mean that you do not plan to integrate the SW fallback for
the turbo coding feature?
Even if it is packaged separately, it could be integrated with bbdev API.
[...]
The application can query how many bbdevs were discovered by the EAL through
rte_bbdev_count() and then knows the range of valid device IDs that can be used
for further device interaction.
You must have an iterator macro to be able to manage id range with holes.
I see it is already implemented as RTE_BBDEV_FOREACH.
[...]
**ops is an array of pointers to struct rte_bbdev_op structures which contain
all the details needed by the device to perform a single operation.
As the bbdev interface supports different operation types (although individual
devices may only support a subset of these), it contains a type field, and a
union of parameters for each operation type.
struct rte_bbdev_op {
enum rte_bbdev_op_type type;
union {
void *generic;
struct rte_bbdev_op_turbo_dec *turbo_dec;
struct rte_bbdev_op_turbo_enc *turbo_enc;
};
};
I do not understand this part.
It seems you want only two generic function to perform processing.
I do not see the benefit.
It is usually easier to have one function per type of processing.
I will continue the review with the code itself.
From: Thomas Monjalon <hidden> Date: 2017-09-21 14:56:07
25/08/2017 15:46, Amr Mokhtar:
+/**
+ * Configure a device.
+ * This function must be called on a device before setting up the queues and
+ * starting the device. It can also be called when a device is in the stopped
+ * state. If any device queues have been configured their configuration will be
+ * cleared by a call to this function.
+ *
+ * @param dev_id
+ * The identifier of the device.
+ * @param num_queues
+ * Number of queues to configure on device.
+ * @param conf
+ * The device configuration. If NULL, a default configuration will be used.
+ *
+ * @return
+ * - 0 on success
+ * - EINVAL if num_queues is invalid, 0 or greater than maximum
+ * - EBUSY if the identified device has already started
+ * - ENOMEM if unable to allocate memory
+ */
+int
+rte_bbdev_configure(uint8_t dev_id, uint16_t num_queues,
+ const struct rte_bbdev_conf *conf);
I am not convinced by the "configure all" function in ethdev.
We break the ABI each time we add a new feature to configure.
And it does not really help to have all configurations in one struct.
Would you mind to split the struct rte_bbdev_conf and split
the function accordingly?
[...]
+struct rte_bbdev_info {
+ int socket_id; /**< NUMA socket that device is on */
+ const char *dev_name; /**< Unique device name */
+ const struct rte_pci_device *pci_dev; /**< PCI information */
+ unsigned int num_queues; /**< Number of queues currently configured */
+ struct rte_bbdev_conf conf; /**< Current device configuration */
+ bool started; /**< Set if device is currently started */
+ struct rte_bbdev_driver_info drv; /**< Info from device driver */
+};
As Stephen said, PCI must not appear in this API.
Please use the bus abstraction.
[...]
+struct __rte_cache_aligned rte_bbdev {
+ rte_bbdev_enqueue_ops_t enqueue_ops; /**< Enqueue function */
+ rte_bbdev_dequeue_ops_t dequeue_ops; /**< Dequeue function */
+ const struct rte_bbdev_ops *dev_ops; /**< Functions exported by PMD */
+ struct rte_bbdev_data *data; /**< Pointer to device data */
+ bool attached; /**< If device is currently attached or not */
What "attached" means?
I'm afraid you are trying to manage hotplug in the wrong layer.
SW port should have also a rte_device (vdev).
[...]
+/** Data input and output buffer for Turbo operations */
+struct rte_bbdev_op_data {
Why there is no "turbo" word in the name of this struct?
+ struct rte_mbuf *data;
+ /**< First mbuf segment with input/output data. */
+ uint32_t offset;
+ /**< The starting point for the Turbo input/output, in bytes, from the
+ * start of the data in the data buffer. It must be smaller than
+ * data_len of the mbuf's first segment!
+ */
+ uint32_t length;
+ /**< For input operations: the length, in bytes, of the source buffer
+ * on which the Turbo encode/decode will be computed.
+ * For output operations: the length, in bytes, of the output buffer
+ * of the Turbo operation.
+ */
+};
[...]
+/** Structure specifying a single operation */
+struct rte_bbdev_op {
+ enum rte_bbdev_op_type type; /**< Type of this operation */
+ int status; /**< Status of operation that was performed */
+ struct rte_mempool *mempool; /**< Mempool which op instance is in */
+ void *opaque_data; /**< Opaque pointer for user data */
+ /**
+ * Anonymous union of operation-type specific parameters. When allocated
+ * using rte_bbdev_op_pool_create(), space is allocated for the
+ * parameters at the end of each rte_bbdev_op structure, and the
+ * pointers here point to it.
+ */
+ RTE_STD_C11
+ union {
+ void *generic;
+ struct rte_bbdev_op_turbo_dec *turbo_dec;
+ struct rte_bbdev_op_turbo_enc *turbo_enc;
+ };
+};
I am not sure it is a good idea to fit every operations in the
same struct and the same functions.
[...]
+/**
+ * Helper macro for logging
+ *
+ * @param level
+ * Log level: EMERG, ALERT, CRIT, ERR, WARNING, NOTICE, INFO, or DEBUG
+ * @param fmt
+ * The format string, as in printf(3).
+ * @param ...
+ * The variable arguments required by the format string.
+ *
+ * @return
+ * - 0 on success
+ * - Negative on error
+ */
+#define rte_bbdev_log(level, fmt, ...) \
+ RTE_LOG(level, BBDEV, fmt "\n", ##__VA_ARGS__)
This is the legacy log system.
Please use dynamic log type.
[...]
With the new log functions, you do not need to disable debug log
at compilation time.
+/**
+ * Initialisation params structure that can be used by software based drivers
+ */
+struct rte_bbdev_init_params {
+ int socket_id; /**< Base band null device socket */
+ uint16_t queues_num; /**< Base band null device queues number */
+};
+
+/**
+ * Parse generic parameters that could be used for software based devices.
+ *
+ * @param params
+ * Pointer to structure that will hold the parsed parameters.
+ * @param input_args
+ * Pointer to arguments to be parsed.
+ *
+ * @return
+ * - 0 on success
+ * - EINVAL if invalid parameter pointer is provided
+ * - EFAULT if unable to parse provided arguments
+ */
+int
+rte_bbdev_parse_params(struct rte_bbdev_init_params *params,
+ const char *input_args);
I do not understand the intent of these parameters.
Are they common to every PMDs?
Or could they be moved in software PMDs?
End of this first review pass :)
From: Mokhtar, Amr <hidden> Date: 2017-10-03 14:29:52
Hi Thomas,
Thanks for reviewing.. Kindly find my reply in-line below..
-----Original Message-----
From: Thomas Monjalon [mailto:thomas@monjalon.net]
Sent: Thursday 21 September 2017 15:56
To: Mokhtar, Amr <redacted>
Cc: dev@dpdk.org
Subject: Re: [dpdk-dev] [RFC] Wireless Base Band Device (bbdev)
25/08/2017 15:46, Amr Mokhtar:
quoted
+/**
+ * Configure a device.
+ * This function must be called on a device before setting up the
+queues and
+ * starting the device. It can also be called when a device is in the
+stopped
+ * state. If any device queues have been configured their
+configuration will be
+ * cleared by a call to this function.
+ *
+ * @param dev_id
+ * The identifier of the device.
+ * @param num_queues
+ * Number of queues to configure on device.
+ * @param conf
+ * The device configuration. If NULL, a default configuration will be used.
+ *
+ * @return
+ * - 0 on success
+ * - EINVAL if num_queues is invalid, 0 or greater than maximum
+ * - EBUSY if the identified device has already started
+ * - ENOMEM if unable to allocate memory
+ */
+int
+rte_bbdev_configure(uint8_t dev_id, uint16_t num_queues,
+ const struct rte_bbdev_conf *conf);
I am not convinced by the "configure all" function in ethdev.
We break the ABI each time we add a new feature to configure.
And it does not really help to have all configurations in one struct.
Would you mind to split the struct rte_bbdev_conf and split the function
accordingly?
There is nothing to split tbh. The only parameter it has is the socket_id.
And in fact, it's optional, can be null. The only config we need is num_queues.
I don't see in the near future that we may need to add more config params.
As a side, in the time of the implementation we were trying to avoid any
diversions from the current design ideology of ethdev and cryptodev.
Can we leave it for consideration with future releases?
[...]
quoted
+struct rte_bbdev_info {
+ int socket_id; /**< NUMA socket that device is on */
+ const char *dev_name; /**< Unique device name */
+ const struct rte_pci_device *pci_dev; /**< PCI information */
+ unsigned int num_queues; /**< Number of queues currently configured
*/
quoted
+ struct rte_bbdev_conf conf; /**< Current device configuration */
+ bool started; /**< Set if device is currently started */
+ struct rte_bbdev_driver_info drv; /**< Info from device driver */
+};
As Stephen said, PCI must not appear in this API.
Please use the bus abstraction.
Done.
[...]
quoted
+struct __rte_cache_aligned rte_bbdev {
+ rte_bbdev_enqueue_ops_t enqueue_ops; /**< Enqueue function */
+ rte_bbdev_dequeue_ops_t dequeue_ops; /**< Dequeue function */
+ const struct rte_bbdev_ops *dev_ops; /**< Functions exported by PMD
*/
quoted
+ struct rte_bbdev_data *data; /**< Pointer to device data */
+ bool attached; /**< If device is currently attached or not */
What "attached" means?
I'm afraid you are trying to manage hotplug in the wrong layer.
+/** Data input and output buffer for Turbo operations */ struct
+rte_bbdev_op_data {
Why there is no "turbo" word in the name of this struct?
To keep it a generic input/output data descriptor,
that suits any type of baseband operation not only for turbo.
quoted
+ struct rte_mbuf *data;
+ /**< First mbuf segment with input/output data. */
+ uint32_t offset;
+ /**< The starting point for the Turbo input/output, in bytes, from the
+ * start of the data in the data buffer. It must be smaller than
+ * data_len of the mbuf's first segment!
+ */
+ uint32_t length;
+ /**< For input operations: the length, in bytes, of the source buffer
+ * on which the Turbo encode/decode will be computed.
+ * For output operations: the length, in bytes, of the output buffer
+ * of the Turbo operation.
+ */
+};
[...]
quoted
+/** Structure specifying a single operation */ struct rte_bbdev_op {
+ enum rte_bbdev_op_type type; /**< Type of this operation */
+ int status; /**< Status of operation that was performed */
+ struct rte_mempool *mempool; /**< Mempool which op instance is in
*/
quoted
+ void *opaque_data; /**< Opaque pointer for user data */
+ /**
+ * Anonymous union of operation-type specific parameters. When
allocated
quoted
+ * using rte_bbdev_op_pool_create(), space is allocated for the
+ * parameters at the end of each rte_bbdev_op structure, and the
+ * pointers here point to it.
+ */
+ RTE_STD_C11
+ union {
+ void *generic;
+ struct rte_bbdev_op_turbo_dec *turbo_dec;
+ struct rte_bbdev_op_turbo_enc *turbo_enc;
+ };
+};
I am not sure it is a good idea to fit every operations in the same struct and the
same functions.
Due to the fact that our design adopts this idea that a device can support both
the encode and decode operations.
Then, at the time of PMD registration, the enqueue functions is allocated.
This enqueue() function is common for both operations.
This fitted operation structure is essential for the driver to decide on the operation.
With the new log functions, you do not need to disable debug log at compilation
time.
Right.
quoted
+/**
+ * Initialisation params structure that can be used by software
+based drivers */ struct rte_bbdev_init_params {
+ int socket_id; /**< Base band null device socket */
+ uint16_t queues_num; /**< Base band null device queues number */ };
+
+/**
+ * Parse generic parameters that could be used for software based devices.
+ *
+ * @param params
+ * Pointer to structure that will hold the parsed parameters.
+ * @param input_args
+ * Pointer to arguments to be parsed.
+ *
+ * @return
+ * - 0 on success
+ * - EINVAL if invalid parameter pointer is provided
+ * - EFAULT if unable to parse provided arguments
+ */
+int
+rte_bbdev_parse_params(struct rte_bbdev_init_params *params,
+ const char *input_args);
I do not understand the intent of these parameters.
Are they common to every PMDs?
Or could they be moved in software PMDs?
That was an old design approach, but this now moved and became the
responsibility of the soft PMD.
I am not convinced by the "configure all" function in ethdev.
We break the ABI each time we add a new feature to configure.
And it does not really help to have all configurations in one struct.
Would you mind to split the struct rte_bbdev_conf and split the function
accordingly?
There is nothing to split tbh. The only parameter it has is the socket_id.
And in fact, it's optional, can be null. The only config we need is num_queues.
Indeed, there is nothing in this struct.
If you need only to allocate queues, you just have to rename this function.
I don't see in the near future that we may need to add more config params.
As a side, in the time of the implementation we were trying to avoid any
diversions from the current design ideology of ethdev and cryptodev.
There is no ideology in ethdev, just some mistakes ;)
Can we leave it for consideration with future releases?
No it should be addressed from the beginning.
When you will need to add something more to configure port-wise,
you should add a new function instead of breaking the ABI
of the global conf struct.
That's why the configure option should be more specialized.
Distro people were complaining about ABI breakage last week.
This is exactly an example of how to avoid it from the beginning.
quoted
[...]
quoted
+struct __rte_cache_aligned rte_bbdev {
+ rte_bbdev_enqueue_ops_t enqueue_ops; /**< Enqueue function */
+ rte_bbdev_dequeue_ops_t dequeue_ops; /**< Dequeue function */
+ const struct rte_bbdev_ops *dev_ops; /**< Functions exported by PMD
*/
quoted
+ struct rte_bbdev_data *data; /**< Pointer to device data */
+ bool attached; /**< If device is currently attached or not */
What "attached" means?
I'm afraid you are trying to manage hotplug in the wrong layer.
Hotplug is not supported in the current release.
It is not answering the question.
What is an "attached" device?
quoted
[...]
quoted
+/** Structure specifying a single operation */ struct rte_bbdev_op {
+ enum rte_bbdev_op_type type; /**< Type of this operation */
+ int status; /**< Status of operation that was performed */
+ struct rte_mempool *mempool; /**< Mempool which op instance is in
*/
quoted
+ void *opaque_data; /**< Opaque pointer for user data */
+ /**
+ * Anonymous union of operation-type specific parameters. When
allocated
quoted
+ * using rte_bbdev_op_pool_create(), space is allocated for the
+ * parameters at the end of each rte_bbdev_op structure, and the
+ * pointers here point to it.
+ */
+ RTE_STD_C11
+ union {
+ void *generic;
+ struct rte_bbdev_op_turbo_dec *turbo_dec;
+ struct rte_bbdev_op_turbo_enc *turbo_enc;
+ };
+};
I am not sure it is a good idea to fit every operations
in the same struct and the same functions.
Due to the fact that our design adopts this idea that a device can support both
the encode and decode operations.
Then, at the time of PMD registration, the enqueue functions is allocated.
This enqueue() function is common for both operations.
This fitted operation structure is essential for the driver to decide on the operation.
Sorry I do not understand why you must have a "generic operation".
Please, could you try again to explain this design to someone
not fully understanding how turbo enc/dec works?
I am not convinced by the "configure all" function in ethdev.
We break the ABI each time we add a new feature to configure.
And it does not really help to have all configurations in one struct.
Would you mind to split the struct rte_bbdev_conf and split the function
accordingly?
There is nothing to split tbh. The only parameter it has is the socket_id.
And in fact, it's optional, can be null. The only config we need is num_queues.
Indeed, there is nothing in this struct.
If you need only to allocate queues, you just have to rename this function.
quoted
I don't see in the near future that we may need to add more config params.
As a side, in the time of the implementation we were trying to avoid any
diversions from the current design ideology of ethdev and cryptodev.
There is no ideology in ethdev, just some mistakes ;)
quoted
Can we leave it for consideration with future releases?
No it should be addressed from the beginning.
When you will need to add something more to configure port-wise,
you should add a new function instead of breaking the ABI
of the global conf struct.
That's why the configure option should be more specialized.
Distro people were complaining about ABI breakage last week.
This is exactly an example of how to avoid it from the beginning.
Exactly, and fixing in future is unlikely to happen or could be
more difficult and even if it happens, it will cause another breakage.
--
Flavio
From: Mokhtar, Amr <hidden> Date: 2017-10-05 20:06:20
Hi Thomas,
Kindly find my inline replies below..
-----Original Message-----
From: Thomas Monjalon [mailto:thomas@monjalon.net]
Sent: Thursday 21 September 2017 15:35
To: Mokhtar, Amr <redacted>
Cc: dev@dpdk.org
Subject: Re: [dpdk-dev] [RFC] Wireless Base Band Device (bbdev)
25/08/2017 15:46, Amr Mokhtar:
quoted
This RFC describes a proposal for the Wireless Base Band Device
(bbdev) in DPDK that abstracts HW accelerators based on FPGA and/or
Fixed Function Accelerators that assist with LTE Physical Layer
processing. Furthermore, it decouples the application from the
compute-intensive wireless functions by abstracting their optimized libraries to
appear as virtual bbdev devices.
quoted
This makes bbdev a common programming framework that enables the same
application code to be run on different systems with a single software
architecture and programming model. If the system has hardware
accelerators, they will be used, but if the system does not have
hardware accelerators, software implementations can be used.
Looks interesting.
When do you plan to send the first version?
The description done in this RFC is very complete and clear. Thanks I will ask few
questions below.
I assume packets are mbuf and Rx/Tx is done by ethdev. Right?
Right.
Did you think about the API required for inline processing (i.e. bbdev combined
with ethdev Rx/Tx)?
The current programming model is that ethdev is being used for input/output and
the bbdev is offloaded for lookaside acceleration.
The inline processing topic sounds interesting, this is something we can look at in
the future. Appreciate if you can share your thoughts in that regard.
[...]
quoted
Other design approaches where considered during design selection phase
like a wireless device interface is to have individual interfaces for
each operation type within the LTE physical layer. This somewhat
follows the cryptodev model, where the device interface can be used to
perform a single class of operation type. However, it is difficult to
map a device which performs multiple operations into this model.
Consider the hardware accelerator that performs Rate (De)Matching,
Turbo encoding/decoding (Turbo is a Forward Error Correction
algorithm) and CRC handling. The device would have to register with
three interfaces, and it would need three look-aside operations to do
the processing (impacting performance).
It is not correct to use it with a FEC (Forward Error Correction)
device interface, as the device does more than that. Also, there is a
wide range of FEC algorithms, many of which have no parameters or
use-cases in common with Turbo (for example Reed-Solomon used in
storage), so the usefulness of such an interface is questionable.
So you decided to dedicate an API to the wireless base band functions, which is a
functional split.
I think the cryptodev API is a different split: it is targetting all processing which
falls into the crypto category.
Some crypto algorithms are associated to the wireless function, while others are
more generic.
It is very difficult to know how to split the scope of an API.
The way we view this functional split is:
- If it is a cryptographic function -> cryptodev
- If it is a Wireless L1 function, or in other words, more related to signal processing
(coding, scrambling, modulation, ...) -> bbdev
With the proposed scheme, if a wireless LTE device implements ZUC algorithm,
we will have to support it in a cryptodev PMD while having a bbdev PMD for
other wireless functions.
Thoughts?
ZUC stays a cryptographic algorithm, it should go to cryptodev. It's true that ZUC
is a crypto algorithm used in the mobile wireless domain, but it is not related to signal
processing (Layer 1).
bbdev is targeting all or some of those wireless L1 functions.
quoted
The initial release of the bbdev includes CRC attachment, Turbo Coding
and Rate (De)Matching supported in software.
A device reports its capabilities when registering itself in the bbdev framework.
With the aid of this capabilities mechanism, an application can query
devices to discover which operations within the LTE physical layer
they are capable of performing.
Turbo code software library can be added as a virtual device to
simulate the functionality being performed by the HW in case it is not
existent or in case the application needs to use the two flavors to
suit different types of workloads, for example: short payloads to use
software Turbo and the HW for larger payloads. This software library
is not part of DPDK mainstream, but it can be downloaded from an external
link and linked to DPDK at compile time.
Do you mean that you do not plan to integrate the SW fallback for the turbo
coding feature?
We DO actually plan to support SW-fallback of Turbo FEC in bbdev.
Even if it is packaged separately, it could be integrated with bbdev API.
Right. It is packaged separately and link-able to bbdev library.
[...]
quoted
The application can query how many bbdevs were discovered by the EAL
through
rte_bbdev_count() and then knows the range of valid device IDs that
can be used for further device interaction.
You must have an iterator macro to be able to manage id range with holes.
I see it is already implemented as RTE_BBDEV_FOREACH.
Right. bbdev has the iterator macro.
But, sequential (gapless) device IDs only are currently supported in the first release.
**ops is an array of pointers to struct rte_bbdev_op structures which
contain all the details needed by the device to perform a single operation.
As the bbdev interface supports different operation types (although
individual devices may only support a subset of these), it contains a
type field, and a union of parameters for each operation type.
struct rte_bbdev_op {
enum rte_bbdev_op_type type;
union {
void *generic;
struct rte_bbdev_op_turbo_dec *turbo_dec;
struct rte_bbdev_op_turbo_enc *turbo_enc;
};
};
I do not understand this part.
It seems you want only two generic function to perform processing.
I do not see the benefit.
It is usually easier to have one function per type of processing.
Bbdev devices support Turbo encode and Turbo decode operations.
Both have separate sets of parameters and different functionalities, but
each queue is capable of doing either encode or decode (keep in mind
that this freedom of choice is only applicable before the q gets configured).
There is only one enqueue function for both enc/dec, and similarly one
dequeue function for both. The pmd internally interprets its argument
array of type "rte_bbdev_op" differently based on whether this q was set
up for enc or dec.
See this pseudo-code to give more projection of the idea:
enqueue(struct rte_bbdev_queue_data *q_data, struct rte_bbdev_op *op) {
void *queue = q_data->queue_private;
struct pmd_prv_queue *q = queue;
switch (q->type) {
case RTE_BBDEV_OP_TURBO_ENC:
struct rte_bbdev_op_turbo_enc *enc = op->turbo_enc;
/* do encode */
encode(enc);
break;
case RTE_BBDEV_OP_TURBO_DEC:
struct rte_bbdev_op_turbo_dec *dec = op->turbo_edec;
/* do decode */
decode(dec);
break;
}
Since an enqueue was received on a decode queue, then the union is interpreted
as (rte_bbdev_op_turbo_dec), and vice versa for the encode (rte_bbdev_op_turbo_enc).
From: Thomas Monjalon <hidden> Date: 2017-10-05 20:49:11
05/10/2017 22:06, Mokhtar, Amr:
From: Thomas Monjalon [mailto:thomas@monjalon.net]
quoted
25/08/2017 15:46, Amr Mokhtar:
Did you think about the API required for inline processing (i.e. bbdev combined
with ethdev Rx/Tx)?
The current programming model is that ethdev is being used for input/output and
the bbdev is offloaded for lookaside acceleration.
The inline processing topic sounds interesting, this is something we can look at in
the future. Appreciate if you can share your thoughts in that regard.
When inlining processing in ethdev, it is possible to use rte_flow to
configure processing to be applied on some flows.
However it requires to define the specific action (i.e. processing).
The problem is that you are going to duplicate the API for bbdev processing
if the original API does not fit into a rte_flow action.
The rte_flow actions are still a new idea.
I think it would be nice to have a common structure for
enqueue/dequeue functions and rte_flow configuration.
With this idea, configuring an inline processing would be just
calling an ethdev rte_flow function instead of a bbdev enqueue/dequeue.
Opinions?
[...]
The way we view this functional split is:
- If it is a cryptographic function -> cryptodev
- If it is a Wireless L1 function, or in other words, more related to signal processing
(coding, scrambling, modulation, ...) -> bbdev
quoted
With the proposed scheme, if a wireless LTE device implements ZUC algorithm,
we will have to support it in a cryptodev PMD while having a bbdev PMD for
other wireless functions.
Thoughts?
ZUC stays a cryptographic algorithm, it should go to cryptodev. It's true that ZUC
is a crypto algorithm used in the mobile wireless domain, but it is not related to signal
processing (Layer 1).
bbdev is targeting all or some of those wireless L1 functions.
OK, this definition of the bbdev scope is very interesting.
Please could you explain it in the first lines of bbdev doxygen?
[...]
**ops is an array of pointers to struct rte_bbdev_op structures which
contain all the details needed by the device to perform a single operation.
As the bbdev interface supports different operation types (although
individual devices may only support a subset of these), it contains a
type field, and a union of parameters for each operation type.
struct rte_bbdev_op {
enum rte_bbdev_op_type type;
union {
void *generic;
struct rte_bbdev_op_turbo_dec *turbo_dec;
struct rte_bbdev_op_turbo_enc *turbo_enc;
};
};
I do not understand this part.
It seems you want only two generic function to perform processing.
I do not see the benefit.
It is usually easier to have one function per type of processing.
Bbdev devices support Turbo encode and Turbo decode operations.
Both have separate sets of parameters and different functionalities, but
each queue is capable of doing either encode or decode (keep in mind
that this freedom of choice is only applicable before the q gets configured).
There is only one enqueue function for both enc/dec, and similarly one
dequeue function for both. The pmd internally interprets its argument
array of type "rte_bbdev_op" differently based on whether this q was set
up for enc or dec.
See this pseudo-code to give more projection of the idea:
enqueue(struct rte_bbdev_queue_data *q_data, struct rte_bbdev_op *op) {
void *queue = q_data->queue_private;
struct pmd_prv_queue *q = queue;
switch (q->type) {
case RTE_BBDEV_OP_TURBO_ENC:
struct rte_bbdev_op_turbo_enc *enc = op->turbo_enc;
/* do encode */
encode(enc);
break;
case RTE_BBDEV_OP_TURBO_DEC:
struct rte_bbdev_op_turbo_dec *dec = op->turbo_edec;
/* do decode */
decode(dec);
break;
}
Since an enqueue was received on a decode queue, then the union is interpreted
as (rte_bbdev_op_turbo_dec), and vice versa for the encode (rte_bbdev_op_turbo_enc).
I still do not see the benefit.
Why not 4 functions?
enqueue_enc
enqueue_dec
dequeue_enc
dequeue_dec
Sorry if the question is very basic.
I am not convinced by the "configure all" function in ethdev.
We break the ABI each time we add a new feature to configure.
And it does not really help to have all configurations in one struct.
Would you mind to split the struct rte_bbdev_conf and split the
function accordingly?
There is nothing to split tbh. The only parameter it has is the socket_id.
And in fact, it's optional, can be null. The only config we need is num_queues.
Indeed, there is nothing in this struct.
If you need only to allocate queues, you just have to rename this function.
quoted
I don't see in the near future that we may need to add more config params.
As a side, in the time of the implementation we were trying to avoid
any diversions from the current design ideology of ethdev and cryptodev.
There is no ideology in ethdev, just some mistakes ;)
quoted
Can we leave it for consideration with future releases?
No it should be addressed from the beginning.
When you will need to add something more to configure port-wise, you should
add a new function instead of breaking the ABI of the global conf struct.
That's why the configure option should be more specialized.
Distro people were complaining about ABI breakage last week.
This is exactly an example of how to avoid it from the beginning.
Ok, got your point. I was looking at it from an API-only standpoint.
How about modifying it into?
int
rte_bbdev_setup_queues(uint16_t dev_id, uint16_t num_queues, int socket_id);
quoted
quoted
[...]
quoted
+struct __rte_cache_aligned rte_bbdev {
+ rte_bbdev_enqueue_ops_t enqueue_ops; /**< Enqueue function */
+ rte_bbdev_dequeue_ops_t dequeue_ops; /**< Dequeue function */
+ const struct rte_bbdev_ops *dev_ops; /**< Functions exported by
+PMD
*/
quoted
+ struct rte_bbdev_data *data; /**< Pointer to device data */
+ bool attached; /**< If device is currently attached or not */
What "attached" means?
I'm afraid you are trying to manage hotplug in the wrong layer.
Hotplug is not supported in the current release.
It is not answering the question.
What is an "attached" device?
"Attached" means that the PCI device was probed and the bbdev device slot is allocated.
For software devices, means that a virtual bbdev device (vdev) is allocated for bbdev.
Same way the "attached" approach used in cryptodev.
quoted
quoted
[...]
quoted
+/** Structure specifying a single operation */ struct rte_bbdev_op {
+ enum rte_bbdev_op_type type; /**< Type of this operation */
+ int status; /**< Status of operation that was performed */
+ struct rte_mempool *mempool; /**< Mempool which op instance is
+in
*/
quoted
+ void *opaque_data; /**< Opaque pointer for user data */
+ /**
+ * Anonymous union of operation-type specific parameters. When
allocated
quoted
+ * using rte_bbdev_op_pool_create(), space is allocated for the
+ * parameters at the end of each rte_bbdev_op structure, and the
+ * pointers here point to it.
+ */
+ RTE_STD_C11
+ union {
+ void *generic;
+ struct rte_bbdev_op_turbo_dec *turbo_dec;
+ struct rte_bbdev_op_turbo_enc *turbo_enc;
+ };
+};
I am not sure it is a good idea to fit every operations in the same
struct and the same functions.
Due to the fact that our design adopts this idea that a device can
support both the encode and decode operations.
Then, at the time of PMD registration, the enqueue functions is allocated.
This enqueue() function is common for both operations.
This fitted operation structure is essential for the driver to decide on the
operation.
Sorry I do not understand why you must have a "generic operation".
Please, could you try again to explain this design to someone not fully
understanding how turbo enc/dec works?
Oh, sorry, I was not paying attention that you're referring to "void *generic"
It is just a place-holder for any other operation types. Can be removed if you like.
I am not convinced by the "configure all" function in ethdev.
We break the ABI each time we add a new feature to configure.
And it does not really help to have all configurations in one struct.
Would you mind to split the struct rte_bbdev_conf and split the
function accordingly?
There is nothing to split tbh. The only parameter it has is the socket_id.
And in fact, it's optional, can be null. The only config we need is num_queues.
Indeed, there is nothing in this struct.
If you need only to allocate queues, you just have to rename this function.
quoted
I don't see in the near future that we may need to add more config params.
As a side, in the time of the implementation we were trying to avoid
any diversions from the current design ideology of ethdev and cryptodev.
There is no ideology in ethdev, just some mistakes ;)
quoted
Can we leave it for consideration with future releases?
No it should be addressed from the beginning.
When you will need to add something more to configure port-wise, you should
add a new function instead of breaking the ABI of the global conf struct.
That's why the configure option should be more specialized.
Distro people were complaining about ABI breakage last week.
This is exactly an example of how to avoid it from the beginning.
Ok, got your point. I was looking at it from an API-only standpoint.
How about modifying it into?
int
rte_bbdev_setup_queues(uint16_t dev_id, uint16_t num_queues, int socket_id);
Yes OK
[...]
quoted
quoted
quoted
quoted
+struct __rte_cache_aligned rte_bbdev {
+ rte_bbdev_enqueue_ops_t enqueue_ops; /**< Enqueue function */
+ rte_bbdev_dequeue_ops_t dequeue_ops; /**< Dequeue function */
+ const struct rte_bbdev_ops *dev_ops; /**< Functions exported by
+PMD
*/
quoted
+ struct rte_bbdev_data *data; /**< Pointer to device data */
+ bool attached; /**< If device is currently attached or not */
What "attached" means?
I'm afraid you are trying to manage hotplug in the wrong layer.
Hotplug is not supported in the current release.
It is not answering the question.
What is an "attached" device?
"Attached" means that the PCI device was probed and the bbdev device slot is allocated.
For software devices, means that a virtual bbdev device (vdev) is allocated for bbdev.
Same way the "attached" approach used in cryptodev.
Not sure to understand.
If "attached" means "allocated", when is it false?
[...]
quoted
quoted
quoted
quoted
+/** Structure specifying a single operation */ struct rte_bbdev_op {
+ enum rte_bbdev_op_type type; /**< Type of this operation */
+ int status; /**< Status of operation that was performed */
+ struct rte_mempool *mempool; /**< Mempool which op instance is
+in
*/
quoted
+ void *opaque_data; /**< Opaque pointer for user data */
+ /**
+ * Anonymous union of operation-type specific parameters. When
allocated
quoted
+ * using rte_bbdev_op_pool_create(), space is allocated for the
+ * parameters at the end of each rte_bbdev_op structure, and the
+ * pointers here point to it.
+ */
+ RTE_STD_C11
+ union {
+ void *generic;
+ struct rte_bbdev_op_turbo_dec *turbo_dec;
+ struct rte_bbdev_op_turbo_enc *turbo_enc;
+ };
+};
I am not sure it is a good idea to fit every operations in the same
struct and the same functions.
Due to the fact that our design adopts this idea that a device can
support both the encode and decode operations.
Then, at the time of PMD registration, the enqueue functions is allocated.
This enqueue() function is common for both operations.
This fitted operation structure is essential for the driver to decide on the
operation.
Sorry I do not understand why you must have a "generic operation".
Please, could you try again to explain this design to someone not fully
understanding how turbo enc/dec works?
Oh, sorry, I was not paying attention that you're referring to "void *generic"
It is just a place-holder for any other operation types. Can be removed if you like.
No I was not referring to void *generic.
It is the same question as in the RFC.
I don't understand the benefit of grouping different things in an union.
I am not convinced by the "configure all" function in ethdev.
We break the ABI each time we add a new feature to configure.
And it does not really help to have all configurations in one struct.
Would you mind to split the struct rte_bbdev_conf and split the
function accordingly?
There is nothing to split tbh. The only parameter it has is the socket_id.
And in fact, it's optional, can be null. The only config we need is
num_queues.
quoted
quoted
Indeed, there is nothing in this struct.
If you need only to allocate queues, you just have to rename this function.
quoted
I don't see in the near future that we may need to add more config params.
As a side, in the time of the implementation we were trying to
avoid any diversions from the current design ideology of ethdev and
cryptodev.
quoted
quoted
There is no ideology in ethdev, just some mistakes ;)
quoted
Can we leave it for consideration with future releases?
No it should be addressed from the beginning.
When you will need to add something more to configure port-wise, you
should add a new function instead of breaking the ABI of the global conf
struct.
quoted
quoted
That's why the configure option should be more specialized.
Distro people were complaining about ABI breakage last week.
This is exactly an example of how to avoid it from the beginning.
Ok, got your point. I was looking at it from an API-only standpoint.
How about modifying it into?
int
rte_bbdev_setup_queues(uint16_t dev_id, uint16_t num_queues, int
socket_id);
+ const struct rte_bbdev_ops *dev_ops; /**< Functions
+exported by PMD
*/
quoted
+ struct rte_bbdev_data *data; /**< Pointer to device data */
+ bool attached; /**< If device is currently attached or not
+*/
What "attached" means?
I'm afraid you are trying to manage hotplug in the wrong layer.
Hotplug is not supported in the current release.
It is not answering the question.
What is an "attached" device?
"Attached" means that the PCI device was probed and the bbdev device slot is
allocated.
quoted
For software devices, means that a virtual bbdev device (vdev) is allocated for
bbdev.
quoted
Same way the "attached" approach used in cryptodev.
Not sure to understand.
If "attached" means "allocated", when is it false?
Currently in bbdev, it is set to true and never goes false.
As I said the Hotplug feature is not fully supported in the current version. I can remove that flag for now.
But generally, it should be cleared to false when rte_pci_driver->remove function is called. (Hotplug?)
[...]
quoted
quoted
quoted
quoted
quoted
+/** Structure specifying a single operation */ struct rte_bbdev_op {
+ enum rte_bbdev_op_type type; /**< Type of this operation */
+ int status; /**< Status of operation that was performed */
+ struct rte_mempool *mempool; /**< Mempool which op
instance
quoted
quoted
quoted
quoted
quoted
+is in
*/
quoted
+ void *opaque_data; /**< Opaque pointer for user data */
+ /**
+ * Anonymous union of operation-type specific parameters.
+When
allocated
quoted
+ * using rte_bbdev_op_pool_create(), space is allocated for the
+ * parameters at the end of each rte_bbdev_op structure, and
the
quoted
quoted
quoted
quoted
quoted
+ * pointers here point to it.
+ */
+ RTE_STD_C11
+ union {
+ void *generic;
+ struct rte_bbdev_op_turbo_dec *turbo_dec;
+ struct rte_bbdev_op_turbo_enc *turbo_enc;
+ };
+};
I am not sure it is a good idea to fit every operations in the
same struct and the same functions.
Due to the fact that our design adopts this idea that a device can
support both the encode and decode operations.
Then, at the time of PMD registration, the enqueue functions is allocated.
This enqueue() function is common for both operations.
This fitted operation structure is essential for the driver to
decide on the
operation.
Sorry I do not understand why you must have a "generic operation".
Please, could you try again to explain this design to someone not
fully understanding how turbo enc/dec works?
Oh, sorry, I was not paying attention that you're referring to "void *generic"
It is just a place-holder for any other operation types. Can be removed if you
like.
No I was not referring to void *generic.
It is the same question as in the RFC.
I don't understand the benefit of grouping different things in an union.
There is no benefit, this is a restriction because there is only one function pointer
for enq and another one for deq in the ops structure. Again for the same reason
of trying to keep things in sync with ethdev and cryptodev.
I've always wanted to make it as you proposed, that way it is more performant
(no checking for the type of operation.) If this is agreed, I will do it with all my pleasure :)
The optimum solution though IMHO would be to make the generic enq/deq function pointers
per queue, instead of being per device; that way every enqueue goes straight to
the queue-specific function that matches its operation type.
Notice that currently we have turbo_enc/turbo_dec, but in the future we may have more..
I am not convinced by the "configure all" function in ethdev.
We break the ABI each time we add a new feature to configure.
And it does not really help to have all configurations in one struct.
Would you mind to split the struct rte_bbdev_conf and split the
function accordingly?
There is nothing to split tbh. The only parameter it has is the socket_id.
And in fact, it's optional, can be null. The only config we need is
num_queues.
quoted
quoted
Indeed, there is nothing in this struct.
If you need only to allocate queues, you just have to rename this function.
quoted
I don't see in the near future that we may need to add more config params.
As a side, in the time of the implementation we were trying to
avoid any diversions from the current design ideology of ethdev and
cryptodev.
quoted
quoted
There is no ideology in ethdev, just some mistakes ;)
quoted
Can we leave it for consideration with future releases?
No it should be addressed from the beginning.
When you will need to add something more to configure port-wise, you
should add a new function instead of breaking the ABI of the global conf
struct.
quoted
quoted
That's why the configure option should be more specialized.
Distro people were complaining about ABI breakage last week.
This is exactly an example of how to avoid it from the beginning.
Ok, got your point. I was looking at it from an API-only standpoint.
How about modifying it into?
int
rte_bbdev_setup_queues(uint16_t dev_id, uint16_t num_queues, int
socket_id);
+ const struct rte_bbdev_ops *dev_ops; /**< Functions
+exported by PMD
*/
quoted
+ struct rte_bbdev_data *data; /**< Pointer to device data */
+ bool attached; /**< If device is currently attached or not
+*/
What "attached" means?
I'm afraid you are trying to manage hotplug in the wrong layer.
Hotplug is not supported in the current release.
It is not answering the question.
What is an "attached" device?
"Attached" means that the PCI device was probed and the bbdev device slot is
allocated.
quoted
For software devices, means that a virtual bbdev device (vdev) is allocated for
bbdev.
quoted
Same way the "attached" approach used in cryptodev.
Not sure to understand.
If "attached" means "allocated", when is it false?
Currently in bbdev, it is set to true and never goes false.
As I said the Hotplug feature is not fully supported in the current version. I can remove that flag for now.
But generally, it should be cleared to false when rte_pci_driver->remove function is called. (Hotplug?)
Hotplug is still a work in progress in DPDK.
Please remove this flag if it is useless.
We will add something if needed when hotplug support will be better designed.
quoted
[...]
quoted
quoted
quoted
quoted
quoted
+/** Structure specifying a single operation */ struct rte_bbdev_op {
+ enum rte_bbdev_op_type type; /**< Type of this operation */
+ int status; /**< Status of operation that was performed */
+ struct rte_mempool *mempool; /**< Mempool which op
instance
quoted
quoted
quoted
quoted
quoted
+is in
*/
quoted
+ void *opaque_data; /**< Opaque pointer for user data */
+ /**
+ * Anonymous union of operation-type specific parameters.
+When
allocated
quoted
+ * using rte_bbdev_op_pool_create(), space is allocated for the
+ * parameters at the end of each rte_bbdev_op structure, and
the
quoted
quoted
quoted
quoted
quoted
+ * pointers here point to it.
+ */
+ RTE_STD_C11
+ union {
+ void *generic;
+ struct rte_bbdev_op_turbo_dec *turbo_dec;
+ struct rte_bbdev_op_turbo_enc *turbo_enc;
+ };
+};
I am not sure it is a good idea to fit every operations in the
same struct and the same functions.
Due to the fact that our design adopts this idea that a device can
support both the encode and decode operations.
Then, at the time of PMD registration, the enqueue functions is allocated.
This enqueue() function is common for both operations.
This fitted operation structure is essential for the driver to
decide on the
operation.
Sorry I do not understand why you must have a "generic operation".
Please, could you try again to explain this design to someone not
fully understanding how turbo enc/dec works?
Oh, sorry, I was not paying attention that you're referring to "void *generic"
It is just a place-holder for any other operation types. Can be removed if you
like.
No I was not referring to void *generic.
It is the same question as in the RFC.
I don't understand the benefit of grouping different things in an union.
There is no benefit, this is a restriction because there is only one function pointer
for enq and another one for deq in the ops structure. Again for the same reason
of trying to keep things in sync with ethdev and cryptodev.
I've always wanted to make it as you proposed, that way it is more performant
(no checking for the type of operation.) If this is agreed, I will do it with all my pleasure :)
The optimum solution though IMHO would be to make the generic enq/deq function pointers
per queue, instead of being per device; that way every enqueue goes straight to
the queue-specific function that matches its operation type.
Notice that currently we have turbo_enc/turbo_dec, but in the future we may have more..
Please do not impose some restrictions to your API just because you want
to mimic ethdev.
Feel free to innovate :)